Versuchen zu optimieren-line-vs Zylinder Kreuzung

Mein Gehirn Schmelzen über einen line-segment-vs-Zylinder-Kreuzung routine, die ich gearbeitet habe.

 ///Line segment VS <cylinder>
 //- cylinder (A, B, r) (start point, end point, radius)
 //- line has starting point (x0, y0, z0) and ending point (x0+ux, y0+uy, z0+uz) ((ux, uy, uz) is "direction")
 //=> start = (x0, y0, z0)
 //  dir = (ux, uy, uz)
 //  A
 //  B
 //  r
 //  optimize? (= don't care for t > 1)
 //<= t  = "time" of intersection
 //  norm = surface normal of intersection point
 void CollisionExecuter::cylinderVSline(const Ogre::Vector3& start, const Ogre::Vector3& dir, const Ogre::Vector3& A, const Ogre::Vector3& B, const double r,
             const bool optimize, double& t, Ogre::Vector3& normal) {
  t = NaN;

  //Solution : http://www.gamedev.net/community/forums/topic.asp?topic_id=467789
  double cxmin, cymin, czmin, cxmax, cymax, czmax;
  if (A.z < B.z) { czmin = A.z - r; czmax = B.z + r; } else { czmin = B.z - r; czmax = A.z + r; }
  if (A.y < B.y) { cymin = A.y - r; cymax = B.y + r; } else { cymin = B.y - r; cymax = A.y + r; }
  if (A.x < B.x) { cxmin = A.x - r; cxmax = B.x + r; } else { cxmin = B.x - r; cxmax = A.x + r; }
  if (optimize) {
   if (start.z >= czmax && (start.z + dir.z) > czmax) return;
   if (start.z <= czmin && (start.z + dir.z) < czmin) return;
   if (start.y >= cymax && (start.y + dir.y) > cymax) return;
   if (start.y <= cymin && (start.y + dir.y) < cymin) return;
   if (start.x >= cxmax && (start.x + dir.x) > cxmax) return;
   if (start.x <= cxmin && (start.x + dir.x) < cxmin) return;
  }

  Ogre::Vector3 AB = B - A;
  Ogre::Vector3 AO = start - A;
  Ogre::Vector3 AOxAB = AO.crossProduct(AB);
  Ogre::Vector3 VxAB  = dir.crossProduct(AB);
  double ab2 = AB.dotProduct(AB);
  double a = VxAB.dotProduct(VxAB);
  double b = 2 * VxAB.dotProduct(AOxAB);
  double c = AOxAB.dotProduct(AOxAB) - (r*r * ab2);
  double d = b * b - 4 * a * c;
  if (d < 0) return;
  double time = (-b - sqrt(d)) / (2 * a);
  if (time < 0) return;

  Ogre::Vector3 intersection = start + dir * time;        ///intersection point
  Ogre::Vector3 projection = A + (AB.dotProduct(intersection - A) / ab2) * AB; ///intersection projected onto cylinder axis
  if ((projection - A).length() + (B - projection).length() > AB.length()) return; ///THIS IS THE SLOW SAFE WAY
  //if (projection.z > czmax - r || projection.z < czmin + r ||
  //projection.y > cymax - r || projection.y < cymin + r ||
  //projection.x > cxmax - r || projection.x < cxmin + r ) return; ///THIS IS THE FASTER BUGGY WAY

  normal = (intersection - projection);
  normal.normalise();
  t = time; ///at last
 }

Ich dachte, dieser Weg, um die Geschwindigkeit der Entdeckung, ob die Projektion der Schnittpunkt liegt innerhalb des Zylinders der Länge. Jedoch, es funktioniert nicht und ich kann nicht wirklich bekommen, weil es scheint so logisch :
wenn der projizierte Punkt x -, y-oder z-Koordinate nicht innerhalb des Zylinders Grenzen, es sollte sein, als außerhalb. Es scheint jedoch, dass dies nicht funktioniert in der Praxis.

Jede Hilfe wäre sehr geschätzt werden!

Cheers,

Bill Kotsias

Edit : Es scheint, dass die Probleme steigen mit den Grenz-Fällen ich.e, wenn der Zylinder parallel zu einer der Achsen. Rundungsfehler kommen in die Gleichung, und die "Optimierung" nicht mehr funktioniert korrekt.

Vielleicht, wenn die Logik ist richtig ist, die Probleme verschwinden durch einfügen von ein wenig Toleranz wie :

  if (projection.z > czmax - r + 0.001 || projection.z < czmin + r - 0.001 || ... etc...

InformationsquelleAutor Bill Kotsias | 2010-11-02

Schreibe einen Kommentar