16 #define TACHYON_INTERNAL 1 23 #define TRIANGLE_PRIVATE 28 (
void (*)(
const void *,
const void *,
const void *,
void *))(
tri_normal),
35 (
void (*)(
const void *,
const void *,
const void *,
void *))(
stri_normal),
54 object *
newtri(
void * tex, vector v0, vector v1, vector v2) {
56 vector edge1, edge2, edge3;
58 VSub(&v1, &v0, &edge1);
59 VSub(&v2, &v0, &edge2);
60 VSub(&v2, &v1, &edge3);
63 if ((
VLength(&edge1) >= EPSILON) &&
67 t=(tri *) malloc(
sizeof(tri));
84 object *
newstri(
void * tex, vector v0, vector v1, vector v2,
85 vector n0, vector n1, vector n2) {
87 vector edge1, edge2, edge3;
89 VSub(&v1, &v0, &edge1);
90 VSub(&v2, &v0, &edge2);
91 VSub(&v2, &v1, &edge3);
94 if ((
VLength(&edge1) >= EPSILON) &&
98 t=(stri *) malloc(
sizeof(stri));
119 stri *t = (stri *) otri;
141 object *
newvcstri(
void * voidtex, vector v0, vector v1, vector v2,
142 vector n0, vector n1, vector n2,
143 color c0, color c1, color c2) {
145 vector edge1, edge2, edge3;
146 vcstri_texture * tex = (vcstri_texture *) voidtex;
148 VSub(&v1, &v0, &edge1);
149 VSub(&v2, &v0, &edge2);
150 VSub(&v2, &v1, &edge3);
153 if ((
VLength(&edge1) >= EPSILON) &&
154 (
VLength(&edge2) >= EPSILON) &&
155 (
VLength(&edge3) >= EPSILON)) {
157 t=(vcstri *) malloc(
sizeof(vcstri));
173 tex->texfunc = (color(*)(
const void *,
const void *,
void *))(
vcstri_color);
174 t->tex = (texture *) tex;
184 vcstri *t = (vcstri *) otri;
206 #define CROSS(dest,v1,v2) \ 207 dest.x=v1.y*v2.z-v1.z*v2.y; \ 208 dest.y=v1.z*v2.x-v1.x*v2.z; \ 209 dest.z=v1.x*v2.y-v1.y*v2.x; 211 #define DOT(v1,v2) (v1.x*v2.x+v1.y*v2.y+v1.z*v2.z) 213 #define SUB(dest,v1,v2) \ 218 static int tri_bbox(
void * obj, vector * min, vector * max) {
219 tri * t = (tri *) obj;
222 VAdd(&t->v0, &t->edge1, &v1);
223 VAdd(&t->v0, &t->edge2, &v2);
225 min->x =
MYMIN( t->v0.x ,
MYMIN( v1.x , v2.x ));
226 min->y =
MYMIN( t->v0.y ,
MYMIN( v1.y , v2.y ));
227 min->z =
MYMIN( t->v0.z ,
MYMIN( v1.z , v2.z ));
229 max->x =
MYMAX( t->v0.x ,
MYMAX( v1.x , v2.x ));
230 max->y =
MYMAX( t->v0.y ,
MYMAX( v1.y , v2.y ));
231 max->z =
MYMAX( t->v0.z ,
MYMAX( v1.z , v2.z ));
237 vector tvec, pvec, qvec;
238 flt det, inv_det, t, u, v;
241 CROSS(pvec, ry->d, trn->edge2);
244 det =
DOT(trn->edge1, pvec);
251 SUB(tvec, ry->o, trn->v0);
255 if (u < 0.0 || u > det)
259 CROSS(qvec, tvec, trn->edge1);
262 v =
DOT(ry->d, qvec);
263 if (v < 0.0 || u + v > det)
267 t =
DOT(trn->edge2, qvec);
273 if (det > -EPSILON && det < EPSILON)
279 SUB(tvec, ry->o, trn->v0);
282 u =
DOT(tvec, pvec) * inv_det;
283 if (u < 0.0 || u > 1.0)
287 CROSS(qvec, tvec, trn->edge1);
290 v =
DOT(ry->d, qvec) * inv_det;
291 if (v < 0.0 || u + v > 1.0)
295 t =
DOT(trn->edge2, qvec) * inv_det;
298 ry->add_intersection(t,(
object *) trn, ry);
302 static void tri_normal(
const tri * trn,
const vector * hit,
const ray * incident, vector * N) {
305 CROSS((*N), trn->edge1, trn->edge2);
307 invlen = 1.0 /
SQRT(N->x*N->x + N->y*N->y + N->z*N->z);
313 if (
VDot(N, &(incident->d)) > 0.0) {
321 static void stri_normal(
const stri * trn,
const vector * hit,
const ray * incident, vector * N) {
322 flt U, V, W, lensqr, invlen;
325 CROSS(norm, trn->edge1, trn->edge2);
326 lensqr =
DOT(norm, norm);
328 VSUB((*hit), trn->v0, P);
330 CROSS(tmp, P, trn->edge2);
331 U =
DOT(tmp, norm) / lensqr;
333 CROSS(tmp, trn->edge1, P);
334 V =
DOT(tmp, norm) / lensqr;
338 N->x = W*trn->n0.x + U*trn->n1.x + V*trn->n2.x;
339 N->y = W*trn->n0.y + U*trn->n1.y + V*trn->n2.y;
340 N->z = W*trn->n0.z + U*trn->n1.z + V*trn->n2.z;
342 invlen = 1.0 /
SQRT(N->x*N->x + N->y*N->y + N->z*N->z);
352 if (
VDot(&norm, &(incident->d)) > 0.0) {
360 color
vcstri_color(
const vector * hit,
const texture * tx,
const ray * incident) {
361 vcstri_texture * tex = (vcstri_texture *) tx;
362 const vcstri * trn = (vcstri *) tex->obj;
367 CROSS(norm, trn->edge1, trn->edge2);
368 lensqr =
DOT(norm, norm);
370 VSUB((*hit), trn->v0, P);
372 CROSS(tmp, P, trn->edge2);
373 U =
DOT(tmp, norm) / lensqr;
375 CROSS(tmp, trn->edge1, P);
376 V =
DOT(tmp, norm) / lensqr;
380 col.r = W*tex->c0.r + U*tex->c1.r + V*tex->c2.r;
381 col.g = W*tex->c0.g + U*tex->c1.g + V*tex->c2.g;
382 col.b = W*tex->c0.b + U*tex->c1.b + V*tex->c2.b;
389 flt U, V, W, lensqr, invlen;
392 CROSS(norm, trn->edge1, trn->edge2);
393 lensqr =
DOT(norm, norm);
395 VSUB((*hit), trn->v0, P);
397 CROSS(tmp, P, trn->edge2);
398 U =
DOT(tmp, norm) / lensqr;
400 CROSS(tmp, trn->edge1, P);
401 V =
DOT(tmp, norm) / lensqr;
405 N->x = W*trn->n0.x + U*trn->n1.x + V*trn->n2.x;
406 N->y = W*trn->n0.y + U*trn->n1.y + V*trn->n2.y;
407 N->z = W*trn->n0.z + U*trn->n1.z + V*trn->n2.z;
409 invlen = 1.0 /
SQRT(N->x*N->x + N->y*N->y + N->z*N->z);
420 if (
VDot(&norm, &(incident->d)) < 0.0) {
428 static void stri_normal_guess(
const stri * trn,
const vector * hit,
const ray * incident, vector * N) {
429 flt U, V, W, lensqr, invlen;
432 CROSS(norm, trn->edge1, trn->edge2);
433 lensqr =
DOT(norm, norm);
435 VSUB((*hit), trn->v0, P);
437 CROSS(tmp, P, trn->edge2);
438 U =
DOT(tmp, norm) / lensqr;
440 CROSS(tmp, trn->edge1, P);
441 V =
DOT(tmp, norm) / lensqr;
445 N->x = W*trn->n0.x + U*trn->n1.x + V*trn->n2.x;
446 N->y = W*trn->n0.y + U*trn->n1.y + V*trn->n2.y;
447 N->z = W*trn->n0.z + U*trn->n1.z + V*trn->n2.z;
449 invlen = 1.0 /
SQRT(N->x*N->x + N->y*N->y + N->z*N->z);
460 if (
VDot(N, &(incident->d)) > 0.0) {
static void stri_normal_guess(const stri *trn, const vector *hit, const ray *incident, vector *N)
static object_methods tri_methods
static void stri_normal(const stri *trn, const vector *hit, const ray *incident, vector *N)
void VSub(apivector *a, apivector *b, apivector *c)
static object_methods stri_methods_guess
static object_methods stri_methods
flt VDot(apivector *a, apivector *b)
static void tri_normal(const tri *trn, const vector *hit, const ray *incident, vector *N)
object * newstri(void *tex, vector v0, vector v1, vector v2, vector n0, vector n1, vector n2)
flt VLength(const vector *a)
double flt
generic floating point number, using double
object * newvcstri(void *voidtex, vector v0, vector v1, vector v2, vector n0, vector n1, vector n2, color c0, color c1, color c2)
static object_methods stri_methods_reverse
color vcstri_color(const vector *hit, const texture *tx, const ray *incident)
void stri_normal_fixup(object *otri, int mode)
Tachyon cross-platform timers, special math function wrappers, and RNGs.
static void stri_normal_reverse(const stri *trn, const vector *hit, const ray *incident, vector *N)
static void tri_intersect(const tri *trn, ray *ry)
#define CROSS(dest, v1, v2)
void VAdd(apivector *a, apivector *b, apivector *c)
#define SUB(dest, v1, v2)
Tachyon public API function prototypes and declarations used to drive the ray tracing engine...
static int tri_bbox(void *obj, vector *min, vector *max)
object * newtri(void *tex, vector v0, vector v1, vector v2)
void vcstri_normal_fixup(object *otri, int mode)