1 /*
2  * intersect.c - This file contains code for CSG and intersection routines.
3  *
4  *  $Id: intersect.c,v 1.39 2007/02/09 08:05:32 johns Exp $
5  */
6 
7 #include "machine.h"
8 #include "types.h"
9 #include "intersect.h"
10 #include "macros.h"
11 
new_objectid(scenedef * scene)12 unsigned int new_objectid(scenedef * scene) {
13   return scene->objgroup.numobjects++; /* generate unique object ID's */
14 }
15 
max_objectid(scenedef * scene)16 unsigned int max_objectid(scenedef * scene) {
17   return scene->objgroup.numobjects;
18 }
19 
free_objects(object * start)20 void free_objects(object * start) {
21   object * cur;
22   object * next;
23 
24   cur=start;
25   while (cur != NULL) {
26     next=cur->nextobj;
27     cur->methods->freeobj(cur);
28     cur=next;
29   }
30 }
31 
32 
intersect_objects(ray * ry)33 void intersect_objects(ray * ry) {
34   object * cur;
35   object temp;
36 
37   reset_intersection(ry); /* eliminate any existing intersections */
38 
39   /* do unbounded objects first, to help early-exit bounded object tests */
40   temp.nextobj = ry->scene->objgroup.unboundedobj;
41   cur = &temp;
42   while ((cur=cur->nextobj) != NULL)
43     cur->methods->intersect(cur, ry);
44 
45   /* do bounded objects last, taking advantage of early-exit opportunities */
46   temp.nextobj = ry->scene->objgroup.boundedobj;
47   cur = &temp;
48   while ((cur=cur->nextobj) != NULL)
49     cur->methods->intersect(cur, ry);
50 }
51 
52 
53 /* Only keeps closest intersection, no clipping, no CSG */
add_regular_intersection(flt t,const object * obj,ray * ry)54 void add_regular_intersection(flt t, const object * obj, ray * ry) {
55   if (t > EPSILON) {
56     /* if we hit something before maxdist update maxdist */
57     if (t < ry->maxdist) {
58       ry->maxdist = t;
59       ry->intstruct.num=1;
60       ry->intstruct.closest.obj = obj;
61       ry->intstruct.closest.t = t;
62     }
63   }
64 }
65 
66 /* Only keeps closest intersection, also handles clipping, no CSG */
add_clipped_intersection(flt t,const object * obj,ray * ry)67 void add_clipped_intersection(flt t, const object * obj, ray * ry) {
68   if (t > EPSILON) {
69     /* if we hit something before maxdist update maxdist */
70     if (t < ry->maxdist) {
71 
72       /* handle clipped object tests */
73       if (obj->clip != NULL) {
74         vector hit;
75         int i;
76 
77         RAYPNT(hit, (*ry), t);    /* find the hit point for further tests */
78         for (i=0; i<obj->clip->numplanes; i++) {
79           if ((obj->clip->planes[i * 4    ] * hit.x +
80                obj->clip->planes[i * 4 + 1] * hit.y +
81                obj->clip->planes[i * 4 + 2] * hit.z) >
82                obj->clip->planes[i * 4 + 3]) {
83             return; /* hit point was clipped */
84           }
85         }
86       }
87 
88       ry->maxdist = t;
89       ry->intstruct.num=1;
90       ry->intstruct.closest.obj = obj;
91       ry->intstruct.closest.t = t;
92     }
93   }
94 }
95 
closest_intersection(flt * t,object const ** obj,ray * ry)96 int closest_intersection(flt * t, object const ** obj, ray * ry) {
97   if (ry->intstruct.num > 0) {
98       *t = ry->intstruct.closest.t;
99     *obj = ry->intstruct.closest.obj;
100   }
101 
102   return ry->intstruct.num;
103 }
104 /* End of CSG-unsafe */
105 
106 
107 /* Only meant for shadow rays, unsafe for anything else */
add_shadow_intersection(flt t,const object * obj,ray * ry)108 void add_shadow_intersection(flt t, const object * obj, ray * ry) {
109   if (t > EPSILON) {
110     /* if we hit something before maxdist update maxdist */
111     if (t < ry->maxdist) {
112       /* if this object doesn't cast a shadow, modulate the */
113       /* light by its opacity value                         */
114       if (!(obj->tex->flags & RT_TEXTURE_SHADOWCAST)) {
115         ry->intstruct.shadowfilter *= (1.0 - obj->tex->opacity);
116         return;
117       }
118 
119       ry->maxdist = t;
120       ry->intstruct.num=1;
121 
122       /* if we hit *anything* before maxdist, and we're firing a */
123       /* shadow ray, then we are finished ray tracing the shadow */
124       ry->flags |= RT_RAY_FINISHED;
125     }
126   }
127 }
128 
129 /* Only meant for clipped shadow rays, unsafe for anything else */
add_clipped_shadow_intersection(flt t,const object * obj,ray * ry)130 void add_clipped_shadow_intersection(flt t, const object * obj, ray * ry) {
131   if (t > EPSILON) {
132     /* if we hit something before maxdist update maxdist */
133     if (t < ry->maxdist) {
134       /* if this object doesn't cast a shadow, modulate the */
135       /* light by its opacity value                         */
136       if (!(obj->tex->flags & RT_TEXTURE_SHADOWCAST)) {
137         ry->intstruct.shadowfilter *= (1.0 - obj->tex->opacity);
138         return;
139       }
140 
141       /* handle clipped object tests */
142       if (obj->clip != NULL) {
143         vector hit;
144         int i;
145 
146         RAYPNT(hit, (*ry), t);    /* find the hit point for further tests */
147         for (i=0; i<obj->clip->numplanes; i++) {
148           if ((obj->clip->planes[i * 4    ] * hit.x +
149                obj->clip->planes[i * 4 + 1] * hit.y +
150                obj->clip->planes[i * 4 + 2] * hit.z) >
151                obj->clip->planes[i * 4 + 3]) {
152             return; /* hit point was clipped */
153           }
154         }
155       }
156 
157       ry->maxdist = t;
158       ry->intstruct.num=1;
159 
160       /* if we hit *anything* before maxdist, and we're firing a */
161       /* shadow ray, then we are finished ray tracing the shadow */
162       ry->flags |= RT_RAY_FINISHED;
163     }
164   }
165 }
166 
167 
shadow_intersection(ray * ry)168 int shadow_intersection(ray * ry) {
169   if (ry->intstruct.num > 0)
170     return 1;
171 
172   return 0;
173 }
174 
175