color shade_reflection(ray * incident, vector * hit, vector * N, flt specular) { ray specray; color col; vector R; VAddS(-2.0 * (incident->d.x * N->x + incident->d.y * N->y + incident->d.z * N->z), N, &incident->d, &R); specray.intstruct=incident->intstruct; /* what thread are we */ specray.depth=incident->depth - 1; /* go up a level in recursion depth */ specray.flags = RT_RAY_REGULAR; /* infinite ray, to start with */ specray.serial = incident->serial + 1; /* next serial number */ specray.mbox = incident->mbox; specray.o=*hit; specray.d=R; /* reflect incident ray about normal */ specray.o=Raypnt(&specray, EPSILON); /* avoid numerical precision bugs */ specray.maxdist = FHUGE; /* take any intersection */ specray.scene=incident->scene; /* global scenedef info */ col=trace(&specray); /* trace specular reflection ray */ incident->serial = specray.serial; /* update the serial number */ ColorScale(&col, specular); return col; }
ray camray(scenedef *scene, int x, int y) { ray ray1, newray; vector projcent; vector projpixel; flt px, py, sx, sy; sx = (flt) scene->hres; sy = (flt) scene->vres; /* calculate the width and height of the image plane given the */ /* aspect ratio, image resolution, and zoom factor */ px=((sx / sy) / scene->aspectratio) / scene->camzoom; py=1.0 / scene->camzoom; /* assuming viewvec is a unit vector, then the center of the */ /* image plane is the camera center + vievec */ projcent.x = scene->camcent.x + scene->camviewvec.x; projcent.y = scene->camcent.y + scene->camviewvec.y; projcent.z = scene->camcent.z + scene->camviewvec.z; /* starting from the center of the image plane, we move the */ /* center of the pel we're calculating, to */ /* projcent + (rightvec * x distance) */ ray1.o=projcent; ray1.d=scene->camrightvec; projpixel=Raypnt(&ray1, ((x*px/sx) - (px / 2.0))); /* starting from the horizontally translated pel, we move the */ /* center of the pel we're calculating, to */ /* projcent + (upvec * y distance) */ ray1.o=projpixel; ray1.d=scene->camupvec; projpixel=Raypnt(&ray1, ((y*py/sy) - (py / 2.0))); /* now that we have the exact pel center in the image plane */ /* we create the real primary ray that will be used by the */ /* rest of the system. */ /* The ray is expected to be re-normalized elsewhere, we're */ /* only really concerned about getting its direction right. */ newray.o=scene->camcent; VSub(&projpixel, &scene->camcent, &newray.d); newray.depth = scene->raydepth; newray.flags = RT_RAY_REGULAR; /* camera only generates primary rays */ return newray; }
static void ring_intersect(ring * rng, ray * ry) { flt d; flt t,td; vector hit, pnt; d = -VDot(&(rng->ctr), &(rng->norm)); t=-(d+VDot(&(rng->norm), &(ry->o))); td=VDot(&(rng->norm),&(ry->d)); if (td != 0.0) { t= t / td; if (t>=0.0) { hit=Raypnt(ry, t); VSUB(hit, rng->ctr, pnt); VDOT(td, pnt, pnt); td=sqrt(td); if ((td > rng->inrad) && (td < rng->outrad)) add_intersection(t,(object *) rng, ry); } } }
color shade_transmission(ray * incident, vector * hit, flt trans) { ray transray; color col; transray.intstruct=incident->intstruct; /* what thread are we */ transray.depth=incident->depth - 1; /* go up a level in recursion depth */ transray.flags = RT_RAY_REGULAR; /* infinite ray, to start with */ transray.serial = incident->serial + 1; /* update serial number */ transray.mbox = incident->mbox; transray.o=*hit; transray.d=incident->d; /* ray continues along incident path */ transray.o=Raypnt(&transray, EPSILON); /* avoid numerical precision bugs */ transray.maxdist = FHUGE; /* take any intersection */ transray.scene=incident->scene; /* global scenedef info */ col=trace(&transray); /* trace transmission ray */ incident->serial = transray.serial; ColorScale(&col, trans); return col; }
/* the real thing */ static void grid_intersect(grid * g, ray * ry) { flt tnear, tfar, offset; vector curpos, tmax, tdelta, pdeltaX, pdeltaY, pdeltaZ, nXp, nYp, nZp; gridindex curvox, step, out; int voxindex; objectlist * cur; if (ry->flags & RT_RAY_FINISHED) return; if (!grid_bounds_intersect(g, ry, &tnear, &tfar)) return; if (ry->maxdist < tnear) return; curpos = Raypnt(ry, tnear); pos2grid(g, &curpos, &curvox); offset = tnear; /* Setup X iterator stuff */ if (fabs(ry->d.x) < EPSILON) { tmax.x = FHUGE; tdelta.x = 0.0; step.x = 0; out.x = 0; /* never goes out of bounds on this axis */ } else if (ry->d.x < 0.0) { tmax.x = offset + ((voxel2x(g, curvox.x) - curpos.x) / ry->d.x); tdelta.x = g->voxsize.x / - ry->d.x; step.x = out.x = -1; } else { tmax.x = offset + ((voxel2x(g, curvox.x + 1) - curpos.x) / ry->d.x); tdelta.x = g->voxsize.x / ry->d.x; step.x = 1; out.x = g->xsize; } /* Setup Y iterator stuff */ if (fabs(ry->d.y) < EPSILON) { tmax.y = FHUGE; tdelta.y = 0.0; step.y = 0; out.y = 0; /* never goes out of bounds on this axis */ } else if (ry->d.y < 0.0) { tmax.y = offset + ((voxel2y(g, curvox.y) - curpos.y) / ry->d.y); tdelta.y = g->voxsize.y / - ry->d.y; step.y = out.y = -1; } else { tmax.y = offset + ((voxel2y(g, curvox.y + 1) - curpos.y) / ry->d.y); tdelta.y = g->voxsize.y / ry->d.y; step.y = 1; out.y = g->ysize; } /* Setup Z iterator stuff */ if (fabs(ry->d.z) < EPSILON) { tmax.z = FHUGE; tdelta.z = 0.0; step.z = 0; out.z = 0; /* never goes out of bounds on this axis */ } else if (ry->d.z < 0.0) { tmax.z = offset + ((voxel2z(g, curvox.z) - curpos.z) / ry->d.z); tdelta.z = g->voxsize.z / - ry->d.z; step.z = out.z = -1; } else { tmax.z = offset + ((voxel2z(g, curvox.z + 1) - curpos.z) / ry->d.z); tdelta.z = g->voxsize.z / ry->d.z; step.z = 1; out.z = g->zsize; } pdeltaX = ry->d; VScale(&pdeltaX, tdelta.x); pdeltaY = ry->d; VScale(&pdeltaY, tdelta.y); pdeltaZ = ry->d; VScale(&pdeltaZ, tdelta.z); nXp = Raypnt(ry, tmax.x); nYp = Raypnt(ry, tmax.y); nZp = Raypnt(ry, tmax.z); voxindex = curvox.z*g->xsize*g->ysize + curvox.y*g->xsize + curvox.x; while (1) { if (tmax.x < tmax.y && tmax.x < tmax.z) { cur = g->cells[voxindex]; while (cur != NULL) { if (ry->mbox[cur->obj->id] != ry->serial) { ry->mbox[cur->obj->id] = ry->serial; cur->obj->methods->intersect(cur->obj, ry); } cur = cur->next; } curvox.x += step.x; if (ry->maxdist < tmax.x || curvox.x == out.x) break; voxindex += step.x; tmax.x += tdelta.x; curpos = nXp; nXp.x += pdeltaX.x; nXp.y += pdeltaX.y; nXp.z += pdeltaX.z; } else if (tmax.z < tmax.y) { cur = g->cells[voxindex]; while (cur != NULL) { if (ry->mbox[cur->obj->id] != ry->serial) { ry->mbox[cur->obj->id] = ry->serial; cur->obj->methods->intersect(cur->obj, ry); } cur = cur->next; } curvox.z += step.z; if (ry->maxdist < tmax.z || curvox.z == out.z) break; voxindex += step.z*g->xsize*g->ysize; tmax.z += tdelta.z; curpos = nZp; nZp.x += pdeltaZ.x; nZp.y += pdeltaZ.y; nZp.z += pdeltaZ.z; } else { cur = g->cells[voxindex]; while (cur != NULL) { if (ry->mbox[cur->obj->id] != ry->serial) { ry->mbox[cur->obj->id] = ry->serial; cur->obj->methods->intersect(cur->obj, ry); } cur = cur->next; } curvox.y += step.y; if (ry->maxdist < tmax.y || curvox.y == out.y) break; voxindex += step.y*g->xsize; tmax.y += tdelta.y; curpos = nYp; nYp.x += pdeltaY.x; nYp.y += pdeltaY.y; nYp.z += pdeltaY.z; } if (ry->flags & RT_RAY_FINISHED) break; } }