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