2017-04-26 17:20:15 +02:00
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* Copyright (c) 1994 Stanford University */
|
|
|
|
/* */
|
|
|
|
/* All rights reserved. */
|
|
|
|
/* */
|
|
|
|
/* Permission is given to use, copy, and modify this software for any */
|
|
|
|
/* non-commercial purpose as long as this copyright notice is not */
|
|
|
|
/* removed. All other uses, including redistribution in whole or in */
|
|
|
|
/* part, are forbidden without prior written permission. */
|
|
|
|
/* */
|
|
|
|
/* This software is provided with absolutely no warranty and no */
|
|
|
|
/* support. */
|
|
|
|
/* */
|
|
|
|
/*************************************************************************/
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* NAME
|
|
|
|
* trace.c
|
|
|
|
*
|
|
|
|
* DESCRIPTION
|
|
|
|
* This file contains the routines to process ray jobs from the work pool
|
|
|
|
* containing primary ray jobs.
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
2017-04-26 18:03:02 +02:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <math.h>
|
2017-04-26 17:20:15 +02:00
|
|
|
#include "rt.h"
|
|
|
|
|
|
|
|
/*
|
|
|
|
* NAME
|
|
|
|
* frand - generate random floating point number
|
|
|
|
*
|
|
|
|
* SYNOPSIS
|
|
|
|
* REAL frand()
|
|
|
|
* Used instead of standard srand for portability to other systems than Unix.
|
|
|
|
*
|
|
|
|
* RETURNS
|
|
|
|
* A random floating point number in the range 0 <= x < 1.
|
|
|
|
*/
|
|
|
|
|
|
|
|
REAL frand()
|
2017-04-26 18:03:02 +02:00
|
|
|
{
|
|
|
|
REAL r;
|
|
|
|
static LONG lLastRand = 0;
|
2017-04-26 17:20:15 +02:00
|
|
|
|
2017-04-26 18:03:02 +02:00
|
|
|
lLastRand = lLastRand*214013L + 2531011L;
|
|
|
|
r = (REAL)((lLastRand >> 16) & 0x7FFF)/32768.0;
|
|
|
|
return (r);
|
|
|
|
}
|
2017-04-26 17:20:15 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* NAME
|
|
|
|
* GetRayJobFromBundle -
|
|
|
|
*
|
|
|
|
* SYNOPSIS
|
|
|
|
* BOOL GetRayJobFromBundle(job, x, y)
|
|
|
|
* RAYJOB *job; // Ray job from work pool.
|
|
|
|
* INT *x, *y; // Pixel address.
|
|
|
|
*
|
|
|
|
* DESCRIPTION
|
|
|
|
* This routine determines if there are any more primary rays left to
|
|
|
|
* process in the ray bundle job.
|
|
|
|
*
|
|
|
|
* The routine returns FALSE if the bundle processing is complete. If
|
|
|
|
* there are more jobs, the current x and y pixel position are returned
|
|
|
|
* through procedure parameters. Then, x and y are bundle is updated for
|
|
|
|
* the next inquiry and TRUE is returned.
|
|
|
|
*
|
|
|
|
* RETURNS
|
|
|
|
* See above.
|
|
|
|
*/
|
|
|
|
|
|
|
|
BOOL GetRayJobFromBundle(RAYJOB *job, INT *x, INT *y)
|
2017-04-26 18:03:02 +02:00
|
|
|
{
|
|
|
|
*x = job->xcurr; /* Set pixel address first. */
|
|
|
|
*y = job->ycurr;
|
2017-04-26 17:20:15 +02:00
|
|
|
|
2017-04-26 18:03:02 +02:00
|
|
|
if ((job->y + job->ylen) == job->ycurr) /* All done? */
|
|
|
|
return (FALSE);
|
2017-04-26 17:20:15 +02:00
|
|
|
|
2017-04-26 18:03:02 +02:00
|
|
|
job->xcurr++; /* Update to next pixel. */
|
|
|
|
if ((job->x +job->xlen) == job->xcurr )
|
|
|
|
{
|
|
|
|
job->xcurr = job->x; /* Go to new scanline. */
|
|
|
|
job->ycurr++;
|
|
|
|
}
|
2017-04-26 17:20:15 +02:00
|
|
|
|
2017-04-26 18:03:02 +02:00
|
|
|
return (TRUE);
|
|
|
|
}
|
2017-04-26 17:20:15 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* NAME
|
|
|
|
* ConvertPrimRayJobToRayMsg - convert primary ray job to the ray message format
|
|
|
|
*
|
|
|
|
* SYNOPSIS
|
|
|
|
* VOID ConvertPrimRayJobToRayMsg(ray, x, y)
|
|
|
|
* RAY *ray; // Ray message.
|
|
|
|
* REAL x, y; // Pixel.
|
|
|
|
*
|
|
|
|
* DESCRIPTION
|
|
|
|
* This routine converts the primary ray job to the ray message format.
|
|
|
|
* The ray origin and direction are computed and the other ray message
|
|
|
|
* variables are initialized.
|
|
|
|
*
|
|
|
|
* Perspective Projection:
|
|
|
|
*
|
|
|
|
* Calculate ray direction thru pixel and transform it back to
|
|
|
|
* the world coordinate system. Origin of ray is eye position.
|
|
|
|
*
|
|
|
|
* Orthographic Projection:
|
|
|
|
*
|
|
|
|
* Calculate ray direction thru pixel and transform it back to
|
|
|
|
* the world coordinate system. Origin of ray must also be
|
|
|
|
* calculated.
|
|
|
|
* RETURNS
|
|
|
|
* Nothing.
|
|
|
|
*/
|
|
|
|
|
|
|
|
VOID ConvertPrimRayJobToRayMsg(RAY *ray, REAL x, REAL y)
|
2017-04-26 18:03:02 +02:00
|
|
|
{
|
|
|
|
VEC4 dir;
|
|
|
|
VEC4 origin;
|
2017-04-26 17:20:15 +02:00
|
|
|
|
2017-04-26 18:03:02 +02:00
|
|
|
if (View.projection == PT_PERSP)
|
|
|
|
{
|
|
|
|
dir[0] = -Display.scrHalfWidth + (x*Display.vWscale);
|
|
|
|
dir[1] = Display.scrHalfHeight - (y*Display.vHscale);
|
|
|
|
dir[2] = Display.scrDist;
|
|
|
|
dir[3] = 0.0;
|
2017-04-26 17:20:15 +02:00
|
|
|
|
2017-04-26 18:03:02 +02:00
|
|
|
/* Transform ray back to world. */
|
|
|
|
TransformViewRay(dir);
|
2017-04-26 17:20:15 +02:00
|
|
|
|
2017-04-26 18:03:02 +02:00
|
|
|
VecNorm(dir);
|
|
|
|
VecCopy(ray->D, dir);
|
|
|
|
VecCopy(ray->P, View.eye);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Orthographic projection. */
|
2017-04-26 17:20:15 +02:00
|
|
|
|
2017-04-26 18:03:02 +02:00
|
|
|
dir[0] = 0.0;
|
|
|
|
dir[1] = 0.0;
|
|
|
|
dir[2] = 1.0;
|
|
|
|
dir[3] = 0.0;
|
2017-04-26 17:20:15 +02:00
|
|
|
|
2017-04-26 18:03:02 +02:00
|
|
|
/* Transform ray back to world. */
|
|
|
|
TransformViewRay(dir);
|
|
|
|
VecNorm(dir);
|
2017-04-26 17:20:15 +02:00
|
|
|
|
2017-04-26 18:03:02 +02:00
|
|
|
VecCopy(ray->D, dir);
|
2017-04-26 17:20:15 +02:00
|
|
|
|
2017-04-26 18:03:02 +02:00
|
|
|
/* Calculate origin. */
|
2017-04-26 17:20:15 +02:00
|
|
|
|
2017-04-26 18:03:02 +02:00
|
|
|
origin[0] = -Display.scrHalfWidth + (x*Display.vWscale);
|
|
|
|
origin[1] = Display.scrHalfHeight - (y*Display.vHscale);
|
|
|
|
origin[2] = 0.0;
|
|
|
|
origin[3] = 1.0;
|
2017-04-26 17:20:15 +02:00
|
|
|
|
2017-04-26 18:03:02 +02:00
|
|
|
/* Transform origin back to world. */
|
2017-04-26 17:20:15 +02:00
|
|
|
|
2017-04-26 18:03:02 +02:00
|
|
|
TransformViewRay(origin);
|
|
|
|
VecCopy(ray->P, origin);
|
|
|
|
}
|
2017-04-26 17:20:15 +02:00
|
|
|
|
|
|
|
|
2017-04-26 18:03:02 +02:00
|
|
|
/* Initialize other fields of ray message. */
|
2017-04-26 17:20:15 +02:00
|
|
|
|
2017-04-26 18:03:02 +02:00
|
|
|
ray->level = 0;
|
|
|
|
ray->weight = 1.0/(REAL)NumSubRays;
|
2017-04-26 17:20:15 +02:00
|
|
|
|
2017-04-26 18:03:02 +02:00
|
|
|
LOCK(gm->ridlock);
|
|
|
|
ray->id = gm->rid++;
|
|
|
|
UNLOCK(gm->ridlock);
|
2017-04-26 17:20:15 +02:00
|
|
|
|
2017-04-26 18:03:02 +02:00
|
|
|
ray->x = (INT)x;
|
|
|
|
ray->y = (INT)y;
|
2017-04-26 17:20:15 +02:00
|
|
|
|
2017-04-26 18:03:02 +02:00
|
|
|
}
|
2017-04-26 17:20:15 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* NAME
|
|
|
|
* RayTrace - process primary ray bundle jobs from the workpool
|
|
|
|
*
|
|
|
|
* SYNOPSIS
|
|
|
|
* VOID RayTrace(pid)
|
|
|
|
* INT pid; // Process id.
|
|
|
|
*
|
|
|
|
* DESCRIPTION
|
|
|
|
* Process primary ray bundle jobs from the workpool. Each ray job from
|
|
|
|
* the ray bundle list performs the following tasks.
|
|
|
|
*
|
|
|
|
* A ray bundle job is converted to a ray message and pushed
|
|
|
|
* on the raytree stack. A ray job consists of a pixel address
|
|
|
|
* while the ray message also contains the ray origin, direction,
|
|
|
|
* level in tree, ray weight, ray id, and grid parameters.
|
|
|
|
* Processing begins with the primary ray and secondary rays being
|
|
|
|
* pushed onto the stack as the raytree is built and processed.
|
|
|
|
* The raytree stack is used to avoid recursion.
|
|
|
|
*
|
|
|
|
* Processes all jobs on raytree stack.
|
|
|
|
*
|
|
|
|
* Calls routines for intersecting a ray with the environment and
|
|
|
|
* for shading the ray.
|
|
|
|
*
|
|
|
|
* RETURNS
|
|
|
|
* Nothing.
|
|
|
|
*/
|
|
|
|
|
|
|
|
VOID RayTrace(INT pid)
|
2017-04-26 18:03:02 +02:00
|
|
|
{
|
|
|
|
INT j;
|
|
|
|
INT x, y; /* Pixel address. */
|
|
|
|
REAL xx, yy;
|
|
|
|
VEC3 N; /* Normal at intersection. */
|
|
|
|
VEC3 Ipoint; /* Intersection point. */
|
|
|
|
COLOR c; /* Color for storing background. */
|
|
|
|
RAY *ray; /* Ray pointer. */
|
|
|
|
RAY rmsg; /* Ray message. */
|
|
|
|
RAYJOB job; /* Ray job from work pool. */
|
|
|
|
OBJECT *po; /* Ptr to object. */
|
|
|
|
BOOL hit; /* An object hit? */
|
|
|
|
IRECORD hitrecord; /* Intersection record. */
|
|
|
|
|
|
|
|
ray = &rmsg;
|
|
|
|
|
|
|
|
while (GetJobs(&job, pid) != WPS_EMPTY)
|
|
|
|
{
|
|
|
|
while (GetRayJobFromBundle(&job, &x, &y))
|
|
|
|
{
|
|
|
|
/* Convert the ray job to the ray message format. */
|
|
|
|
|
|
|
|
xx = (REAL)x;
|
|
|
|
yy = (REAL)y;
|
|
|
|
|
|
|
|
if (AntiAlias)
|
|
|
|
for (j = 0; j < NumSubRays; j++)
|
|
|
|
{
|
|
|
|
ConvertPrimRayJobToRayMsg(ray, xx + frand(), yy + frand());
|
|
|
|
PushRayTreeStack(ray, pid);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ConvertPrimRayJobToRayMsg(ray, xx, yy);
|
|
|
|
PushRayTreeStack(ray, pid);
|
|
|
|
}
|
|
|
|
|
|
|
|
while (PopRayTreeStack(ray, pid) != RTS_EMPTY)
|
|
|
|
{
|
|
|
|
/* Find which object is closest along the ray. */
|
|
|
|
|
|
|
|
switch (TraversalType)
|
|
|
|
{
|
|
|
|
case TT_LIST:
|
|
|
|
hit = Intersect(ray, &hitrecord);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case TT_HUG:
|
|
|
|
hit = TraverseHierarchyUniform(ray, &hitrecord, pid);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Process the object ray hit. */
|
|
|
|
|
|
|
|
if (hit)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Get parent object to be able to access
|
|
|
|
* object operations.
|
|
|
|
*/
|
|
|
|
|
|
|
|
po = hitrecord.pelem->parent;
|
|
|
|
|
|
|
|
/* Calculate intersection point. */
|
|
|
|
RayPoint(Ipoint, ray, hitrecord.t);
|
|
|
|
|
|
|
|
/* Calculate normal at this point. */
|
|
|
|
(*po->procs->normal)(&hitrecord, Ipoint, N);
|
|
|
|
|
|
|
|
/* Make sure normal is pointing toward ray origin. */
|
|
|
|
if ((VecDot(ray->D, N)) > 0.0)
|
|
|
|
VecNegate(N, N);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Compute shade at this point - will process
|
|
|
|
* shadow rays and add secondary reflection
|
|
|
|
* and refraction rays to ray tree stack
|
|
|
|
*/
|
|
|
|
|
|
|
|
Shade(Ipoint, N, ray, &hitrecord, pid);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Add background as pixel contribution. */
|
|
|
|
|
|
|
|
VecCopy(c, View.bkg);
|
|
|
|
VecScale(c, ray->weight, c);
|
|
|
|
AddPixelColor(c, ray->x, ray->y);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2017-04-26 17:20:15 +02:00
|
|
|
|