gem5/splash2/codes/apps/raytrace/sph.C
Sanchayan Maity 0f4b39775c Fix splash2 benchmark
During the last commit of splash2 benchmark it seems before committing
when we ran "make clean", it effectively undid what the patch at below
link did
http://www.capsl.udel.edu/splash/Download.html

Fix this since without this it is not possible to build the arcane
splash2 benchmark.
2017-04-26 21:33:02 +05:30

491 lines
10 KiB
C

/*************************************************************************/
/* */
/* 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
* sph.c
*
* DESCRIPTION
* This file contains all routines that operate on sphere objects.
*
*/
#include <stdio.h>
#include <math.h>
#include "rt.h"
/*
* NAME
* SphName - return the object name
*
* SYNOPSIS
* CHAR *SphName()
*
* RETURNS
* A pointer to the name string.
*/
CHAR *SphName()
{
return ("sphere");
}
/*
* NAME
* SphPrint - print the sphere object data to stdout
*
* SYNOPSIS
* VOID SphPrint(po)
* OBJECT *po; // Ptr to sphere object.
*
* RETURNS
* Nothing.
*/
VOID SphPrint(OBJECT *po)
{
INT i;
SPHERE *ps; /* Ptr to sphere data. */
ELEMENT *pe; /* Ptr to sphere element. */
pe = po->pelem;
fprintf(stderr,"\tSphere object\n");
for (i = 0; i < po->numelements; i++)
{
ps = (SPHERE *)(pe->data);
fprintf(stderr,"\t\tcenter %f %f %f\n", ps->center[0], ps->center[1], ps->center[2]);
fprintf(stderr,"\t\t radius %f %f\n\n", ps->rad, ps->rad2);
pe++;
}
}
/*
* NAME
* SphElementBoundBox - compute sphere element bounding box
*
* SYNOPSIS
* VOID SphElementBoundBox(pe, ps)
* ELEMENT *pe; // Ptr to sphere element.
* SPHERE *ps; // Ptr to sphere data.
*
* RETURNS
* Nothing.
*/
VOID SphElementBoundBox(ELEMENT *pe, SPHERE *ps)
{
BBOX *pbb; /* Ptr to bounding box. */
pbb = &(pe->bv);
pbb->dnear[0] = ps->center[0] - ps->rad;
pbb->dnear[1] = ps->center[1] - ps->rad;
pbb->dnear[2] = ps->center[2] - ps->rad;
pbb->dfar[0] = ps->center[0] + ps->rad;
pbb->dfar[1] = ps->center[1] + ps->rad;
pbb->dfar[2] = ps->center[2] + ps->rad;
}
/*
* NAME
* SphBoundBox - compute sphere object bounding box
*
* SYNOPSIS
* VOID SphBoundBox(po)
* OBJECT *po; // Ptr to sphere object.
*
* RETURNS
* Nothing.
*/
VOID SphBoundBox(OBJECT *po)
{
INT i;
SPHERE *ps; /* Ptr to sphere data. */
ELEMENT *pe; /* Ptr to sphere element. */
BBOX *pbb; /* Ptr to bounding box. */
REAL minx, maxx;
REAL miny, maxy;
REAL minz, maxz;
pe = po->pelem;
pbb = &(po->bv);
minx = miny = minz = HUGE_REAL;
maxx = maxy = maxz = -HUGE_REAL;
for (i = 0; i < po->numelements; i++)
{
ps = (SPHERE *)(pe->data);
SphElementBoundBox(pe, ps);
minx = Min(minx, pe->bv.dnear[0]);
miny = Min(miny, pe->bv.dnear[1]);
minz = Min(minz, pe->bv.dnear[2]);
maxx = Max(maxx, pe->bv.dfar[0]);
maxy = Max(maxy, pe->bv.dfar[1]);
maxz = Max(maxz, pe->bv.dfar[2]);
pe++;
}
pbb->dnear[0] = minx;
pbb->dnear[1] = miny;
pbb->dnear[2] = minz;
pbb->dfar[0] = maxx;
pbb->dfar[1] = maxy;
pbb->dfar[2] = maxz;
}
/*
* NAME
* SphNormal - compute sphere unit normal at given point on the surface
*
* SYNOPSIS
* VOID SphNormal(hit, Pi, Ni)
* IRECORD *hit; // Ptr to intersection record.
* POINT Pi; // Ipoint.
* POINT Ni; // Normal.
*
* NOTES
* The normal is the unit vector from the given point to the sphere
* center point.
*
* RETURNS
* Nothing.
*/
VOID SphNormal(IRECORD *hit, POINT Pi, POINT Ni)
{
ELEMENT *pe;
SPHERE *ps; /* Ptr to sphere data. */
/* Compute normal and make it a unit vector. */
pe = hit->pelem;
ps = (SPHERE *)pe->data;
VecSub(Ni, Pi, ps->center);
Ni[0] /= ps->rad;
Ni[1] /= ps->rad;
Ni[2] /= ps->rad;
}
/*
* NAME
* SphDataNormalize - normalize the sphere by the given normalization matrix
*
* SYNOPSIS
* VOID SphDataNormalize(po, normMat)
* OBJECT *po; // Ptr to sphere object.
* MATRIX normMat; // Normalization matrix.
*
* RETURNS
* Nothing.
*/
VOID SphDataNormalize(OBJECT *po, MATRIX normMat)
{
INT i;
SPHERE *ps; /* Ptr to sphere data. */
ELEMENT *pe; /* Ptr to sphere element. */
POINT surf_point; /* Point on surface. */
POINT center_point; /* Center point. */
POINT rad_vector; /* Radius vector. */
NormalizeBoundBox(&po->bv, normMat);
pe = po->pelem;
for (i = 0; i < po->numelements; i++)
{
ps = (SPHERE *)pe->data;
NormalizeBoundBox(&pe->bv, normMat);
surf_point[0] = ps->center[0] + ps->rad;
surf_point[1] = ps->center[1];
surf_point[2] = ps->center[2];
surf_point[3] = 1.0;
center_point[0] = ps->center[0];
center_point[1] = ps->center[1];
center_point[2] = ps->center[2];
center_point[3] = 1.0;
/* Transform center point. */
VecMatMult(center_point, normMat, center_point);
VecMatMult(surf_point, normMat, surf_point);
/* Find new radius. */
VecSub(rad_vector, surf_point, center_point);
VecCopy(ps->center, center_point);
ps->rad = VecLen(rad_vector);
ps->rad2 = ps->rad * ps->rad;
pe++;
}
}
/*
* NAME
* SphPeIntersect - calculate intersection of ray with sphere
*
* SYNOPSIS
* INT SphPeIntersect(pr, pe, hit)
* RAY *pr; // Ptr to incident ray.
* ELEMENT *pe; // Ptr to sphere element.
* IRECORD *hit; // Intersection recorder.
*
* NOTES
* Calculate intersection of ray, X = P + tD with sphere,
* | X - C | = r2. C = sphere center. r2 = radius squared.
* This solves t2 - 2t(D*V) + (V*V - r2) = 0 at
* t = (D*V) +/- sqrt((D*V)2 - (V*V) + r2 ),
* where t2 = t squared, V = C - P and |D| = 1.
*
* RETURNS
* The number of intersection points.
*/
INT SphPeIntersect(RAY *pr, ELEMENT *pe, IRECORD *hit)
{
INT nhits; /* Number of hits. */
REAL b, disc, t1, t2, vsq; /* Formula variables. */
SPHERE *ps; /* Ptr to sphere data. */
POINT V; /* C - P */
IRECORD *sphhit;
ps = (SPHERE *)(pe->data);
sphhit = hit;
VecSub(V, ps->center, pr->P); /* Ray from origin to center.*/
vsq = VecDot(V, V); /* Length sq of V. */
b = VecDot(V, pr->D); /* Perpendicular scale of V. */
if (vsq > ps->rad2 && b < RAYEPS) /* Behind ray origin. */
return (0);
disc = b*b - vsq + ps->rad2; /* Discriminate. */
if (disc < 0.0) /* Misses ray. */
return (0);
disc = sqrt(disc); /* Find intersection param. */
t2 = b + disc;
t1 = b - disc;
if (t2 <= RAYEPS) /* Behind ray origin. */
return (0);
nhits = 0;
if (t1 > RAYEPS) /* Entering sphere. */
{
IsectAdd(sphhit, t1, pe);
sphhit++;
nhits++;
}
IsectAdd(sphhit, t2, pe); /* Exiting sphere */
nhits++;
return (nhits);
}
/*
* NAME
* SphIntersect - call sphere object intersection routine
*
* SYNOPSIS
* INT SphIntersect(pr, po, hit)
* RAY *pr; // Ptr to incident ray.
* OBJECT *po; // Ptr to sphere object.
* IRECORD *hit; // Intersection record.
*
* RETURNS
* The number of intersections found.
*/
INT SphIntersect(RAY *pr, OBJECT *po, IRECORD *hit)
{
INT i;
INT nhits; /* # hits in sphere. */
ELEMENT *pe; /* Ptr to sphere element. */
IRECORD newhit[2]; /* Hit list. */
/* Traverse sphere list to find intersections. */
nhits = 0;
pe = po->pelem;
hit[0].t = HUGE_REAL;
for (i = 0; i < po->numelements; i++)
{
if (SphPeIntersect(pr, pe, newhit))
if (newhit[0].t < hit[0].t)
{
nhits++;
hit[0].t = newhit[0].t;
hit[0].pelem = newhit[0].pelem;
}
pe++;
}
return (nhits);
}
/*
* NAME
* SphTransform - transform sphere object by a transformation matrix
*
* SYNOPSIS
* VOID SphTransform(po, xtrans, xinvT)
* OBJECT *po; // Ptr to sphere object.
* MATRIX xtrans; // Transformation matrix.
* MATRIX xinvT; // Transpose of inverse matrix.
*
* RETURNS
* Nothing.
*/
VOID SphTransform(OBJECT *po, MATRIX xtrans, MATRIX xinvT)
{
INT i;
INT numelems; /* Number of object elements. */
REAL new_rad;
SPHERE *ps; /* Ptr to sphere data. */
ELEMENT *pe; /* Ptr to sphere element. */
POINT surf_point; /* Point on surface. */
POINT center_point; /* Center_point. */
POINT rad_vector; /* Radius vector. */
pe = po->pelem;
numelems = po->numelements;
for (i = 0; i < numelems; i++)
{
ps = (SPHERE *)pe->data;
/* See if radius has changed with a scale. */
surf_point[0] = ps->center[0] + ps->rad;
surf_point[1] = ps->center[1];
surf_point[2] = ps->center[2];
surf_point[3] = 1.0;
center_point[0] = ps->center[0];
center_point[1] = ps->center[1];
center_point[2] = ps->center[2];
center_point[3] = 1.0;
/* Transform center point. */
VecMatMult(center_point, xtrans, center_point);
VecMatMult(surf_point, xtrans, surf_point);
/* Find radius. */
VecSub(rad_vector, surf_point, center_point);
VecCopy(ps->center, center_point);
new_rad = VecLen(rad_vector);
if (new_rad != ps->rad)
{
ps->rad = new_rad;
ps->rad2 = ps->rad * ps->rad;
}
pe++;
}
}
/*
* NAME
* SphRead - read sphere object data from file
*
* SYNOPSIS
* VOID SphRead(po, pf)
* OBJECT *po; // Ptr to sphere object.
* FILE *pf; // Ptr to file.
*
* RETURNS
* Nothing.
*/
VOID SphRead(OBJECT *po, FILE *pf)
{
INT i;
INT instat; /* Input counter */
SPHERE *ps; /* Ptr to sphere data. */
ELEMENT *pe; /* Ptr to sphere element. */
pe = po->pelem;
ps = GlobalMalloc(sizeof(SPHERE)*po->numelements, "sph.c");
for (i = 0; i < po->numelements; i++)
{
instat = fscanf(pf,"%lf %lf %lf %lf", &(ps->center[0]), &(ps->center[1]), &(ps->center[2]), &(ps->rad));
if (instat != 4)
{
printf("Error in SphRead: sphere %ld.\n", i);
exit(1);
}
ps->center[3] = 1.0; /* w initialization. */
ps->rad2 = ps->rad*ps->rad;
pe->data = (CHAR *)ps;
pe->parent = po;
SphElementBoundBox(pe, ps);
ps++;
pe++;
}
}