2015-01-27 15 views
5

Ich prüfe, ob ein Strahl ein Dreieck schneidet, also teste den folgenden Code, um zu testen, ob es einen Schnittpunkt zwischen einem bestimmten Strahl gibt, der an dieser Stelle eine Richtung zum Mittelpunkt von a hat Zufalls Dreieck:Ray-Triangle Schnitt C++

Ray<float> *ray = new Ray<float>(Vec3<float>(0), chosenTriangle->GetTriangleMidpoint()); 

an der Seite ist die vec3 Objekt, das die Vektoroperationen zu speichern, im mit:

template<typename T> 
class Vec3 
{ 
public: 
    T x, y, z; 
    Vec3() : x(T(0)), y(T(0)), z(T(0)) { } 
    Vec3(T xx) : x(xx), y(xx), z(xx) { } 

    Vec3(T xx, T yy, T zz) : x(xx), y(yy), z(zz) {} 
    Vec3& normalize() 
    { 
     T nor2 = length2(); 
     if (nor2 > 0) { 
      T invNor = 1/sqrt(nor2); 
      x *= invNor, y *= invNor, z *= invNor; 
     } 
     return *this; 
    } 

    Vec3<T> operator * (const T &f) const { return Vec3<T>(x * f, y * f, z * f); } 
    Vec3<T> operator * (const Vec3<T> &v) const { return Vec3<T>(x * v.x, y * v.y, z * v.z); } 
    T dot(const Vec3<T> &v) const { return x * v.x + y * v.y + z * v.z; } 
    Vec3<T> operator - (const Vec3<T> &v) const { return Vec3<T>(x - v.x, y - v.y, z - v.z); } 
    Vec3<T> operator + (const Vec3<T> &v) const { return Vec3<T>(x + v.x, y + v.y, z + v.z); } 
    bool operator == (const Vec3<T> &v) { return x == v.x && y == v.y && z == v.z; } 
    Vec3<T> operator -() const { return Vec3<T>(-x, -y, -z); } 
    T length2() const { return x * x + y * y + z * z; } 
    T length() const { return sqrt(length2()); } 
    Vec3<T> CrossProduct(Vec3<T> other) 
    { 
     return Vec3<T>(y*other.z - other.y*z, x*other.z - z*other.x, x*other.y - y*other.x); 
    } 
    friend std::ostream & operator << (std::ostream &os, const Vec3<T> &v) 
    { 
     os << "[" << v.x << " " << v.y << " " << v.z << "]"; 
     return os; 
    } 

das gewählte Dreieck und der Strahl haben folgende Werte in dem VERTA, vertB und vertC sind Ecken des Dreiecks und sind in einem Objekt gefunden was ein Dreieck darstellt.

enter image description here

und der Code, die zwischen einem festgelegten Strahl eine Kreuzung ist, und ein Schnittpunkt ist der followin, wird dieser Code innerhalb des Dreiecks Objektmethode gefunden, wo VERTA, vertB und vertC sind globale Variablen, wenn es berechnet.

bool CheckRayIntersection(Vec3<T> &o, Vec3<T> &d) 
{ 
    Vec3<T> e1 = vertB - vertA; 
    Vec3<T> e2 = vertC - vertA; 
    Vec3<T> p = d.CrossProduct(e2); 
    T a = e1.dot(p); 

    if(a == 0) 
     return false; 

    float f = 1.0f/a; 

    Vec3<T> s = o - vertA; 
    T u = f * s.dot(p); 
    if(u < 0.0f || u > 1.0f) 
     return false; 

    Vec3<T> q = s.CrossProduct(e1); 
    T v = f * d.dot(q); 

    if(v < 0.0f || u+v > 1.0f) 
     return false; 

    T t = f * e2.dot(q); 

    return (t >= 0); 

} 

ich immer noch ein falsche von der Funktion zurückgegeben, aber im vorausgesetzt es einen Fall, da ein Vektor durch den Mittelpunkt des Dreiecks zurückkehren sollte das Dreieck an einem gewissen Punkt schneiden soll. Kann mir jemand erklären, was in meinem Code falsch ist? oder wenn der Test ist gut, um eine falsche

+0

Wo haben Verta, vertB und vertC kam? Sie sind nicht innerhalb von Funktionsparametern. Das sind globale Variablen oder Sie haben keine vollständige Funktion angegeben. – SigTerm

+0

@SigTerm hat den kompletten Code nicht angegeben, sie sind nur die Koordinaten des Dreiecks, werden aktualisiert –

+1

Es scheint, dass Sie [den Möller-Trumbore] implementieren (http://www.cs.virginia.edu/~gfx/Courses/ 2003/ImageSynthesis/Papiere/Beschleunigung/Fast% 20MinimumStorage% 20RayTriangle% 20Intersection.pdf) Algorithmus. Mein Bauchgefühl sagt mir, dass Sie eine Ihrer 'Vec3'-Methoden falsch verstanden haben, da Ihre Implementierung die _shape_ der von mir angegebenen – Rerito

Antwort

3

Mit Ihren Daten, ich habe es geschafft, konsistente Ergebnisse erhalten, indem die Strahlrichtung normalisiert (dies ist die einzige offensichtliche Änderung im Code). Hier

ist die Code-Implementierung (I verwendet, um das Papier als Referenz, und es ist nicht sehr optimiert):

struct quickVect 
{ 

    float x,y,z; 
    float l; 
}; 

#define DOT(v1,v2) (v1.x*v2.x + v1.y*v2.y+v1.z*v2.z) 
#define CROSS(rez,v1,v2) \ 
rez.x = v1.y*v2.z - v1.z*v2.y; \ 
rez.y = v1.z*v2.x - v1.x*v2.z; \ 
rez.z = v1.x*v2.y - v1.y*v2.x; 

#define SUB(rez,v1,v2) \ 
rez.x = v1.x-v2.x; \ 
rez.y = v1.y-v2.y; \ 
rez.z = v1.z-v2.z; 


#define LENGTH(v) (sqrtf(v.x* v.x + v.y*v.y + v.z*v.z)) 

#define NORMALIZE(v) \ 
v.l = LENGTH(v); \ 
v.x = v.x/v.l; \ 
v.y = v.y/v.l; \ 
v.z = v.z/v.l; 

#define EPSILON 0.000001f 

//#define TEST_CULL 

bool testIntersection(quickVect& v1, quickVect& v2, quickVect& v3, quickVect& orig,quickVect& dir) 
{ 
quickVect e1,e2,pvec,qvec,tvec; 

SUB(e1,v2,v1); 
SUB(e2,v3,v1); 

CROSS(pvec,dir,e2); 

NORMALIZE(dir); 
//NORMALIZE(pvec); 
float det = DOT(pvec,e1); 
#ifdef TEST_CULL 
if (det <EPSILON) 
{ 

    return false; 
} 
SUB(tvec,orig,v1); 
float u = DOT(tvec,pvec); 
if (u < 0.0 || u > det) 
{ 

    return false; 
} 
CROSS(qvec,tvec,e1); 
float v = DOT(dir,qvec); 
if (v < 0.0f || v + u > det) 
{ 

    return false; 
} 
#else 
if (det < EPSILON && det > -EPSILON) 
{ 

    return false; 
} 

float invDet = 1.0f/det; 
SUB(tvec,orig,v1); 
// NORMALIZE(tvec); 
float u = invDet * DOT(tvec,pvec); 
if (u <0.0f || u > 1.0f) 
{ 

    return false; 
} 
CROSS(qvec,tvec,e1); 
// NORMALIZE(qvec); 
float v = invDet* DOT(qvec,dir); 
if (v < 0.0f || u+v > 1.0f) 
{ 

    return false; 
} 
#endif 
return true; 
}