home *** CD-ROM | disk | FTP | other *** search
- /*
- Generated image output in one of the following few formats.
-
- (1) RLE format.
-
- (2) RAW : Binary file.
- Has a header of 5 bytes.
- Header Content:
- color_channels : 1 byte
- cols : 2 bytes
- rows : 2 bytes
- Followed by Pixel data in the following format.
- For each row
- For each channel
- one row of pixel value.
- (Each pixel value is a byte 0-255.)
- (3) TEXT : Readable file
- Header line:
- color_channels cols rows
- Followed by
- For each row
- for each channel
- one row of integer pixel value
- (0 to 255).
- (4) RADIANCE : Radiance output format.
- (5) SUNRASTER format.
- ------
- sumant
- */
-
- #include <stdio.h>
- #include <math.h>
- #include <malloc.h>
-
- #include "GraphicsGems.h"
- #include "data_structure.h"
- #include "objects.h"
- #include "vox.h"
- #include "render.h"
- extern int verbose_flag;
-
- #include "raddecl.h"
-
- #include "rle.h"
- rle_pixel **rle_rows=NULL;
-
- #include "color.h"
- #include "resolu.h"
- COLOR *scanout;
-
- #include "rasterfile.h"
- unsigned char *rowbuffer=NULL;
-
- static void initialise_output(rows,cols,fl)
- int rows,cols;
- FILE *fl;
- {
- if (output_format==Rle){
- rle_dflt_hdr.ncolors=color_channels;
- rle_dflt_hdr.xmax = cols-1;
- rle_dflt_hdr.ymax = rows-1;
- rle_dflt_hdr.rle_file = fl;
- rle_put_setup(&rle_dflt_hdr);
- (void)fflush(rle_dflt_hdr.rle_file);
- if (rle_rows==NULL)
- if (rle_row_alloc(&rle_dflt_hdr, &rle_rows) < 0)
- error("Unable to allocate image memory.");
- }
- else if (output_format==Radiance){
- fputformat(COLRFMT, fl);
- putc('\n', fl);
- fprtresolu(cols, rows, fl);
- scanout = (COLOR *)malloc(cols*sizeof(COLOR));
- if (scanout == NULL)
- error("out of memory to allocate scanline");
- }
- else if (output_format==Sunraster){
- struct rasterfile header;
- rowbuffer=(unsigned char *)malloc(
- sizeof(unsigned char)*cols*3);
- if (rowbuffer == NULL)
- error("out of memory to allocate scanline");
- header.ras_magic=RAS_MAGIC;
- header.ras_width=cols;
- header.ras_height=rows;
- header.ras_depth=24;
- header.ras_length=cols*rows;
- header.ras_type=RT_STANDARD;
- header.ras_maptype=RMT_RAW;
- header.ras_maplength=0;
-
- fwrite(&header,sizeof(unsigned char),sizeof(header),fl);
- }
- else if (output_format==Raw){
- /*
- Header of 5 bytes.
- Content:
- color_channels : 1 byte
- cols : 2 bytes
- rows : 2 bytes
- */
- unsigned char b;
- b = color_channels; fwrite(&b,1,1,fl);
- b = cols;fwrite(&b,1,1,fl);
- b = cols>>8;fwrite(&b,1,1,fl);
- b = rows;fwrite(&b,1,1,fl);
- b = rows>>8;fwrite(&b,1,1,fl);
- }
- else fprintf(fl,"%d %d %d\n",color_channels,cols,rows);
- }
-
- extern double brightness_mult_factor;
- /*
- brightness_mult_factor: (default = 1.0)
- A mechanism to brighten up less bright area, with
- the understainding that any intensity above 1 will
- clamped to 1.
- */
- static unsigned char quantise(f)
- double f;
- {
- int c = (int)(f * brightness_mult_factor * 255);
- if (c > 255) c = 255;
- else if (c < 0) c = 0;
- return((unsigned char)c);
- }
-
- static void dump_row(fl,cols,row_pixels)
- FILE *fl;
- int cols;
- Pixel *row_pixels;
- {
- int i,j;
- if (output_format==Rle){
- for(j=0;j<color_channels;j++)
- for(i=0;i<cols;i++)
- rle_rows[j][i]=quantise(row_pixels[i].color[j]);
- rle_putrow( rle_rows,cols,&rle_dflt_hdr);
- }
- else if (output_format==Radiance){
- int components=color_channels;
- if (components>3) components=3;
- for(i=0;i<cols;i++){
- for(j=0;j<components;j++)
- scanout[i][j]=row_pixels[i].color[j]*
- brightness_mult_factor;
- for(j=components;j<3;j++) scanout[i][j]=0.;
- }
- if (fwritescan(scanout, cols, fl) < 0)
- error("error writing Radiance picture");
- }
- else if (output_format==Sunraster){
- int components=color_channels;
- if (components>3) components=3;
- for(i=0;i<cols;i++){
- for(j=0;j<components;j++)
- rowbuffer[3*i+j]=
- quantise(row_pixels[i].color[j]);
- for(j=components;j<3;j++) rowbuffer[3*i+j]=0;
- }
- if (fwrite(rowbuffer, sizeof(unsigned char),3*cols, fl)
- < 0)
- error("error writing SunRaster picture");
- }
- else if (output_format==Raw)
- for(j=0;j<color_channels;j++)
- for(i=0;i<cols;i++){
- unsigned char b;
- b = quantise(row_pixels[i].color[j]);
- fwrite(&b,1,1,fl);
- }
- else
- for(j=0;j<color_channels;j++){
- for(i=0;i<cols;i++)
- fprintf(fl,"%d ",quantise(row_pixels[i].color[j]));
- fprintf(fl,"\n");
- }
-
- }
-
- static void terminate_frame(fl)
- FILE *fl;
- {
- if (output_format==Rle) {
- rle_puteof(&rle_dflt_hdr);
- fclose(fl);
- }
- else if (output_format==Radiance){
- free((char *)scanout);
- fclose(fl);
- }
- else if (output_format==Sunraster){
- free((char *)rowbuffer);
- fclose(fl);
- }
- else fclose(fl);
- }
-
- static void terminate_output(fl)
- FILE *fl;
- {
- if (output_format==Rle)
- if (rle_rows != NULL){
- rle_row_free(&rle_dflt_hdr,rle_rows);
- rle_rows = NULL;
- }
- }
-
- static void color_from_diffuse_surface(ray,n,t,u1,v1,s)
- /*
- Returns the computed view independent intensity.
- */
- Ray *ray;
- int n;
- double t,u1,v1;
- Pixel *s;
- {
- int i;
- double Uindex=grid_u(n,u1);
- double Vindex=grid_v(n,v1);
- int uindex=(int)Uindex;
- int vindex=(int)Vindex;
-
- if ((view.shading_type == FLAT)||
- ((object[n].grid_h_reso==1)&&(object[n].grid_v_reso==1))){
- int gindex=gridindex(n,uindex,vindex);
- double *scolor=object[n].grid[gindex].normalized_flux_density;
- for(i=0;i<color_channels;i++) s->color[i]=scolor[i];
- }
- else{/* (view.shading_type == GOURAUD) */
- /*
- Bilinear Interpolation.
- -----------------------
- | |
- | |
- (P7) | (P8) | (P9)
- | |
- P01| |P11
- --------------------------------------
- | |
- | (Unindex, |
- (P4) | Vindex) | (P6)
- | * |
- | |
- P00 | | P10
- ----uindex,vindex---------------------
- | |
- | |
- (P1) | (P2) | (P3)
- | |
- | |
- */
- double P00,P10,P11,P01;
- double u=Uindex-uindex,v=Vindex-vindex;
- double *P1,*P2,*P3,*P4,*P5,*P6,*P7,*P8,*P9;
- int i,j;
- i=uindex-1;j=vindex-1;
- P1=object[n].grid[gridindex(n,i,j)].normalized_flux_density;
- i++;
- P2=object[n].grid[gridindex(n,i,j)].normalized_flux_density;
- i++;
- P3=object[n].grid[gridindex(n,i,j)].normalized_flux_density;
- i=uindex-1;j=vindex;
- P4=object[n].grid[gridindex(n,i,j)].normalized_flux_density;
- i++;
- P5=object[n].grid[gridindex(n,i,j)].normalized_flux_density;
- i++;
- P6=object[n].grid[gridindex(n,i,j)].normalized_flux_density;
- i=uindex-1;j=vindex+1;
- P7=object[n].grid[gridindex(n,i,j)].normalized_flux_density;
- i++;
- P8=object[n].grid[gridindex(n,i,j)].normalized_flux_density;
- i++;
- P9=object[n].grid[gridindex(n,i,j)].normalized_flux_density;
- for(i=0;i<color_channels;i++){
- P00=(P1[i]+P2[i]+P4[i]+P5[i])/4.0;
- P10=(P2[i]+P3[i]+P5[i]+P6[i])/4.0;
- P11=(P5[i]+P6[i]+P8[i]+P9[i])/4.0;
- P01=(P4[i]+P5[i]+P7[i]+P8[i])/4.0;
- s->color[i]=(1-u)*(P00*(1.0-v)+P01*v)+u*(P10*(1.0-v)+P11*v);
- }
- }
- }
-
- static void color_from_specular_surface(ray,objectnum,t,u,v,s)
- /*
- There is no view independent information in this surface.
- This surface was used as a path for light transport.
- So the view ray has to be reflected from this surface and the
- process continued till a diffuse surface is reached.
-
- IMPORTANT
- ---------
- 1.The ray start position and the direction are changed.
- 2.As get_color is called with the new ray this leads to RECURSION.
-
- */
- Ray *ray;
- int objectnum;
- double t,u,v;
- Pixel *s;
- {
- Pixel get_color();
- Vector3 N;
- /* .... set the new ray */
- point_on_line(ray->start,ray->direction,t,ray->start);
- N = ofunc[object[objectnum].surface_geometry_type].
- get_surface_normal(
- object[objectnum].object_specific_structure,u,v
- );
- mirror_reflection(&N,&(ray->direction),&(object[objectnum]));
- (ray->number)++;
- *s=get_color(ray);
- }
-
- static void color_from_other_surface(ray,objectnum,t,u,v,s)
- Ray *ray;
- int objectnum;
- double t,u,v;
- Pixel *s;
- {
- error("Not Implemented.");
- }
-
- static void (*get_surface_specific_color[MAX_REFLECTION_TYPE])()={
- color_from_diffuse_surface,
- color_from_specular_surface,
- color_from_other_surface
- };
-
- static Pixel get_color(ray)
- /*
- i
- IMPORTANT
- ---------
- If nondiffuse surfaces are present, get_color invokes itself indirectly
- from get_surface_specific_color with modified ray. So the ray.start and
- directions are changed.
- */
- Ray *ray;
- {
- int i;
- double t_entry,t_exit;
- int HitBoundingBox();
- Pixel pixel;
-
- /* Initialise */
- for(i=0;i<color_channels;i++)pixel.color[i]=0;
-
- if (HitBoundingBox(&(volume_grid.extent.min),&(volume_grid.extent.max),
- &(ray->start),&(ray->direction),&t_entry,&t_exit)){
- int get_nearest_object_in_voxel();
- Vlist *create_vlist();
- Vlist *vlist,*templist;
- int nearest_object= UNDEFINED;
- double t,u,v;
- vlist=templist=create_vlist(
- &(ray->start),&(ray->direction),t_entry,t_exit
- );
- while (templist!=NULL){
- Voxel *vox = volume_grid.voxels+templist->voxnum;
- double tmax=templist->t_far, tmin=templist->t_near;
- /* ASSERT((tmax>=0)&&(tmin>=0)); */
- if(vox->nobjects)
- if((nearest_object=get_nearest_object_in_voxel
- (ray,templist->t_near,templist->t_far,vox,&t,&u,&v))
- !=UNDEFINED) tmax=t;
- if (nearest_object!=UNDEFINED) break;
- templist=templist->next;
- }
- purge_vlist(vlist);
- if (nearest_object!=UNDEFINED){
- /* Add the attenuated surface intensity */
- Pixel from_surface;
- get_surface_specific_color[
- object[nearest_object].surface_reflection_type
- ](ray,nearest_object,t,u,v,&from_surface);
- for(i=0;i<color_channels;i++)
- pixel.color[i] += from_surface.color[i];
- }
- }
- return(pixel);
- }
-
-
- long render(flname)
- /*
- Using Ray-tracing for rendering using the computed equillibrium
- flux-density on the surfaces.
-
- Initialises the new ray ray_number to (total_rays+1) so that the mail_box querry
- is proper.
- */
- char *flname;
- {
- int i,j,k;
- Pixel get_color();
- Pixel *row_pixels;
- Ray ray;
- char name[100];
- FILE *fl;
-
- row_pixels = (Pixel *)malloc(sizeof(Pixel)*view.cols);
- ray.number=total_rays;
- #if defined (DEBUG)
- ray.intersections=0;
- #endif
- ray.path_length= -1;
- for(i=0; i < view.nframes; i++){
- if(view.nframes>1)sprintf(name,"%s.%03d",flname,i);
- else sprintf(name,"%s",flname);
- if (verbose_flag)fprintf(stderr,"Image file %s:",name);
- #if defined(__MSDOS__) || defined(__WATCOMC__)
- if ((fl = fopen(name,"wb"))==NULL)
- error("Cannot open Image file.");
- #else
- if ((fl = fopen(name,"w"))==NULL)
- error("Cannot open Image file.");
- #endif
- initialise_output(view.rows,view.cols,fl);
- for (j=0; j < view.rows; j++){
- Vector3 dir;
- dir=view.view_direction[i];
- for(k=0; k < view.cols; k++){
- ray.start=view.eye_point[i];
- ray.direction=dir;
- V3Normalize(&(ray.direction));
- row_pixels[k]=get_color(&ray);
- (ray.number)++;
- V3Add(&dir,&(view.delta_u[i]),&dir);
- }
- dump_row(fl,view.cols,row_pixels);
- V3Add(&(view.view_direction[i]),&(view.delta_v[i]),
- &(view.view_direction[i]));
- if (verbose_flag)fprintf(stderr,".");
- }
- terminate_frame(fl);
- if (verbose_flag)fprintf(stderr,"\n");
- }
- terminate_output(fl);
- free(row_pixels);
- return(ray.number-total_rays);
- }