Sanchayan Maity
0f4b39775c
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.
828 lines
16 KiB
C
828 lines
16 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
|
|
* poly.c
|
|
*
|
|
* DESCRIPTION
|
|
* This file contains all routines that operate on polygon objects.
|
|
*
|
|
*/
|
|
|
|
|
|
#include <stdio.h>
|
|
#include <math.h>
|
|
#include "rt.h"
|
|
|
|
|
|
|
|
/*
|
|
* NAME
|
|
* PolyName - return the object name
|
|
*
|
|
* SYNOPSIS
|
|
* CHAR *PolyName()
|
|
*
|
|
* RETURNS
|
|
* A pointer to the name string.
|
|
*/
|
|
|
|
CHAR *PolyName()
|
|
{
|
|
return ("poly");
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
* NAME
|
|
* PolyPrint - print the polygon object data to stdout
|
|
*
|
|
* SYNOPSIS
|
|
* VOID PolyPrint(po)
|
|
* OBJECT *po; // Ptr to polygon object.
|
|
*
|
|
* RETURNS
|
|
* Nothing.
|
|
*/
|
|
|
|
VOID PolyPrint(OBJECT *po)
|
|
{
|
|
INT i, j;
|
|
INT *vindex; /* Ptr to vertex index. */
|
|
VEC3 *vlist, *vptr; /* Ptr to vertex list. */
|
|
POLY *pp; /* Ptr to polygon data. */
|
|
ELEMENT *pe; /* Ptr to polygon element. */
|
|
|
|
pe = po->pelem;
|
|
fprintf(stderr, "\tpolygon: %ld polygons.\n", po->numelements);
|
|
|
|
for (i = 0; i < po->numelements; i++)
|
|
{
|
|
pp = (POLY *)pe->data;
|
|
|
|
fprintf(stderr, "\t\tVertices: %ld Plane eq: %f %f %f %f\n", pp->nverts, pp->norm[0], pp->norm[1], pp->norm[2], pp->d);
|
|
|
|
vlist = pp->vptr;
|
|
vindex = pp->vindex;
|
|
|
|
for (j = 0; j < pp->nverts; j++)
|
|
{
|
|
vptr = vlist + (*vindex);
|
|
fprintf(stderr, "\t\t%f %f %f \n", (*vptr)[0], (*vptr)[1], (*vptr)[2]);
|
|
vindex++;
|
|
}
|
|
|
|
pe++;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
* NAME
|
|
* PolyElementBoundBox - compute polygon element bounding box
|
|
*
|
|
* SYNOPSIS
|
|
* VOID PolyElementBoundBox(pe, pp)
|
|
* ELEMENT *pe; // Ptr to polygon element.
|
|
* POLY *pp; // Ptr to polygon data.
|
|
*
|
|
* RETURNS
|
|
* Nothing.
|
|
*/
|
|
|
|
VOID PolyElementBoundBox(ELEMENT *pe, POLY *pp)
|
|
{
|
|
INT i; /* Index. */
|
|
INT *vindex; /* Vertex index pointer. */
|
|
BBOX *pbb; /* Ptr to bounding box. */
|
|
VEC3 *vlist, *vptr; /* Vertex list pointer. */
|
|
REAL minx, maxx;
|
|
REAL miny, maxy;
|
|
REAL minz, maxz;
|
|
|
|
pbb = &(pe->bv);
|
|
|
|
minx = miny = minz = HUGE_REAL;
|
|
maxx = maxy = maxz = -HUGE_REAL;
|
|
|
|
vlist = pp->vptr;
|
|
vindex = pp->vindex;
|
|
|
|
for (i = 0; i < pp->nverts; i++)
|
|
{
|
|
vptr = vlist + (*vindex);
|
|
|
|
minx = Min(minx, (*vptr)[0]);
|
|
miny = Min(miny, (*vptr)[1]);
|
|
minz = Min(minz, (*vptr)[2]);
|
|
|
|
maxx = Max(maxx, (*vptr)[0]);
|
|
maxy = Max(maxy, (*vptr)[1]);
|
|
maxz = Max(maxz, (*vptr)[2]);
|
|
|
|
vindex++;
|
|
}
|
|
|
|
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
|
|
* PolyBoundBox - compute polygon object bounding box
|
|
*
|
|
* SYNOPSIS
|
|
* VOID PolyBoundBox(po)
|
|
* OBJECT *po; // Ptr to polygon object.
|
|
*
|
|
* RETURNS
|
|
* Nothing.
|
|
*/
|
|
|
|
VOID PolyBoundBox(OBJECT *po)
|
|
{
|
|
INT i;
|
|
POLY *pp; /* Ptr to polygon data. */
|
|
ELEMENT *pe; /* Ptr to polygon 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++)
|
|
{
|
|
pp = (POLY *)pe->data;
|
|
PolyElementBoundBox(pe, pp);
|
|
|
|
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
|
|
* PolyNormal - compute polygon unit normal at given point on the surface
|
|
*
|
|
* SYNOPSIS
|
|
* VOID PolyNormal(hit, Pi, Ni)
|
|
* IRECORD *hit; // Ptr to intersection record.
|
|
* POINT Pi; // Ipoint.
|
|
* POINT Ni; // Normal.
|
|
*
|
|
* NOTES
|
|
* If no normal interpolation, the normal is the face normal. Otherwise,
|
|
* interpolate with the normal plane equation.
|
|
*
|
|
* RETURNS
|
|
* Nothing.
|
|
*/
|
|
|
|
VOID PolyNormal(IRECORD *hit, POINT Pi, POINT Ni)
|
|
{
|
|
ELEMENT *pe;
|
|
POLY *pp;
|
|
|
|
/* Retrieve normal from hit polygon. */
|
|
|
|
pe = hit->pelem;
|
|
pp = (POLY *)pe->data;
|
|
VecCopy(Ni, pp->norm);
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
* NAME
|
|
* PolyDataNormalize - normalize polygon data and bounding box
|
|
*
|
|
* SYNOPSIS
|
|
* VOID PolyDataNormalize(po, normMat)
|
|
* OBJECT *po; // Ptr to polygon object.
|
|
* MATRIX normMat; // Normalization matrix.
|
|
*
|
|
* RETURNS
|
|
* Nothing.
|
|
*/
|
|
|
|
VOID PolyDataNormalize(OBJECT *po, MATRIX normMat)
|
|
{
|
|
INT i;
|
|
POINT coord;
|
|
VEC3 *pv; /* Ptr to vertex list. */
|
|
POLY *pp; /* Ptr to polygon data. */
|
|
ELEMENT *pe; /* Ptr to polygon element. */
|
|
|
|
|
|
/* Normalize bounding box. */
|
|
|
|
pe = po->pelem;
|
|
NormalizeBoundBox(&po->bv, normMat);
|
|
|
|
|
|
/* Normalize vertex list. */
|
|
|
|
pp = (POLY *)pe->data;
|
|
pv = pp->vptr;
|
|
|
|
coord[0] = (*pv)[0];
|
|
coord[1] = (*pv)[1];
|
|
coord[2] = (*pv)[2];
|
|
coord[3] = 1.0;
|
|
|
|
|
|
/* Transform coordinate by xform matrix. */
|
|
|
|
while (coord[0] != HUGE_REAL && coord[1] != HUGE_REAL && coord[2] != HUGE_REAL)
|
|
{
|
|
VecMatMult(coord, normMat, coord);
|
|
|
|
(*pv)[0] = coord[0];
|
|
(*pv)[1] = coord[1];
|
|
(*pv)[2] = coord[2];
|
|
|
|
pv++;
|
|
|
|
coord[0] = (*pv)[0];
|
|
coord[1] = (*pv)[1];
|
|
coord[2] = (*pv)[2];
|
|
coord[3] = 1.0;
|
|
}
|
|
|
|
|
|
/* Normalize bounding boxes of object elements. */
|
|
|
|
for (i = 0; i < po->numelements; i++)
|
|
{
|
|
pp = (POLY *)pe->data;
|
|
NormalizeBoundBox(&pe->bv, normMat);
|
|
|
|
/* Find new d of plane equation. */
|
|
|
|
pv = pp->vptr + (*(pp->vindex));
|
|
pp->d = -(pp->norm[0]*(*pv)[0] + pp->norm[1]*(*pv)[1] + pp->norm[2]*(*pv)[2]);
|
|
|
|
pe++;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
* NAME
|
|
* PolyPeIntersect - calculate intersection of ray with polygon
|
|
*
|
|
* SYNOPSIS
|
|
* INT PolyPeIntersect(pr, pe, hit)
|
|
* RAY *pr; // Ptr to incident ray.
|
|
* ELEMENT *pe; // Polyangle object
|
|
* IRECORD *hit; // Intersection record.
|
|
*
|
|
* NOTES
|
|
* Check first to see if ray is parallel to plane or if the intersection
|
|
* point with the plane is behind the eye.
|
|
*
|
|
* If neither of these cases applies, determine if the intersection point
|
|
* is contained in the polygon. First, project onto a plane. Translate
|
|
* the intersection point to the origin. If a ray starting from the
|
|
* origin along the 2 - d X axis of the plane crosses an odd number of
|
|
* polygon edges, the point is in the polygon.
|
|
*
|
|
* RETURNS
|
|
* The number of intersection points.
|
|
*/
|
|
|
|
INT PolyPeIntersect(RAY *pr, ELEMENT *pe, IRECORD *hit)
|
|
{
|
|
INT i;
|
|
INT *vindex; /* Vertex index pointer. */
|
|
INT toright; /* Counter. */
|
|
INT sh, nsh; /* Sign holders. */
|
|
REAL Rd_dot_Pn; /* Polygon normal dot ray direction. */
|
|
REAL Ro_dot_Pn; /* Polygon normal dot ray origin. */
|
|
REAL tval; /* Intersection t distance value. */
|
|
REAL x[MAX_VERTS + 1]; /* Projection list. */
|
|
REAL y[MAX_VERTS + 1]; /* Projection list. */
|
|
REAL ix, iy; /* Intersection projection point. */
|
|
REAL dx, dy; /* Deltas between 2 vertices. */
|
|
REAL xint; /* Intersection value. */
|
|
VEC3 I; /* Intersection point. */
|
|
VEC3 *vlist, *vpos; /* Vertex list pointer. */
|
|
POLY *pp; /* Ptr to polygon data. */
|
|
|
|
pp = (POLY *)pe->data;
|
|
|
|
Rd_dot_Pn = VecDot(pp->norm, pr->D);
|
|
|
|
if (ABS(Rd_dot_Pn) < RAYEPS) /* Ray is parallel. */
|
|
return (0);
|
|
|
|
Ro_dot_Pn = VecDot(pp->norm, pr->P);
|
|
|
|
tval = -(pp->d + Ro_dot_Pn)/Rd_dot_Pn; /* Intersection distance. */
|
|
if (tval < RAYEPS) /* Intersects behind ray. */
|
|
return (0);
|
|
|
|
RayPoint(I, pr, tval);
|
|
|
|
|
|
/* Polygon containment. */
|
|
|
|
/* Project onto plane with greatest normal component. */
|
|
|
|
vlist = pp->vptr;
|
|
vindex = pp->vindex;
|
|
|
|
switch (pp->axis_proj)
|
|
{
|
|
case X_AXIS:
|
|
for (i = 0; i < pp->nverts; i++)
|
|
{
|
|
vpos = vlist + (*vindex);
|
|
x[i] = (*vpos)[1];
|
|
y[i] = (*vpos)[2];
|
|
vindex++;
|
|
}
|
|
|
|
ix = I[1];
|
|
iy = I[2];
|
|
break;
|
|
|
|
case Y_AXIS:
|
|
for (i = 0; i < pp->nverts; i++)
|
|
{
|
|
vpos = vlist + (*vindex);
|
|
x[i] = (*vpos)[0];
|
|
y[i] = (*vpos)[2];
|
|
vindex++;
|
|
}
|
|
|
|
ix = I[0];
|
|
iy = I[2];
|
|
break;
|
|
|
|
case Z_AXIS:
|
|
for (i = 0; i < pp->nverts; i++)
|
|
{
|
|
vpos = vlist + (*vindex);
|
|
x[i] = (*vpos)[0];
|
|
y[i] = (*vpos)[1];
|
|
vindex++;
|
|
}
|
|
|
|
ix = I[0];
|
|
iy = I[1];
|
|
break;
|
|
}
|
|
|
|
|
|
/* Translate to origin. */
|
|
|
|
for (i = 0; i < pp->nverts; i++)
|
|
{
|
|
x[i] -= ix;
|
|
y[i] -= iy;
|
|
|
|
if (ABS(y[i]) < RAYEPS)
|
|
y[i] = 0.0;
|
|
}
|
|
|
|
x[pp->nverts] = x[0];
|
|
y[pp->nverts] = y[0];
|
|
|
|
|
|
/*
|
|
* If intersection point crosses an odd number of line segments,
|
|
* the point is inside the polygon
|
|
*/
|
|
|
|
|
|
if (y[0] < 0.0)
|
|
sh = 0;
|
|
else
|
|
sh = 1;
|
|
|
|
toright = 0;
|
|
|
|
for (i = 0; i < pp->nverts; i++)
|
|
{
|
|
/* Check if segment crosses in y. */
|
|
|
|
if (y[i + 1] < 0.0)
|
|
nsh = 0;
|
|
else
|
|
nsh = 1;
|
|
|
|
if (nsh ^ sh)
|
|
{
|
|
dy = y[i + 1] - y[i];
|
|
|
|
if (ABS(dy) >= RAYEPS)
|
|
{
|
|
dx = x[i + 1] - x[i];
|
|
xint = x[i] - y[i]*dx / dy;
|
|
|
|
if (xint > 0.0)
|
|
toright++;
|
|
}
|
|
}
|
|
|
|
sh = nsh;
|
|
}
|
|
|
|
if (toright%2 == 1)
|
|
{
|
|
IsectAdd(hit, tval, pe);
|
|
return (1);
|
|
}
|
|
else
|
|
return (0);
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
* NAME
|
|
* PolyIntersect - call polygon object intersection routine
|
|
*
|
|
* SYNOPSIS
|
|
* INT PolyIntersect(pr, po, hit)
|
|
* RAY *pr; // Ptr to incident ray.
|
|
* OBJECT *po; // Ptr to polygon object.
|
|
* IRECORD *hit; // Intersection record.
|
|
*
|
|
* RETURNS
|
|
* The number of intersections found.
|
|
*/
|
|
|
|
INT PolyIntersect(RAY *pr, OBJECT *po, IRECORD *hit)
|
|
{
|
|
INT i;
|
|
INT nhits; /* # hits in polyhedra. */
|
|
ELEMENT *pe; /* Ptr to polygon element. */
|
|
IRECORD newhit; /* Hit list. */
|
|
|
|
/* Traverse polygon list to find intersections. */
|
|
|
|
nhits = 0;
|
|
pe = po->pelem;
|
|
hit[0].t = HUGE_REAL;
|
|
|
|
for (i = 0; i < po->numelements; i++)
|
|
{
|
|
if (PolyPeIntersect(pr, pe, &newhit))
|
|
{
|
|
nhits++;
|
|
if (newhit.t < hit[0].t)
|
|
{
|
|
hit[0].t = newhit.t;
|
|
hit[0].pelem = newhit.pelem;
|
|
}
|
|
}
|
|
|
|
pe++;
|
|
}
|
|
|
|
return (nhits);
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
* NAME
|
|
* PolyTransform - transform polygon object by a transformation matrix
|
|
*
|
|
* SYNOPSIS
|
|
* VOID PolyTransform(po, xtrans, xinvT)
|
|
* OBJECT *po; // Ptr to polygon object.
|
|
* MATRIX xtrans; // Transformation matrix.
|
|
* MATRIX xinvT; // Transpose of inverse matrix.
|
|
*
|
|
* NOTES
|
|
* Routine must:
|
|
* - transform face normals
|
|
* - transform vertices
|
|
* - calculate plane equation d variables
|
|
*
|
|
* RETURNS
|
|
* Nothing.
|
|
*/
|
|
|
|
VOID PolyTransform(OBJECT *po, MATRIX xtrans, MATRIX xinvT)
|
|
{
|
|
INT i; /* Indices. */
|
|
INT numelems; /* # of elements. */
|
|
VEC3 *vptr, *vp; /* Vertex list pointers. */
|
|
VEC4 norm, coord; /* Transform 4 vectors. */
|
|
POLY *pp; /* Ptr to polygon data. */
|
|
ELEMENT *pe; /* Ptr to polygon element. */
|
|
|
|
|
|
pe = po->pelem;
|
|
numelems = po->numelements;
|
|
|
|
/* Get vertex list address and transform vertices. */
|
|
|
|
pp = (POLY *)pe->data;
|
|
vptr = pp->vptr;
|
|
|
|
coord[0] = (*vptr)[0];
|
|
coord[1] = (*vptr)[1];
|
|
coord[2] = (*vptr)[2];
|
|
coord[3] = 1.0;
|
|
|
|
while (coord[0] != HUGE_REAL && coord[1] != HUGE_REAL && coord[2] != HUGE_REAL)
|
|
{
|
|
/* Transform coordinate by xform matrix. */
|
|
|
|
VecMatMult(coord, xtrans, coord);
|
|
|
|
(*vptr)[0] = coord[0];
|
|
(*vptr)[1] = coord[1];
|
|
(*vptr)[2] = coord[2];
|
|
|
|
vptr++;
|
|
|
|
coord[0] = (*vptr)[0];
|
|
coord[1] = (*vptr)[1];
|
|
coord[2] = (*vptr)[2];
|
|
coord[3] = 1.0;
|
|
}
|
|
|
|
|
|
/* Transform polygon list. */
|
|
|
|
for (i = 0; i < numelems; i++)
|
|
{
|
|
pp = (POLY *)pe->data;
|
|
|
|
/* Transform face normal by view matrix inverse. */
|
|
|
|
norm[0] = pp->norm[0];
|
|
norm[1] = pp->norm[1];
|
|
norm[2] = pp->norm[2];
|
|
norm[3] = 0.0;
|
|
|
|
VecMatMult(norm, xinvT, norm);
|
|
VecNorm(norm);
|
|
|
|
pp->norm[0] = norm[0];
|
|
pp->norm[1] = norm[1];
|
|
pp->norm[2] = norm[2];
|
|
|
|
|
|
/* Calculate plane equation variable d. */
|
|
|
|
vp = pp->vptr + *(pp->vindex);
|
|
pp->d = -(pp->norm[0]*(*vp)[0] + pp->norm[1]*(*vp)[1] + pp->norm[2]*(*vp)[2]);
|
|
|
|
|
|
/* Set best axis projection. */
|
|
|
|
norm[0] = ABS(pp->norm[0]);
|
|
norm[1] = ABS(pp->norm[1]);
|
|
norm[2] = ABS(pp->norm[2]);
|
|
|
|
if (norm[0] >= norm[1] && norm[0] >= norm[2])
|
|
pp->axis_proj = X_AXIS;
|
|
else
|
|
if (norm[1] >= norm[0] && norm[1] >= norm[2])
|
|
pp->axis_proj = Y_AXIS;
|
|
else
|
|
pp->axis_proj = Z_AXIS;
|
|
|
|
pe++;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
* NAME
|
|
* PolyRead - read polygon object data from file
|
|
*
|
|
* SYNOPSIS
|
|
* VOID PolyRead(po, pf)
|
|
* OBJECT *po; // Ptr to polygon object.
|
|
* FILE *pf; // Ptr to file.
|
|
*
|
|
* RETURNS
|
|
* Nothing.
|
|
*/
|
|
|
|
VOID PolyRead(OBJECT *po, FILE *pf)
|
|
{
|
|
INT i, j; /* Indices. */
|
|
INT instat; /* Read status. */
|
|
INT *vindex;
|
|
INT totalverts; /* Total # of vertices in poly mesh. */
|
|
CHAR normstr[5]; /* Face/vertex normal flag string. */
|
|
BOOL pnormals; /* Face normals present? */
|
|
VEC3 pnorm; /* Polygon normal accumulator. */
|
|
VEC3 *vlist, *vptr, *vp; /* Ptr to vertex list. */
|
|
VEC3 *vptmp, *vptmp2; /* Ptr to vertex list. */
|
|
VEC3 tmppnt, tmppnt2, cross;
|
|
POLY *pp; /* Ptr to polygon data. */
|
|
ELEMENT *pe; /* Ptr to polygon element. */
|
|
|
|
|
|
pe = po->pelem;
|
|
|
|
/* Allocate space for object data. */
|
|
|
|
instat = fscanf(pf, "%ld", &totalverts);
|
|
|
|
if (instat != 1)
|
|
{
|
|
printf("Error in PolyRead: totalverts.\n");
|
|
exit(-1);
|
|
}
|
|
|
|
pp = GlobalMalloc(sizeof(POLY)*po->numelements, "poly.c");
|
|
vlist = GlobalMalloc(sizeof(VEC3)*(totalverts + 1), "poly.c");
|
|
vptr = vlist;
|
|
|
|
|
|
/* Are polygon face normals supplied? */
|
|
|
|
instat = fscanf(pf, "%s\n", normstr);
|
|
|
|
if (instat != 1)
|
|
{
|
|
printf("Error in PolyRead: face normal indicator.\n");
|
|
exit(-1);
|
|
}
|
|
|
|
pnormals = (normstr[2] == 'y' ? TRUE : FALSE);
|
|
|
|
|
|
/* Read vertex list. */
|
|
|
|
for (i = 0; i < totalverts; i++)
|
|
{
|
|
instat = fscanf(pf, "%lf %lf %lf", &(*vptr)[0], &(*vptr)[1], &(*vptr)[2]);
|
|
|
|
if (instat != 3)
|
|
{
|
|
printf("Error in PolyRead: vertex %ld.\n", i);
|
|
exit(-1);
|
|
}
|
|
|
|
vptr++;
|
|
}
|
|
|
|
|
|
(*vptr)[0] = HUGE_REAL;
|
|
(*vptr)[1] = HUGE_REAL;
|
|
(*vptr)[2] = HUGE_REAL;
|
|
|
|
|
|
/* Read polygon list. */
|
|
|
|
for (i = 0; i < po->numelements; i++)
|
|
{
|
|
instat = fscanf(pf, "%ld", &(pp->nverts));
|
|
|
|
if (instat != 1)
|
|
{
|
|
printf("Error in PolyRead: vertex count.\n");
|
|
exit(-1);
|
|
}
|
|
|
|
if (pp->nverts > MAX_VERTS)
|
|
{
|
|
printf("Polygon vertex count, %ld, exceeds maximum.\n", pp->nverts);
|
|
exit(-1);
|
|
}
|
|
|
|
if (pnormals)
|
|
{
|
|
instat = fscanf(pf, " %lf %lf %lf", &(pp->norm[0]), &(pp->norm[1]), &(pp->norm[2]));
|
|
|
|
if (instat != 3)
|
|
{
|
|
printf("Error in PolyRead: face normal %ld.\n", i);
|
|
exit(-1);
|
|
}
|
|
}
|
|
|
|
pp->vptr = vlist;
|
|
pp->vindex = GlobalMalloc(sizeof(INT)*pp->nverts, "poly.c");
|
|
vindex = pp->vindex;
|
|
|
|
for (j = 0; j < pp->nverts; j++)
|
|
{
|
|
instat = fscanf(pf, "%ld", vindex++);
|
|
|
|
if (instat != 1)
|
|
{
|
|
printf("Error in PolyRead: vertex index %ld.\n", i);
|
|
exit(-1);
|
|
}
|
|
}
|
|
|
|
/* If not supplied, calculate plane normal. */
|
|
|
|
vindex = pp->vindex;
|
|
vptr = vlist;
|
|
|
|
if (!pnormals)
|
|
{
|
|
vp = vptr + (*vindex);
|
|
VecZero(pnorm);
|
|
|
|
for (j = 0; j < pp->nverts - 2; j++)
|
|
{
|
|
vptmp = vptr + (*(vindex + 1));
|
|
vptmp2 = vptr + (*(vindex + 2));
|
|
|
|
VecSub(tmppnt, (*vptmp), (*vp));
|
|
VecSub(tmppnt2, (*vptmp2), (*vptmp));
|
|
|
|
VecCross(cross, tmppnt, tmppnt2);
|
|
VecAdd(pnorm, pnorm, cross);
|
|
|
|
vp = vptmp;
|
|
vindex += 1;
|
|
}
|
|
|
|
VecSub(tmppnt, (*vptmp2), (*vp));
|
|
vindex = pp->vindex;
|
|
vp = vptr + (*vindex);
|
|
|
|
VecSub(tmppnt2, (*vp), (*vptmp2));
|
|
VecCross(cross, tmppnt, tmppnt2);
|
|
VecAdd(pnorm, pnorm, cross);
|
|
|
|
vp = vptr + (*vindex);
|
|
VecSub(tmppnt, (*vp), (*vptmp2));
|
|
vptmp = vptr + (*(vindex + 1));
|
|
|
|
VecSub(tmppnt2, (*vptmp), (*vp));
|
|
VecCross(cross, tmppnt, tmppnt2);
|
|
VecAdd(pnorm, pnorm, cross);
|
|
VecScale(pp->norm, 1.0/VecLen(pnorm), pnorm);
|
|
}
|
|
|
|
|
|
/* Calculate plane equation d. */
|
|
|
|
vp = pp->vptr + *(pp->vindex);
|
|
pp->d = -(pp->norm[0]*(*vp)[0] + pp->norm[1]*(*vp)[1] + pp->norm[2]*(*vp)[2]);
|
|
|
|
pe->data = (CHAR *)pp;
|
|
pe->parent = po;
|
|
|
|
PolyElementBoundBox(pe, pp);
|
|
|
|
pp++;
|
|
pe++;
|
|
}
|
|
}
|
|
|