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