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