1 /*
2 * api.c - This file contains all of the API calls that are defined for
3 * external driver code to use.
4 *
5 * $Id: api.c,v 1.164 2009/05/18 03:31:48 johns Exp $
6 */
7
8 #include "machine.h"
9 #include "types.h"
10 #include "macros.h"
11
12 #include "parallel.h"
13 #include "threads.h"
14
15 #include "box.h"
16 #include "cylinder.h"
17 #include "plane.h"
18 #include "quadric.h"
19 #include "ring.h"
20 #include "sphere.h"
21 #include "triangle.h"
22 #include "vol.h"
23 #include "extvol.h"
24
25 #include "texture.h"
26 #include "light.h"
27 #include "render.h"
28 #include "trace.h"
29 #include "camera.h"
30 #include "vector.h"
31 #include "intersect.h"
32 #include "shade.h"
33 #include "util.h"
34 #include "imap.h"
35 #include "global.h"
36 #include "ui.h"
37 #include "shade.h"
38
39 typedef void * SceneHandle;
40 typedef vector apivector;
41 typedef color apicolor;
42
43 typedef struct {
44 int texturefunc; /* which texture function to use */
45 apicolor col; /* base object color */
46 int shadowcast; /* does the object cast a shadow */
47 apiflt ambient; /* ambient lighting */
48 apiflt diffuse; /* diffuse reflection */
49 apiflt specular; /* specular reflection */
50 apiflt opacity; /* how opaque the object is */
51 apivector ctr; /* origin of texture */
52 apivector rot; /* rotation of texture around origin */
53 apivector scale; /* scale of texture on x,y,z */
54 apivector uaxs; /* planar map U axis */
55 apivector vaxs; /* planar map V axis */
56 apivector waxs; /* volume map W axis */
57 char imap[96]; /* name of image map*/
58 } apitexture;
59
rt_vector(apiflt x,apiflt y,apiflt z)60 apivector rt_vector(apiflt x, apiflt y, apiflt z) {
61 apivector v;
62
63 v.x = x;
64 v.y = y;
65 v.z = z;
66
67 return v;
68 }
69
rt_color(apiflt r,apiflt g,apiflt b)70 apicolor rt_color(apiflt r, apiflt g, apiflt b) {
71 apicolor c;
72
73 c.r = r;
74 c.g = g;
75 c.b = b;
76
77 return c;
78 }
79
rt_initialize(int * argc,char *** argv)80 int rt_initialize(int * argc, char ***argv) {
81 InitTextures();
82
83 if (!parinitted) {
84 rt_par_init(argc, argv);
85 parinitted=1;
86 }
87
88 return rt_mynode(); /* return our node id */
89 }
90
rt_finalize(void)91 void rt_finalize(void) {
92 FreeTextures();
93 rt_par_finish();
94 }
95
rt_renderscene(SceneHandle voidscene)96 void rt_renderscene(SceneHandle voidscene) {
97 scenedef * scene = (scenedef *) voidscene;
98 renderscene(scene);
99 }
100
rt_normal_fixup_mode(SceneHandle voidscene,int mode)101 void rt_normal_fixup_mode(SceneHandle voidscene, int mode) {
102 scenedef * scene = (scenedef *) voidscene;
103 switch (mode) {
104 /* RT_NORMAL_FIXUP_MODE_GUESS */
105 case 2:
106 scene->normalfixupmode = 2; /* accept any normal/winding order combo */
107 /* and suffer the consequences, since this */
108 /* leaves an unhandled case where surface */
109 /* normals on poorly tessellated objects */
110 /* will cause black edges. */
111 break;
112
113 /* RT_NORMAL_FIXUP_MODE_FLIP */
114 case 1:
115 scene->normalfixupmode = 1; /* reverse the surface normal */
116 break;
117
118 /* RT_NORMAL_FIXUP_MODE_OFF */
119 case 0:
120 default:
121 scene->normalfixupmode = 0; /* use strict winding order rules */
122 break;
123 }
124 }
125
rt_aa_maxsamples(SceneHandle voidscene,int maxsamples)126 void rt_aa_maxsamples(SceneHandle voidscene, int maxsamples) {
127 scenedef * scene = (scenedef *) voidscene;
128
129 if (maxsamples >= 0)
130 scene->antialiasing=maxsamples;
131 else
132 scene->antialiasing=0;
133 }
134
rt_camera_setup(SceneHandle voidscene,apiflt zoom,apiflt aspectratio,int antialiasing,int raydepth,apivector camcent,apivector viewvec,apivector upvec)135 void rt_camera_setup(SceneHandle voidscene, apiflt zoom, apiflt aspectratio,
136 int antialiasing, int raydepth,
137 apivector camcent, apivector viewvec, apivector upvec) {
138 scenedef * scene = (scenedef *) voidscene;
139
140 camerasetup(scene, zoom, camcent, viewvec, upvec);
141
142 scene->aspectratio=aspectratio;
143
144 rt_aa_maxsamples(voidscene, antialiasing);
145
146 scene->raydepth=raydepth;
147 }
148
rt_camera_projection(SceneHandle voidscene,int mode)149 void rt_camera_projection(SceneHandle voidscene, int mode) {
150 scenedef * scene = (scenedef *) voidscene;
151 cameraprojection(&scene->camera, mode);
152 }
153
rt_camera_dof(SceneHandle voidscene,flt focallength,flt aperture)154 void rt_camera_dof(SceneHandle voidscene, flt focallength, flt aperture) {
155 scenedef * scene = (scenedef *) voidscene;
156 cameradof(&scene->camera, focallength, aperture);
157 }
158
rt_camera_position(SceneHandle voidscene,apivector camcent,apivector viewvec,apivector upvec)159 void rt_camera_position(SceneHandle voidscene, apivector camcent,
160 apivector viewvec, apivector upvec) {
161 scenedef * scene = (scenedef *) voidscene;
162 cameraposition(&scene->camera, camcent, viewvec, upvec);
163 }
164
rt_get_camera_position(SceneHandle voidscene,apivector * camcent,apivector * viewvec,apivector * upvec,apivector * rightvec)165 void rt_get_camera_position(SceneHandle voidscene, apivector * camcent,
166 apivector * viewvec, apivector * upvec, apivector * rightvec) {
167 scenedef * scene = (scenedef *) voidscene;
168
169 getcameraposition(&scene->camera, camcent, viewvec, upvec, rightvec);
170 }
171
rt_camera_frustum(SceneHandle voidscene,flt left,flt right,flt bottom,flt top)172 void rt_camera_frustum(SceneHandle voidscene, flt left, flt right, flt bottom, flt top) {
173 scenedef * scene = (scenedef *) voidscene;
174 camerafrustum(&scene->camera, left, right, bottom, top);
175 }
176
rt_outputfile(SceneHandle voidscene,const char * outname)177 void rt_outputfile(SceneHandle voidscene, const char * outname) {
178 scenedef * scene = (scenedef *) voidscene;
179 if (strlen(outname) > 0) {
180 strcpy((char *) &scene->outfilename, outname);
181 scene->writeimagefile = 1;
182 }
183 else {
184 scene->writeimagefile = 0;
185 }
186 }
187
rt_outputformat(SceneHandle voidscene,int format)188 void rt_outputformat(SceneHandle voidscene, int format) {
189 scenedef * scene = (scenedef *) voidscene;
190 scene->imgfileformat = format;
191 }
192
rt_resolution(SceneHandle voidscene,int hres,int vres)193 void rt_resolution(SceneHandle voidscene, int hres, int vres) {
194 scenedef * scene = (scenedef *) voidscene;
195 scene->hres=hres;
196 scene->vres=vres;
197 scene->scenecheck = 1;
198 }
199
rt_get_resolution(SceneHandle voidscene,int * hres,int * vres)200 void rt_get_resolution(SceneHandle voidscene, int *hres, int *vres) {
201 scenedef * scene = (scenedef *) voidscene;
202 *hres = scene->hres;
203 *vres = scene->vres;
204 }
205
rt_crop_disable(SceneHandle voidscene)206 void rt_crop_disable(SceneHandle voidscene) {
207 scenedef * scene = (scenedef *) voidscene;
208 scene->imgcrop.cropmode = RT_CROP_DISABLED;
209 scene->imgcrop.xres = 0;
210 scene->imgcrop.yres = 0;
211 scene->imgcrop.xstart = 0;
212 scene->imgcrop.ystart = 0;
213 }
214
rt_crop_output(SceneHandle voidscene,int hres,int vres,int sx,int sy)215 void rt_crop_output(SceneHandle voidscene, int hres, int vres, int sx, int sy) {
216 scenedef * scene = (scenedef *) voidscene;
217 scene->imgcrop.cropmode = RT_CROP_ENABLED;
218 scene->imgcrop.xres = hres;
219 scene->imgcrop.yres = vres;
220 scene->imgcrop.xstart = sx;
221 scene->imgcrop.ystart = sy;
222 }
223
rt_verbose(SceneHandle voidscene,int v)224 void rt_verbose(SceneHandle voidscene, int v) {
225 scenedef * scene = (scenedef *) voidscene;
226 scene->verbosemode = v;
227 }
228
rt_rawimage_rgb24(SceneHandle voidscene,unsigned char * img)229 void rt_rawimage_rgb24(SceneHandle voidscene, unsigned char *img) {
230 scenedef * scene = (scenedef *) voidscene;
231 scene->img = (void *) img;
232 scene->imginternal = 0; /* image was allocated by the caller */
233 scene->imgbufformat = RT_IMAGE_BUFFER_RGB24;
234 scene->scenecheck = 1;
235 }
236
237
rt_rawimage_rgb96f(SceneHandle voidscene,float * img)238 void rt_rawimage_rgb96f(SceneHandle voidscene, float *img) {
239 scenedef * scene = (scenedef *) voidscene;
240 scene->img = (void *) img;
241 scene->imginternal = 0; /* image was allocated by the caller */
242 scene->imgbufformat = RT_IMAGE_BUFFER_RGB96F;
243 scene->scenecheck = 1;
244 }
245
246
rt_image_clamp(SceneHandle voidscene)247 void rt_image_clamp(SceneHandle voidscene) {
248 scenedef * scene = (scenedef *) voidscene;
249 scene->imgprocess = RT_IMAGE_CLAMP;
250 }
251
252
rt_image_normalize(SceneHandle voidscene)253 void rt_image_normalize(SceneHandle voidscene) {
254 scenedef * scene = (scenedef *) voidscene;
255 scene->imgprocess = RT_IMAGE_NORMALIZE;
256 }
257
258
rt_image_gamma(SceneHandle voidscene,float gamma)259 void rt_image_gamma(SceneHandle voidscene, float gamma) {
260 scenedef * scene = (scenedef *) voidscene;
261 scene->imggamma = gamma;
262 scene->imgprocess = RT_IMAGE_NORMALIZE | RT_IMAGE_GAMMA;
263 }
264
265
rt_set_numthreads(SceneHandle voidscene,int numthreads)266 void rt_set_numthreads(SceneHandle voidscene, int numthreads) {
267 scenedef * scene = (scenedef *) voidscene;
268 #ifdef THR
269 if (numthreads > 0) {
270 scene->numthreads = numthreads;
271 }
272 else {
273 scene->numthreads = rt_thread_numprocessors();
274 }
275
276 /* force set of # kernel threads */
277 rt_thread_setconcurrency(scene->numthreads);
278
279 #else
280 scene->numthreads = 1;
281 #endif
282 scene->scenecheck = 1;
283 }
284
rt_background(SceneHandle voidscene,apicolor col)285 void rt_background(SceneHandle voidscene, apicolor col) {
286 scenedef * scene = (scenedef *) voidscene;
287 scene->bgtex.background.r = col.r;
288 scene->bgtex.background.g = col.g;
289 scene->bgtex.background.b = col.b;
290 }
291
rt_background_sky_sphere(SceneHandle voidscene,apivector up,apiflt topval,apiflt botval,apicolor topcol,apicolor botcol)292 void rt_background_sky_sphere(SceneHandle voidscene,
293 apivector up,
294 apiflt topval, apiflt botval, apicolor topcol, apicolor botcol) {
295 scenedef * scene = (scenedef *) voidscene;
296
297 scene->bgtex.gradient = up;
298
299 scene->bgtex.gradtopval = topval;
300 scene->bgtex.gradbotval = botval;
301
302 scene->bgtex.backgroundtop.r = topcol.r;
303 scene->bgtex.backgroundtop.g = topcol.g;
304 scene->bgtex.backgroundtop.b = topcol.b;
305
306 scene->bgtex.backgroundbot.r = botcol.r;
307 scene->bgtex.backgroundbot.g = botcol.g;
308 scene->bgtex.backgroundbot.b = botcol.b;
309 }
310
rt_background_mode(SceneHandle voidscene,int mode)311 void rt_background_mode(SceneHandle voidscene, int mode) {
312 scenedef * scene = (scenedef *) voidscene;
313 switch (mode) {
314 case RT_BACKGROUND_TEXTURE_SKY_SPHERE:
315 scene->bgtexfunc=sky_sphere_background_texture;
316 break;
317
318 case RT_BACKGROUND_TEXTURE_SOLID:
319 default:
320 scene->bgtexfunc=solid_background_texture;
321 break;
322 }
323 }
324
325
rt_ambient_occlusion(SceneHandle voidscene,int numsamples,apicolor col)326 void rt_ambient_occlusion(SceneHandle voidscene, int numsamples, apicolor col) {
327 scenedef * scene = (scenedef *) voidscene;
328 scene->ambocc.numsamples = numsamples;
329 scene->ambocc.col.r = col.r;
330 scene->ambocc.col.g = col.g;
331 scene->ambocc.col.b = col.b;
332 }
333
rt_fog_parms(SceneHandle voidscene,apicolor col,apiflt start,apiflt end,apiflt density)334 void rt_fog_parms(SceneHandle voidscene, apicolor col, apiflt start, apiflt end, apiflt density) {
335 scenedef * scene = (scenedef *) voidscene;
336 scene->fog.col = col;
337 scene->fog.start = start;
338 scene->fog.end = end;
339 scene->fog.density = density;
340 }
341
rt_fog_rendering_mode(SceneHandle voidscene,int mode)342 void rt_fog_rendering_mode(SceneHandle voidscene, int mode) {
343 scenedef * scene = (scenedef *) voidscene;
344 switch (mode) {
345 case RT_FOG_VMD:
346 scene->fog.type = RT_FOG_VMD;
347 break;
348
349 case RT_FOG_NORMAL:
350 default:
351 scene->fog.type = RT_FOG_NORMAL;
352 break;
353 }
354 }
355
rt_fog_mode(SceneHandle voidscene,int mode)356 void rt_fog_mode(SceneHandle voidscene, int mode) {
357 scenedef * scene = (scenedef *) voidscene;
358
359 switch (mode) {
360 case RT_FOG_LINEAR:
361 scene->fog.fog_fctn = fog_color_linear;
362 break;
363
364 case RT_FOG_EXP:
365 scene->fog.fog_fctn = fog_color_exp;
366 break;
367
368 case RT_FOG_EXP2:
369 scene->fog.fog_fctn = fog_color_exp2;
370 break;
371
372 case RT_FOG_NONE:
373 default:
374 scene->fog.fog_fctn = NULL;
375 break;
376 }
377 }
378
rt_trans_mode(SceneHandle voidscene,int mode)379 void rt_trans_mode(SceneHandle voidscene, int mode) {
380 scenedef * scene = (scenedef *) voidscene;
381 scene->transmode = mode;
382 }
383
rt_boundmode(SceneHandle voidscene,int mode)384 void rt_boundmode(SceneHandle voidscene, int mode) {
385 scenedef * scene = (scenedef *) voidscene;
386 scene->boundmode = mode;
387 scene->scenecheck = 1;
388 }
389
rt_boundthresh(SceneHandle voidscene,int threshold)390 void rt_boundthresh(SceneHandle voidscene, int threshold) {
391 scenedef * scene = (scenedef *) voidscene;
392
393 if (threshold > 1) {
394 scene->boundthresh = threshold;
395 }
396 else {
397 if (rt_mynode() == 0) {
398 rt_ui_message(MSG_0, "Out-of-range automatic bounding threshold.\n");
399 rt_ui_message(MSG_0, "Automatic bounding threshold reset to default.\n");
400 }
401 scene->boundthresh = BOUNDTHRESH;
402 }
403 scene->scenecheck = 1;
404 }
405
rt_shadermode(SceneHandle voidscene,int mode)406 void rt_shadermode(SceneHandle voidscene, int mode) {
407 scenedef * scene = (scenedef *) voidscene;
408
409 /* Main shader used for whole scene */
410 switch (mode) {
411 case RT_SHADER_LOWEST:
412 scene->shader = (color (*)(void *)) lowest_shader;
413 break;
414 case RT_SHADER_LOW:
415 scene->shader = (color (*)(void *)) low_shader;
416 break;
417 case RT_SHADER_MEDIUM:
418 scene->shader = (color (*)(void *)) medium_shader;
419 break;
420 case RT_SHADER_HIGH:
421 scene->shader = (color (*)(void *)) full_shader;
422 break;
423 case RT_SHADER_FULL:
424 scene->shader = (color (*)(void *)) full_shader;
425 break;
426 case RT_SHADER_AUTO:
427 default:
428 scene->shader = NULL;
429 break;
430 }
431 }
432
rt_rescale_lights(SceneHandle voidscene,apiflt lightscale)433 void rt_rescale_lights(SceneHandle voidscene, apiflt lightscale) {
434 scenedef * scene = (scenedef *) voidscene;
435 scene->light_scale = lightscale;
436 }
437
rt_phong_shader(SceneHandle voidscene,int mode)438 void rt_phong_shader(SceneHandle voidscene, int mode) {
439 scenedef * scene = (scenedef *) voidscene;
440 switch (mode) {
441 case RT_SHADER_NULL_PHONG:
442 scene->phongfunc = shade_nullphong;
443 break;
444 case RT_SHADER_BLINN_FAST:
445 scene->phongfunc = shade_blinn_fast;
446 break;
447 case RT_SHADER_BLINN:
448 scene->phongfunc = shade_blinn;
449 break;
450 default:
451 case RT_SHADER_PHONG:
452 scene->phongfunc = shade_phong;
453 break;
454 }
455 }
456
457 /* allocate and initialize a scene with default parameters */
rt_newscene(void)458 SceneHandle rt_newscene(void) {
459 scenedef * scene;
460 SceneHandle voidscene;
461 apicolor bgcolor = rt_color(0.0, 0.0, 0.0);
462 apicolor ambcolor = rt_color(1.0, 1.0, 1.0);
463
464 scene = (scenedef *) malloc(sizeof(scenedef));
465 memset(scene, 0, sizeof(scenedef)); /* clear all valuas to 0 */
466
467 voidscene = (SceneHandle) scene;
468
469 rt_outputfile(voidscene, "/tmp/outfile.tga"); /* default output file */
470 rt_crop_disable(voidscene); /* disable cropping */
471 rt_outputformat(voidscene, RT_FORMAT_TARGA); /* default iamge format */
472 rt_resolution(voidscene, 512, 512); /* 512x512 resolution */
473 rt_verbose(voidscene, 0); /* verbose messages off */
474
475 rt_image_gamma(voidscene, 2.2); /* set default gamma */
476 rt_image_clamp(voidscene); /* clamp image colors */
477
478 #if 1
479 rt_rawimage_rgb96f(voidscene, NULL); /* raw image output off */
480 #else
481 rt_rawimage_rgb24(voidscene, NULL); /* raw image output off */
482 #endif
483
484 rt_boundmode(voidscene, RT_BOUNDING_ENABLED); /* spatial subdivision on */
485 rt_boundthresh(voidscene, BOUNDTHRESH); /* default threshold */
486 rt_camera_setup(voidscene, 1.0, 1.0, 0, 6,
487 rt_vector(0.0, 0.0, 0.0),
488 rt_vector(0.0, 0.0, 1.0),
489 rt_vector(0.0, 1.0, 0.0));
490 rt_camera_dof(voidscene, 1.0, 0.0);
491 rt_shadermode(voidscene, RT_SHADER_AUTO);
492 rt_rescale_lights(voidscene, 1.0);
493 rt_phong_shader(voidscene, RT_SHADER_BLINN);
494
495 rt_background(voidscene, bgcolor);
496 rt_background_sky_sphere(voidscene, rt_vector(0.0, 1.0, 0.0), 0.3, 0,
497 rt_color(0.0, 0.0, 0.0), rt_color(0.0, 0.0, 0.5));
498 rt_background_mode(voidscene, RT_BACKGROUND_TEXTURE_SOLID);
499
500 rt_ambient_occlusion(voidscene, 0, ambcolor); /* disable AO by default */
501 rt_fog_rendering_mode(voidscene, RT_FOG_NORMAL); /* radial fog by default */
502 rt_fog_mode(voidscene, RT_FOG_NONE); /* disable fog by default */
503 rt_fog_parms(voidscene, bgcolor, 0.0, 1.0, 1.0);
504 rt_trans_mode(voidscene, RT_TRANS_ORIG); /* set transparency mode */
505 rt_normal_fixup_mode(voidscene, 0); /* disable normal fixup */
506
507 scene->objgroup.boundedobj = NULL;
508 scene->objgroup.unboundedobj = NULL;
509 scene->objgroup.numobjects = 0;
510
511 scene->texlist = NULL;
512 scene->lightlist = NULL;
513 scene->cliplist = NULL;
514 scene->numlights = 0;
515 scene->scenecheck = 1;
516 scene->parbuf = NULL;
517 scene->threads = NULL;
518 scene->threadparms = NULL;
519 scene->flags = RT_SHADE_NOFLAGS;
520
521 rt_set_numthreads(voidscene, -1); /* auto determine num threads */
522
523 /* number of distributed memory nodes, fills in array of node/cpu info */
524 scene->nodes = rt_getcpuinfo(&scene->cpuinfo);
525 scene->mynode = rt_mynode();
526
527 return scene;
528 }
529
530
531
rt_deletescene(SceneHandle voidscene)532 void rt_deletescene(SceneHandle voidscene) {
533 scenedef * scene = (scenedef *) voidscene;
534 list * cur, * next;
535
536 if (scene != NULL) {
537 if (scene->imginternal) {
538 free(scene->img);
539 }
540
541 /* tear down and deallocate persistent rendering threads */
542 destroy_render_threads(scene);
543
544 /* tear down and deallocate persistent scanline receives */
545 if (scene->parbuf != NULL)
546 rt_delete_scanlinereceives(scene->parbuf);
547
548 /* free all lights */
549 cur = scene->lightlist;
550 while (cur != NULL) {
551 next = cur->next;
552
553 /* free lights that have special data, or aren't freed */
554 /* as part of the object list deallocation loop. */
555 free_light_special(cur->item);
556 free(cur);
557 cur = next;
558 }
559
560 /* free all textures */
561 cur = scene->texlist;
562 while (cur != NULL) {
563 next = cur->next;
564 ((texture *) cur->item)->methods->freetex(cur->item); /* free texture */
565 free(cur); /* free list entry */
566 cur = next;
567 }
568
569 /* free all clipping planes */
570 cur = scene->cliplist;
571 while (cur != NULL) {
572 next = cur->next;
573 free(((clip_group *) cur->item)->planes); /* free array of clip planes */
574 free(cur->item); /* free clip group struct */
575 free(cur); /* free list entry */
576 cur = next;
577 }
578
579 /* free all other textures, MIP Maps, and images */
580 FreeTextures();
581
582 free(scene->cpuinfo);
583 free_objects(scene->objgroup.boundedobj);
584 free_objects(scene->objgroup.unboundedobj);
585
586 free(scene);
587 }
588 }
589
apitextotex(apitexture * apitex,texture * tx)590 void apitextotex(apitexture * apitex, texture * tx) {
591 standard_texture * tex = (standard_texture *) tx;
592 tex->img = NULL;
593
594 switch(apitex->texturefunc) {
595 case RT_TEXTURE_3D_CHECKER:
596 tex->texfunc=(color(*)(const void *, const void *, void *))(checker_texture);
597 break;
598
599 case RT_TEXTURE_GRIT:
600 tex->texfunc=(color(*)(const void *, const void *, void *))(grit_texture);
601 break;
602
603 case RT_TEXTURE_MARBLE:
604 tex->texfunc=(color(*)(const void *, const void *, void *))(marble_texture);
605 break;
606
607 case RT_TEXTURE_WOOD:
608 tex->texfunc=(color(*)(const void *, const void *, void *))(wood_texture);
609 break;
610
611 case RT_TEXTURE_GRADIENT:
612 tex->texfunc=(color(*)(const void *, const void *, void *))(gnoise_texture);
613 break;
614
615 case RT_TEXTURE_CYLINDRICAL_CHECKER:
616 tex->texfunc=(color(*)(const void *, const void *, void *))(cyl_checker_texture);
617 break;
618
619 case RT_TEXTURE_CYLINDRICAL_IMAGE:
620 tex->texfunc=(color(*)(const void *, const void *, void *))(image_cyl_texture);
621 tex->img=LoadMIPMap(apitex->imap, 0);
622 break;
623
624 case RT_TEXTURE_SPHERICAL_IMAGE:
625 tex->texfunc=(color(*)(const void *, const void *, void *))(image_sphere_texture);
626 tex->img=LoadMIPMap(apitex->imap, 0);
627 break;
628
629 case RT_TEXTURE_PLANAR_IMAGE:
630 tex->texfunc=(color(*)(const void *, const void *, void *))(image_plane_texture);
631 tex->img=LoadMIPMap(apitex->imap, 0);
632 break;
633
634 case RT_TEXTURE_VOLUME_IMAGE:
635 tex->texfunc=(color(*)(const void *, const void *, void *))(image_volume_texture);
636 tex->img=LoadMIPMap(apitex->imap, 0);
637 break;
638
639 case RT_TEXTURE_CONSTANT:
640 default:
641 tex->texfunc=(color(*)(const void *, const void *, void *))(constant_texture);
642 break;
643 }
644
645 tex->ctr = apitex->ctr;
646 tex->rot = apitex->rot;
647 tex->scale = apitex->scale;
648 tex->uaxs = apitex->uaxs;
649 tex->vaxs = apitex->vaxs;
650 tex->waxs = apitex->waxs;
651 tex->ambient = apitex->ambient;
652 tex->diffuse = apitex->diffuse;
653 tex->specular = apitex->specular;
654 tex->opacity = apitex->opacity;
655 tex->col = apitex->col;
656
657 /* initialize texture flags */
658 tex->flags = RT_TEXTURE_NOFLAGS;
659
660 /* anything less than an entirely opaque object will modulate */
661 /* the light intensity rather than completly occluding it */
662 if (apitex->opacity >= 0.99999)
663 tex->flags = RT_TEXTURE_SHADOWCAST;
664
665 tex->phong = 0.0;
666 tex->phongexp = 0.0;
667 tex->phongtype = 0;
668
669 tex->outline = 0.0;
670 tex->outlinewidth = 0.0;
671 }
672
rt_texture(SceneHandle sc,apitexture * apitex)673 void * rt_texture(SceneHandle sc, apitexture * apitex) {
674 scenedef * scene = (scenedef *) sc;
675 texture * tex;
676 list * lst;
677
678 tex = new_standard_texture();
679 apitextotex(apitex, tex);
680
681 /* add texture to the scene texture list */
682 lst = (list *) malloc(sizeof(list));
683 lst->item = (void *) tex;
684 lst->next = scene->texlist;
685 scene->texlist = lst;
686
687 return(tex);
688 }
689
690
rt_define_image(const char * name,int xs,int ys,int zs,unsigned char * rgb)691 void rt_define_image(const char *name, int xs, int ys, int zs, unsigned char *rgb) {
692 AllocateImageRGB24(name, xs, ys, zs, rgb);
693 }
694
695
696 /* this is a gross hack that needs to be eliminated */
697 /* by writing a new mesh triangle object that doesn't */
698 /* need multiple instantiations of texture objects for */
699 /* correct operation. Ideally we'd store the object */
700 /* pointer in the intersection record so the texture */
701 /* needn't store this itself */
rt_texture_copy_standard(SceneHandle sc,void * oldtex)702 void * rt_texture_copy_standard(SceneHandle sc, void *oldtex) {
703 texture *newtex;
704 newtex = new_standard_texture();
705 memcpy(newtex, oldtex, sizeof(standard_texture));
706 return newtex;
707 }
rt_texture_copy_vcstri(SceneHandle sc,void * oldtex)708 void * rt_texture_copy_vcstri(SceneHandle sc, void *oldtex) {
709 texture *newtex;
710 newtex = new_vcstri_texture();
711 memcpy(newtex, oldtex, sizeof(vcstri_texture));
712 return newtex;
713 }
714
715
rt_tex_phong(void * voidtex,apiflt phong,apiflt phongexp,int type)716 void rt_tex_phong(void * voidtex, apiflt phong, apiflt phongexp, int type) {
717 texture * tex = (texture *) voidtex;
718 tex->phong = phong;
719 tex->phongexp = phongexp;
720 tex->phongtype = type;
721 }
722
723
rt_tex_outline(void * voidtex,apiflt outline,apiflt outlinewidth)724 void rt_tex_outline(void * voidtex, apiflt outline, apiflt outlinewidth) {
725 texture * tex = (texture *) voidtex;
726 tex->outline = outline;
727 tex->outlinewidth = outlinewidth;
728 }
729
730
add_bounded_object(scenedef * scene,object * obj)731 static void add_bounded_object(scenedef * scene, object * obj) {
732 object * objtemp;
733
734 if (obj == NULL)
735 return;
736
737 obj->id = new_objectid(scene);
738 objtemp = scene->objgroup.boundedobj;
739 scene->objgroup.boundedobj = obj;
740 obj->nextobj = objtemp;
741 obj->clip = scene->curclipgroup;
742
743 /* XXX Clipping ought to be applied to objects before they */
744 /* are even added to the internal data structures, so */
745 /* they aren't even considered during rendering. */
746
747 scene->scenecheck = 1;
748 }
749
add_unbounded_object(scenedef * scene,object * obj)750 static void add_unbounded_object(scenedef * scene, object * obj) {
751 object * objtemp;
752
753 if (obj == NULL)
754 return;
755
756 obj->id = new_objectid(scene);
757 objtemp = scene->objgroup.unboundedobj;
758 scene->objgroup.unboundedobj = obj;
759 obj->nextobj = objtemp;
760 obj->clip = scene->curclipgroup;
761 scene->scenecheck = 1;
762 }
763
764
rt_light(SceneHandle voidscene,void * tex,apivector ctr,apiflt rad)765 void * rt_light(SceneHandle voidscene, void * tex, apivector ctr, apiflt rad) {
766 point_light * li;
767 scenedef * scene = (scenedef *) voidscene;
768 list * lst;
769
770 li=newpointlight(tex, ctr, rad);
771
772 /* add light to the scene lightlist */
773 lst = (list *) malloc(sizeof(list));
774 lst->item = (void *) li;
775 lst->next = scene->lightlist;
776 scene->lightlist = lst;
777 scene->numlights++;
778
779 /* add light as an object as well... */
780 add_bounded_object((scenedef *) scene, (object *)li);
781
782 return li;
783 }
784
785
786
rt_directional_light(SceneHandle voidscene,void * tex,apivector dir)787 void * rt_directional_light(SceneHandle voidscene, void * tex, apivector dir) {
788 directional_light * li;
789 scenedef * scene = (scenedef *) voidscene;
790 list * lst;
791
792 VNorm(&dir);
793 li=newdirectionallight(tex, dir);
794
795 /* add light to the scene lightlist */
796 lst = (list *) malloc(sizeof(list));
797 lst->item = (void *) li;
798 lst->next = scene->lightlist;
799 scene->lightlist = lst;
800 scene->numlights++;
801
802 /* don't add to the object list since it's at infinity */
803 /* XXX must loop over light list and deallocate these */
804 /* specially since they aren't in the obj list. */
805
806 return li;
807 }
808
rt_spotlight(SceneHandle voidscene,void * tex,apivector ctr,apiflt rad,apivector dir,apiflt start,apiflt end)809 void * rt_spotlight(SceneHandle voidscene, void * tex, apivector ctr, apiflt rad, apivector dir,
810 apiflt start, apiflt end) {
811 flt fallstart, fallend;
812 point_light * li;
813 scenedef * scene = (scenedef *) voidscene;
814 list * lst;
815
816 fallstart = start * 3.1415926 / 180.0;
817 fallend = end * 3.1415926 / 180.0;
818 VNorm(&dir);
819 li = newspotlight(tex, ctr, rad, dir, fallstart, fallend);
820
821 /* add light to the scene lightlist */
822 lst = (list *) malloc(sizeof(list));
823 lst->item = (void *) li;
824 lst->next = scene->lightlist;
825 scene->lightlist = lst;
826 scene->numlights++;
827
828 /* add light as an object as well... */
829 add_bounded_object(scene, (object *) li);
830
831 return li;
832 }
833
rt_light_attenuation(void * vli,apiflt Kc,apiflt Kl,apiflt Kq)834 void rt_light_attenuation(void * vli, apiflt Kc, apiflt Kl, apiflt Kq) {
835 light_set_attenuation((point_light *) vli, Kc, Kl, Kq);
836 }
837
rt_scalarvol(SceneHandle scene,void * tex,apivector min,apivector max,int xs,int ys,int zs,const char * fname,scalarvol * invol)838 void rt_scalarvol(SceneHandle scene, void * tex, apivector min, apivector max,
839 int xs, int ys, int zs, const char * fname, scalarvol * invol) {
840 add_bounded_object((scenedef *) scene, (object *) newscalarvol(tex, min, max, xs, ys, zs, fname, invol));
841 }
842
rt_extvol(SceneHandle scene,void * tex,apivector min,apivector max,int samples,flt (* evaluator)(flt,flt,flt))843 void rt_extvol(SceneHandle scene, void * tex, apivector min, apivector max, int samples, flt (* evaluator)(flt, flt, flt)) {
844 add_bounded_object((scenedef *) scene, (object *) newextvol(tex, min, max, samples, evaluator));
845 }
846
rt_box(SceneHandle scene,void * tex,apivector min,apivector max)847 void rt_box(SceneHandle scene, void * tex, apivector min, apivector max) {
848 add_bounded_object((scenedef *) scene, (object *) newbox(tex, min, max));
849 }
850
rt_cylinder(SceneHandle scene,void * tex,apivector ctr,apivector axis,apiflt rad)851 void rt_cylinder(SceneHandle scene, void * tex, apivector ctr, apivector axis, apiflt rad) {
852 add_unbounded_object((scenedef *) scene, newcylinder(tex, ctr, axis, rad));
853 }
854
rt_fcylinder(SceneHandle scene,void * tex,apivector ctr,apivector axis,apiflt rad)855 void rt_fcylinder(SceneHandle scene, void * tex, apivector ctr, apivector axis, apiflt rad) {
856 add_bounded_object((scenedef *) scene, newfcylinder(tex, ctr, axis, rad));
857 }
858
rt_plane(SceneHandle scene,void * tex,apivector ctr,apivector norm)859 void rt_plane(SceneHandle scene, void * tex, apivector ctr, apivector norm) {
860 add_unbounded_object((scenedef *) scene, newplane(tex, ctr, norm));
861 }
862
rt_ring(SceneHandle scene,void * tex,apivector ctr,apivector norm,apiflt a,apiflt b)863 void rt_ring(SceneHandle scene, void * tex, apivector ctr, apivector norm, apiflt a, apiflt b) {
864 add_bounded_object((scenedef *) scene, newring(tex, ctr, norm, a, b));
865 }
866
rt_sphere(SceneHandle scene,void * tex,apivector ctr,apiflt rad)867 void rt_sphere(SceneHandle scene, void * tex, apivector ctr, apiflt rad) {
868 add_bounded_object((scenedef *) scene, newsphere(tex, ctr, rad));
869 }
870
rt_tri(SceneHandle voidscene,void * tex,apivector v0,apivector v1,apivector v2)871 void rt_tri(SceneHandle voidscene, void * tex, apivector v0, apivector v1, apivector v2) {
872 scenedef * scene = (scenedef *) voidscene;
873 object * o = newtri(tex, v0, v1, v2);
874 /* don't add degenerate triangles */
875 if (o != NULL) {
876 add_bounded_object(scene, o);
877 }
878 }
879
rt_stri(SceneHandle voidscene,void * tex,apivector v0,apivector v1,apivector v2,apivector n0,apivector n1,apivector n2)880 void rt_stri(SceneHandle voidscene, void * tex, apivector v0, apivector v1, apivector v2, apivector n0, apivector n1, apivector n2) {
881 scenedef * scene = (scenedef *) voidscene;
882 object * o = newstri(tex, v0, v1, v2, n0, n1, n2);
883 /* don't add degenerate triangles */
884 if (o != NULL) {
885 if (scene->normalfixupmode)
886 stri_normal_fixup(o, scene->normalfixupmode);
887 add_bounded_object(scene, o);
888 }
889 }
890
rt_vcstri(SceneHandle voidscene,void * tex,apivector v0,apivector v1,apivector v2,apivector n0,apivector n1,apivector n2,apicolor c0,apicolor c1,apicolor c2)891 void rt_vcstri(SceneHandle voidscene, void * tex, apivector v0, apivector v1, apivector v2, apivector n0, apivector n1, apivector n2,
892 apicolor c0, apicolor c1, apicolor c2) {
893 scenedef * scene = (scenedef *) voidscene;
894 object * o = newvcstri(tex, v0, v1, v2, n0, n1, n2, c0, c1, c2);
895 /* don't add degenerate triangles */
896 if (o != NULL) {
897 if (scene->normalfixupmode)
898 vcstri_normal_fixup(o, scene->normalfixupmode);
899 add_bounded_object(scene, o);
900 }
901 }
902
rt_tristripscnv3fv(SceneHandle voidscene,void * tex,int numverts,const float * cnv,int numstrips,int * vertsperstrip,int * facets)903 void rt_tristripscnv3fv(SceneHandle voidscene, void * tex,
904 int numverts, const float * cnv,
905 int numstrips, int *vertsperstrip, int *facets) {
906 int strip, t, v;
907 int stripaddr[2][3] = { {0, 1, 2}, {1, 0, 2} };
908 scenedef * scene = (scenedef *) voidscene;
909
910 /* render triangle strips one triangle at a time
911 * triangle winding order is:
912 * v0, v1, v2, then v2, v1, v3, then v2, v3, v4, etc.
913 */
914 /* loop over all of the triangle strips */
915 for (strip=0, v=0; strip < numstrips; strip++) {
916 /* loop over all triangles in this triangle strip */
917 for (t=0; t < (vertsperstrip[strip] - 2); t++) {
918 apivector v0, v1, v2;
919 apivector n0, n1, n2;
920 apicolor c0, c1, c2;
921 int a0, a1, a2;
922 list * lst;
923 object * o;
924
925 /* copy the original input texture to each of the triangles... */
926 /* converting to a vcstri texture if it isn't already */
927 vcstri_texture * newtex=rt_texture_copy_vcstri(scene, tex);
928
929 /* add texture to the scene texture list */
930 lst = (list *) malloc(sizeof(list));
931 lst->item = (void *) tex;
932 lst->next = scene->texlist;
933 scene->texlist = lst;
934
935 /* render one triangle, using lookup table to fix winding order */
936 a0 = facets[v + (stripaddr[t & 0x01][0])] * 10;
937 a1 = facets[v + (stripaddr[t & 0x01][1])] * 10;
938 a2 = facets[v + (stripaddr[t & 0x01][2])] * 10;
939
940 c0.r = cnv[a0 + 0];
941 c0.g = cnv[a0 + 1];
942 c0.b = cnv[a0 + 2];
943 n0.x = cnv[a0 + 4];
944 n0.y = cnv[a0 + 5];
945 n0.z = cnv[a0 + 6];
946 v0.x = cnv[a0 + 7];
947 v0.y = cnv[a0 + 8];
948 v0.z = cnv[a0 + 9];
949
950 c1.r = cnv[a1 + 0];
951 c1.g = cnv[a1 + 1];
952 c1.b = cnv[a1 + 2];
953 n1.x = cnv[a1 + 4];
954 n1.y = cnv[a1 + 5];
955 n1.z = cnv[a1 + 6];
956 v1.x = cnv[a1 + 7];
957 v1.y = cnv[a1 + 8];
958 v1.z = cnv[a1 + 9];
959
960 c2.r = cnv[a2 + 0];
961 c2.g = cnv[a2 + 1];
962 c2.b = cnv[a2 + 2];
963 n2.x = cnv[a2 + 4];
964 n2.y = cnv[a2 + 5];
965 n2.z = cnv[a2 + 6];
966 v2.x = cnv[a2 + 7];
967 v2.y = cnv[a2 + 8];
968 v2.z = cnv[a2 + 9];
969
970 o = newvcstri(newtex, v0, v1, v2, n0, n1, n2, c0, c1, c2);
971 if (scene->normalfixupmode)
972 vcstri_normal_fixup(o, scene->normalfixupmode);
973 add_bounded_object((scenedef *) scene, o);
974 v++; /* move on to next vertex */
975 }
976 v+=2; /* last two vertices are already used by last triangle */
977 }
978 }
979
980
rt_quadsphere(SceneHandle scene,void * tex,apivector ctr,apiflt rad)981 void rt_quadsphere(SceneHandle scene, void * tex, apivector ctr, apiflt rad) {
982 quadric * q;
983 flt factor;
984 q=(quadric *) newquadric();
985 factor= 1.0 / (rad*rad);
986 q->tex=tex;
987 q->ctr=ctr;
988
989 q->mat.a=factor;
990 q->mat.b=0.0;
991 q->mat.c=0.0;
992 q->mat.d=0.0;
993 q->mat.e=factor;
994 q->mat.f=0.0;
995 q->mat.g=0.0;
996 q->mat.h=factor;
997 q->mat.i=0.0;
998 q->mat.j=-1.0;
999
1000 add_unbounded_object((scenedef *) scene, (object *)q);
1001 }
1002
1003
rt_clip_fv(SceneHandle voidscene,int numplanes,float * planes)1004 void rt_clip_fv(SceneHandle voidscene, int numplanes, float *planes) {
1005 list * lst;
1006 clip_group * clip;
1007 int i;
1008 scenedef * scene = (scenedef *) voidscene;
1009
1010 /* copy clipping info into structure */
1011 clip = (clip_group *) malloc(sizeof(clip_group));
1012 clip->numplanes = numplanes;
1013 clip->planes = (flt *) malloc(numplanes * sizeof(flt) * 4);
1014 for (i=0; i<(numplanes*4); i++) {
1015 clip->planes[i] = planes[i];
1016 }
1017
1018 /* add clipping info to the scene clip list */
1019 lst = (list *) malloc(sizeof(list));
1020 lst->item = (void *) clip;
1021 lst->next = scene->cliplist;
1022 scene->cliplist = lst;
1023
1024 /* all objects added from this point on are added with this clip group */
1025 scene->curclipgroup = clip;
1026 }
1027
1028
rt_clip_dv(SceneHandle voidscene,int numplanes,double * planes)1029 void rt_clip_dv(SceneHandle voidscene, int numplanes, double *planes) {
1030 list * lst;
1031 clip_group * clip;
1032 int i;
1033 scenedef * scene = (scenedef *) voidscene;
1034
1035 /* copy clipping info into structure */
1036 clip = (clip_group *) malloc(sizeof(clip_group));
1037 clip->numplanes = numplanes;
1038 clip->planes = (flt *) malloc(numplanes * sizeof(flt) * 4);
1039 for (i=0; i<(numplanes*4); i++) {
1040 clip->planes[i] = planes[i];
1041 }
1042
1043 /* add clipping info to the scene clip list */
1044 lst = (list *) malloc(sizeof(list));
1045 lst->item = (void *) clip;
1046 lst->next = scene->cliplist;
1047 scene->cliplist = lst;
1048
1049 /* all objects added from this point on are added with this clip group */
1050 scene->curclipgroup = clip;
1051 }
1052
1053
rt_clip_off(SceneHandle voidscene)1054 void rt_clip_off(SceneHandle voidscene) {
1055 scenedef * scene = (scenedef *) voidscene;
1056
1057 /* all objects added from this point on are added without clipping */
1058 scene->curclipgroup = NULL;
1059 }
1060
1061
1062