ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/common/cone.c
Revision: 2.10
Committed: Thu Apr 21 00:40:35 2016 UTC (8 years ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.9: +19 -16 lines
Log Message:
Made zero cone and ring radii non-fatal (degenerate -> ignore)

File Contents

# User Rev Content
1 greg 1.1 #ifndef lint
2 greg 2.10 static const char RCSid[] = "$Id: cone.c,v 2.9 2003/07/27 22:12:01 schorsch Exp $";
3 greg 1.1 #endif
4     /*
5     * cone.c - routines for making cones
6 greg 2.5 */
7    
8 greg 2.6 #include "copyright.h"
9 greg 1.1
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 greg 2.10 getcone( /* get cone structure */
45     OBJREC *o,
46     int getxf
47     )
48 greg 1.1 {
49 greg 1.4 int sgn0, sgn1;
50 greg 2.10 CONE *co;
51 greg 1.1
52     if ((co = (CONE *)o->os) == NULL) {
53    
54     co = (CONE *)malloc(sizeof(CONE));
55     if (co == NULL)
56     error(SYSTEM, "out of memory in makecone");
57    
58     co->ca = o->oargs.farg;
59     /* get radii */
60 schorsch 2.9 if ((o->otype == OBJ_CYLINDER) | (o->otype == OBJ_TUBE)) {
61 greg 1.1 if (o->oargs.nfargs != 7)
62     goto argcerr;
63 greg 1.4 if (co->ca[6] < -FTINY) {
64     objerror(o, WARNING, "negative radius");
65     o->otype = o->otype == OBJ_CYLINDER ?
66     OBJ_TUBE : OBJ_CYLINDER;
67     co->ca[6] = -co->ca[6];
68     } else if (co->ca[6] <= FTINY)
69 greg 1.1 goto raderr;
70 greg 2.2 co->p0 = 0; co->p1 = 3;
71 greg 1.1 co->r0 = co->r1 = 6;
72     } else {
73     if (o->oargs.nfargs != 8)
74     goto argcerr;
75 greg 1.4 if (co->ca[6] < -FTINY) sgn0 = -1;
76     else if (co->ca[6] > FTINY) sgn0 = 1;
77     else sgn0 = 0;
78     if (co->ca[7] < -FTINY) sgn1 = -1;
79     else if (co->ca[7] > FTINY) sgn1 = 1;
80     else sgn1 = 0;
81     if (sgn0+sgn1 == 0)
82 greg 1.1 goto raderr;
83 schorsch 2.9 if ((sgn0 < 0) | (sgn1 < 0)) {
84 greg 1.4 objerror(o, o->otype==OBJ_RING?USER:WARNING,
85     "negative radii");
86     o->otype = o->otype == OBJ_CONE ?
87     OBJ_CUP : OBJ_CONE;
88     }
89     co->ca[6] = co->ca[6]*sgn0;
90     co->ca[7] = co->ca[7]*sgn1;
91 greg 2.2 if (co->ca[7] - co->ca[6] > FTINY) {
92 greg 1.4 if (o->otype == OBJ_RING)
93 greg 2.2 co->p0 = co->p1 = 0;
94     else {
95     co->p0 = 0; co->p1 = 3;
96     }
97     co->r0 = 6; co->r1 = 7;
98     } else if (co->ca[6] - co->ca[7] > FTINY) {
99     if (o->otype == OBJ_RING)
100     co->p0 = co->p1 = 0;
101     else {
102     co->p0 = 3; co->p1 = 0;
103     }
104     co->r0 = 7; co->r1 = 6;
105     } else {
106     if (o->otype == OBJ_RING)
107 greg 1.4 goto raderr;
108     o->otype = o->otype == OBJ_CONE ?
109     OBJ_CYLINDER : OBJ_TUBE;
110     o->oargs.nfargs = 7;
111 greg 2.2 co->p0 = 0; co->p1 = 3;
112     co->r0 = co->r1 = 6;
113 greg 1.4 }
114 greg 1.1 }
115     /* get axis orientation */
116 greg 2.2 if (o->otype == OBJ_RING)
117 greg 1.1 VCOPY(co->ad, o->oargs.farg+3);
118 greg 2.2 else {
119     co->ad[0] = CO_P1(co)[0] - CO_P0(co)[0];
120     co->ad[1] = CO_P1(co)[1] - CO_P0(co)[1];
121     co->ad[2] = CO_P1(co)[2] - CO_P0(co)[2];
122 greg 1.1 }
123     co->al = normalize(co->ad);
124 greg 2.10 if (co->al == 0.0) {
125     objerror(o, WARNING, "unknown orientation");
126     free(co);
127     return(NULL);
128     }
129 greg 1.1 /* 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 schorsch 2.9 } 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 greg 2.10 objerror(o, WARNING, "illegal radii");
150     free(co);
151     return(NULL);
152 greg 1.1 }
153    
154    
155 greg 2.5 void
156 greg 2.10 freecone(OBJREC *o) /* free memory associated with cone */
157 greg 1.1 {
158 greg 2.10 CONE *co = (CONE *)o->os;
159 greg 1.1
160 greg 2.4 if (co == NULL)
161 greg 1.5 return;
162 greg 1.1 if (co->tm != NULL)
163 greg 2.5 free((void *)co->tm);
164     free((void *)co);
165 greg 1.1 o->os = NULL;
166     }
167    
168    
169 greg 2.5 void
170 greg 2.10 conexform(CONE *co) /* get cone transformation matrix */
171 greg 1.1 {
172 greg 1.6 MAT4 m4;
173 greg 2.10 double d;
174     int i;
175 greg 1.1
176 schorsch 2.8 co->tm = (RREAL (*)[4])malloc(sizeof(MAT4));
177 greg 1.1 if (co->tm == NULL)
178     error(SYSTEM, "out of memory in conexform");
179    
180     /* translate to origin */
181     setident4(co->tm);
182     if (co->r0 == co->r1)
183     d = 0.0;
184     else
185 greg 2.2 d = CO_R0(co) / (CO_R1(co) - CO_R0(co));
186 greg 1.1 for (i = 0; i < 3; i++)
187 greg 2.2 co->tm[3][i] = d*(CO_P1(co)[i] - CO_P0(co)[i])
188     - CO_P0(co)[i];
189 greg 1.1
190     /* rotate to positive z-axis */
191     setident4(m4);
192     d = co->ad[1]*co->ad[1] + co->ad[2]*co->ad[2];
193     if (d <= FTINY*FTINY) {
194     m4[0][0] = 0.0;
195     m4[0][2] = co->ad[0];
196     m4[2][0] = -co->ad[0];
197     m4[2][2] = 0.0;
198     } else {
199     d = sqrt(d);
200     m4[0][0] = d;
201     m4[1][0] = -co->ad[0]*co->ad[1]/d;
202     m4[2][0] = -co->ad[0]*co->ad[2]/d;
203     m4[1][1] = co->ad[2]/d;
204     m4[2][1] = -co->ad[1]/d;
205     m4[0][2] = co->ad[0];
206     m4[1][2] = co->ad[1];
207     m4[2][2] = co->ad[2];
208     }
209     multmat4(co->tm, co->tm, m4);
210    
211     /* scale z-axis */
212 schorsch 2.9 if ((co->p0 != co->p1) & (co->r0 != co->r1)) {
213 greg 2.2 setident4(m4);
214     m4[2][2] = (CO_R1(co) - CO_R0(co)) / co->al;
215     multmat4(co->tm, co->tm, m4);
216 greg 1.1 }
217     }