1 /*
2 Copyright (c) 2005-2020 Intel Corporation
3
4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
15 */
16
17 /*
18 The original source for this example is
19 Copyright (c) 1994-2008 John E. Stone
20 All rights reserved.
21
22 Redistribution and use in source and binary forms, with or without
23 modification, are permitted provided that the following conditions
24 are met:
25 1. Redistributions of source code must retain the above copyright
26 notice, this list of conditions and the following disclaimer.
27 2. Redistributions in binary form must reproduce the above copyright
28 notice, this list of conditions and the following disclaimer in the
29 documentation and/or other materials provided with the distribution.
30 3. The name of the author may not be used to endorse or promote products
31 derived from this software without specific prior written permission.
32
33 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
34 OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
35 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
36 ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
37 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
38 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
39 OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
40 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
41 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
42 OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
43 SUCH DAMAGE.
44 */
45
46 /*
47 * extvol.cpp - Volume rendering helper routines etc.
48 */
49
50 #include<stdio.h>
51
52 #include "machine.h"
53 #include "types.h"
54 #include "macros.h"
55 #include "vector.h"
56 #include "util.h"
57 #include "box.h"
58 #include "extvol.h"
59 #include "trace.h"
60 #include "sphere.h"
61 #include "light.h"
62 #include "shade.h"
63 #include "global.h"
64
65
extvol_bbox(void * obj,vector * min,vector * max)66 int extvol_bbox(void * obj, vector * min, vector * max) {
67 box * b = (box *) obj;
68
69 *min = b->min;
70 *max = b->max;
71
72 return 1;
73 }
74
75 static object_methods extvol_methods = {
76 (void (*)(void *, void *))(box_intersect),
77 (void (*)(void *, void *, void *, void *))(box_normal),
78 extvol_bbox,
79 free
80 };
81
newextvol(void * voidtex,vector min,vector max,int samples,flt (* evaluator)(flt,flt,flt))82 extvol * newextvol(void * voidtex, vector min, vector max,
83 int samples, flt (* evaluator)(flt, flt, flt)) {
84 extvol * xvol;
85 texture * tex;
86
87 tex = (texture *) voidtex;
88
89 xvol = (extvol *) rt_getmem(sizeof(extvol));
90 memset(xvol, 0, sizeof(extvol));
91
92 xvol->methods = &extvol_methods;
93
94 xvol->min=min;
95 xvol->max=max;
96 xvol->evaluator = evaluator;
97 xvol->ambient = tex->ambient;
98 xvol->diffuse = tex->diffuse;
99 xvol->opacity = tex->opacity;
100 xvol->samples = samples;
101
102 xvol->tex = (texture *)rt_getmem(sizeof(texture));
103 memset(xvol->tex, 0, sizeof(texture));
104
105 xvol->tex->ctr.x = 0.0;
106 xvol->tex->ctr.y = 0.0;
107 xvol->tex->ctr.z = 0.0;
108 xvol->tex->rot = xvol->tex->ctr;
109 xvol->tex->scale = xvol->tex->ctr;
110 xvol->tex->uaxs = xvol->tex->ctr;
111 xvol->tex->vaxs = xvol->tex->ctr;
112 xvol->tex->islight = 0;
113 xvol->tex->shadowcast = 0;
114
115 xvol->tex->col=tex->col;
116 xvol->tex->ambient=1.0;
117 xvol->tex->diffuse=0.0;
118 xvol->tex->specular=0.0;
119 xvol->tex->opacity=1.0;
120 xvol->tex->img=NULL;
121 xvol->tex->texfunc=(color(*)(void *, void *, void *))(ext_volume_texture);
122 xvol->tex->obj = (void *) xvol; /* XXX hack! */
123
124 return xvol;
125 }
126
ExtVoxelColor(flt scalar)127 color ExtVoxelColor(flt scalar) {
128 color col;
129
130 if (scalar > 1.0)
131 scalar = 1.0;
132
133 if (scalar < 0.0)
134 scalar = 0.0;
135
136 if (scalar < 0.5) {
137 col.g = 0.0;
138 }
139 else {
140 col.g = (scalar - 0.5) * 2.0;
141 }
142
143 col.r = scalar;
144 col.b = 1.0 - (scalar / 2.0);
145
146 return col;
147 }
148
ext_volume_texture(vector * hit,texture * tex,ray * ry)149 color ext_volume_texture(vector * hit, texture * tex, ray * ry) {
150 color col, col2;
151 box * bx;
152 extvol * xvol;
153 flt a, tx1, tx2, ty1, ty2, tz1, tz2;
154 flt tnear, tfar;
155 flt t, tdist, dt, ddt, sum, tt;
156 vector pnt, bln;
157 flt scalar, transval;
158 int i;
159 point_light * li;
160 color diffint;
161 vector N, L;
162 flt inten;
163
164 col.r = 0.0;
165 col.g = 0.0;
166 col.b = 0.0;
167
168 bx = (box *) tex->obj;
169 xvol = (extvol *) tex->obj;
170
171 tnear= -FHUGE;
172 tfar= FHUGE;
173
174 if (ry->d.x == 0.0) {
175 if ((ry->o.x < bx->min.x) || (ry->o.x > bx->max.x)) return col;
176 }
177 else {
178 tx1 = (bx->min.x - ry->o.x) / ry->d.x;
179 tx2 = (bx->max.x - ry->o.x) / ry->d.x;
180 if (tx1 > tx2) { a=tx1; tx1=tx2; tx2=a; }
181 if (tx1 > tnear) tnear=tx1;
182 if (tx2 < tfar) tfar=tx2;
183 }
184 if (tnear > tfar) return col;
185 if (tfar < 0.0) return col;
186
187 if (ry->d.y == 0.0) {
188 if ((ry->o.y < bx->min.y) || (ry->o.y > bx->max.y)) return col;
189 }
190 else {
191 ty1 = (bx->min.y - ry->o.y) / ry->d.y;
192 ty2 = (bx->max.y - ry->o.y) / ry->d.y;
193 if (ty1 > ty2) { a=ty1; ty1=ty2; ty2=a; }
194 if (ty1 > tnear) tnear=ty1;
195 if (ty2 < tfar) tfar=ty2;
196 }
197 if (tnear > tfar) return col;
198 if (tfar < 0.0) return col;
199
200 if (ry->d.z == 0.0) {
201 if ((ry->o.z < bx->min.z) || (ry->o.z > bx->max.z)) return col;
202 }
203 else {
204 tz1 = (bx->min.z - ry->o.z) / ry->d.z;
205 tz2 = (bx->max.z - ry->o.z) / ry->d.z;
206 if (tz1 > tz2) { a=tz1; tz1=tz2; tz2=a; }
207 if (tz1 > tnear) tnear=tz1;
208 if (tz2 < tfar) tfar=tz2;
209 }
210 if (tnear > tfar) return col;
211 if (tfar < 0.0) return col;
212
213 if (tnear < 0.0) tnear=0.0;
214
215 tdist = xvol->samples;
216
217 tt = (xvol->opacity / tdist);
218
219 bln.x=fabs(bx->min.x - bx->max.x);
220 bln.y=fabs(bx->min.y - bx->max.y);
221 bln.z=fabs(bx->min.z - bx->max.z);
222
223 dt = 1.0 / tdist;
224 sum = 0.0;
225
226 /* Accumulate color as the ray passes through the voxels */
227 for (t=tnear; t<=tfar; t+=dt) {
228 if (sum < 1.0) {
229 pnt.x=((ry->o.x + (ry->d.x * t)) - bx->min.x) / bln.x;
230 pnt.y=((ry->o.y + (ry->d.y * t)) - bx->min.y) / bln.y;
231 pnt.z=((ry->o.z + (ry->d.z * t)) - bx->min.z) / bln.z;
232
233 /* call external evaluator assume 0.0 -> 1.0 range.. */
234 scalar = xvol->evaluator(pnt.x, pnt.y, pnt.z);
235
236 transval = tt * scalar;
237 sum += transval;
238
239 col2 = ExtVoxelColor(scalar);
240
241 col.r += transval * col2.r * xvol->ambient;
242 col.g += transval * col2.g * xvol->ambient;
243 col.b += transval * col2.b * xvol->ambient;
244
245 ddt = dt;
246
247 /* Add in diffuse shaded light sources (no shadows) */
248 if (xvol->diffuse > 0.0) {
249
250 /* Calculate the Volume gradient at the voxel */
251 N.x = (xvol->evaluator(pnt.x - ddt, pnt.y, pnt.z) -
252 xvol->evaluator(pnt.x + ddt, pnt.y, pnt.z)) * 8.0 * tt;
253
254 N.y = (xvol->evaluator(pnt.x, pnt.y - ddt, pnt.z) -
255 xvol->evaluator(pnt.x, pnt.y + ddt, pnt.z)) * 8.0 * tt;
256
257 N.z = (xvol->evaluator(pnt.x, pnt.y, pnt.z - ddt) -
258 xvol->evaluator(pnt.x, pnt.y, pnt.z + ddt)) * 8.0 * tt;
259
260 /* only light surfaces with enough of a normal.. */
261 if ((N.x*N.x + N.y*N.y + N.z*N.z) > 0.0) {
262 diffint.r = 0.0;
263 diffint.g = 0.0;
264 diffint.b = 0.0;
265
266 /* add the contribution of each of the lights.. */
267 for (i=0; i<numlights; i++) {
268 li=lightlist[i];
269 VSUB(li->ctr, (*hit), L)
270 VNorm(&L);
271 VDOT(inten, N, L)
272
273 /* only add light if its from the front of the surface */
274 /* could add back-lighting if we wanted to later.. */
275 if (inten > 0.0) {
276 diffint.r += inten*li->tex->col.r;
277 diffint.g += inten*li->tex->col.g;
278 diffint.b += inten*li->tex->col.b;
279 }
280 }
281 col.r += col2.r * diffint.r * xvol->diffuse;
282 col.g += col2.g * diffint.g * xvol->diffuse;
283 col.b += col2.b * diffint.b * xvol->diffuse;
284 }
285 }
286 }
287 else {
288 sum=1.0;
289 }
290 }
291
292 /* Add in transmitted ray from outside environment */
293 if (sum < 1.0) { /* spawn transmission rays / refraction */
294 color transcol;
295
296 transcol = shade_transmission(ry, hit, 1.0 - sum);
297
298 col.r += transcol.r; /* add the transmitted ray */
299 col.g += transcol.g; /* to the diffuse and */
300 col.b += transcol.b; /* transmission total.. */
301 }
302
303 return col;
304 }
305
306
307
308