home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
DP Tool Club 8
/
CDASC08.ISO
/
NEWS
/
RADIANCE
/
SRC
/
COMMON
/
CONE.C
< prev
next >
Wrap
C/C++ Source or Header
|
1993-10-07
|
5KB
|
215 lines
/* Copyright (c) 1992 Regents of the University of California */
#ifndef lint
static char SCCSid[] = "@(#)cone.c 2.3 10/2/92 LBL";
#endif
/*
* cone.c - routines for making cones
*
* 2/12/86
*/
#include "standard.h"
#include "object.h"
#include "otypes.h"
#include "cone.h"
/*
* In general, a cone may be any one of a cone, a cylinder, a ring,
* a cup (inverted cone), or a tube (inverted cylinder).
* Most cones are specified with a starting point and radius and
* an ending point and radius. In the cases of a cylinder or tube,
* only one radius is needed. In the case of a ring, a normal direction
* is specified instead of a second endpoint.
*
* mtype (cone|cup) name
* 0
* 0
* 8 P0x P0y P0z P1x P1y P1z R0 R1
*
* mtype (cylinder|tube) name
* 0
* 0
* 7 P0x P0y P0z P1x P1y P1z R
*
* mtype ring name
* 0
* 0
* 8 Px Py Pz Nx Ny Nz R0 R1
*/
CONE *
getcone(o, getxf) /* get cone structure */
register OBJREC *o;
int getxf;
{
int sgn0, sgn1;
register CONE *co;
if ((co = (CONE *)o->os) == NULL) {
co = (CONE *)malloc(sizeof(CONE));
if (co == NULL)
error(SYSTEM, "out of memory in makecone");
co->ca = o->oargs.farg;
/* get radii */
if (o->otype == OBJ_CYLINDER | o->otype == OBJ_TUBE) {
if (o->oargs.nfargs != 7)
goto argcerr;
if (co->ca[6] < -FTINY) {
objerror(o, WARNING, "negative radius");
o->otype = o->otype == OBJ_CYLINDER ?
OBJ_TUBE : OBJ_CYLINDER;
co->ca[6] = -co->ca[6];
} else if (co->ca[6] <= FTINY)
goto raderr;
co->p0 = 0; co->p1 = 3;
co->r0 = co->r1 = 6;
} else {
if (o->oargs.nfargs != 8)
goto argcerr;
if (co->ca[6] < -FTINY) sgn0 = -1;
else if (co->ca[6] > FTINY) sgn0 = 1;
else sgn0 = 0;
if (co->ca[7] < -FTINY) sgn1 = -1;
else if (co->ca[7] > FTINY) sgn1 = 1;
else sgn1 = 0;
if (sgn0+sgn1 == 0)
goto raderr;
if (sgn0 < 0 | sgn1 < 0) {
objerror(o, o->otype==OBJ_RING?USER:WARNING,
"negative radii");
o->otype = o->otype == OBJ_CONE ?
OBJ_CUP : OBJ_CONE;
}
co->ca[6] = co->ca[6]*sgn0;
co->ca[7] = co->ca[7]*sgn1;
if (co->ca[7] - co->ca[6] > FTINY) {
if (o->otype == OBJ_RING)
co->p0 = co->p1 = 0;
else {
co->p0 = 0; co->p1 = 3;
}
co->r0 = 6; co->r1 = 7;
} else if (co->ca[6] - co->ca[7] > FTINY) {
if (o->otype == OBJ_RING)
co->p0 = co->p1 = 0;
else {
co->p0 = 3; co->p1 = 0;
}
co->r0 = 7; co->r1 = 6;
} else {
if (o->otype == OBJ_RING)
goto raderr;
o->otype = o->otype == OBJ_CONE ?
OBJ_CYLINDER : OBJ_TUBE;
o->oargs.nfargs = 7;
co->p0 = 0; co->p1 = 3;
co->r0 = co->r1 = 6;
}
}
/* get axis orientation */
if (o->otype == OBJ_RING)
VCOPY(co->ad, o->oargs.farg+3);
else {
co->ad[0] = CO_P1(co)[0] - CO_P0(co)[0];
co->ad[1] = CO_P1(co)[1] - CO_P0(co)[1];
co->ad[2] = CO_P1(co)[2] - CO_P0(co)[2];
}
co->al = normalize(co->ad);
if (co->al == 0.0)
objerror(o, USER, "zero orientation");
/* compute axis and side lengths */
if (o->otype == OBJ_RING) {
co->al = 0.0;
co->sl = CO_R1(co) - CO_R0(co);
} else if (o->otype == OBJ_CONE | o->otype == OBJ_CUP) {
co->sl = co->ca[7] - co->ca[6];
co->sl = sqrt(co->sl*co->sl + co->al*co->al);
} else { /* OBJ_CYLINDER or OBJ_TUBE */
co->sl = co->al;
}
co->tm = NULL;
o->os = (char *)co;
}
if (getxf && co->tm == NULL)
conexform(co);
return(co);
argcerr:
objerror(o, USER, "bad # arguments");
raderr:
objerror(o, USER, "illegal radii");
}
freecone(o) /* free memory associated with cone */
OBJREC *o;
{
register CONE *co = (CONE *)o->os;
if (o->os == NULL)
return;
if (co->tm != NULL)
free((char *)co->tm);
free(o->os);
o->os = NULL;
}
conexform(co) /* get cone transformation matrix */
register CONE *co;
{
MAT4 m4;
register double d;
register int i;
co->tm = (FLOAT (*)[4])malloc(sizeof(MAT4));
if (co->tm == NULL)
error(SYSTEM, "out of memory in conexform");
/* translate to origin */
setident4(co->tm);
if (co->r0 == co->r1)
d = 0.0;
else
d = CO_R0(co) / (CO_R1(co) - CO_R0(co));
for (i = 0; i < 3; i++)
co->tm[3][i] = d*(CO_P1(co)[i] - CO_P0(co)[i])
- CO_P0(co)[i];
/* rotate to positive z-axis */
setident4(m4);
d = co->ad[1]*co->ad[1] + co->ad[2]*co->ad[2];
if (d <= FTINY*FTINY) {
m4[0][0] = 0.0;
m4[0][2] = co->ad[0];
m4[2][0] = -co->ad[0];
m4[2][2] = 0.0;
} else {
d = sqrt(d);
m4[0][0] = d;
m4[1][0] = -co->ad[0]*co->ad[1]/d;
m4[2][0] = -co->ad[0]*co->ad[2]/d;
m4[1][1] = co->ad[2]/d;
m4[2][1] = -co->ad[1]/d;
m4[0][2] = co->ad[0];
m4[1][2] = co->ad[1];
m4[2][2] = co->ad[2];
}
multmat4(co->tm, co->tm, m4);
/* scale z-axis */
if (co->p0 != co->p1 & co->r0 != co->r1) {
setident4(m4);
m4[2][2] = (CO_R1(co) - CO_R0(co)) / co->al;
multmat4(co->tm, co->tm, m4);
}
}