1 /*
2  * texture.c - This file contains functions for implementing textures.
3  *
4  *  $Id: texture.c,v 1.31 2007/02/07 04:59:44 johns Exp $
5  */
6 
7 #include "machine.h"
8 #include "types.h"
9 #include "macros.h"
10 #include "texture.h"
11 #include "coordsys.h"
12 #include "imap.h"
13 #include "vector.h"
14 #include "box.h"
15 #include "util.h"
16 
17 static texture_methods normal_methods = {
18   free
19 };
20 
21 static texture_methods standard_methods = {
22   free_standard_texture
23 };
24 
25 static texture_methods vcstri_methods = {
26   free
27 };
28 
new_texture(void)29 texture * new_texture(void) {
30   texture * tex;
31   tex = (texture *) malloc(sizeof(texture));
32   tex->methods = &normal_methods;
33   return tex;
34 }
35 
new_standard_texture(void)36 texture * new_standard_texture(void) {
37   standard_texture * tex;
38   tex = (standard_texture *) malloc(sizeof(standard_texture));
39   tex->methods = &standard_methods;
40   return (texture *) tex;
41 }
42 
new_vcstri_texture(void)43 texture * new_vcstri_texture(void) {
44   vcstri_texture * tex;
45   tex = (vcstri_texture *) malloc(sizeof(vcstri_texture));
46   tex->methods = &vcstri_methods;
47   return (texture *) tex;
48 }
49 
free_standard_texture(void * voidtex)50 void free_standard_texture(void * voidtex) {
51   standard_texture * tex = (standard_texture *) voidtex;
52   if (tex->img != NULL) {
53     if ((tex->texfunc == (color (*)(const void *, const void *, void *)) image_plane_texture) ||
54         (tex->texfunc == (color (*)(const void *, const void *, void *)) image_cyl_texture) ||
55         (tex->texfunc == (color (*)(const void *, const void *, void *)) image_sphere_texture) ||
56         (tex->texfunc == (color (*)(const void *, const void *, void *)) image_volume_texture)) {
57       FreeMIPMap(tex->img);
58       tex->img = NULL;
59     } else {
60 printf("XXX Doh, unrecognized image map type!\n");
61     }
62   }
63   free(tex);
64 }
65 
66 
67 /* standard solid background texture */
solid_background_texture(const ray * ry)68 color solid_background_texture(const ray *ry) {
69   return ry->scene->bgtex.background;
70 }
71 
72 /* sky sphere background texture, linear mapping */
sky_sphere_background_texture(const ray * ry)73 color sky_sphere_background_texture(const ray *ry) {
74   color col;
75   flt IdotG = VDot(&ry->d, &ry->scene->bgtex.gradient);
76   flt range = ry->scene->bgtex.gradtopval - ry->scene->bgtex.gradbotval;
77 
78   flt val = (IdotG - ry->scene->bgtex.gradbotval) / range;
79 
80   if (val < 0.0)
81     val = 0.0;
82 
83   if (val > 1.0)
84     val = 1.0;
85 
86   col.r = val * ry->scene->bgtex.backgroundtop.r +
87           (1.0 - val) * ry->scene->bgtex.backgroundbot.r;
88   col.g = val * ry->scene->bgtex.backgroundtop.g +
89           (1.0 - val) * ry->scene->bgtex.backgroundbot.g;
90   col.b = val * ry->scene->bgtex.backgroundtop.b +
91           (1.0 - val) * ry->scene->bgtex.backgroundbot.b;
92 
93   return col;
94 }
95 
96 
97 /* plain vanilla texture solely based on object color */
constant_texture(const vector * hit,const texture * tx,const ray * ry)98 color constant_texture(const vector * hit, const texture * tx, const ray * ry) {
99   standard_texture * tex = (standard_texture *) tx;
100   return tex->col;
101 }
102 
103 /* cylindrical image map */
image_cyl_texture(const vector * hit,const texture * tx,const ray * ry)104 color image_cyl_texture(const vector * hit, const texture * tx, const ray * ry) {
105   vector rh;
106   flt u, v, miprad, maxscale, cyrad;
107   standard_texture * tex = (standard_texture *) tx;
108 
109   rh.x=hit->x - tex->ctr.x;
110   rh.z=hit->y - tex->ctr.y;
111   rh.y=hit->z - tex->ctr.z;
112 
113   xyztocyl(rh, 1.0, &u, &v);
114 
115   u = u * tex->scale.x;
116   u = u + tex->rot.x;
117   u = u - ((int) u);
118   if (u < 0.0) u+=1.0;
119 
120   v = v * tex->scale.y;
121   v = v + tex->rot.y;
122   v = v - ((int) v);
123   if (v < 0.0) v+=1.0;
124 
125   cyrad = EPSILON + 8.0 * sqrt(rh.x*rh.x + rh.y*rh.y + rh.z*rh.z);
126 
127   maxscale = (fabs(tex->scale.x) > fabs(tex->scale.y)) ?
128              tex->scale.x : tex->scale.y;
129 
130   miprad = (0.05 * ry->opticdist * fabs(maxscale)) / cyrad;
131 
132   return MIPMap(tex->img, u, v, miprad);
133 }
134 
135 /* spherical image map */
image_sphere_texture(const vector * hit,const texture * tx,const ray * ry)136 color image_sphere_texture(const vector * hit, const texture * tx, const ray * ry) {
137   vector rh;
138   flt u, v, miprad, maxscale, sprad;
139   standard_texture * tex = (standard_texture *) tx;
140 
141   rh.x=hit->x - tex->ctr.x;
142   rh.y=hit->y - tex->ctr.y;
143   rh.z=hit->z - tex->ctr.z;
144 
145   xyztospr(rh, &u, &v);
146 
147   u = u * tex->scale.x;
148   u = u + tex->rot.x;
149   u = u - ((int) u);
150   if (u < 0.0) u+=1.0;
151 
152   v = v * tex->scale.y;
153   v = v + tex->rot.y;
154   v = v - ((int) v);
155   if (v < 0.0) v+=1.0;
156 
157   sprad = EPSILON + 8.0 * sqrt(rh.x*rh.x + rh.y*rh.y + rh.z*rh.z);
158 
159   maxscale = (fabs(tex->scale.x) > fabs(tex->scale.y)) ?
160              tex->scale.x : tex->scale.y;
161 
162   miprad = (0.05 * ry->opticdist * fabs(maxscale)) / sprad;
163 
164   return MIPMap(tex->img, u, v, miprad);
165 }
166 
167 /* planar image map */
image_plane_texture(const vector * hit,const texture * tx,const ray * ry)168 color image_plane_texture(const vector * hit, const texture * tx, const ray * ry) {
169   vector pnt;
170   flt u, v, miprad, maxscale;
171   standard_texture * tex = (standard_texture *) tx;
172 
173   pnt.x=hit->x - tex->ctr.x;
174   pnt.y=hit->y - tex->ctr.y;
175   pnt.z=hit->z - tex->ctr.z;
176 
177   VDOT(u, tex->uaxs, pnt);
178   VDOT(v, tex->vaxs, pnt);
179 
180   u = u * tex->scale.x;
181   u = u + tex->rot.x;
182   u = u - ((int) u);
183   if (u < 0.0) u += 1.0;
184 
185   v = v * tex->scale.y;
186   v = v + tex->rot.y;
187   v = v - ((int) v);
188   if (v < 0.0) v += 1.0;
189 
190 
191   maxscale = (fabs(tex->scale.x) > fabs(tex->scale.y)) ?
192              tex->scale.x : tex->scale.y;
193 
194   miprad = 0.05 * ry->opticdist * fabs(maxscale);
195 
196   return MIPMap(tex->img, u, v, miprad);
197 }
198 
199 
200 /* volumetric texture map (applied to surface geometry etc) */
image_volume_texture(const vector * hit,const texture * tx,const ray * ry)201 color image_volume_texture(const vector * hit, const texture * tx, const ray * ry) {
202   vector pnt;
203   flt u, v, w, miprad, maxscale;
204   standard_texture * tex = (standard_texture *) tx;
205 
206   pnt.x=hit->x - tex->ctr.x;
207   pnt.y=hit->y - tex->ctr.y;
208   pnt.z=hit->z - tex->ctr.z;
209 
210   VDOT(u, tex->uaxs, pnt);
211   VDOT(v, tex->vaxs, pnt);
212   VDOT(w, tex->waxs, pnt);
213 
214   u = u * tex->scale.x;
215   u = u + tex->rot.x;
216   u = u - ((int) u);
217   if (u < 0.0) u += 1.0;
218 
219   v = v * tex->scale.y;
220   v = v + tex->rot.y;
221   v = v - ((int) v);
222   if (v < 0.0) v += 1.0;
223 
224   w = w * tex->scale.z;
225   w = w + tex->rot.z;
226   w = w - ((int) w);
227   if (w < 0.0) w += 1.0;
228 
229   maxscale = (fabs(tex->scale.x) > fabs(tex->scale.y)) ?
230              tex->scale.x : tex->scale.y;
231   if (fabs(tex->scale.z) > fabs(maxscale))
232     maxscale = tex->scale.z;
233 
234   miprad = 0.05 * ry->opticdist * fabs(maxscale);
235 
236   return VolMIPMap(tex->img, u, v, w, miprad);
237 }
238 
239 
grit_texture(const vector * hit,const texture * tx,const ray * ry)240 color grit_texture(const vector * hit, const texture * tx, const ray * ry) {
241   int rnum;
242   flt fnum;
243   color col;
244   standard_texture * tex = (standard_texture *) tx;
245 
246   rnum=rand() % 4096;
247   fnum=(rnum / 4096.0 * 0.2) + 0.8;
248 
249   col.r=tex->col.r * fnum;
250   col.g=tex->col.g * fnum;
251   col.b=tex->col.b * fnum;
252 
253   return col;
254 }
255 
checker_texture(const vector * hit,const texture * tx,const ray * ry)256 color checker_texture(const vector * hit, const texture * tx, const ray * ry) {
257   long x,y,z;
258   flt xh,yh,zh;
259   color col;
260   standard_texture * tex = (standard_texture *) tx;
261 
262   xh=hit->x - tex->ctr.x;
263   x=(long) ((fabs(xh) * 3) + 0.5);
264   x=x % 2;
265   yh=hit->y - tex->ctr.y;
266   y=(long) ((fabs(yh) * 3) + 0.5);
267   y=y % 2;
268   zh=hit->z - tex->ctr.z;
269   z=(long) ((fabs(zh) * 3) + 0.5);
270   z=z % 2;
271 
272   if (((x + y + z) % 2)==1) {
273     col.r=1.0;
274     col.g=0.2;
275     col.b=0.0;
276   }
277   else {
278     col.r=0.0;
279     col.g=0.2;
280     col.b=1.0;
281   }
282 
283   return col;
284 }
285 
cyl_checker_texture(const vector * hit,const texture * tx,const ray * ry)286 color cyl_checker_texture(const vector * hit, const texture * tx, const ray * ry) {
287   long x,y;
288   vector rh;
289   flt u,v;
290   color col;
291   standard_texture * tex = (standard_texture *) tx;
292 
293   rh.x=hit->x - tex->ctr.x;
294   rh.y=hit->y - tex->ctr.y;
295   rh.z=hit->z - tex->ctr.z;
296 
297   xyztocyl(rh, 1.0, &u, &v);
298 
299   x=(long) (fabs(u) * 18.0);
300   x=x % 2;
301   y=(long) (fabs(v) * 10.0);
302   y=y % 2;
303 
304   if (((x + y) % 2)==1) {
305     col.r=1.0;
306     col.g=0.2;
307     col.b=0.0;
308   }
309   else {
310     col.r=0.0;
311     col.g=0.2;
312     col.b=1.0;
313   }
314 
315   return col;
316 }
317 
318 
wood_texture(const vector * hit,const texture * tx,const ray * ry)319 color wood_texture(const vector * hit, const texture * tx, const ray * ry) {
320   flt radius, angle;
321   int grain;
322   color col;
323   flt x,y,z;
324   standard_texture * tex = (standard_texture *) tx;
325 
326   x=(hit->x - tex->ctr.x) / tex->scale.x;
327   y=(hit->y - tex->ctr.y) / tex->scale.y;
328   z=(hit->z - tex->ctr.z) / tex->scale.z;
329 
330   radius=sqrt(x*x + z*z);
331   if (z == 0.0)
332     angle=3.1415926/2.0;
333   else
334     angle=atan(x / z);
335 
336   radius=radius + 3.0 * sin(20 * angle + y / 150.0);
337   grain=((int) (radius + 0.5)) % 60;
338   if (grain < 40) {
339     col.r=0.8;
340     col.g=1.0;
341     col.b=0.2;
342   }
343   else {
344     col.r=0.0;
345     col.g=0.0;
346     col.b=0.0;
347   }
348 
349   return col;
350 }
351 
352 
353 
354 #define NMAX 28
355 short int NoiseMatrix[NMAX][NMAX][NMAX];
356 
InitNoise(void)357 void InitNoise(void) {
358   byte x,y,z,i,j,k;
359   unsigned int rndval = 1234567; /* pathetic random number seed */
360 
361   for (x=0; x<NMAX; x++) {
362     for (y=0; y<NMAX; y++) {
363       for (z=0; z<NMAX; z++) {
364         NoiseMatrix[x][y][z]=(short int) ((rt_rand(&rndval) / RT_RAND_MAX) * 12000.0);
365 
366         if (x==NMAX-1) i=0;
367         else i=x;
368 
369         if (y==NMAX-1) j=0;
370         else j=y;
371 
372         if (z==NMAX-1) k=0;
373         else k=z;
374 
375         NoiseMatrix[x][y][z]=NoiseMatrix[i][j][k];
376       }
377     }
378   }
379 }
380 
Noise(flt x,flt y,flt z)381 int Noise(flt x, flt y, flt z) {
382   byte ix, iy, iz;
383   flt ox, oy, oz;
384   int p000, p001, p010, p011;
385   int p100, p101, p110, p111;
386   int p00, p01, p10, p11;
387   int p0, p1;
388   int d00, d01, d10, d11;
389   int d0, d1, d;
390 
391   x=fabs(x);
392   y=fabs(y);
393   z=fabs(z);
394 
395   ix=((int) x) % NMAX;
396   iy=((int) y) % NMAX;
397   iz=((int) z) % NMAX;
398 
399   ox=(x - ((int) x));
400   oy=(y - ((int) y));
401   oz=(z - ((int) z));
402 
403   p000=NoiseMatrix[ix][iy][iz];
404   p001=NoiseMatrix[ix][iy][iz+1];
405   p010=NoiseMatrix[ix][iy+1][iz];
406   p011=NoiseMatrix[ix][iy+1][iz+1];
407   p100=NoiseMatrix[ix+1][iy][iz];
408   p101=NoiseMatrix[ix+1][iy][iz+1];
409   p110=NoiseMatrix[ix+1][iy+1][iz];
410   p111=NoiseMatrix[ix+1][iy+1][iz+1];
411 
412   d00=p100-p000;
413   d01=p101-p001;
414   d10=p110-p010;
415   d11=p111-p011;
416 
417   p00=(int) ((int) d00*ox) + p000;
418   p01=(int) ((int) d01*ox) + p001;
419   p10=(int) ((int) d10*ox) + p010;
420   p11=(int) ((int) d11*ox) + p011;
421   d0=p10-p00;
422   d1=p11-p01;
423   p0=(int) ((int) d0*oy) + p00;
424   p1=(int) ((int) d1*oy) + p01;
425   d=p1-p0;
426 
427   return (int) ((int) d*oz) + p0;
428 }
429 
marble_texture(const vector * hit,const texture * tx,const ray * ry)430 color marble_texture(const vector * hit, const texture * tx, const ray * ry) {
431   flt i,d;
432   flt x,y,z;
433   color col;
434 /*
435   standard_texture * tex = (standard_texture *) tx;
436 */
437 
438   x=hit->x;
439   y=hit->y;
440   z=hit->z;
441 
442   x=x * 1.0;
443 
444   d=x + 0.0006 * Noise(x, (y * 1.0), (z * 1.0));
445   d=d*(((int) d) % 25);
446   i=0.0 + 0.10 * fabs(d - 10.0 - 20.0 * ((int) d * 0.05));
447   if (i > 1.0) i=1.0;
448   if (i < 0.0) i=0.0;
449 
450 /*
451   col.r=i * tex->col.r;
452   col.g=i * tex->col.g;
453   col.b=i * tex->col.b;
454 */
455 
456   col.r = (1.0 + sin(i * 6.28)) / 2.0;
457   col.g = (1.0 + sin(i * 16.28)) / 2.0;
458   col.b = (1.0 + cos(i * 30.28)) / 2.0;
459 
460   return col;
461 }
462 
463 
gnoise_texture(const vector * hit,const texture * tx,const ray * ry)464 color gnoise_texture(const vector * hit, const texture * tx, const ray * ry) {
465   color col;
466   flt f;
467   standard_texture * tex = (standard_texture *) tx;
468 
469   f=Noise((hit->x - tex->ctr.x),
470           (hit->y - tex->ctr.y),
471 	  (hit->z - tex->ctr.z));
472 
473   if (f < 0.01) f=0.01;
474   if (f > 1.0) f=1.0;
475 
476   col.r=tex->col.r * f;
477   col.g=tex->col.g * f;
478   col.b=tex->col.b * f;
479 
480   return col;
481 }
482 
InitTextures(void)483 void InitTextures(void) {
484   InitNoise();
485   ResetImages();
486 }
487 
FreeTextures(void)488 void FreeTextures(void) {
489   FreeImages();
490 }
491 
492