static void fcylinder_intersect(cylinder * cyl, ray * ry) { vector rc, n, O, hit, tmp2, ctmp4; flt t, s, tin, tout, ln, d, tmp, tmp3; rc.x = ry->o.x - cyl->ctr.x; rc.y = ry->o.y - cyl->ctr.y; rc.z = ry->o.z - cyl->ctr.z; VCross(&ry->d, &cyl->axis, &n); VDOT(ln, n, n); ln=sqrt(ln); /* finish length calculation */ if (ln == 0.0) { /* ray is parallel to the cylinder.. */ return; /* in this case, we want to miss or go through the "hole" */ } VNorm(&n); VDOT(d, rc, n); d = fabs(d); if (d <= cyl->rad) { /* ray intersects cylinder.. */ VCross(&rc, &cyl->axis, &O); VDOT(t, O, n); t = - t / ln; VCross(&n, &cyl->axis, &O); VNorm(&O); VDOT(s, ry->d, O); s = fabs(sqrt(cyl->rad*cyl->rad - d*d) / s); tin = t - s; RAYPNT(hit, (*ry), tin); ctmp4=cyl->axis; VNorm(&ctmp4); tmp2.x = hit.x - cyl->ctr.x; tmp2.y = hit.y - cyl->ctr.y; tmp2.z = hit.z - cyl->ctr.z; VDOT(tmp, tmp2, ctmp4); VDOT(tmp3, cyl->axis, cyl->axis); if ((tmp > 0.0) && (tmp < sqrt(tmp3))) add_intersection(tin, (object *) cyl, ry); tout = t + s; RAYPNT(hit, (*ry), tout); tmp2.x = hit.x - cyl->ctr.x; tmp2.y = hit.y - cyl->ctr.y; tmp2.z = hit.z - cyl->ctr.z; VDOT(tmp, tmp2, ctmp4); VDOT(tmp3, cyl->axis, cyl->axis); if ((tmp > 0.0) && (tmp < sqrt(tmp3))) add_intersection(tout, (object *) cyl, ry); } }
static void bndbox_intersect(bndbox * bx, ray * ry) { flt a, tx1, tx2, ty1, ty2, tz1, tz2; flt tnear, tfar; object * obj; ray newray; /* eliminate bounded rays whose bounds do not intersect */ /* the bounds of the box.. */ if (ry->flags & RT_RAY_BOUNDED) { if ((ry->s.x > bx->max.x) && (ry->e.x > bx->max.x)) return; if ((ry->s.x < bx->min.x) && (ry->e.x < bx->min.x)) return; if ((ry->s.y > bx->max.y) && (ry->e.y > bx->max.y)) return; if ((ry->s.y < bx->min.y) && (ry->e.y < bx->min.y)) return; if ((ry->s.z > bx->max.z) && (ry->e.z > bx->max.z)) return; if ((ry->s.z < bx->min.z) && (ry->e.z < bx->min.z)) return; } tnear= -FHUGE; tfar= FHUGE; if (ry->d.x == 0.0) { if ((ry->o.x < bx->min.x) || (ry->o.x > bx->max.x)) return; } else { tx1 = (bx->min.x - ry->o.x) / ry->d.x; tx2 = (bx->max.x - ry->o.x) / ry->d.x; if (tx1 > tx2) { a=tx1; tx1=tx2; tx2=a; } if (tx1 > tnear) tnear=tx1; if (tx2 < tfar) tfar=tx2; } if (tnear > tfar) return; if (tfar < 0.0) return; if (ry->d.y == 0.0) { if ((ry->o.y < bx->min.y) || (ry->o.y > bx->max.y)) return; } else { ty1 = (bx->min.y - ry->o.y) / ry->d.y; ty2 = (bx->max.y - ry->o.y) / ry->d.y; if (ty1 > ty2) { a=ty1; ty1=ty2; ty2=a; } if (ty1 > tnear) tnear=ty1; if (ty2 < tfar) tfar=ty2; } if (tnear > tfar) return; if (tfar < 0.0) return; if (ry->d.z == 0.0) { if ((ry->o.z < bx->min.z) || (ry->o.z > bx->max.z)) return; } else { tz1 = (bx->min.z - ry->o.z) / ry->d.z; tz2 = (bx->max.z - ry->o.z) / ry->d.z; if (tz1 > tz2) { a=tz1; tz1=tz2; tz2=a; } if (tz1 > tnear) tnear=tz1; if (tz2 < tfar) tfar=tz2; } if (tnear > tfar) return; if (tfar < 0.0) return; /* intersect all of the enclosed objects */ newray=*ry; newray.flags |= RT_RAY_BOUNDED; RAYPNT(newray.s , (*ry) , tnear); RAYPNT(newray.e , (*ry) , (tfar + EPSILON)); obj = bx->objlist; while (obj != NULL) { obj->methods->intersect(obj, &newray); obj = (object *)obj->nextobj; } }
color shader(ray * incident) { color col, diffuse, phongcol; vector N, L, hit; ray shadowray; flt inten, t, Llen; object * obj; int numints, i; point_light * li; numints=closest_intersection(&t, &obj, incident->intstruct); /* find the number of intersections */ /* and return the closest one. */ if (numints < 1) { /* if there weren't any object intersections then return the */ /* background color for the pixel color. */ return incident->scene->background; } if (obj->tex->islight) { /* if the current object is a light, then we */ return obj->tex->col; /* will only use the objects ambient color */ } RAYPNT(hit, (*incident), t) /* find the point of intersection from t */ obj->methods->normal(obj, &hit, incident, &N); /* find the surface normal */ /* execute the object's texture function */ col = obj->tex->texfunc(&hit, obj->tex, incident); diffuse.r = 0.0; diffuse.g = 0.0; diffuse.b = 0.0; phongcol = diffuse; if ((obj->tex->diffuse > 0.0) || (obj->tex->phong > 0.0)) { for (i=0; i<numlights; i++) { /* loop for light contributions */ li=lightlist[i]; /* set li=to the current light */ VSUB(li->ctr, hit, L) /* find the light vector */ /* calculate the distance to the light from the hit point */ Llen = sqrt(L.x*L.x + L.y*L.y + L.z*L.z) + EPSILON; L.x /= Llen; /* normalize the light direction vector */ L.y /= Llen; L.z /= Llen; VDOT(inten, N, L) /* light intensity */ /* add in diffuse lighting for this light if we're facing it */ if (inten > 0.0) { /* test for a shadow */ shadowray.intstruct = incident->intstruct; shadowray.flags = RT_RAY_SHADOW | RT_RAY_BOUNDED; incident->serial++; shadowray.serial = incident->serial; shadowray.mbox = incident->mbox; shadowray.o = hit; shadowray.d = L; shadowray.maxdist = Llen; shadowray.s = hit; shadowray.e = li->ctr; shadowray.scene = incident->scene; reset_intersection(incident->intstruct); intersect_objects(&shadowray); if (!shadow_intersection(incident->intstruct, Llen)) { /* XXX now that opacity is in the code, have to be more careful */ ColorAddS(&diffuse, &li->tex->col, inten); /* phong type specular highlights */ if (obj->tex->phong > 0.0) { flt phongval; phongval = shade_phong(incident, &hit, &N, &L, obj->tex->phongexp); if (obj->tex->phongtype) ColorAddS(&phongcol, &col, phongval); else ColorAddS(&phongcol, &(li->tex->col), phongval); } } } } } ColorScale(&diffuse, obj->tex->diffuse); col.r *= (diffuse.r + obj->tex->ambient); /* do a product of the */ col.g *= (diffuse.g + obj->tex->ambient); /* diffuse intensity with */ col.b *= (diffuse.b + obj->tex->ambient); /* object color + ambient */ if (obj->tex->phong > 0.0) { ColorAccum(&col, &phongcol); } /* spawn reflection rays if necessary */ /* note: this will overwrite the old intersection list */ if (obj->tex->specular > 0.0) { color specol; specol = shade_reflection(incident, &hit, &N, obj->tex->specular); ColorAccum(&col, &specol); } /* spawn transmission rays / refraction */ /* note: this will overwrite the old intersection list */ if (obj->tex->opacity < 1.0) { color transcol; transcol = shade_transmission(incident, &hit, 1.0 - obj->tex->opacity); ColorAccum(&col, &transcol); } return col; /* return the color of the shaded pixel... */ }