home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
rtsi.com
/
2014.01.www.rtsi.com.tar
/
www.rtsi.com
/
OS9
/
OSK
/
GRAPHICS
/
rayshade.lzh
/
triangle.c
< prev
next >
Wrap
Text File
|
1990-05-08
|
7KB
|
271 lines
/*
* triangle.c
*
* Copyright (C) 1989, Craig E. Kolb
*
* This software may be freely copied, modified, and redistributed,
* provided that this copyright notice is preserved on all copies.
*
* There is no warranty or other guarantee of fitness for this software,
* it is provided solely . Bug reports or fixes may be sent
* to the author, who may or may not act on them as he desires.
*
* You may not include this software in a program or other software product
* without supplying the source, or without informing the end-user that the
* source is available for no extra charge.
*
* If you modify this software, you should include a notice giving the
* name of the person performing the modification, the date of modification,
* and the reason for such modification.
*
* $Id: triangle.c,v 3.0.1.2 90/04/04 18:55:45 craig Exp $
*
* $Log: triangle.c,v $
* Revision 3.0.1.2 90/04/04 18:55:45 craig
* patch5: Test for edge-on intersection is more robust.
* patch5: Lint removal.
*
* Revision 3.0.1.1 89/12/06 16:33:32 craig
* patch2: Added calls to new error/warning routines.
*
* Revision 3.0 89/10/27 02:06:07 craig
* Baseline for first official release.
*
*/
#include <stdio.h>
#include <math.h>
#include "constants.h"
#include "typedefs.h"
#include "funcdefs.h"
#define within(x, a) (((a) <= 0 && (x) >= (a) && (x) <= 0) || \
((a) > 0 && (x) >= 0 && (x) <= (a)))
/*
* Create and return reference to a triangle.
*/
Object *
maktri(type, surf, p1, p2, p3, n1, n2, n3)
int type;
char *surf;
Vector *p1, *p2, *p3, *n1, *n2, *n3;
{
Triangle *triangle;
Primitive *prim;
Vector vc1, vc2, vc3, ptmp, anorm;
Object *newobj;
double indexval;
prim = mallocprim();
triangle = (Triangle *)Malloc(sizeof(Triangle));
prim->objpnt.p_triangle = triangle;
newobj = new_object(NULL, (char)type, (char *)prim, (Trans *)NULL);
prim->surf = find_surface(surf);
if (type == PHONGTRI) {
prim->type = PHONGTRI;
(void)normalize(n1);
(void)normalize(n2);
(void)normalize(n3);
triangle->vnorm = (Vector *)Malloc(3 * sizeof(Vector));
triangle->vnorm[0] = *n1;
triangle->vnorm[1] = *n2;
triangle->vnorm[2] = *n3;
triangle->b = (double *)Malloc(3 * sizeof(double));
}
else
prim->type = TRIANGLE;
vecsub(*p2, *p1, &vc1);
vecsub(*p3, *p2, &vc2);
vecsub(*p1, *p3, &vc3);
/* Find plane normal. */
rawcrossp(&triangle->nrm, &vc1, &vc2);
ptmp = triangle->nrm;
if (normalize(&ptmp) == 0.) {
yywarning("Degenerate triangle.\n");
free((char *)prim);
free((char *)triangle);
free((char *)newobj);
return (Object *)0;
}
triangle->d = dotp(&triangle->nrm, p1);
triangle->p1 = *p1;
triangle->p2 = *p2;
triangle->p3 = *p3;
triangle->e1 = vc1;
triangle->e2 = vc2;
triangle->e3 = vc3;
if (type == PHONGTRI && dotp(&triangle->vnorm[0], &ptmp) < 0.) {
/*
* Reverse direction of surface normal on Phong
* triangle if the surface normal points "away"
* from the first vertex normal.
*/
scalar_prod(-1., triangle->nrm, &triangle->nrm);
triangle->d = -triangle->d;
scalar_prod(-1., triangle->e1, &triangle->e1);
scalar_prod(-1., triangle->e2, &triangle->e2);
scalar_prod(-1., triangle->e3, &triangle->e3);
}
/*
* Find "dominant" part of normal vector.
*/
anorm.x = abs(triangle->nrm.x);
anorm.y = abs(triangle->nrm.y);
anorm.z = abs(triangle->nrm.z);
indexval = max(anorm.y, anorm.z);
indexval = max(anorm.x, indexval);
if (indexval == anorm.x)
triangle->index = XNORMAL;
else if (indexval == anorm.y)
triangle->index = YNORMAL;
else
triangle->index = ZNORMAL;
return newobj;
}
/*
* Intersect ray with triangle. See Snyder & Barr for details on
* how this works.
*/
double
inttri(pos, ray, obj)
register Vector *pos, *ray;
Primitive *obj;
{
register Triangle *triangle;
double qi1, qi2, s, k, b1, b2, b3;
extern unsigned long primtests[];
primtests[obj->type]++;
triangle = obj->objpnt.p_triangle;
/*
* Plane intersection.
*/
k = dotp(&triangle->nrm, ray);
if (equal(k, 0.))
return 0.;
s = (triangle->d - dotp(&triangle->nrm, pos)) / k;
if (s <= 0.)
return 0.;
if (triangle->index == XNORMAL) {
qi1 = pos->y + s * ray->y;
qi2 = pos->z + s * ray->z;
b1 = triangle->e2.y * (qi2 - triangle->p2.z) -
triangle->e2.z * (qi1 - triangle->p2.y);
if (!within(b1, triangle->nrm.x))
return 0.;
b2 = triangle->e3.y * (qi2 - triangle->p3.z) -
triangle->e3.z * (qi1 - triangle->p3.y);
if (!within(b2, triangle->nrm.x))
return 0.;
b3 = triangle->e1.y * (qi2 - triangle->p1.z) -
triangle->e1.z * (qi1 - triangle->p1.y);
if (!within(b3, triangle->nrm.x))
return 0.;
} else if (triangle->index == YNORMAL) {
qi1 = pos->x + s * ray->x;
qi2 = pos->z + s * ray->z;
b1 = triangle->e2.z * (qi1 - triangle->p2.x) -
triangle->e2.x * (qi2 - triangle->p2.z);
if (!within(b1, triangle->nrm.y))
return 0.;
b2 = triangle->e3.z * (qi1 - triangle->p3.x) -
triangle->e3.x * (qi2 - triangle->p3.z);
if (!within(b2, triangle->nrm.y))
return 0.;
b3 = triangle->e1.z * (qi1 - triangle->p1.x) -
triangle->e1.x * (qi2 - triangle->p1.z);
if (!within(b3, triangle->nrm.y))
return 0.;
} else {
qi1 = pos->x + s * ray->x;
qi2 = pos->y + s * ray->y;
b1 = triangle->e2.x * (qi2 - triangle->p2.y) -
triangle->e2.y * (qi1 - triangle->p2.x);
if (!within(b1, triangle->nrm.z))
return 0.;
b2 = triangle->e3.x * (qi2 - triangle->p3.y) -
triangle->e3.y * (qi1 - triangle->p3.x);
if (!within(b2, triangle->nrm.z))
return 0.;
b3 = triangle->e1.x * (qi2 - triangle->p1.y) -
triangle->e1.y * (qi1 - triangle->p1.x);
if (!within(b3, triangle->nrm.z))
return 0.;
}
/*
* Take abs value if there was an intersection.
*/
if (obj->type == PHONGTRI) {
triangle->b[0] = abs(b1);
triangle->b[1] = abs(b2);
triangle->b[2] = abs(b3);
}
return s;
}
/*ARGSUSED*/
nrmtri(pos, obj, nrm)
Vector *pos, *nrm;
Primitive *obj;
{
Triangle *tri;
/*
* Normals will be normalized later...
*/
if (obj->type == TRIANGLE) {
*nrm = obj->objpnt.p_triangle->nrm;
} else {
/*
* Interpolate normals of Phong-shaded triangles.
*/
tri = obj->objpnt.p_triangle;
nrm->x = tri->b[0]*tri->vnorm[0].x+tri->b[1]*tri->vnorm[1].x+
tri->b[2]*tri->vnorm[2].x;
nrm->y = tri->b[0]*tri->vnorm[0].y+tri->b[1]*tri->vnorm[1].y+
tri->b[2]*tri->vnorm[2].y;
nrm->z = tri->b[0]*tri->vnorm[0].z+tri->b[1]*tri->vnorm[1].z+
tri->b[2]*tri->vnorm[2].z;
}
}
triextent(o, bounds)
Primitive *o;
double bounds[2][3];
{
Triangle *tri;
tri = o->objpnt.p_triangle;
bounds[LOW][X] = bounds[HIGH][X] = tri->p1.x;
bounds[LOW][Y] = bounds[HIGH][Y] = tri->p1.y;
bounds[LOW][Z] = bounds[HIGH][Z] = tri->p1.z;
if (tri->p2.x < bounds[LOW][X]) bounds[LOW][X] = tri->p2.x;
if (tri->p2.x > bounds[HIGH][X]) bounds[HIGH][X] = tri->p2.x;
if (tri->p3.x < bounds[LOW][X]) bounds[LOW][X] = tri->p3.x;
if (tri->p3.x > bounds[HIGH][X]) bounds[HIGH][X] = tri->p3.x;
if (tri->p2.y < bounds[LOW][Y]) bounds[LOW][Y] = tri->p2.y;
if (tri->p2.y > bounds[HIGH][Y]) bounds[HIGH][Y] = tri->p2.y;
if (tri->p3.y < bounds[LOW][Y]) bounds[LOW][Y] = tri->p3.y;
if (tri->p3.y > bounds[HIGH][Y]) bounds[HIGH][Y] = tri->p3.y;
if (tri->p2.z < bounds[LOW][Z]) bounds[LOW][Z] = tri->p2.z;
if (tri->p2.z > bounds[HIGH][Z]) bounds[HIGH][Z] = tri->p2.z;
if (tri->p3.z < bounds[LOW][Z]) bounds[LOW][Z] = tri->p3.z;
if (tri->p3.z > bounds[HIGH][Z]) bounds[HIGH][Z] = tri->p3.z;
}