ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/common/cone.c
Revision: 2.6
Committed: Tue Feb 25 02:47:21 2003 UTC (21 years, 2 months ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: rad3R5
Changes since 2.5: +1 -56 lines
Log Message:
Replaced inline copyright notice with #include "copyright.h"

File Contents

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id$";
3 #endif
4 /*
5 * cone.c - routines for making cones
6 */
7
8 #include "copyright.h"
9
10 #include "standard.h"
11
12 #include "object.h"
13
14 #include "otypes.h"
15
16 #include "cone.h"
17
18 /*
19 * In general, a cone may be any one of a cone, a cylinder, a ring,
20 * a cup (inverted cone), or a tube (inverted cylinder).
21 * Most cones are specified with a starting point and radius and
22 * an ending point and radius. In the cases of a cylinder or tube,
23 * only one radius is needed. In the case of a ring, a normal direction
24 * is specified instead of a second endpoint.
25 *
26 * mtype (cone|cup) name
27 * 0
28 * 0
29 * 8 P0x P0y P0z P1x P1y P1z R0 R1
30 *
31 * mtype (cylinder|tube) name
32 * 0
33 * 0
34 * 7 P0x P0y P0z P1x P1y P1z R
35 *
36 * mtype ring name
37 * 0
38 * 0
39 * 8 Px Py Pz Nx Ny Nz R0 R1
40 */
41
42
43 CONE *
44 getcone(o, getxf) /* get cone structure */
45 register OBJREC *o;
46 int getxf;
47 {
48 int sgn0, sgn1;
49 register CONE *co;
50
51 if ((co = (CONE *)o->os) == NULL) {
52
53 co = (CONE *)malloc(sizeof(CONE));
54 if (co == NULL)
55 error(SYSTEM, "out of memory in makecone");
56
57 co->ca = o->oargs.farg;
58 /* get radii */
59 if (o->otype == OBJ_CYLINDER | o->otype == OBJ_TUBE) {
60 if (o->oargs.nfargs != 7)
61 goto argcerr;
62 if (co->ca[6] < -FTINY) {
63 objerror(o, WARNING, "negative radius");
64 o->otype = o->otype == OBJ_CYLINDER ?
65 OBJ_TUBE : OBJ_CYLINDER;
66 co->ca[6] = -co->ca[6];
67 } else if (co->ca[6] <= FTINY)
68 goto raderr;
69 co->p0 = 0; co->p1 = 3;
70 co->r0 = co->r1 = 6;
71 } else {
72 if (o->oargs.nfargs != 8)
73 goto argcerr;
74 if (co->ca[6] < -FTINY) sgn0 = -1;
75 else if (co->ca[6] > FTINY) sgn0 = 1;
76 else sgn0 = 0;
77 if (co->ca[7] < -FTINY) sgn1 = -1;
78 else if (co->ca[7] > FTINY) sgn1 = 1;
79 else sgn1 = 0;
80 if (sgn0+sgn1 == 0)
81 goto raderr;
82 if (sgn0 < 0 | sgn1 < 0) {
83 objerror(o, o->otype==OBJ_RING?USER:WARNING,
84 "negative radii");
85 o->otype = o->otype == OBJ_CONE ?
86 OBJ_CUP : OBJ_CONE;
87 }
88 co->ca[6] = co->ca[6]*sgn0;
89 co->ca[7] = co->ca[7]*sgn1;
90 if (co->ca[7] - co->ca[6] > FTINY) {
91 if (o->otype == OBJ_RING)
92 co->p0 = co->p1 = 0;
93 else {
94 co->p0 = 0; co->p1 = 3;
95 }
96 co->r0 = 6; co->r1 = 7;
97 } else if (co->ca[6] - co->ca[7] > FTINY) {
98 if (o->otype == OBJ_RING)
99 co->p0 = co->p1 = 0;
100 else {
101 co->p0 = 3; co->p1 = 0;
102 }
103 co->r0 = 7; co->r1 = 6;
104 } else {
105 if (o->otype == OBJ_RING)
106 goto raderr;
107 o->otype = o->otype == OBJ_CONE ?
108 OBJ_CYLINDER : OBJ_TUBE;
109 o->oargs.nfargs = 7;
110 co->p0 = 0; co->p1 = 3;
111 co->r0 = co->r1 = 6;
112 }
113 }
114 /* get axis orientation */
115 if (o->otype == OBJ_RING)
116 VCOPY(co->ad, o->oargs.farg+3);
117 else {
118 co->ad[0] = CO_P1(co)[0] - CO_P0(co)[0];
119 co->ad[1] = CO_P1(co)[1] - CO_P0(co)[1];
120 co->ad[2] = CO_P1(co)[2] - CO_P0(co)[2];
121 }
122 co->al = normalize(co->ad);
123 if (co->al == 0.0)
124 objerror(o, USER, "zero orientation");
125 /* compute axis and side lengths */
126 if (o->otype == OBJ_RING) {
127 co->al = 0.0;
128 co->sl = CO_R1(co) - CO_R0(co);
129 } else if (o->otype == OBJ_CONE | o->otype == OBJ_CUP) {
130 co->sl = co->ca[7] - co->ca[6];
131 co->sl = sqrt(co->sl*co->sl + co->al*co->al);
132 } else { /* OBJ_CYLINDER or OBJ_TUBE */
133 co->sl = co->al;
134 }
135 co->tm = NULL;
136 o->os = (char *)co;
137 }
138 if (getxf && co->tm == NULL)
139 conexform(co);
140 return(co);
141
142 argcerr:
143 objerror(o, USER, "bad # arguments");
144 raderr:
145 objerror(o, USER, "illegal radii");
146 }
147
148
149 void
150 freecone(o) /* free memory associated with cone */
151 OBJREC *o;
152 {
153 register CONE *co = (CONE *)o->os;
154
155 if (co == NULL)
156 return;
157 if (co->tm != NULL)
158 free((void *)co->tm);
159 free((void *)co);
160 o->os = NULL;
161 }
162
163
164 void
165 conexform(co) /* get cone transformation matrix */
166 register CONE *co;
167 {
168 MAT4 m4;
169 register double d;
170 register int i;
171
172 co->tm = (FLOAT (*)[4])malloc(sizeof(MAT4));
173 if (co->tm == NULL)
174 error(SYSTEM, "out of memory in conexform");
175
176 /* translate to origin */
177 setident4(co->tm);
178 if (co->r0 == co->r1)
179 d = 0.0;
180 else
181 d = CO_R0(co) / (CO_R1(co) - CO_R0(co));
182 for (i = 0; i < 3; i++)
183 co->tm[3][i] = d*(CO_P1(co)[i] - CO_P0(co)[i])
184 - CO_P0(co)[i];
185
186 /* rotate to positive z-axis */
187 setident4(m4);
188 d = co->ad[1]*co->ad[1] + co->ad[2]*co->ad[2];
189 if (d <= FTINY*FTINY) {
190 m4[0][0] = 0.0;
191 m4[0][2] = co->ad[0];
192 m4[2][0] = -co->ad[0];
193 m4[2][2] = 0.0;
194 } else {
195 d = sqrt(d);
196 m4[0][0] = d;
197 m4[1][0] = -co->ad[0]*co->ad[1]/d;
198 m4[2][0] = -co->ad[0]*co->ad[2]/d;
199 m4[1][1] = co->ad[2]/d;
200 m4[2][1] = -co->ad[1]/d;
201 m4[0][2] = co->ad[0];
202 m4[1][2] = co->ad[1];
203 m4[2][2] = co->ad[2];
204 }
205 multmat4(co->tm, co->tm, m4);
206
207 /* scale z-axis */
208 if (co->p0 != co->p1 & co->r0 != co->r1) {
209 setident4(m4);
210 m4[2][2] = (CO_R1(co) - CO_R0(co)) / co->al;
211 multmat4(co->tm, co->tm, m4);
212 }
213 }