ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/common/cone.c
Revision: 2.2
Committed: Sun Sep 6 11:53:47 1992 UTC (31 years, 7 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.1: +39 -33 lines
Log Message:
major aesthetic changes -- made R0 always smaller than R1

File Contents

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