Skip to main content
gamedev.net
🔒 Locked

ray - triangle isect. problem

Started by psycoding Dec 9, 2008 at 11:46 AM 2 replies 1.1k views
Original Post
psycoding
psycoding
Now where I'm finished with my radiosity renderer, I wanted to write a photon tracer. I've been looking for a whole lot of time to find a fast ray triangle intersection code and ended up with the following. For some time it worked, but later I've encountered problems with it. I don't have a clue what the problem is, so I hope you could help me out of this. this is a picture of the result, I've drawn in the missing architecture of the room. http://home.arcor.de/irigyt/bild/failure.JPG first I thought that it may be a problem with my octree, but then I removed it and it still didn't look better, only slower. the strange thing is, when I get an intersection, half the time (during one rendering) the ray_lval that's returned does not have the right triangle based variables (photons LL, normal) and if i want to acces them outside of the code, it crashes. but now it's even worse, I can't remember to have changed anything in the intersection code, and now it even messes things up when there's no intersection. (the windows in the pic above) here's the code : class ray { public: vector *pos; vector *dir; ray() {pos = new vector();dir=new vector();} ~ray() {free(pos);free(dir);free(this);} }; class ray_lval { public: bool hit; float u,v; int r,g,b; float t; vertex *normal; LinkedList *photons; ray_lval() {r=0;g=0;b=0;} ~ray_lval() {free(this);}; }; ray_lval* ray_intersects_triangle(ray_lval *lval, ray *ray, triangle *t) { vector *E1, *E2, *H, *S, *Q; E1 = new vector(); E2 = new vector(); H = new vector(); S = new vector(); Q = new vector(); lval->r=0; lval->g=0; lval->b=0; lval->hit=false; E1->x = t->vp[1]->x - t->vp[0]->x; E1->y = t->vp[1]->y - t->vp[0]->y; E1->z = t->vp[1]->z - t->vp[0]->z; E2->x = t->vp[2]->x - t->vp[0]->x; E2->y = t->vp[2]->y - t->vp[0]->y; E2->z = t->vp[2]->z - t->vp[0]->z; cross(H,ray->dir,E2); float a = dot(E1,H); if (a > -0.00001 && a < 0.00001) return lval; float f = 1.0 / a; S->x = ray->pos->x - t->vp[0]->x; S->y = ray->pos->y - t->vp[0]->y; S->z = ray->pos->z - t->vp[0]->z; float u = f*dot(S,H); if (u < 0.0 || u > 1.0) return lval; cross(Q,S,E1); float v = f*dot(ray->dir,Q); if (v < 0.0 || (u + v) > 1.0) return lval; lval->t=dot(E2,Q)*f; lval->u=t->vp[0]->u+(t->vp[1]->u-t->vp[0]->u)*u+(t->vp[2]->u-t->vp[0]->u)*v; lval->v=t->vp[0]->v+(t->vp[1]->v-t->vp[0]->v)*u+(t->vp[2]->v-t->vp[0]->v *v; lval->r=(t->obj->texture[(int)u*3+(int)v*256*3]*t->light)>>8; lval->g=(t->obj->texture[(int)u*3+(int)v*256*3+1]*t->light)>>8; lval->b=(t->obj->texture[(int)u*3+(int)v*256*3+2]*t->light)>>8; lval->normal=t->normal; lval->photons = t->obj->photons; lval->hit=true; free(E1); free(E2); free(H); free(S); free(Q); return lval; } If the code is right, and someone wanted to look at the whole source, please tell me, I'd then upload it as soon as possible. but be warned, it's quite a mess ^^ and if someone's got a good tutorial btw of how to use an KD-Tree for fast photon gathering, I'd be very thankful if he'd postet it here.
bluntman
bluntman
Well it looks okay except:
- Why allocate everything on the heap? Stack allocation is faster and safer (in this case).
- You have memory leaks, every time the intersection returns early the vectors *E1, *E2, *H, *S, *Q are not freed, if you _have_ to heap allocate at least use a smart pointer, or manually check every code path deallocates.
- Use source tags! See the faq on that.

I didn't check the math as you are saying the problm is invalid pointers (I am extrapolating slightly), but here is an interesting thread on tri-intersection tests linky.
If your scene is static them maybe you can make use of the plucker coordinates mentioned, but at least you could store the triangle normals.
I think the problem is in some other code.

Hint: use source control!! If you had you could view all the changes you have made and see exactly where it stopped working.
matches81
matches81
I'd first place a breakpoint in the destructor for ray_lval and see if it's called by accident somewhere. Had that happen to me once for some odd reason.
If it's called, you can then use the call stack to find out from where.

If your scene is static you should definitely look into a ray-tri-intersection test based on Pluecker coordinates, seems like a nice idea.
I also wrote a raytracer as part of my studies and we used to project the triangles along the axis corresponding to the biggest component of its normal and store that projection. Worked pretty well and was fast enough for our purposes. I could probably check if I still find a description of the method we used.
bluntman
bluntman
More weird things in this code:
- You are calling "free(this)" from the destructor.
- You are using "new" to allocate but "free" to deallocate.
Allocations using "new" should always be matched with deallocations using "delete". "delete" will first call the destructor and then free the associated memory, where as free will not call the destructor, and (I'm not certain about this, maybe someone can clarify?) depending on the whether the object is a derived or base type may not free memory correctly either.
Calling free(this) does not make sense in a destructor as you should be destroying the object using "delete" and this will take care of calling the destructor for you.
I think you should take more time studying memory management of objects in C++ before embarking on something as ambitious as a ray-tracer.
"Bjarne Stroustrup: The C++ Programming Language" was recommended to me as covering what you need to know (I haven't read it myself).

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.