c++ - raytracer - ray tracing fov
Ray-Triangle Intersection C++ (1)
Con sus datos, logré obtener resultados consistentes al normalizar la dirección del rayo (este es el único cambio aparente en el código).
Aquí está la implementación del código (utilicé el documento como referencia, y no está muy optimizado):
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;
}
Estoy probando si un rayo se cruza con un triángulo, por lo que estoy usando el siguiente código para probar si hay una intersección entre un rayo especificado que en este punto tiene una dirección en el punto medio de un triángulo aleatorio:
Ray<float> *ray = new Ray<float>(Vec3<float>(0), chosenTriangle->GetTriangleMidpoint());
Al lado está el objeto Vec3 que estoy usando para almacenar las operaciones vectoriales:
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;
}
el triángulo elegido y el rayo tienen los siguientes valores donde vertA, vertB y vertC son los vértices del triángulo y se encuentran en un objeto que representa un triángulo.
y el código que calcula si hay una intersección entre un rayo especificado y una intersección es el siguiente, este código se encuentra dentro del método del objeto triángulo donde vertA, vertB y vertC son variables globales.
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);
}
Todavía obtengo un resultado falso de la función, pero supongo que debería devolver un valor verdadero, ya que un vector que pasa por el punto medio del triángulo debe cruzarse con el triángulo en algún punto. ¿Alguien puede aclararme qué está mal en mi código? o si la prueba es buena para devolver un resultado falso