This is my first post here and i must say i'm really excited about the ease of using Newton. I just started a few days ago, but i can't seem to get correct raycasting WITH normal and texture coords interpolation. I'm developing a simple(toy) raytracer and i need to find the closest intersection of the whole scene with a ray, the normal at that intersection and the texture coordinates. I'm using multiple objects (spheres and collision trees) but let's concentrate on collision trees because they are the source of my problem. I build the collision tree as follows:
- Code: Select all
NewtonCollision* collision;
NewtonWorld* newtonWorld = (NewtonWorld*)worldPointer;
// now create and empty collision tree
collision = NewtonCreateTreeCollision (newtonWorld, 0);
// start adding faces to the collision tree
NewtonTreeCollisionBeginBuild (collision);
faceArray.reset(new FaceArray);
verticesArray.reset(new Endeavour::Assets::Vector3fArray);
normalsArray.reset(new Endeavour::Assets::Vector3fArray);
texCoordsArray.reset(new Endeavour::Assets::Vector2fArray);
int i,oldFace = 0;
for (i=0; i<faceArrays.size(); i++)
{
Endeavour::Assets::FaceArray* faceArray = faceArrays[i];
Endeavour::Math::Vector3fArray* vertices = verticesArrays[i];
Endeavour::Math::Vector3fArray* normals = normalsArrays[i];
Endeavour::Math::Vector2fArray* texCoords = texCoordsArrays[i];
int face;
for (face=0; face<faceArray->size(); face++)
{
Face f = faceArray->at(face);
dVector faceVect[3];
faceVect[0] = dVector(vertices->at(f.index1).x, vertices->at(f.index1).y, vertices->at(f.index1).z);
faceVect[1] = dVector(vertices->at(f.index2).x, vertices->at(f.index2).y, vertices->at(f.index2).z);
faceVect[2] = dVector(vertices->at(f.index3).x, vertices->at(f.index3).y, vertices->at(f.index3).z);
this->verticesArray->push_back(vertices->at(f.index1));
this->verticesArray->push_back(vertices->at(f.index2));
this->verticesArray->push_back(vertices->at(f.index3));
this->normalsArray->push_back(normals->at(f.index1));
this->normalsArray->push_back(normals->at(f.index2));
this->normalsArray->push_back(normals->at(f.index3));
/*
this->texCoordsArray->push_back(texCoords->at(f.index1));
this->texCoordsArray->push_back(texCoords->at(f.index2));
this->texCoordsArray->push_back(texCoords->at(f.index3));
*/
f.index1 = (oldFace+face)*3 + 0;
f.index2 = (oldFace+face)*3 + 1;
f.index3 = (oldFace+face)*3 + 2;
this->faceArray->push_back(f);
NewtonTreeCollisionAddFace(collision, 3, &faceVect[0].m_x, sizeof (dVector), oldFace+face);
}
printf("numFaces=%d\n", this->faceArray->size());
oldFace += faceArray->size();
}
printf("*numFaces=%d\n", this->faceArray->size());
Endeavour::System::Timer timer;
// end adding faces to the collision tree, also optimize the mesh for best performance
NewtonTreeCollisionEndBuild (collision, 1);
printf("Time to construct: %f\n", timer.elapsed());
NewtonTreeCollisionSetUserRayCastCallback(collision, UserMeshCollisionCallback);
Also here is the UserMeshCollisionCallback function:
- Code: Select all
static dFloat UserMeshCollisionCallback (const NewtonBody* const body, const NewtonCollision* const collisionTree, dFloat interception, dFloat* normal, int faceId, void* usedData)
{
((RaycastInfoObject*)usedData)->faceIndex = faceId;
return interception;
}
And here is the RayCastFilter function, passed to NewtonWorldRayCast routine:
- Code: Select all
static dFloat RayCastFilter (const NewtonBody* body, const dFloat* normal, int collisionID, void* userData, dFloat intersetParam)
{
if (intersetParam < ((RaycastInfoObject*)userData)->pickedParam)
{
((RaycastInfoObject*)userData)->pickedParam = intersetParam;
((RaycastInfoObject*)userData)->pickedBody = (NewtonBody*)body;
((RaycastInfoObject*)userData)->normal =
Endeavour::Math::Vector3f(normal[0], normal[1], normal[2]);
}
return intersetParam;
}
Here's what kind of image i'm getting by just outputting the normal retrieved from RayCastFilter:

As you can see, the normal is not smooth, i need it to be that way for lighting computations. Is there a way to make the normal smooth? Also, how would i go about getting texture coordinates along with the smooth normal? Is there a way to pass texture coordinates to the collision tree while constructing it?
I must say that i've tried the following method for smoothing normals and getting texture coordinates: store face id's for each face added to the collision tree. Once a collision is found i lookup the face's vertices and based on this and the point of collision(transformed in local space by me) i compute barycentric coordinates. The problem is that sometimes the barycentric coordinates don't recognize the point i'm using to compute them, to be part of the triangle indexed by the face id returned by the collision routine. This is rather weird and it only happens on certain parts of the mesh: the white positions on the mesh generated wrong barycentric coordinates (that classified the input point as not being part of the input triangle):

I wonder, if my barycentric coordinates routine is wrong in any way... I post the code for this also:
- Code: Select all
Vector2<float> Endeavour::Math::barycentric(const Vector3<float> &P,
const Vector3<float> &A,
const Vector3<float> &B,
const Vector3<float> &C)
{
// Compute vectors
Vector3<float> v0 = B - A;
Vector3<float> v1 = C - A;
Vector3<float> v2 = P - A;
// Compute dot products
float dot00 = dot(v0, v0);
float dot01 = dot(v0, v1);
float dot02 = dot(v0, v2);
float dot11 = dot(v1, v1);
float dot12 = dot(v1, v2);
// Compute barycentric coordinates
float invDenom = 1 / (dot00 * dot11 - dot01 * dot01);
float u = (dot11 * dot02 - dot01 * dot12) * invDenom;
float v = (dot00 * dot12 - dot01 * dot02) * invDenom;
// if (!((u >= 0) && (v >= 0) && (u + v <= 1)))
// printf("AAA: %f %f\n", u, v);
return Vector2<float>(u, v);
}
So, my questions are: how to integrate smooth normals and texture coordinates into the collision information retrieval process? If this is something newton isn't supposed to do, what's wrong with my current approach to get a hold of this information?
EDIT: I used the latest sourced from the SVN (rev. 750) and compiled the projects in the coreLibrary_200 directory.