viewing source for "crt.c"

last commit

commit 2fcfc3b2e8e18bd4ab667b82d939cc2ba9b6a5d3 Author: Andrew Rader <andrew.r.rader@gmail.com> Date: Sun Jan 13 09:25:46 2008 -0800
Initial Commit

source code

001: #include <stdio.h>
002: #include <stdlib.h>
003: #include <dlfcn.h>
004: #include <math.h>
005: #include <string.h>
006: 
007: #include "vector.h"
008: #include "objects.h"
009: 
010: #define EPSILON     0.001f
011: #define TRACE_DEPTH 6
012: 
013: void render( int, int, color***, primitive*, int, int );
014: color* trace( ray*, primitive*, int, float, float*, int );
015: intersection* intersect( ray*, primitive* );
016: float calc_shade( primitive*, vector*, vector*, vector*, primitive*, int );
017: void usage(void);
018: 
019: void render( int width, int height, color ***image, primitive *scene,
020:         int aa_level, int shadows ) {
021:     float world_left, world_right, world_top, world_bot;
022:     float delta_x, delta_y;
023:     float screen_x, screen_y;
024:     float tmpf;
025:     int x, y;
026:     int aa_x, aa_y;
027:     int aa_root;
028:     vector origin, dir;
029:     ray r;
030:     color *tmpc;
031: 
032:     world_left = -(4.0f * ((float)width / (float)height) );
033:     world_right = -world_left;
034:     world_top = 4.0f;
035:     world_bot = -4.0f;
036: 
037:     /* The amount to shift for each pixel */
038:     delta_x = (world_right - world_left) / width;
039:     delta_y = (world_bot - world_top) / height;
040: 
041:     origin.x = 0.0f;
042:     origin.y = 0.0f;
043:     origin.z = -5.0f;
044: 
045:     aa_root = (int)sqrt( aa_level );
046: 
047:     screen_y = world_top;
048:     for( y = 0; y < height; y++ ) {
049:         screen_x = world_left;
050:         for( x = 0; x < width; x++ ) {
051:             for( aa_x = 0; aa_x < aa_root; aa_x++ ) {
052:                 for( aa_y = 0; aa_y < aa_root; aa_y++ ) {
053:                     dir.x = screen_x + delta_x * aa_x / (float)aa_root;
054:                     dir.y = screen_y + delta_y * aa_y / (float)aa_root;
055:                     dir.z = 0.0f;
056: 
057:                     vect_sub( &dir, &origin );
058:                     vect_normalize( &dir );
059: 
060:                     r.origin = &origin;
061:                     r.dir = &dir;
062: 
063:                     tmpc = trace( &r, scene, 0, 1.0f, &tmpf, shadows );
064:                     if( image[y][x] == NULL ) {
065:                         image[y][x] = tmpc;
066:                     }
067:                     else {
068:                         vect_add( image[y][x], tmpc );
069:                         free( tmpc );
070:                     }
071:                 }
072:             }
073: 
074:             vect_multf( image[y][x], 1.0f / aa_level );
075: 
076:             screen_x += delta_x;
077:         }
078:         screen_y += delta_y;
079:     }
080: }
081: 
082: color* trace( ray *aray, primitive *scene, int depth, float refr, float *dist,
083:         int shadows ){
084:     intersection *isect;
085:     primitive *prim, *iter;
086:     vector isect_pt, pn, lv, ln, tmpv1, tmpv2;
087:     ray tmpr;
088:     float tmpf1, tmpf2, tmpf3, shade;
089:     color *tmpc;
090:     color *c = (color*)malloc( sizeof( color ) );
091:     if( c == NULL ) {
092:         fprintf( stderr, "*** error: could not allocate color memory\n" );
093:         exit( 1 );
094:     }
095: 
096:     c->x = 0.0f;
097:     c->y = 0.0f;
098:     c->z = 0.0f;
099: 
100:     isect = intersect( aray, scene );
101: 
102:     if( isect == NULL ) {
103:         return c;
104:     }
105: 
106:     *dist = isect->dist;
107: 
108:     prim = isect->prim;
109: 
110:     if( prim->is_light ) {
111:         vect_copy( c, &(isect->prim->mat.col) );
112:         free( isect );
113:         return c;
114:     }
115: 
116:     vect_copy( &isect_pt, aray->dir );
117:     vect_multf( &isect_pt, isect->dist );
118:     vect_add( &isect_pt, aray->origin );
119: 
120:     prim->normal( prim, &isect_pt, &pn );
121: 
122:     iter = scene;
123:     while( iter != NULL ) {
124:         if( iter->is_light ) {
125:             vect_copy( &lv, &iter->center );
126:             vect_sub( &lv, &isect_pt );
127: 
128:             vect_copy( &ln, &lv );
129:             vect_normalize( &ln );
130: 
131:             shade = calc_shade( iter, &isect_pt, &lv, &ln, scene, shadows );
132: 
133:             if( shade > 0.0f ) {
134:                 /* determine the diffuse component */
135:                 tmpf1 = prim->mat.diffuse;
136:                 if( tmpf1 > 0.0f ) {
137:                     tmpf2 = vect_dot( &pn, &ln );
138:                     if( tmpf2 > 0.0f ) {
139:                         tmpf1 *= tmpf2 * shade;
140:                         vect_copy( &tmpv1, &prim->mat.col );
141:                         vect_mult( &tmpv1, &iter->mat.col );
142:                         vect_multf( &tmpv1, tmpf1 );
143:                         vect_add( c, &tmpv1 );
144:                     }
145:                 }
146: 
147:                 /* determine the specular component */
148:                 tmpf1 = prim->mat.specular;
149:                 if( tmpf1 > 0.0f ) {
150:                     vect_copy( &tmpv1, &pn );
151:                     vect_copy( &tmpv2, &ln );
152:                     tmpf2 = 2.0f * vect_dot( &ln, &pn );
153:                     vect_multf( &tmpv1, tmpf2 );
154:                     vect_sub( &tmpv2, &tmpv1 );
155:                     tmpf2 = vect_dot( aray->dir, &tmpv2 );
156:                     if( tmpf2 > 0.0f ) {
157:                         tmpf1 = powf( tmpf2, 20.0f ) * tmpf1 * shade;
158:                         vect_copy( &tmpv1, &iter->mat.col );
159:                         vect_multf( &tmpv1, tmpf1 );
160:                         vect_add( c, &tmpv1 );
161:                     }
162:                 }
163:             }
164:         }
165: 
166:         iter = iter->next;
167:     }
168: 
169:     /* calculate reflection */
170:     if( prim->mat.refl > 0.0f && depth < TRACE_DEPTH ) {
171:         vect_copy( &tmpv1, &pn );
172:         vect_multf( &tmpv1, 2.0f * vect_dot( &pn, aray->dir ) );
173:         vect_copy( &tmpv2, aray->dir );
174:         vect_sub( &tmpv2, &tmpv1 );
175: 
176:         vect_copy( &tmpv1, &tmpv2 );
177:         vect_multf( &tmpv1, EPSILON );
178:         vect_add( &tmpv1, &isect_pt );
179: 
180:         tmpr.origin = &tmpv1;
181:         tmpr.dir = &tmpv2;
182: 
183:         tmpc = trace( &tmpr, scene, depth + 1, refr, &tmpf1, shadows );
184:         vect_multf( tmpc, prim->mat.refl );
185: 
186:         vect_copy( &tmpv1, &prim->mat.col );
187:         vect_mult( &tmpv1, tmpc );
188:         vect_add( c, &tmpv1 );
189: 
190:         free( tmpc );
191:     }
192: 
193:     /* calculate refraction */
194:     if( prim->mat.is_refr && depth < TRACE_DEPTH ) {
195:         vect_copy( &tmpv1, &pn );
196:         if( isect->inside ) {
197:             vect_multf( &tmpv1, -1.0f );
198:         }
199: 
200:         tmpf1 = refr / prim->mat.refr;
201:         tmpf2 = -( vect_dot( &tmpv1, aray->dir ) );
202:         tmpf3 = 1.0f - tmpf1 * tmpf1 * (1.0f - tmpf2 * tmpf2);
203:         if( tmpf3 > 0.0f ) {
204:             vect_copy( &tmpv2, aray->dir );
205:             vect_multf( &tmpv2, tmpf1 );
206:             vect_multf( &tmpv1, tmpf1 * tmpf2 - sqrtf( tmpf3 ) );
207:             vect_add( &tmpv1, &tmpv2 );
208: 
209:             vect_copy( &tmpv2, &tmpv1 );
210:             vect_multf( &tmpv2, EPSILON );
211:             vect_add( &tmpv2, &isect_pt );
212: 
213:             tmpr.origin = &tmpv2;
214:             tmpr.dir = &tmpv1;
215: 
216:             tmpc = trace( &tmpr, scene, depth + 1, refr, &tmpf1, shadows );
217: 
218:             vect_copy( &tmpv1, &prim->mat.col );
219:             vect_multf( &tmpv1, prim->mat.absorb * tmpf1 );
220: 
221:             tmpv2.x = expf( -tmpv1.x );
222:             tmpv2.y = expf( -tmpv1.y );
223:             tmpv2.z = expf( -tmpv1.z );
224: 
225:             vect_mult( tmpc, &tmpv2 );
226:             vect_add( c, tmpc );
227: 
228:             free( tmpc );
229:         }
230:     }
231: 
232:     free( isect );
233: 
234:     if( c->x > 1.0f ) {
235:         c->x = 1.0f;
236:     }
237:     else if( c->x < 0.0f ) {
238:         c->x = 0.0f;
239:     }
240: 
241:     if( c->y > 1.0f ) {
242:         c->y = 1.0f;
243:     }
244:     else if( c->y < 0.0f ) {
245:         c->y = 0.0f;
246:     }
247: 
248:     if( c->z > 1.0f ) {
249:         c->z = 1.0f;
250:     }
251:     else if( c->z < 0.0f ) {
252:         c->z = 0.0f;
253:     }
254: 
255:     return c;
256: }
257: 
258: float calc_shade( primitive *light, vector *isect_pt, vector *lv, vector *ln,
259:         primitive *scene, int shadows ) {
260:     float shade = 1.0f;
261:     float l_dist;
262:     int i;
263:     ray r;
264:     vector o, dir;
265:     intersection *isect;
266:     primitive *iter;
267: 
268:     if( light->is_light == AREA_LIGHT && shadows > 1 && light->grid != NULL ) {
269:         for( i = 0; i < shadows; i++ ) {
270:             dir.x = light->grid[(i&63)*3] +
271:                 ((float)rand()/RAND_MAX)*light->dx;
272:             dir.y = light->grid[(i&63)*3+1] +
273:                 ((float)rand()/RAND_MAX)*light->dy;
274:             dir.z = light->grid[(i&63)*3+2] +
275:                 ((float)rand()/RAND_MAX)*light->dz;
276: 
277:             vect_sub( &dir, isect_pt );
278:             l_dist = vect_length( &dir );
279:             vect_multf( &dir, 1.0f / l_dist );
280: 
281:             vect_copy( &o, &dir );
282:             vect_multf( &o, EPSILON );
283:             vect_add( &o, isect_pt );
284: 
285:             r.origin = &o;
286:             r.dir = &dir;
287: 
288:             for( iter = scene; iter != NULL; iter = iter->next ) {
289:                 isect = iter->intersect( iter, &r );
290: 
291:                 if( isect != NULL &&
292:                         !iter->is_light && isect->dist < l_dist ) {
293:                     shade -= 1.0f / shadows;
294:                     free( isect );
295:                     break;
296:                 }
297: 
298:                 free( isect );
299:             }
300:         }
301:     }
302:     else {
303:         /* setup the ray */
304:         vect_copy( &o, ln );
305:         vect_multf( &o, EPSILON );
306:         vect_add( &o, isect_pt );
307: 
308:         r.origin = &o;
309:         r.dir = ln;
310: 
311:         l_dist = vect_length( lv );
312: 
313:         for( iter = scene; iter != NULL; iter = iter->next ) {
314:             isect = iter->intersect( iter, &r );
315: 
316:             if( isect != NULL && !iter->is_light && isect->dist < l_dist ) {
317:                 shade = 0.0f;
318:                 free( isect );
319:                 break;
320:             }
321: 
322:             free( isect );
323:         }
324:     }
325: 
326:     return shade;
327: }
328: 
329: intersection* intersect( ray *r, primitive *scene ) {
330:     intersection *isect = NULL;
331:     intersection *closest = NULL;
332:     primitive *p = scene;
333: 
334:     while( p != NULL ) {
335:         if( (isect = p->intersect( p, r )) ) {
336:             if( closest == NULL || isect->dist < closest->dist ) {
337:                 free( closest );
338:                 closest = isect;
339:             }
340:             else {
341:                 free( isect );
342:             }
343:         }
344: 
345:         p = p->next;
346:     }
347: 
348:     return closest;
349: }
350: 
351: void usage( void ) {
352:     printf("crt usage: crt [options] <scene> <output>\n" );
353:     printf("options:\n" );
354:     printf("\t--input <in plugin>   - specifies the method of scene input\n" );
355:     printf("\t                        defaults to 'xml.so'\n" );
356:     printf("\t--output <out plugin> - specifies the fild output method\n" );
357:     printf("\t                        defaults to 'bmp.so'\n" );
358:     printf("\t--aa <aa level>       - specifies the level of anti-aliasing\n");
359:     printf("\t                        use, defaults to '1', values should\n");
360:     printf("\t                        be squares (such as 4, 16, 36, etc)\n" );
361: }
362: 
363: int main( int argc, char **argv ) {
364:     void *dl_out = NULL;
365:     void *dl_in = NULL;
366:     char *dl_error = NULL;
367:     primitive *scene = NULL;
368:     primitive *tmp = NULL;
369: 
370:     int aa_level = 1;
371:     int shadows = 1;
372:     char *input = NULL;
373:     char *output = NULL;
374: 
375:     int (*so_write)(int,int,color***,char*);
376:     primitive* (*so_load)(char*);
377: 
378:     int width = 512;
379:     int height = 512;
380: 
381:     color ***img = NULL;
382:     int i,j;
383: 
384:     printf( "CRT - version 0.2.0\n" );
385: 
386:     if( argc < 3 ) {
387:         usage();
388:         exit( 1 );
389:     }
390: 
391:     for( i = 1; i < argc - 2; i++ ) {
392:         if( strcmp( argv[i], "--help" ) == 0 ) {
393:             usage();
394:             exit( 0 );
395:         }
396:         else if( strcmp( argv[i], "--input" ) == 0 ) {
397:             if( i == argc - 3 || (strncmp( argv[i+1], "--", 2 ) == 0) ) {
398:                 fprintf( stderr, "*** crt: missing argument to \"--input\"\n" );
399:                 exit( 1 );
400:             }
401:             else {
402:                 input = argv[i+1];
403:             }
404:         }
405:         else if( strcmp( argv[i], "--output" ) == 0 ) {
406:             if( i == argc - 3 || (strncmp( argv[i+1], "--", 2 ) == 0) ) {
407:                 fprintf( stderr,"*** crt: missing argument to \"--output\"\n" );
408:                 exit( 1 );
409:             }
410:             else {
411:                 output = argv[i+1];
412:             }
413:         }
414:         else if( strcmp( argv[i], "--aa" ) == 0 ) {
415:             if( i == argc - 3 || (strncmp( argv[i+1], "--", 2 ) == 0) ) {
416:                 fprintf( stderr, "*** crt: missing argument to \"--aa\"\n" );
417:                 exit( 1 );
418:             }
419:             else {
420:                 aa_level = atoi( argv[i+1] );
421:             }
422:         }
423:         else if( strcmp( argv[i], "--shadows" ) == 0 ) {
424:             if( i == argc - 3 || (strncmp( argv[i+1], "--", 2 ) == 0) ) {
425:                 fprintf(stderr, "*** crt: missing argument to \"--shadow\"\n");
426:                 exit( 1 );
427:             }
428:             else {
429:                 shadows = atoi( argv[i+1] );
430:             }
431:         }
432:         else if( strcmp( argv[i], "--width" ) == 0 ) {
433:             if( i == argc - 3 || (strncmp( argv[i+1], "--", 2 ) == 0) ) {
434:                 fprintf( stderr, "*** crt: missing argument to \"--width\"\n" );
435:             }
436:             else {
437:                 width = atoi( argv[i+1] );
438:             }
439:         }
440:         else if( strcmp( argv[i], "--height" ) == 0 ) {
441:             if( i == argc - 3 || (strncmp( argv[i+1], "--", 2 ) == 0) ) {
442:                 fprintf( stderr,"*** crt: missing argument to \"--height\"\n" );
443:             }
444:             else {
445:                 height = atoi( argv[i+1] );
446:             }
447:         }
448:     }
449: 
450:     /* setup the output plugin */
451:     if( output == NULL ) {
452:         dl_out = dlopen( "./outputs/bmp.so", RTLD_LAZY );
453:     }
454:     else {
455:         dl_out = dlopen( output, RTLD_LAZY );
456:     }
457:     if( !dl_out ) {
458:         fprintf( stderr, "*** error: %s\n", dlerror() );
459:         exit( 1 );
460:     }
461: 
462:     dlerror();      /* clear error code */
463:     so_write = (int (*)(int,int,color***,char*))dlsym( dl_out, "write_img" );
464:     if( (dl_error = dlerror()) != NULL ) {
465:         fprintf( stderr, "*** error: %s\n", dl_error );
466:         exit( 1 );
467:     }
468: 
469:     /* setup the input plugin */
470:     if( input == NULL ) {
471:         dl_in = dlopen( "./inputs/xml.so", RTLD_LAZY );
472:     }
473:     else {
474:         dl_in = dlopen( input, RTLD_LAZY );
475:     }
476:     if( !dl_in ) {
477:         fprintf( stderr, "*** error: %s\n", dlerror() );
478:         exit( 1 );
479:     }
480:     
481:     dlerror();
482:     so_load = (primitive* (*)(char*))dlsym( dl_in, "load_scene" );
483:     if( (dl_error = dlerror()) != NULL ) {
484:         fprintf( stderr, "*** error: %s\n", dl_error );
485:         exit( 1 );
486:     }
487: 
488:     /* setup the image's memory */
489:     img = malloc( height * sizeof(color**) );
490:     if( img == NULL ) {
491:         fprintf( stderr, "*** error: could not allocate image memory\n" );
492:         exit( 1 );
493:     }
494: 
495:     for( i = 0; i < height; i++ ) {
496:         img[i] = calloc( width, sizeof( color* ) );
497:         if( img[i] == NULL ) {
498:             fprintf( stderr, "*** error: could not allocate image memory\n" );
499:             exit( 1 );
500:         }
501:     }
502: 
503:     scene = so_load( argv[argc-2] );
504: 
505:     render( width, height, img, scene, aa_level, shadows );
506: 
507:     so_write( width, height, img, argv[argc-1] );
508: 
509:     for( i = 0; i < height; i++ ) {
510:         for( j = 0; j < width; j++ ) {
511:             /* free the color's memory */
512:             free( img[i][j] );
513:         }
514: 
515:         /* free the line's memory */
516:         free( img[i] );
517:     }
518: 
519:     /* free the image memory */
520:     free( img );
521: 
522:     /* free the scene object's memory */
523: 
524:     while( scene != NULL ) {
525:         free( scene->data );
526:         if( scene->grid != NULL ) {
527:             free( scene->grid );
528:         }
529: 
530:         tmp = scene->next;
531:         free( scene );
532: 
533:         scene = tmp;
534:     }
535: 
536:     dlclose( dl_out );
537:     dlclose( dl_in );
538: 
539:     return 0;
540: }