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