Esempio n. 1
0
Real Cylinder3D::closestPoint(const Point3D& pt,Point3D& closest) const
{
  Real h = dot(pt-center,axis);
  if(h < 0) {
    Circle3D c;
    getBase(c);
    return c.closestPoint(pt,closest);
  }
  else if (h > height) {
    Circle3D c;
    getCap(c);
    return c.closestPoint(pt,closest);
  }
  else {
    Vector3 vperp = (pt-center) - h*axis;
    Real rv = vperp.norm();
    if(rv <= radius) { 
      //inside cylinder
      closest = pt;
      return 0;
    }
    else {
      closest = center + axis*h + vperp*(radius/rv);
      return rv - radius;
    }
  }
}
Esempio n. 2
0
bool Cylinder3D::intersects(const Line3D& line,Real* tmin,Real* tmax) const
{
  Real axistmin,axistmax;

  //quick reject - infinite cylinder
  Vector3 src=line.source-center;
  const Vector3& dir=line.direction;
  assert(FuzzyEquals(axis.normSquared(),One));
  //quadratic equation
  Real a,b,c;
  Real dv,sv;
  dv = dir.dot(axis);
  sv = src.dot(axis);
  a=dir.normSquared()-Sqr(dv);
  b=Two*(dir.dot(src)-sv*dv);
  c=src.normSquared()-Sqr(sv)-Sqr(radius);
  int nroots=quadratic(a,b,c,axistmin,axistmax);
  //TODO: if the line is contained within the cylinder, ignore this
  if(nroots == 0) return false;
  else if(nroots == 1) axistmax=axistmin;
  else if(nroots == 2) {
    if(axistmin > axistmax) std::swap(axistmin,axistmax);
  }
  else if(nroots == -1) return false;
  else return false;  //what case is this?

  //projection of intersection pts on the cyl axis
  Real axisumin,axisumax;
  Vector3 temp;
  line.eval(axistmin,temp);  axisumin = axis.dot(temp-center);
  line.eval(axistmax,temp);  axisumax = axis.dot(temp-center);

  //now check the caps
  Real tc;
  Circle3D cir;
  if(axisumin < 0) {   //hits a cap first
    if(dv > 0) //line points along axis
      getBase(cir);
    else  //line points against axis
      getCap(cir);
    if(!cir.intersects(line,&tc)) return false;
    axistmin = tc;
  }
  if(axisumin > height) {  //hits a cap last
    if(dv > 0) //line points along axis
      getCap(cir);
    else  //line points against axis
      getBase(cir);
    if(!cir.intersects(line,&tc)) return false;
    axistmax = tc;
  }
  //if(axistmin > axistmax) return false;
  if(tmin) *tmin=axistmin;
  if(tmax) *tmax=axistmax;
  return true;
}
Esempio n. 3
0
bool Circle3D::boundaryIntersects(const Sphere3D& s) const
{
  //slice the ball along the plane of the circle, check for circle-disk intersection
  Plane3D p;
  Circle3D cs;
  getPlane(p);

  if(!cs.setIntersection(s,p)) return false;
  return Sphere3D::ballSphereIntersect(cs.center,cs.radius,center,radius);
}
Esempio n. 4
0
void Cylinder3D::getAABB(AABB3D& aabb) const
{
  Circle3D c;
  getBase(c);
  c.getAABB(aabb);
  if(axis.x > 0) aabb.bmax.x += axis.x*height;
  else aabb.bmin.x -= axis.x*height;
  if(axis.y > 0) aabb.bmax.y += axis.y*height;
  else aabb.bmin.y -= axis.y*height;
  if(axis.z > 0) aabb.bmax.z += axis.z*height;
  else aabb.bmin.z -= axis.z*height;
}
Esempio n. 5
0
bool BallCircleCollision(const Sphere3D& a, const Circle3D& b)
{
  return b.boundaryIntersects(a);
}
Esempio n. 6
0
bool TransformWidget::Hover(int x,int y,Camera::Viewport& viewport,double& distance)
{
  Real globalScale = 1.0;
  if(scaleToScreen) {
    float sx,sy,sz;
    viewport.project(T.t,sx,sy,sz);
    globalScale = sz/viewport.scale;
  }
  distance = Inf;
  int oldHoverItem = hoverItem;
  hoverItem = -1;
  Ray3D r;
  viewport.getClickSource(x,y,r.source);
  viewport.getClickVector(x,y,r.direction);
  //check origin
  if(enableTranslation && enableOriginTranslation) {
    Sphere3D s;
    s.center = T.t;
    s.radius = originRadius*globalScale;
    Real tmin,tmax;
    if(s.intersects(r,&tmin,&tmax)) {
      distance = tmin;
      hoverItem = 0;
    }
  }
  //check translation axes
  for(int i=0;i<3;i++) {
    if(!enableTranslation) break;
    if(!enableTranslationAxes[i]) continue;
    Line3D axisLine;
    axisLine.source = T.t;
    axisLine.direction = Vector3(T.R.col(i));
    Real t,u;
    axisLine.closestPoint(r,t,u);
    t = Clamp(t,0.0,axisLength*globalScale);
    u = Clamp(u,0.0,Inf);
    Vector3 paxis,pray;
    axisLine.eval(t,paxis);
    r.eval(u,pray);
    if(paxis.distanceSquared(pray) <= Sqr(axisRadius*globalScale)) {
      if(u < distance) {
	distance = u;
	hoverItem = 1+i;
      }
    }
  }
  if(enableRotation) {
    //check rotation rings
    Circle3D c;
    c.center = T.t;
    for(int i=0;i<3;i++) {
      if(!enableRotationAxes[i]) continue;
      c.axis = Vector3(T.R.col(i));
      c.radius = ringOuterRadius*globalScale;
      Real t;
      if(c.intersects(r,&t) && t >= 0) {
	c.radius = ringInnerRadius*globalScale;
	if(!c.intersects(r,NULL)) {
	  if(t < distance) {
	    distance = t;
	    hoverItem = i+4;
	  }
	}
      }
    }
  }
  if(enableRotation && enableOuterRingRotation) {
    //check outer ring
    Circle3D c;
    c.center = T.t;
    viewport.getViewVector(c.axis);
    c.radius = (ringOuterRadius+arrowHeight)*globalScale;
    Real t;
    if(c.intersects(r,&t) && t >= 0) {
      c.radius = (ringInnerRadius+arrowHeight)*globalScale;
      if(!c.intersects(r,NULL)) {
	if(t < distance) {
	  distance = t;
	  hoverItem = 7;
	}
      }
    }
    clickAxis = c.axis;
  }
  if(hoverItem != oldHoverItem) Refresh();
  r.eval(distance,hoverPos);
  return hoverItem != -1;
}