home *** CD-ROM | disk | FTP | other *** search
/ Stars of Shareware: Raytrace & Morphing / SOS-RAYTRACE.ISO / programm / rad386 / radiosit / src / render.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-04-24  |  12.0 KB  |  444 lines

  1. /*
  2.     Generated image output in one of the following few formats.
  3.  
  4.     (1) RLE format. 
  5.  
  6.     (2) RAW : Binary file.
  7.                 Has a header of 5 bytes.
  8.            Header Content:
  9.                 color_channels : 1 byte
  10.                 cols : 2 bytes
  11.                 rows : 2 bytes
  12.            Followed by Pixel data in the following format.
  13.            For each row
  14.                 For each channel
  15.                         one row of pixel value.
  16.                         (Each pixel value is a byte 0-255.)
  17.         (3) TEXT : Readable file
  18.                 Header line:
  19.                         color_channels cols rows
  20.                 Followed by
  21.                 For each row
  22.                         for each channel
  23.                                 one row of integer pixel value
  24.                                  (0 to 255).
  25.     (4) RADIANCE : Radiance output format.
  26.     (5) SUNRASTER format.
  27. ------
  28. sumant
  29. */
  30.  
  31. #include <stdio.h>
  32. #include <math.h>
  33. #include <malloc.h>
  34.  
  35. #include "GraphicsGems.h"
  36. #include "data_structure.h"
  37. #include "objects.h"
  38. #include "vox.h"
  39. #include "render.h"
  40. extern int verbose_flag;
  41.  
  42. #include "raddecl.h"
  43.  
  44. #include "rle.h"
  45.     rle_pixel **rle_rows=NULL;
  46.  
  47. #include  "color.h"
  48. #include "resolu.h"
  49.         COLOR   *scanout;
  50.  
  51. #include "rasterfile.h"
  52.     unsigned char *rowbuffer=NULL;    
  53.  
  54. static void initialise_output(rows,cols,fl)
  55. int rows,cols;
  56. FILE *fl;
  57. {
  58.     if (output_format==Rle){
  59.         rle_dflt_hdr.ncolors=color_channels;
  60.         rle_dflt_hdr.xmax = cols-1;
  61.             rle_dflt_hdr.ymax = rows-1;
  62.             rle_dflt_hdr.rle_file = fl;
  63.         rle_put_setup(&rle_dflt_hdr);
  64.         (void)fflush(rle_dflt_hdr.rle_file);
  65.         if (rle_rows==NULL)
  66.         if (rle_row_alloc(&rle_dflt_hdr, &rle_rows) < 0)
  67.             error("Unable to allocate image memory.");
  68.     }
  69.     else if (output_format==Radiance){
  70.             fputformat(COLRFMT, fl);
  71.             putc('\n', fl);
  72.             fprtresolu(cols, rows, fl);
  73.             scanout = (COLOR *)malloc(cols*sizeof(COLOR));
  74.             if (scanout == NULL)
  75.                 error("out of memory to allocate scanline");
  76.     }
  77.     else if (output_format==Sunraster){
  78.         struct rasterfile header;
  79.         rowbuffer=(unsigned char *)malloc(
  80.             sizeof(unsigned char)*cols*3);
  81.                 if (rowbuffer == NULL)
  82.                 error("out of memory to allocate scanline");
  83.         header.ras_magic=RAS_MAGIC;
  84.         header.ras_width=cols;
  85.         header.ras_height=rows;
  86.         header.ras_depth=24;
  87.         header.ras_length=cols*rows;
  88.         header.ras_type=RT_STANDARD;
  89.         header.ras_maptype=RMT_RAW;
  90.         header.ras_maplength=0;
  91.  
  92.         fwrite(&header,sizeof(unsigned char),sizeof(header),fl);
  93.     }
  94.     else if (output_format==Raw){
  95.     /* 
  96.        Header of 5 bytes.
  97.        Content:
  98.         color_channels : 1 byte
  99.         cols : 2 bytes
  100.         rows : 2 bytes
  101.     */
  102.         unsigned char b;
  103.         b = color_channels; fwrite(&b,1,1,fl);
  104.         b = cols;fwrite(&b,1,1,fl);
  105.             b = cols>>8;fwrite(&b,1,1,fl);
  106.         b = rows;fwrite(&b,1,1,fl); 
  107.             b = rows>>8;fwrite(&b,1,1,fl);
  108.     }
  109.     else fprintf(fl,"%d %d %d\n",color_channels,cols,rows);
  110. }
  111.  
  112. extern double brightness_mult_factor;
  113.         /*
  114.                 brightness_mult_factor: (default = 1.0)
  115.                 A mechanism to brighten up less bright area, with
  116.                 the understainding that any intensity above 1 will
  117.                 clamped to 1.
  118.         */
  119. static unsigned char quantise(f)
  120. double f;
  121. {
  122.     int c = (int)(f * brightness_mult_factor * 255);
  123.     if (c > 255) c = 255;
  124.     else if (c < 0) c = 0;
  125.     return((unsigned char)c);
  126. }
  127.  
  128. static void dump_row(fl,cols,row_pixels)
  129. FILE *fl;
  130. int cols;
  131. Pixel *row_pixels;
  132. {
  133.     int i,j;
  134.     if (output_format==Rle){
  135.         for(j=0;j<color_channels;j++)
  136.             for(i=0;i<cols;i++)
  137.             rle_rows[j][i]=quantise(row_pixels[i].color[j]);
  138.         rle_putrow( rle_rows,cols,&rle_dflt_hdr);
  139.     }
  140.     else if (output_format==Radiance){
  141.             int components=color_channels;
  142.             if (components>3) components=3;
  143.             for(i=0;i<cols;i++){
  144.                     for(j=0;j<components;j++)
  145.                             scanout[i][j]=row_pixels[i].color[j]*
  146.                     brightness_mult_factor;
  147.                     for(j=components;j<3;j++) scanout[i][j]=0.;
  148.             }
  149.             if (fwritescan(scanout, cols, fl) < 0)
  150.                     error("error writing Radiance picture");
  151.         }
  152.     else if (output_format==Sunraster){
  153.             int components=color_channels;
  154.             if (components>3) components=3;
  155.             for(i=0;i<cols;i++){
  156.                     for(j=0;j<components;j++)
  157.                             rowbuffer[3*i+j]=
  158.                        quantise(row_pixels[i].color[j]);
  159.                 for(j=components;j<3;j++) rowbuffer[3*i+j]=0;
  160.             }
  161.             if (fwrite(rowbuffer, sizeof(unsigned char),3*cols, fl)
  162.             < 0)
  163.                     error("error writing SunRaster picture");
  164.     }
  165.     else if (output_format==Raw)
  166.         for(j=0;j<color_channels;j++)
  167.             for(i=0;i<cols;i++){
  168.                 unsigned char b;
  169.                 b = quantise(row_pixels[i].color[j]);
  170.                    fwrite(&b,1,1,fl);
  171.             }
  172.     else
  173.     for(j=0;j<color_channels;j++){
  174.         for(i=0;i<cols;i++)
  175.            fprintf(fl,"%d ",quantise(row_pixels[i].color[j]));
  176.         fprintf(fl,"\n");
  177.     }
  178.  
  179. }
  180.  
  181. static void terminate_frame(fl)
  182. FILE *fl;
  183. {
  184.     if (output_format==Rle) {
  185.         rle_puteof(&rle_dflt_hdr);
  186.         fclose(fl);
  187.     }
  188.     else if (output_format==Radiance){
  189.             free((char *)scanout);
  190.             fclose(fl);
  191.     }
  192.     else if (output_format==Sunraster){
  193.         free((char *)rowbuffer);
  194.         fclose(fl);
  195.     }
  196.     else fclose(fl);
  197. }
  198.  
  199. static void terminate_output(fl)
  200. FILE *fl;
  201. {
  202.     if (output_format==Rle)
  203.         if (rle_rows != NULL){
  204.             rle_row_free(&rle_dflt_hdr,rle_rows);
  205.             rle_rows = NULL;
  206.         }
  207. }
  208.  
  209. static void color_from_diffuse_surface(ray,n,t,u1,v1,s)
  210. /*
  211.     Returns the computed view independent intensity.
  212. */
  213. Ray *ray;
  214. int n;
  215. double t,u1,v1;
  216. Pixel *s;
  217. {
  218.     int i;
  219.     double Uindex=grid_u(n,u1);
  220.     double Vindex=grid_v(n,v1);
  221.     int uindex=(int)Uindex;
  222.     int vindex=(int)Vindex;
  223.  
  224.     if ((view.shading_type == FLAT)||
  225.         ((object[n].grid_h_reso==1)&&(object[n].grid_v_reso==1))){
  226.         int gindex=gridindex(n,uindex,vindex);
  227.         double *scolor=object[n].grid[gindex].normalized_flux_density;
  228.         for(i=0;i<color_channels;i++) s->color[i]=scolor[i];
  229.     }
  230.     else{/* (view.shading_type == GOURAUD) */
  231.         /* 
  232.             Bilinear Interpolation. 
  233.             -----------------------
  234.                        |             |
  235.                        |             |
  236.             (P7)       |     (P8)    |    (P9)
  237.                        |             |
  238.                     P01|             |P11
  239.             --------------------------------------
  240.                        |             |
  241.                        | (Unindex,   |
  242.             (P4)       |    Vindex)  |    (P6)
  243.                        |     *       |
  244.                        |             |
  245.                    P00 |             | P10
  246.             ----uindex,vindex---------------------
  247.                        |             |
  248.                        |             |
  249.             (P1)       |    (P2)     |    (P3)
  250.                        |             |
  251.                        |             |
  252.         */
  253.         double P00,P10,P11,P01;
  254.         double u=Uindex-uindex,v=Vindex-vindex;
  255.         double *P1,*P2,*P3,*P4,*P5,*P6,*P7,*P8,*P9;
  256.         int i,j;
  257.         i=uindex-1;j=vindex-1;
  258.         P1=object[n].grid[gridindex(n,i,j)].normalized_flux_density;
  259.         i++;
  260.         P2=object[n].grid[gridindex(n,i,j)].normalized_flux_density;
  261.         i++;
  262.         P3=object[n].grid[gridindex(n,i,j)].normalized_flux_density;
  263.         i=uindex-1;j=vindex;
  264.         P4=object[n].grid[gridindex(n,i,j)].normalized_flux_density;
  265.         i++;
  266.         P5=object[n].grid[gridindex(n,i,j)].normalized_flux_density;
  267.         i++;
  268.         P6=object[n].grid[gridindex(n,i,j)].normalized_flux_density;
  269.         i=uindex-1;j=vindex+1;
  270.         P7=object[n].grid[gridindex(n,i,j)].normalized_flux_density;
  271.         i++;
  272.         P8=object[n].grid[gridindex(n,i,j)].normalized_flux_density;
  273.         i++;
  274.         P9=object[n].grid[gridindex(n,i,j)].normalized_flux_density;
  275.         for(i=0;i<color_channels;i++){
  276.             P00=(P1[i]+P2[i]+P4[i]+P5[i])/4.0;
  277.             P10=(P2[i]+P3[i]+P5[i]+P6[i])/4.0;
  278.             P11=(P5[i]+P6[i]+P8[i]+P9[i])/4.0;
  279.             P01=(P4[i]+P5[i]+P7[i]+P8[i])/4.0;
  280.             s->color[i]=(1-u)*(P00*(1.0-v)+P01*v)+u*(P10*(1.0-v)+P11*v);
  281.         }
  282.     }
  283. }
  284.  
  285. static void color_from_specular_surface(ray,objectnum,t,u,v,s)
  286. /*
  287.     There is no view independent information in this surface.
  288.     This surface was used as a path for light transport.
  289.     So the view ray has to be reflected from this surface and the
  290.     process continued till a diffuse surface is reached.
  291.     
  292.     IMPORTANT
  293.     ---------
  294.     1.The ray start position and the direction are changed.
  295.     2.As get_color is called with the new ray this leads to RECURSION.
  296.     
  297. */
  298. Ray *ray;
  299. int objectnum;
  300. double t,u,v;
  301. Pixel *s;
  302. {
  303.     Pixel get_color();
  304.     Vector3 N;
  305.     /* .... set the new ray */
  306.     point_on_line(ray->start,ray->direction,t,ray->start);
  307.     N = ofunc[object[objectnum].surface_geometry_type].
  308.         get_surface_normal(
  309.             object[objectnum].object_specific_structure,u,v
  310.     );
  311.     mirror_reflection(&N,&(ray->direction),&(object[objectnum]));
  312.     (ray->number)++;
  313.     *s=get_color(ray);
  314. }
  315.  
  316. static void color_from_other_surface(ray,objectnum,t,u,v,s)
  317. Ray *ray;
  318. int objectnum;
  319. double t,u,v;
  320. Pixel *s;
  321. {
  322.     error("Not Implemented.");
  323. }
  324.  
  325. static void (*get_surface_specific_color[MAX_REFLECTION_TYPE])()={
  326.     color_from_diffuse_surface,
  327.     color_from_specular_surface,
  328.     color_from_other_surface
  329. };
  330.  
  331. static Pixel get_color(ray)
  332. /*
  333.                                    i
  334.     IMPORTANT
  335.     ---------
  336.     If nondiffuse surfaces are present, get_color invokes itself indirectly
  337.     from get_surface_specific_color with modified ray. So the ray.start and
  338.     directions are changed.
  339. */
  340. Ray *ray;
  341. {
  342.     int i;
  343.     double t_entry,t_exit;
  344.     int HitBoundingBox();
  345.     Pixel pixel;
  346.  
  347.     /* Initialise */
  348.     for(i=0;i<color_channels;i++)pixel.color[i]=0;
  349.  
  350.     if (HitBoundingBox(&(volume_grid.extent.min),&(volume_grid.extent.max),
  351.                &(ray->start),&(ray->direction),&t_entry,&t_exit)){
  352.         int get_nearest_object_in_voxel();
  353.         Vlist *create_vlist();
  354.         Vlist *vlist,*templist;
  355.         int nearest_object= UNDEFINED;
  356.         double t,u,v;
  357.         vlist=templist=create_vlist(
  358.             &(ray->start),&(ray->direction),t_entry,t_exit
  359.         );
  360.         while (templist!=NULL){
  361.             Voxel *vox = volume_grid.voxels+templist->voxnum;
  362.             double tmax=templist->t_far, tmin=templist->t_near;
  363.             /* ASSERT((tmax>=0)&&(tmin>=0)); */
  364.             if(vox->nobjects)
  365.                 if((nearest_object=get_nearest_object_in_voxel
  366.                     (ray,templist->t_near,templist->t_far,vox,&t,&u,&v))
  367.                     !=UNDEFINED) tmax=t;
  368.             if (nearest_object!=UNDEFINED) break;
  369.             templist=templist->next;
  370.         }
  371.         purge_vlist(vlist);
  372.         if (nearest_object!=UNDEFINED){
  373.             /* Add the attenuated surface intensity */
  374.             Pixel from_surface;
  375.             get_surface_specific_color[
  376.                 object[nearest_object].surface_reflection_type
  377.             ](ray,nearest_object,t,u,v,&from_surface);
  378.             for(i=0;i<color_channels;i++)
  379.                 pixel.color[i] += from_surface.color[i];
  380.         }
  381.     }
  382.     return(pixel);
  383. }
  384.  
  385.  
  386. long render(flname)
  387. /*
  388.     Using Ray-tracing for rendering using the computed equillibrium
  389.     flux-density on the surfaces.
  390.  
  391.     Initialises the new ray ray_number to (total_rays+1) so that the mail_box querry 
  392.     is proper.
  393. */
  394. char *flname;
  395. {
  396.     int i,j,k;
  397.     Pixel get_color();
  398.     Pixel *row_pixels;
  399.     Ray ray;
  400.     char name[100];
  401.     FILE *fl;
  402.  
  403.     row_pixels = (Pixel *)malloc(sizeof(Pixel)*view.cols);
  404.     ray.number=total_rays;
  405. #if defined (DEBUG)
  406.     ray.intersections=0;
  407. #endif
  408.     ray.path_length= -1;
  409.     for(i=0; i < view.nframes; i++){
  410.         if(view.nframes>1)sprintf(name,"%s.%03d",flname,i);
  411.         else sprintf(name,"%s",flname);
  412.         if (verbose_flag)fprintf(stderr,"Image file %s:",name);
  413. #if defined(__MSDOS__) || defined(__WATCOMC__)
  414.         if ((fl = fopen(name,"wb"))==NULL)
  415.             error("Cannot open Image file.");
  416. #else
  417.         if ((fl = fopen(name,"w"))==NULL)
  418.             error("Cannot open Image file.");
  419. #endif
  420.         initialise_output(view.rows,view.cols,fl);
  421.         for (j=0; j < view.rows; j++){
  422.             Vector3 dir;
  423.             dir=view.view_direction[i];
  424.             for(k=0; k < view.cols; k++){
  425.                 ray.start=view.eye_point[i];
  426.                 ray.direction=dir;
  427.                 V3Normalize(&(ray.direction));
  428.                 row_pixels[k]=get_color(&ray);
  429.                 (ray.number)++;
  430.                 V3Add(&dir,&(view.delta_u[i]),&dir);
  431.             }
  432.             dump_row(fl,view.cols,row_pixels);
  433.             V3Add(&(view.view_direction[i]),&(view.delta_v[i]),
  434.                 &(view.view_direction[i]));
  435.             if (verbose_flag)fprintf(stderr,".");
  436.         }
  437.         terminate_frame(fl);
  438.         if (verbose_flag)fprintf(stderr,"\n");
  439.     }
  440.     terminate_output(fl);
  441.     free(row_pixels);
  442.     return(ray.number-total_rays);
  443. }
  444.