Hey
So I'm programming a RayTracer from scratch, and I just added support for triangles.
I am using this algorithm for ray-triangle intersection:
http://www.cs.virginia.edu/~gfx/Courses/2003/ImageSynthesis/papers/Acceleration/Fast%20MinimumStorage%20RayTriangle%20Intersection.pdf
The results are good except for the odd triangle. I think the triangle is orthogonal to the lightsource when this happens.
See pic:
http://www.steik.org/dump/out.png
You can see a couple of triangles there in the middle that look like they are completely in shadow.
The shading function is fine (I can add a sphere and it will be perfectly shaded, as will the teapot if I take out shadow checking), so I'm certain that the problem is in the intersection function.
The problem might be that the teapot that I use has predefined normal at each vertex that I use for shading, but the intersection function uses the vertexes to do it's thing. If that is the problem however, I am not sure how to solve it, so I'm open to suggestions :)
But of course, the intersection testing is totally decoupled from the shading function, so for the intersection test I don't have information about the light.
Might as well post some code... the top is the shading function, followed by the intersection stuff..
Shade()
{
else if (light->type == LightBase::DIRECTIONAL)
{
LightDirectional* ld = (LightDirectional*)scene->lights;
float dist = TestRay(Ray(pos, ld->dir), scene);
bool isInShadow = !(dist == 0);
if (!isInShadow)
{
// Calculate color.. this part works
}
}
}
float RayTracer::TestRay(Ray ray, Scene* scene)
{
vector<ISect> *isects = Intersections(ray, scene);
float dist;
if (isects->empty())
dist = 0;
else
dist = (*isects)[0].dist;
delete isects;
return dist;
}
vector<ISect> *RayTracer::Intersections(Ray& ray, Scene* scene)
{
vector<ISect> *list = new vector<ISect>();
for (int i = 0; i < scene->sceneObjects.size(); i++)
{
ISect inter = scene->sceneObjects->Intersect(ray);
if (inter.valid && inter.dist > 0)
list->push_back(inter);
}
struct isectSort
{ bool operator()(ISect a, ISect b) { return a.dist < b.dist; } };
std::sort(list->begin(), list->end(), isectSort());
return list;
}
and well.. since i'm posting code anyway, here is the triangle intersection test:
inline virtual ISect Intersect(Ray& _ray)
{
// From the paper "Fast Minimum Storage Ray Triangle Intersection"
// Tomas Möller
// Ben Trumbore
Vec3 tvec, pvec, qvec;
float det, inv_det;
float u, v, t;
Vec3 edge1 = Vec3::Minus(v1, v0);
Vec3 edge2 = Vec3::Minus(v2, v0);
pvec = Vec3::CrossP(_ray.dir, edge2);
det = Vec3::DotP(edge1, pvec);
if (det > -EPSILON && det < EPSILON)
return ISect(); // false, no intersection
inv_det = 1.0 / det;
tvec = Vec3::Minus(_ray.start, v0);
u = Vec3::DotP(tvec, pvec) * inv_det;
if (u < 0.0 || u > 1.0)
return ISect(); // false, no intersection
qvec = Vec3::CrossP(tvec, edge1);
v = Vec3::DotP(_ray.dir, qvec) * inv_det;
if (v < 0.0 || (u + v) > 1.0)
return ISect(); // false, no intersection
t = Vec3::DotP(edge2, qvec) * inv_det;
return ISect(this, _ray, t);
}