viewing source for "crt.c"
last commit
commit 2fcfc3b2e8e18bd4ab667b82d939cc2ba9b6a5d3
Date: Sun Jan 13 09:25:46 2008 -0800
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: }