ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/hd/sm_geom.c
Revision: 3.11
Committed: Sun Jan 10 10:27:47 1999 UTC (25 years, 3 months ago) by gwlarson
Content type: text/plain
Branch: MAIN
Changes since 3.10: +0 -0 lines
Log Message:
sm.c, sm_del.c sm_ogl.c sm.h
Fixed failure to tone-map on start up
added code for temporary buffer allocation
added bg flag, and fast flag checking routines for drawing
provided graceful backout if deletion triangulation fails

File Contents

# User Rev Content
1 gwlarson 3.1 /* Copyright (c) 1998 Silicon Graphics, Inc. */
2    
3     #ifndef lint
4     static char SCCSid[] = "$SunId$ SGI";
5     #endif
6    
7     /*
8     * sm_geom.c
9     */
10    
11     #include "standard.h"
12     #include "sm_geom.h"
13    
14     tri_centroid(v0,v1,v2,c)
15     FVECT v0,v1,v2,c;
16     {
17     /* Average three triangle vertices to give centroid: return in c */
18     c[0] = (v0[0] + v1[0] + v2[0])/3.0;
19     c[1] = (v0[1] + v1[1] + v2[1])/3.0;
20     c[2] = (v0[2] + v1[2] + v2[2])/3.0;
21     }
22    
23    
24     int
25     vec3_equal(v1,v2)
26     FVECT v1,v2;
27     {
28     return(EQUAL(v1[0],v2[0]) && EQUAL(v1[1],v2[1])&& EQUAL(v1[2],v2[2]));
29     }
30 gwlarson 3.8 #if 0
31     extern FVECT Norm[500];
32     extern int Ncnt;
33     #endif
34 gwlarson 3.1
35     int
36     convex_angle(v0,v1,v2)
37     FVECT v0,v1,v2;
38     {
39 gwlarson 3.7 FVECT cp,cp01,cp12,v10,v02;
40     double dp;
41 gwlarson 3.8
42     /* test sign of (v0Xv1)X(v1Xv2). v1 */
43 gwlarson 3.1 VCROSS(cp01,v0,v1);
44     VCROSS(cp12,v1,v2);
45     VCROSS(cp,cp01,cp12);
46 gwlarson 3.7
47     dp = DOT(cp,v1);
48 gwlarson 3.8 #if 0
49     VCOPY(Norm[Ncnt++],cp01);
50     VCOPY(Norm[Ncnt++],cp12);
51     VCOPY(Norm[Ncnt++],cp);
52     #endif
53 gwlarson 3.7 if(ZERO(dp) || dp < 0.0)
54 gwlarson 3.8 return(FALSE);
55 gwlarson 3.1 return(TRUE);
56     }
57    
58     /* calculates the normal of a face contour using Newell's formula. e
59    
60 gwlarson 3.9 a = SUMi (yi - yi+1)(zi + zi+1);
61 gwlarson 3.1 b = SUMi (zi - zi+1)(xi + xi+1)
62     c = SUMi (xi - xi+1)(yi + yi+1)
63     */
64     double
65     tri_normal(v0,v1,v2,n,norm)
66     FVECT v0,v1,v2,n;
67 gwlarson 3.4 int norm;
68 gwlarson 3.1 {
69     double mag;
70    
71     n[0] = (v0[2] + v1[2]) * (v0[1] - v1[1]) +
72     (v1[2] + v2[2]) * (v1[1] - v2[1]) +
73     (v2[2] + v0[2]) * (v2[1] - v0[1]);
74    
75     n[1] = (v0[2] - v1[2]) * (v0[0] + v1[0]) +
76     (v1[2] - v2[2]) * (v1[0] + v2[0]) +
77 gwlarson 3.9 (v2[2] - v0[2]) * (v2[0] + v0[0]);
78 gwlarson 3.1
79     n[2] = (v0[1] + v1[1]) * (v0[0] - v1[0]) +
80     (v1[1] + v2[1]) * (v1[0] - v2[0]) +
81     (v2[1] + v0[1]) * (v2[0] - v0[0]);
82    
83     if(!norm)
84     return(0);
85    
86     mag = normalize(n);
87    
88     return(mag);
89     }
90    
91    
92 gwlarson 3.7 tri_plane_equation(v0,v1,v2,peqptr,norm)
93     FVECT v0,v1,v2;
94     FPEQ *peqptr;
95 gwlarson 3.4 int norm;
96 gwlarson 3.1 {
97 gwlarson 3.7 tri_normal(v0,v1,v2,FP_N(*peqptr),norm);
98 gwlarson 3.1
99 gwlarson 3.7 FP_D(*peqptr) = -(DOT(FP_N(*peqptr),v0));
100 gwlarson 3.1 }
101    
102     /* From quad_edge-code */
103     int
104     point_in_circle_thru_origin(p,p0,p1)
105     FVECT p;
106     FVECT p0,p1;
107     {
108    
109     double dp0,dp1;
110     double dp,det;
111    
112     dp0 = DOT_VEC2(p0,p0);
113     dp1 = DOT_VEC2(p1,p1);
114     dp = DOT_VEC2(p,p);
115    
116     det = -dp0*CROSS_VEC2(p1,p) + dp1*CROSS_VEC2(p0,p) - dp*CROSS_VEC2(p0,p1);
117    
118 gwlarson 3.10 return (det > (1e-10));
119 gwlarson 3.1 }
120    
121    
122 gwlarson 3.9 double
123 gwlarson 3.1 point_on_sphere(ps,p,c)
124     FVECT ps,p,c;
125     {
126 gwlarson 3.9 double d;
127 gwlarson 3.1 VSUB(ps,p,c);
128 gwlarson 3.9 d= normalize(ps);
129     return(d);
130 gwlarson 3.1 }
131    
132    
133 gwlarson 3.4 /* returns TRUE if ray from origin in direction v intersects plane defined
134     * by normal plane_n, and plane_d. If plane is not parallel- returns
135     * intersection point if r != NULL. If tptr!= NULL returns value of
136     * t, if parallel, returns t=FHUGE
137     */
138 gwlarson 3.1 int
139 gwlarson 3.7 intersect_vector_plane(v,peq,tptr,r)
140     FVECT v;
141     FPEQ peq;
142 gwlarson 3.2 double *tptr;
143 gwlarson 3.1 FVECT r;
144     {
145 gwlarson 3.4 double t,d;
146 gwlarson 3.1 int hit;
147     /*
148     Plane is Ax + By + Cz +D = 0:
149     plane[0] = A,plane[1] = B,plane[2] = C,plane[3] = D
150     */
151    
152     /* line is l = p1 + (p2-p1)t, p1=origin */
153    
154     /* Solve for t: */
155 gwlarson 3.7 d = -(DOT(FP_N(peq),v));
156 gwlarson 3.4 if(ZERO(d))
157     {
158     t = FHUGE;
159     hit = 0;
160     }
161     else
162     {
163 gwlarson 3.7 t = FP_D(peq)/d;
164 gwlarson 3.4 if(t < 0 )
165     hit = 0;
166     else
167     hit = 1;
168     if(r)
169     {
170     r[0] = v[0]*t;
171     r[1] = v[1]*t;
172     r[2] = v[2]*t;
173     }
174     }
175 gwlarson 3.2 if(tptr)
176     *tptr = t;
177 gwlarson 3.1 return(hit);
178     }
179    
180     int
181 gwlarson 3.7 intersect_ray_plane(orig,dir,peq,pd,r)
182 gwlarson 3.1 FVECT orig,dir;
183 gwlarson 3.7 FPEQ peq;
184 gwlarson 3.1 double *pd;
185     FVECT r;
186     {
187 gwlarson 3.8 double t,d;
188 gwlarson 3.1 int hit;
189     /*
190     Plane is Ax + By + Cz +D = 0:
191     plane[0] = A,plane[1] = B,plane[2] = C,plane[3] = D
192     */
193 gwlarson 3.2 /* A(orig[0] + dxt) + B(orig[1] + dyt) + C(orig[2] + dzt) + pd = 0
194     t = -(DOT(plane_n,orig)+ plane_d)/(DOT(plane_n,d))
195     line is l = p1 + (p2-p1)t
196     */
197 gwlarson 3.1 /* Solve for t: */
198 gwlarson 3.8 d = DOT(FP_N(peq),dir);
199     if(ZERO(d))
200     return(0);
201     t = -(DOT(FP_N(peq),orig) + FP_D(peq))/d;
202    
203     if(t < 0)
204 gwlarson 3.4 hit = 0;
205     else
206 gwlarson 3.1 hit = 1;
207 gwlarson 3.4
208     if(r)
209     VSUM(r,orig,dir,t);
210    
211     if(pd)
212     *pd = t;
213     return(hit);
214     }
215    
216    
217     int
218 gwlarson 3.7 intersect_ray_oplane(orig,dir,n,pd,r)
219     FVECT orig,dir;
220     FVECT n;
221     double *pd;
222     FVECT r;
223     {
224 gwlarson 3.8 double t,d;
225 gwlarson 3.7 int hit;
226     /*
227     Plane is Ax + By + Cz +D = 0:
228     plane[0] = A,plane[1] = B,plane[2] = C,plane[3] = D
229     */
230     /* A(orig[0] + dxt) + B(orig[1] + dyt) + C(orig[2] + dzt) + pd = 0
231     t = -(DOT(plane_n,orig)+ plane_d)/(DOT(plane_n,d))
232     line is l = p1 + (p2-p1)t
233     */
234     /* Solve for t: */
235 gwlarson 3.8 d= DOT(n,dir);
236     if(ZERO(d))
237     return(0);
238     t = -(DOT(n,orig))/d;
239 gwlarson 3.7 if(t < 0)
240     hit = 0;
241     else
242     hit = 1;
243    
244     if(r)
245     VSUM(r,orig,dir,t);
246    
247     if(pd)
248     *pd = t;
249     return(hit);
250     }
251    
252 gwlarson 3.9 /* Assumption: know crosses plane:dont need to check for 'on' case */
253     intersect_edge_coord_plane(v0,v1,w,r)
254     FVECT v0,v1;
255     int w;
256     FVECT r;
257     {
258     FVECT dv;
259     int wnext;
260     double t;
261 gwlarson 3.7
262 gwlarson 3.9 VSUB(dv,v1,v0);
263     t = -v0[w]/dv[w];
264     r[w] = 0.0;
265     wnext = (w+1)%3;
266     r[wnext] = v0[wnext] + dv[wnext]*t;
267     wnext = (w+2)%3;
268     r[wnext] = v0[wnext] + dv[wnext]*t;
269     }
270    
271 gwlarson 3.7 int
272     intersect_edge_plane(e0,e1,peq,pd,r)
273 gwlarson 3.4 FVECT e0,e1;
274 gwlarson 3.7 FPEQ peq;
275 gwlarson 3.4 double *pd;
276     FVECT r;
277     {
278     double t;
279     int hit;
280     FVECT d;
281     /*
282     Plane is Ax + By + Cz +D = 0:
283     plane[0] = A,plane[1] = B,plane[2] = C,plane[3] = D
284     */
285     /* A(orig[0] + dxt) + B(orig[1] + dyt) + C(orig[2] + dzt) + pd = 0
286     t = -(DOT(plane_n,orig)+ plane_d)/(DOT(plane_n,d))
287     line is l = p1 + (p2-p1)t
288     */
289     /* Solve for t: */
290     VSUB(d,e1,e0);
291 gwlarson 3.7 t = -(DOT(FP_N(peq),e0) + FP_D(peq))/(DOT(FP_N(peq),d));
292 gwlarson 3.4 if(t < 0)
293     hit = 0;
294 gwlarson 3.1 else
295 gwlarson 3.4 hit = 1;
296 gwlarson 3.1
297 gwlarson 3.4 VSUM(r,e0,d,t);
298 gwlarson 3.1
299     if(pd)
300     *pd = t;
301     return(hit);
302     }
303    
304    
305     int
306     point_in_cone(p,p0,p1,p2)
307     FVECT p;
308     FVECT p0,p1,p2;
309     {
310     FVECT np,x_axis,y_axis;
311 gwlarson 3.7 double d1,d2;
312     FPEQ peq;
313 gwlarson 3.1
314     /* Find the equation of the circle defined by the intersection
315     of the cone with the plane defined by p1,p2,p3- project p into
316     that plane and do an in-circle test in the plane
317     */
318    
319 gwlarson 3.8 /* find the equation of the plane defined by p0-p2 */
320 gwlarson 3.7 tri_plane_equation(p0,p1,p2,&peq,FALSE);
321 gwlarson 3.1
322     /* define a coordinate system on the plane: the x axis is in
323     the direction of np2-np1, and the y axis is calculated from
324     n cross x-axis
325     */
326     /* Project p onto the plane */
327 gwlarson 3.4 /* NOTE: check this: does sideness check?*/
328 gwlarson 3.7 if(!intersect_vector_plane(p,peq,NULL,np))
329 gwlarson 3.1 return(FALSE);
330    
331 gwlarson 3.8 /* create coordinate system on plane: p1-p0 defines the x_axis*/
332 gwlarson 3.1 VSUB(x_axis,p1,p0);
333     normalize(x_axis);
334     /* The y axis is */
335 gwlarson 3.7 VCROSS(y_axis,FP_N(peq),x_axis);
336 gwlarson 3.1 normalize(y_axis);
337    
338     VSUB(p1,p1,p0);
339     VSUB(p2,p2,p0);
340     VSUB(np,np,p0);
341    
342 gwlarson 3.9 p1[0] = DOT(p1,x_axis);
343 gwlarson 3.1 p1[1] = 0;
344    
345     d1 = DOT(p2,x_axis);
346     d2 = DOT(p2,y_axis);
347     p2[0] = d1;
348     p2[1] = d2;
349    
350     d1 = DOT(np,x_axis);
351     d2 = DOT(np,y_axis);
352     np[0] = d1;
353     np[1] = d2;
354    
355     /* perform the in-circle test in the new coordinate system */
356     return(point_in_circle_thru_origin(np,p1,p2));
357     }
358    
359     int
360 gwlarson 3.4 point_set_in_stri(v0,v1,v2,p,n,nset,sides)
361 gwlarson 3.1 FVECT v0,v1,v2,p;
362     FVECT n[3];
363 gwlarson 3.4 int *nset;
364     int sides[3];
365 gwlarson 3.1
366     {
367 gwlarson 3.4 double d;
368 gwlarson 3.1 /* Find the normal to the triangle ORIGIN:v0:v1 */
369     if(!NTH_BIT(*nset,0))
370     {
371 gwlarson 3.8 VCROSS(n[0],v0,v1);
372 gwlarson 3.1 SET_NTH_BIT(*nset,0);
373     }
374     /* Test the point for sidedness */
375     d = DOT(n[0],p);
376    
377 gwlarson 3.4 if(d > 0.0)
378     {
379     sides[0] = GT_OUT;
380     sides[1] = sides[2] = GT_INVALID;
381     return(FALSE);
382 gwlarson 3.1 }
383     else
384     sides[0] = GT_INTERIOR;
385    
386     /* Test next edge */
387     if(!NTH_BIT(*nset,1))
388     {
389 gwlarson 3.8 VCROSS(n[1],v1,v2);
390 gwlarson 3.1 SET_NTH_BIT(*nset,1);
391     }
392     /* Test the point for sidedness */
393     d = DOT(n[1],p);
394 gwlarson 3.4 if(d > 0.0)
395 gwlarson 3.1 {
396     sides[1] = GT_OUT;
397     sides[2] = GT_INVALID;
398     return(FALSE);
399     }
400     else
401     sides[1] = GT_INTERIOR;
402     /* Test next edge */
403     if(!NTH_BIT(*nset,2))
404     {
405 gwlarson 3.8 VCROSS(n[2],v2,v0);
406 gwlarson 3.1 SET_NTH_BIT(*nset,2);
407     }
408     /* Test the point for sidedness */
409     d = DOT(n[2],p);
410 gwlarson 3.4 if(d > 0.0)
411 gwlarson 3.1 {
412 gwlarson 3.4 sides[2] = GT_OUT;
413     return(FALSE);
414 gwlarson 3.1 }
415     else
416     sides[2] = GT_INTERIOR;
417     /* Must be interior to the pyramid */
418     return(GT_INTERIOR);
419     }
420    
421    
422    
423 gwlarson 3.7
424 gwlarson 3.1 int
425 gwlarson 3.4 point_in_stri(v0,v1,v2,p)
426 gwlarson 3.1 FVECT v0,v1,v2,p;
427     {
428 gwlarson 3.4 double d;
429 gwlarson 3.1 FVECT n;
430    
431 gwlarson 3.8 VCROSS(n,v0,v1);
432 gwlarson 3.1 /* Test the point for sidedness */
433     d = DOT(n,p);
434 gwlarson 3.4 if(d > 0.0)
435     return(FALSE);
436    
437 gwlarson 3.1 /* Test next edge */
438 gwlarson 3.8 VCROSS(n,v1,v2);
439 gwlarson 3.1 /* Test the point for sidedness */
440     d = DOT(n,p);
441 gwlarson 3.4 if(d > 0.0)
442 gwlarson 3.1 return(FALSE);
443    
444     /* Test next edge */
445 gwlarson 3.8 VCROSS(n,v2,v0);
446 gwlarson 3.1 /* Test the point for sidedness */
447     d = DOT(n,p);
448 gwlarson 3.4 if(d > 0.0)
449 gwlarson 3.1 return(FALSE);
450     /* Must be interior to the pyramid */
451 gwlarson 3.4 return(GT_INTERIOR);
452 gwlarson 3.1 }
453    
454     int
455 gwlarson 3.4 vertices_in_stri(t0,t1,t2,p0,p1,p2,nset,n,avg,pt_sides)
456 gwlarson 3.1 FVECT t0,t1,t2,p0,p1,p2;
457 gwlarson 3.4 int *nset;
458 gwlarson 3.1 FVECT n[3];
459     FVECT avg;
460 gwlarson 3.4 int pt_sides[3][3];
461 gwlarson 3.1
462     {
463 gwlarson 3.4 int below_plane[3],test;
464 gwlarson 3.1
465     SUM_3VEC3(avg,t0,t1,t2);
466     *nset = 0;
467     /* Test vertex v[i] against triangle j*/
468     /* Check if v[i] lies below plane defined by avg of 3 vectors
469     defining triangle
470     */
471    
472     /* test point 0 */
473 gwlarson 3.4 if(DOT(avg,p0) < 0.0)
474 gwlarson 3.1 below_plane[0] = 1;
475     else
476 gwlarson 3.4 below_plane[0] = 0;
477 gwlarson 3.1 /* Test if b[i] lies in or on triangle a */
478 gwlarson 3.4 test = point_set_in_stri(t0,t1,t2,p0,n,nset,pt_sides[0]);
479 gwlarson 3.1 /* If pts[i] is interior: done */
480     if(!below_plane[0])
481     {
482     if(test == GT_INTERIOR)
483     return(TRUE);
484     }
485     /* Now test point 1*/
486    
487 gwlarson 3.4 if(DOT(avg,p1) < 0.0)
488 gwlarson 3.1 below_plane[1] = 1;
489     else
490     below_plane[1]=0;
491     /* Test if b[i] lies in or on triangle a */
492 gwlarson 3.4 test = point_set_in_stri(t0,t1,t2,p1,n,nset,pt_sides[1]);
493 gwlarson 3.1 /* If pts[i] is interior: done */
494     if(!below_plane[1])
495     {
496     if(test == GT_INTERIOR)
497     return(TRUE);
498     }
499    
500     /* Now test point 2 */
501 gwlarson 3.4 if(DOT(avg,p2) < 0.0)
502 gwlarson 3.1 below_plane[2] = 1;
503     else
504 gwlarson 3.4 below_plane[2] = 0;
505 gwlarson 3.1 /* Test if b[i] lies in or on triangle a */
506 gwlarson 3.4 test = point_set_in_stri(t0,t1,t2,p2,n,nset,pt_sides[2]);
507 gwlarson 3.1
508     /* If pts[i] is interior: done */
509     if(!below_plane[2])
510     {
511     if(test == GT_INTERIOR)
512     return(TRUE);
513     }
514    
515     /* If all three points below separating plane: trivial reject */
516     if(below_plane[0] && below_plane[1] && below_plane[2])
517     return(FALSE);
518     /* Now check vertices in a against triangle b */
519     return(FALSE);
520     }
521    
522    
523     set_sidedness_tests(t0,t1,t2,p0,p1,p2,test,sides,nset,n)
524     FVECT t0,t1,t2,p0,p1,p2;
525 gwlarson 3.4 int test[3];
526     int sides[3][3];
527     int nset;
528 gwlarson 3.1 FVECT n[3];
529     {
530 gwlarson 3.4 int t;
531 gwlarson 3.1 double d;
532    
533    
534     /* p=0 */
535     test[0] = 0;
536     if(sides[0][0] == GT_INVALID)
537     {
538     if(!NTH_BIT(nset,0))
539 gwlarson 3.8 VCROSS(n[0],t0,t1);
540 gwlarson 3.1 /* Test the point for sidedness */
541     d = DOT(n[0],p0);
542 gwlarson 3.4 if(d >= 0.0)
543 gwlarson 3.1 SET_NTH_BIT(test[0],0);
544     }
545     else
546     if(sides[0][0] != GT_INTERIOR)
547     SET_NTH_BIT(test[0],0);
548    
549     if(sides[0][1] == GT_INVALID)
550     {
551     if(!NTH_BIT(nset,1))
552 gwlarson 3.8 VCROSS(n[1],t1,t2);
553 gwlarson 3.1 /* Test the point for sidedness */
554     d = DOT(n[1],p0);
555 gwlarson 3.4 if(d >= 0.0)
556 gwlarson 3.1 SET_NTH_BIT(test[0],1);
557     }
558     else
559     if(sides[0][1] != GT_INTERIOR)
560     SET_NTH_BIT(test[0],1);
561    
562     if(sides[0][2] == GT_INVALID)
563     {
564     if(!NTH_BIT(nset,2))
565 gwlarson 3.8 VCROSS(n[2],t2,t0);
566 gwlarson 3.1 /* Test the point for sidedness */
567     d = DOT(n[2],p0);
568 gwlarson 3.4 if(d >= 0.0)
569 gwlarson 3.1 SET_NTH_BIT(test[0],2);
570     }
571     else
572     if(sides[0][2] != GT_INTERIOR)
573     SET_NTH_BIT(test[0],2);
574    
575     /* p=1 */
576     test[1] = 0;
577     /* t=0*/
578     if(sides[1][0] == GT_INVALID)
579     {
580     if(!NTH_BIT(nset,0))
581 gwlarson 3.8 VCROSS(n[0],t0,t1);
582 gwlarson 3.1 /* Test the point for sidedness */
583     d = DOT(n[0],p1);
584 gwlarson 3.4 if(d >= 0.0)
585 gwlarson 3.1 SET_NTH_BIT(test[1],0);
586     }
587     else
588     if(sides[1][0] != GT_INTERIOR)
589     SET_NTH_BIT(test[1],0);
590    
591     /* t=1 */
592     if(sides[1][1] == GT_INVALID)
593     {
594     if(!NTH_BIT(nset,1))
595 gwlarson 3.8 VCROSS(n[1],t1,t2);
596 gwlarson 3.1 /* Test the point for sidedness */
597     d = DOT(n[1],p1);
598 gwlarson 3.4 if(d >= 0.0)
599 gwlarson 3.1 SET_NTH_BIT(test[1],1);
600     }
601     else
602     if(sides[1][1] != GT_INTERIOR)
603     SET_NTH_BIT(test[1],1);
604    
605     /* t=2 */
606     if(sides[1][2] == GT_INVALID)
607     {
608     if(!NTH_BIT(nset,2))
609 gwlarson 3.8 VCROSS(n[2],t2,t0);
610 gwlarson 3.1 /* Test the point for sidedness */
611     d = DOT(n[2],p1);
612 gwlarson 3.4 if(d >= 0.0)
613 gwlarson 3.1 SET_NTH_BIT(test[1],2);
614     }
615     else
616     if(sides[1][2] != GT_INTERIOR)
617     SET_NTH_BIT(test[1],2);
618    
619     /* p=2 */
620     test[2] = 0;
621     /* t = 0 */
622     if(sides[2][0] == GT_INVALID)
623     {
624     if(!NTH_BIT(nset,0))
625 gwlarson 3.8 VCROSS(n[0],t0,t1);
626 gwlarson 3.1 /* Test the point for sidedness */
627     d = DOT(n[0],p2);
628 gwlarson 3.4 if(d >= 0.0)
629 gwlarson 3.1 SET_NTH_BIT(test[2],0);
630     }
631     else
632     if(sides[2][0] != GT_INTERIOR)
633     SET_NTH_BIT(test[2],0);
634     /* t=1 */
635     if(sides[2][1] == GT_INVALID)
636     {
637     if(!NTH_BIT(nset,1))
638 gwlarson 3.8 VCROSS(n[1],t1,t2);
639 gwlarson 3.1 /* Test the point for sidedness */
640     d = DOT(n[1],p2);
641 gwlarson 3.4 if(d >= 0.0)
642 gwlarson 3.1 SET_NTH_BIT(test[2],1);
643     }
644     else
645     if(sides[2][1] != GT_INTERIOR)
646     SET_NTH_BIT(test[2],1);
647     /* t=2 */
648     if(sides[2][2] == GT_INVALID)
649     {
650     if(!NTH_BIT(nset,2))
651 gwlarson 3.8 VCROSS(n[2],t2,t0);
652 gwlarson 3.1 /* Test the point for sidedness */
653     d = DOT(n[2],p2);
654 gwlarson 3.4 if(d >= 0.0)
655 gwlarson 3.1 SET_NTH_BIT(test[2],2);
656     }
657     else
658     if(sides[2][2] != GT_INTERIOR)
659     SET_NTH_BIT(test[2],2);
660     }
661    
662    
663     int
664 gwlarson 3.4 stri_intersect(a1,a2,a3,b1,b2,b3)
665 gwlarson 3.1 FVECT a1,a2,a3,b1,b2,b3;
666     {
667 gwlarson 3.4 int which,test,n_set[2];
668     int sides[2][3][3],i,j,inext,jnext;
669     int tests[2][3];
670 gwlarson 3.9 FVECT n[2][3],p,avg[2],t1,t2,t3;
671 gwlarson 3.1
672 gwlarson 3.9 #ifdef DEBUG
673     tri_normal(b1,b2,b3,p,FALSE);
674     if(DOT(p,b1) > 0)
675     {
676     VCOPY(t3,b1);
677     VCOPY(t2,b2);
678     VCOPY(t1,b3);
679     }
680     else
681     #endif
682     {
683     VCOPY(t1,b1);
684     VCOPY(t2,b2);
685     VCOPY(t3,b3);
686     }
687    
688 gwlarson 3.1 /* Test the vertices of triangle a against the pyramid formed by triangle
689     b and the origin. If any vertex of a is interior to triangle b, or
690     if all 3 vertices of a are ON the edges of b,return TRUE. Remember
691     the results of the edge normal and sidedness tests for later.
692     */
693 gwlarson 3.9 if(vertices_in_stri(a1,a2,a3,t1,t2,t3,&(n_set[0]),n[0],avg[0],sides[1]))
694 gwlarson 3.1 return(TRUE);
695    
696 gwlarson 3.9 if(vertices_in_stri(t1,t2,t3,a1,a2,a3,&(n_set[1]),n[1],avg[1],sides[0]))
697 gwlarson 3.1 return(TRUE);
698    
699    
700 gwlarson 3.9 set_sidedness_tests(t1,t2,t3,a1,a2,a3,tests[0],sides[0],n_set[1],n[1]);
701 gwlarson 3.1 if(tests[0][0]&tests[0][1]&tests[0][2])
702     return(FALSE);
703    
704 gwlarson 3.9 set_sidedness_tests(a1,a2,a3,t1,t2,t3,tests[1],sides[1],n_set[0],n[0]);
705 gwlarson 3.1 if(tests[1][0]&tests[1][1]&tests[1][2])
706     return(FALSE);
707    
708     for(j=0; j < 3;j++)
709     {
710     jnext = (j+1)%3;
711     /* IF edge b doesnt cross any great circles of a, punt */
712     if(tests[1][j] & tests[1][jnext])
713     continue;
714     for(i=0;i<3;i++)
715     {
716     inext = (i+1)%3;
717     /* IF edge a doesnt cross any great circles of b, punt */
718     if(tests[0][i] & tests[0][inext])
719     continue;
720     /* Now find the great circles that cross and test */
721     if((NTH_BIT(tests[0][i],j)^(NTH_BIT(tests[0][inext],j)))
722     && (NTH_BIT(tests[1][j],i)^NTH_BIT(tests[1][jnext],i)))
723     {
724     VCROSS(p,n[0][i],n[1][j]);
725    
726     /* If zero cp= done */
727     if(ZERO_VEC3(p))
728     continue;
729     /* check above both planes */
730     if(DOT(avg[0],p) < 0 || DOT(avg[1],p) < 0)
731     {
732     NEGATE_VEC3(p);
733     if(DOT(avg[0],p) < 0 || DOT(avg[1],p) < 0)
734     continue;
735     }
736     return(TRUE);
737     }
738     }
739     }
740     return(FALSE);
741     }
742    
743     int
744 gwlarson 3.4 ray_intersect_tri(orig,dir,v0,v1,v2,pt)
745 gwlarson 3.1 FVECT orig,dir;
746     FVECT v0,v1,v2;
747     FVECT pt;
748     {
749 gwlarson 3.7 FVECT p0,p1,p2,p;
750     FPEQ peq;
751 gwlarson 3.4 int type;
752    
753 gwlarson 3.5 VSUB(p0,v0,orig);
754     VSUB(p1,v1,orig);
755     VSUB(p2,v2,orig);
756    
757 gwlarson 3.4 if(point_in_stri(p0,p1,p2,dir))
758 gwlarson 3.1 {
759     /* Intersect the ray with the triangle plane */
760 gwlarson 3.7 tri_plane_equation(v0,v1,v2,&peq,FALSE);
761     return(intersect_ray_plane(orig,dir,peq,NULL,pt));
762 gwlarson 3.1 }
763 gwlarson 3.4 return(FALSE);
764 gwlarson 3.1 }
765    
766    
767     calculate_view_frustum(vp,hv,vv,horiz,vert,near,far,fnear,ffar)
768     FVECT vp,hv,vv;
769     double horiz,vert,near,far;
770     FVECT fnear[4],ffar[4];
771     {
772     double height,width;
773     FVECT t,nhv,nvv,ndv;
774     double w2,h2;
775     /* Calculate the x and y dimensions of the near face */
776     /* hv and vv are the horizontal and vertical vectors in the
777     view frame-the magnitude is the dimension of the front frustum
778     face at z =1
779     */
780     VCOPY(nhv,hv);
781     VCOPY(nvv,vv);
782     w2 = normalize(nhv);
783     h2 = normalize(nvv);
784     /* Use similar triangles to calculate the dimensions at z=near */
785     width = near*0.5*w2;
786     height = near*0.5*h2;
787    
788     VCROSS(ndv,nvv,nhv);
789     /* Calculate the world space points corresponding to the 4 corners
790     of the front face of the view frustum
791     */
792     fnear[0][0] = width*nhv[0] + height*nvv[0] + near*ndv[0] + vp[0] ;
793     fnear[0][1] = width*nhv[1] + height*nvv[1] + near*ndv[1] + vp[1];
794     fnear[0][2] = width*nhv[2] + height*nvv[2] + near*ndv[2] + vp[2];
795     fnear[1][0] = -width*nhv[0] + height*nvv[0] + near*ndv[0] + vp[0];
796     fnear[1][1] = -width*nhv[1] + height*nvv[1] + near*ndv[1] + vp[1];
797     fnear[1][2] = -width*nhv[2] + height*nvv[2] + near*ndv[2] + vp[2];
798     fnear[2][0] = -width*nhv[0] - height*nvv[0] + near*ndv[0] + vp[0];
799     fnear[2][1] = -width*nhv[1] - height*nvv[1] + near*ndv[1] + vp[1];
800     fnear[2][2] = -width*nhv[2] - height*nvv[2] + near*ndv[2] + vp[2];
801     fnear[3][0] = width*nhv[0] - height*nvv[0] + near*ndv[0] + vp[0];
802     fnear[3][1] = width*nhv[1] - height*nvv[1] + near*ndv[1] + vp[1];
803     fnear[3][2] = width*nhv[2] - height*nvv[2] + near*ndv[2] + vp[2];
804    
805     /* Now do the far face */
806     width = far*0.5*w2;
807     height = far*0.5*h2;
808     ffar[0][0] = width*nhv[0] + height*nvv[0] + far*ndv[0] + vp[0] ;
809     ffar[0][1] = width*nhv[1] + height*nvv[1] + far*ndv[1] + vp[1] ;
810     ffar[0][2] = width*nhv[2] + height*nvv[2] + far*ndv[2] + vp[2] ;
811     ffar[1][0] = -width*nhv[0] + height*nvv[0] + far*ndv[0] + vp[0] ;
812     ffar[1][1] = -width*nhv[1] + height*nvv[1] + far*ndv[1] + vp[1] ;
813     ffar[1][2] = -width*nhv[2] + height*nvv[2] + far*ndv[2] + vp[2] ;
814     ffar[2][0] = -width*nhv[0] - height*nvv[0] + far*ndv[0] + vp[0] ;
815     ffar[2][1] = -width*nhv[1] - height*nvv[1] + far*ndv[1] + vp[1] ;
816     ffar[2][2] = -width*nhv[2] - height*nvv[2] + far*ndv[2] + vp[2] ;
817     ffar[3][0] = width*nhv[0] - height*nvv[0] + far*ndv[0] + vp[0] ;
818     ffar[3][1] = width*nhv[1] - height*nvv[1] + far*ndv[1] + vp[1] ;
819     ffar[3][2] = width*nhv[2] - height*nvv[2] + far*ndv[2] + vp[2] ;
820     }
821    
822 gwlarson 3.6 int
823     max_index(v,r)
824     FVECT v;
825     double *r;
826     {
827     double p[3];
828     int i;
829 gwlarson 3.1
830 gwlarson 3.6 p[0] = fabs(v[0]);
831     p[1] = fabs(v[1]);
832     p[2] = fabs(v[2]);
833     i = (p[0]>=p[1])?((p[0]>=p[2])?0:2):((p[1]>=p[2])?1:2);
834     if(r)
835     *r = p[i];
836     return(i);
837     }
838 gwlarson 3.1
839 gwlarson 3.6 int
840     closest_point_in_tri(p0,p1,p2,p,p0id,p1id,p2id)
841     FVECT p0,p1,p2,p;
842     int p0id,p1id,p2id;
843     {
844     double d,d1;
845     int i;
846    
847     d = DIST_SQ(p,p0);
848     d1 = DIST_SQ(p,p1);
849     if(d < d1)
850     {
851     d1 = DIST_SQ(p,p2);
852     i = (d1 < d)?p2id:p0id;
853     }
854     else
855     {
856     d = DIST_SQ(p,p2);
857     i = (d < d1)? p2id:p1id;
858     }
859     return(i);
860     }
861 gwlarson 3.1
862 gwlarson 3.6
863 gwlarson 3.1 int
864 gwlarson 3.4 sedge_intersect(a0,a1,b0,b1)
865 gwlarson 3.1 FVECT a0,a1,b0,b1;
866     {
867     FVECT na,nb,avga,avgb,p;
868     double d;
869     int sb0,sb1,sa0,sa1;
870    
871     /* First test if edge b straddles great circle of a */
872     VCROSS(na,a0,a1);
873     d = DOT(na,b0);
874     sb0 = ZERO(d)?0:(d<0)? -1: 1;
875     d = DOT(na,b1);
876     sb1 = ZERO(d)?0:(d<0)? -1: 1;
877     /* edge b entirely on one side of great circle a: edges cannot intersect*/
878     if(sb0*sb1 > 0)
879     return(FALSE);
880     /* test if edge a straddles great circle of b */
881     VCROSS(nb,b0,b1);
882     d = DOT(nb,a0);
883     sa0 = ZERO(d)?0:(d<0)? -1: 1;
884     d = DOT(nb,a1);
885     sa1 = ZERO(d)?0:(d<0)? -1: 1;
886     /* edge a entirely on one side of great circle b: edges cannot intersect*/
887     if(sa0*sa1 > 0)
888     return(FALSE);
889    
890     /* Find one of intersection points of the great circles */
891     VCROSS(p,na,nb);
892     /* If they lie on same great circle: call an intersection */
893     if(ZERO_VEC3(p))
894     return(TRUE);
895    
896     VADD(avga,a0,a1);
897     VADD(avgb,b0,b1);
898     if(DOT(avga,p) < 0 || DOT(avgb,p) < 0)
899     {
900     NEGATE_VEC3(p);
901     if(DOT(avga,p) < 0 || DOT(avgb,p) < 0)
902     return(FALSE);
903     }
904     if((!sb0 || !sb1) && (!sa0 || !sa1))
905     return(FALSE);
906     return(TRUE);
907     }
908 gwlarson 3.2
909    
910     /* Find the normalized barycentric coordinates of p relative to
911     * triangle v0,v1,v2. Return result in coord
912     */
913     bary2d(x1,y1,x2,y2,x3,y3,px,py,coord)
914     double x1,y1,x2,y2,x3,y3;
915     double px,py;
916     double coord[3];
917     {
918     double a;
919    
920     a = (x2 - x1) * (y3 - y1) - (x3 - x1) * (y2 - y1);
921     coord[0] = ((x2 - px) * (y3 - py) - (x3 - px) * (y2 - py)) / a;
922     coord[1] = ((x3 - px) * (y1 - py) - (x1 - px) * (y3 - py)) / a;
923 gwlarson 3.6 coord[2] = ((x1 - px) * (y2 - py) - (x2 - px) * (y1 - py)) / a;
924 gwlarson 3.2
925     }
926    
927 gwlarson 3.4
928    
929 gwlarson 3.2
930 gwlarson 3.4 bary_parent(coord,i)
931 gwlarson 3.6 BCOORD coord[3];
932     int i;
933 gwlarson 3.2 {
934 gwlarson 3.6 switch(i) {
935     case 0:
936     /* update bary for child */
937 gwlarson 3.9 coord[0] = (coord[0] >> 1) + MAXBCOORD4;
938 gwlarson 3.6 coord[1] >>= 1;
939     coord[2] >>= 1;
940     break;
941     case 1:
942     coord[0] >>= 1;
943 gwlarson 3.9 coord[1] = (coord[1] >> 1) + MAXBCOORD4;
944 gwlarson 3.6 coord[2] >>= 1;
945     break;
946    
947     case 2:
948     coord[0] >>= 1;
949     coord[1] >>= 1;
950 gwlarson 3.9 coord[2] = (coord[2] >> 1) + MAXBCOORD4;
951 gwlarson 3.6 break;
952    
953     case 3:
954 gwlarson 3.9 coord[0] = MAXBCOORD4 - (coord[0] >> 1);
955     coord[1] = MAXBCOORD4 - (coord[1] >> 1);
956     coord[2] = MAXBCOORD4 - (coord[2] >> 1);
957 gwlarson 3.6 break;
958     #ifdef DEBUG
959     default:
960 gwlarson 3.9 eputs("bary_parent():Invalid child\n");
961 gwlarson 3.6 break;
962     #endif
963     }
964 gwlarson 3.2 }
965    
966 gwlarson 3.9 bary_from_child(coord,child,next)
967 gwlarson 3.6 BCOORD coord[3];
968     int child,next;
969     {
970     #ifdef DEBUG
971     if(child <0 || child > 3)
972     {
973 gwlarson 3.9 eputs("bary_from_child():Invalid child\n");
974 gwlarson 3.6 return;
975     }
976     if(next <0 || next > 3)
977     {
978 gwlarson 3.9 eputs("bary_from_child():Invalid next\n");
979 gwlarson 3.6 return;
980     }
981     #endif
982     if(next == child)
983     return;
984    
985     switch(child){
986     case 0:
987     coord[0] = 0;
988 gwlarson 3.9 coord[1] = MAXBCOORD2 - coord[1];
989     coord[2] = MAXBCOORD2 - coord[2];
990 gwlarson 3.6 break;
991     case 1:
992 gwlarson 3.9 coord[0] = MAXBCOORD2 - coord[0];
993 gwlarson 3.6 coord[1] = 0;
994 gwlarson 3.9 coord[2] = MAXBCOORD2 - coord[2];
995 gwlarson 3.6 break;
996     case 2:
997 gwlarson 3.9 coord[0] = MAXBCOORD2 - coord[0];
998     coord[1] = MAXBCOORD2 - coord[1];
999 gwlarson 3.6 coord[2] = 0;
1000     break;
1001     case 3:
1002     switch(next){
1003     case 0:
1004     coord[0] = 0;
1005 gwlarson 3.9 coord[1] = MAXBCOORD2 - coord[1];
1006     coord[2] = MAXBCOORD2 - coord[2];
1007 gwlarson 3.6 break;
1008     case 1:
1009 gwlarson 3.9 coord[0] = MAXBCOORD2 - coord[0];
1010 gwlarson 3.6 coord[1] = 0;
1011 gwlarson 3.9 coord[2] = MAXBCOORD2 - coord[2];
1012 gwlarson 3.6 break;
1013     case 2:
1014 gwlarson 3.9 coord[0] = MAXBCOORD2 - coord[0];
1015     coord[1] = MAXBCOORD2 - coord[1];
1016 gwlarson 3.6 coord[2] = 0;
1017     break;
1018     }
1019     break;
1020     }
1021     }
1022    
1023 gwlarson 3.4 int
1024 gwlarson 3.9 bary_child(coord)
1025 gwlarson 3.6 BCOORD coord[3];
1026 gwlarson 3.4 {
1027 gwlarson 3.6 int i;
1028    
1029 gwlarson 3.9 if(coord[0] > MAXBCOORD4)
1030 gwlarson 3.6 {
1031     /* update bary for child */
1032 gwlarson 3.9 coord[0] = (coord[0]<< 1) - MAXBCOORD2;
1033 gwlarson 3.6 coord[1] <<= 1;
1034     coord[2] <<= 1;
1035     return(0);
1036     }
1037     else
1038 gwlarson 3.9 if(coord[1] > MAXBCOORD4)
1039 gwlarson 3.4 {
1040 gwlarson 3.6 coord[0] <<= 1;
1041 gwlarson 3.9 coord[1] = (coord[1] << 1) - MAXBCOORD2;
1042 gwlarson 3.6 coord[2] <<= 1;
1043     return(1);
1044 gwlarson 3.4 }
1045     else
1046 gwlarson 3.9 if(coord[2] > MAXBCOORD4)
1047 gwlarson 3.6 {
1048     coord[0] <<= 1;
1049     coord[1] <<= 1;
1050 gwlarson 3.9 coord[2] = (coord[2] << 1) - MAXBCOORD2;
1051 gwlarson 3.6 return(2);
1052     }
1053     else
1054     {
1055 gwlarson 3.9 coord[0] = MAXBCOORD2 - (coord[0] << 1);
1056     coord[1] = MAXBCOORD2 - (coord[1] << 1);
1057     coord[2] = MAXBCOORD2 - (coord[2] << 1);
1058 gwlarson 3.6 return(3);
1059     }
1060     }
1061    
1062 gwlarson 3.7 int
1063 gwlarson 3.9 bary_nth_child(coord,i)
1064 gwlarson 3.7 BCOORD coord[3];
1065     int i;
1066     {
1067    
1068     switch(i){
1069     case 0:
1070     /* update bary for child */
1071 gwlarson 3.9 coord[0] = (coord[0]<< 1) - MAXBCOORD2;
1072 gwlarson 3.7 coord[1] <<= 1;
1073     coord[2] <<= 1;
1074     break;
1075     case 1:
1076     coord[0] <<= 1;
1077 gwlarson 3.9 coord[1] = (coord[1] << 1) - MAXBCOORD2;
1078 gwlarson 3.7 coord[2] <<= 1;
1079     break;
1080     case 2:
1081     coord[0] <<= 1;
1082     coord[1] <<= 1;
1083 gwlarson 3.9 coord[2] = (coord[2] << 1) - MAXBCOORD2;
1084 gwlarson 3.7 break;
1085     case 3:
1086 gwlarson 3.9 coord[0] = MAXBCOORD2 - (coord[0] << 1);
1087     coord[1] = MAXBCOORD2 - (coord[1] << 1);
1088     coord[2] = MAXBCOORD2 - (coord[2] << 1);
1089 gwlarson 3.7 break;
1090     }
1091     }
1092 gwlarson 3.2
1093    
1094 gwlarson 3.1