home *** CD-ROM | disk | FTP | other *** search
- /*
- (c) 1990 S.Hawtin.
- Permission is granted to copy this file provided
- 1) It is not used for commercial gain
- 2) This notice is included in all copies
- 3) Altered copies are marked as such
-
- No liability is accepted for the contents of the file.
-
- render.c within NorthC render
- */
-
- /*
- Quick hack to play with transforms for three dimensional objects
- */
-
- #include <stdio.h>
- #include <stddef.h>
- #include <math.h>
-
- #include "3d.h"
-
- /* Controlling variables */
- int solid_fill = -1;
- double rot1 = 0.120;
- double rot2 = 0.011;
-
- /* The position of the lights, they are fixed relative to the viewer */
-
- #define LCOUNT 5
-
- long lights[LCOUNT][3] =
- {
- { 278, 356, 634},
- { 500,-1000,-250},
- {-2000, 0, 1000},
- {0,0,0},
- {0,0,0},
- };
-
- char object_name[32] = "objects/boat.dat";
-
- /* The object is made of an array of triangles */
-
- Triangle **object;
- int obj_count;
-
- Vertex **vertices;
- int vertex_count;
-
- /* Here are the triangles we must draw */
- Triangle **draw_list;
- int draw_count;
-
- /* Angle object is being viewed from */
- double view[2] =
- {0.3,4.0};
-
- /* Transformation matrix in 1024th */
-
- static int scale_factor = 1024;
-
- long transform[4][4] =
- {{ -512, -737, -737, 0},
- { 870, -431, -256, 0},
- { 0, 512, -870, 0},
- { 0, 0, 0, 1024}
- };
-
- trans_vertex(vtex)
- Vertex *vtex;
- {/* Transform a single vertex */
- register long temp;
- if(vtex->is_done==0)
- {/* This vertex has not yet been done, do it */
- temp = (transform[0][0] * vtex->logical.x +
- transform[0][1] * vtex->logical.y +
- transform[0][2] * vtex->logical.z)/(1024*SCALE);
- vtex->screen.x = (int)temp;
- temp = (transform[1][0] * vtex->logical.x +
- transform[1][1] * vtex->logical.y +
- transform[1][2] * vtex->logical.z)/(1024*SCALE);
- vtex->screen.y = (int)temp;
- temp = (transform[2][0] * vtex->logical.x +
- transform[2][1] * vtex->logical.y +
- transform[2][2] * vtex->logical.z)/(1024*SCALE);
- vtex->screen.z = (int)temp;
- vtex->is_done = -1;
- }
- }
-
- int
- illuminate(vect)
- Vector *vect;
- {/* Work out the ammount of illumination from the normal to the
- surface */
- long tx,ty,tz;
- long i,factor,add;
- long sum = 0;
- tx = (transform[0][0] * vect->x + transform[0][1] * vect->y +
- transform[0][2] * vect->z)/1024;
- ty = (transform[1][0] * vect->x + transform[1][1] * vect->y +
- transform[1][2] * vect->z)/1024;
- tz = (transform[2][0] * vect->x + transform[2][1] * vect->y +
- transform[2][2] * vect->z)/1024;
- for(i=0;i<LCOUNT;i++)
- {/* Sum the illumination from each light */
- add = (tx * lights[i][0] + ty * lights[i][1] + tz * lights[i][2]);
- if(add>0)
- sum += add;
- }
- sum = sum/(LCOUNT*1024);
- if(sum>1023)
- return(1023);
- else
- return((int)sum);
- }
-
- int
- cmpz(tri1,tri2)
- Triangle **tri1;
- Triangle **tri2;
- {/* Compare the z values of the triangle centres */
- #ifndef TEST_LIGHTS
- if(tri1[0]->centre.screen.z > tri2[0]->centre.screen.z)
- return(1);
- else if(tri1[0]->centre.screen.z == tri2[0]->centre.screen.z)
- #else
- if(tri1[0]->centre.logical.z > tri2[0]->centre.logical.z)
- return(1);
- else if(tri1[0]->centre.logical.z == tri2[0]->centre.logical.z)
- #endif
- return(0);
- else
- return(-1);
- }
-
- display_object()
- {/* Display the object, first work out all the points */
- int i;
- draw_count = 0;
- for(i=0;i<obj_count;i++)
- {/* Work out the real points for the whole object */
- #ifndef TEST_LIGHTS
- if((transform[2][0] * object[i]->normal.x +
- transform[2][1] * object[i]->normal.y +
- transform[2][2] * object[i]->normal.z)>0)
- #else
- if((object[i]->normal.z)>0)
- #endif
- {trans_vertex(object[i]->v1);
- trans_vertex(object[i]->v2);
- trans_vertex(object[i]->v3);
- trans_vertex(&(object[i]->centre));
- /* Work out the brightness of the lights */
- object[i]->shade = illuminate(&(object[i]->normal));
- draw_list[draw_count++] = object[i];
- }
- }
- qsort(draw_list,draw_count,sizeof(Triangle *),cmpz);
- clear_screen();
- for(i=0;i<draw_count;i++)
- draw_tri((int)((draw_list[i]->shade)/64),
- (int)(draw_list[i]->v1->screen.x),
- (int)(draw_list[i]->v1->screen.y),
- (int)(draw_list[i]->v2->screen.x),
- (int)(draw_list[i]->v2->screen.y),
- (int)(draw_list[i]->v3->screen.x),
- (int)(draw_list[i]->v3->screen.y));
- }
-
- /* Read the object description, */
-
- init_triangle(tri)
- Triangle *tri;
- {long nx,ny,nz,length;
- /* Initialise the triangle once the corners are set up */
- tri->centre.logical.x = (tri->v1->logical.x + tri->v2->logical.x +
- tri->v3->logical.x)/3;
- tri->centre.logical.y = (tri->v1->logical.y + tri->v2->logical.y +
- tri->v3->logical.y)/3;
- tri->centre.logical.z = (tri->v1->logical.z + tri->v2->logical.z +
- tri->v3->logical.z)/3;
-
- nx=(tri->v1->logical.y * (tri->v3->logical.z - tri->v2->logical.z)
- + tri->v2->logical.y * (tri->v1->logical.z - tri->v3->logical.z)
- + tri->v3->logical.y * (tri->v2->logical.z - tri->v1->logical.z));
- ny=(tri->v1->logical.z * (tri->v3->logical.x - tri->v2->logical.x)
- + tri->v2->logical.z * (tri->v1->logical.x - tri->v3->logical.x)
- + tri->v3->logical.z * (tri->v2->logical.x - tri->v1->logical.x));
- nz=(tri->v1->logical.x * (tri->v3->logical.y - tri->v2->logical.y)
- + tri->v2->logical.x * (tri->v1->logical.y - tri->v3->logical.y)
- + tri->v3->logical.x * (tri->v2->logical.y - tri->v1->logical.y));
- /* Now make the vector 1024 units long */
- length = (long)sqrt((double)(nx*nx+ny*ny+nz*nz));
- tri->normal.x = (nx*1024)/length;
- tri->normal.y = (ny*1024)/length;
- tri->normal.z = (nz*1024)/length;
- }
-
- read_file(fptr)
- FILE *fptr;
- {/* First a count of the vertex list */
- Vertex *vdata;
- Triangle *tdata;
- int i,n1,n2,n3;
- char next;
-
- fscanf(fptr,"%d",&vertex_count);
- if(vertex_count<=0)
- printf("No vertices in object\n");
- vertices = (Vertex **)calloc(sizeof(Vertex *),vertex_count);
- vdata = (Vertex *)calloc(sizeof(Vertex),vertex_count);
- if(vertices==NULL || vdata==NULL)
- {printf("Failed to malloc space\n");
- exit(EXIT_FAILURE);
- }
- for(i=0;i<vertex_count;i++)
- {/* Set up the vertex stuff */
- vertices[i] = vdata;
- fscanf(fptr,"%d %d %d",&(vdata->logical.x),
- &(vdata->logical.y),&vdata->logical.z);
- next = fgetc(fptr);
- while(next!='\n')
- next = fgetc(fptr);
- vdata++;
- }
- fscanf(fptr,"%d",&obj_count);
- if(obj_count<=0)
- printf("No triangles in object\n");
- object = (Triangle **)calloc(sizeof(Triangle *),obj_count);
- draw_list = (Triangle **)calloc(sizeof(Triangle *),obj_count);
- tdata = (Triangle *)calloc(sizeof(Triangle),obj_count);
- if(object==NULL || draw_list==NULL || tdata==NULL)
- {printf("Failed to malloc space\n");
- exit(EXIT_FAILURE);
- }
- for(i=0;i<obj_count;i++)
- {/* Set up the triangle stuff */
- object[i] = tdata;
- fscanf(fptr,"%d %d %d",&n1,&n2,&n3);
- tdata->v1 = vertices[n1];
- tdata->v2 = vertices[n2];
- tdata->v3 = vertices[n3];
- next = fgetc(fptr);
- while(next!='\n')
- next = fgetc(fptr);
- init_triangle(tdata);
- tdata++;
- }
- }
-
- /* Transform the view into a transform */
-
- trans_view()
- {/* Constructthe transformation matrix */
- int i;
- double sinth,costh,sinph,cosph;
-
- sinth = sin(view[0]);
- costh = cos(view[0]);
- sinph = sin(view[1]);
- cosph = cos(view[1]);
-
- transform[0][0] = (long)(-sinth*scale_factor); /* -sin(th) */
- transform[2][0] = (long)(costh*scale_factor); /* cos(th) */
- transform[1][0] = (long)0; /* 0 */
-
- transform[0][1] = (long)(-costh*cosph*scale_factor);/* -cos(th)cos(ph) */
- transform[2][1] = (long)(-sinth*cosph*scale_factor);/* -sin(th)cos(ph) */
- transform[1][1] = (long)(sinph*scale_factor); /* sin(ph) */
-
- transform[0][2] = (long)(-costh*sinph*scale_factor);/* -cos(th)sin(ph) */
- transform[2][2] = (long)(-sinth*sinph*scale_factor);/* -sin(th)sin(ph) */
- transform[1][2] = (long)(-cosph*scale_factor); /* -cos(ph) */
-
- /* Note that we havent done any of the transforms yet */
- for(i=0;i<obj_count;i++)
- {object[i]->centre.is_done = 0;
- }
- for(i=0;i<vertex_count;i++)
- {vertices[i]->is_done = 0;
- }
- }
-
- /* SHOW_FACES is set when creating objects */
- /* #define SHOW_FACES */
-
- main(argc,argv)
- int argc;
- char **argv;
- {
- FILE *fptr;
- int i;
-
- /* Read the object file */
- if(argc>=2)
- {strcpy(object_name,argv[argc-1]);
- }
- else
- scale_factor = 1500;
- fptr = fopen(object_name,"r");
- if(fptr==NULL)
- {printf("Cannot open %s\n",object_name);
- exit(EXIT_FAILURE);
- }
- read_file(fptr);
- /* Set SHOW_FACES to get a print out of the centres and normals of
- all the faces, very useful when defining objects */
- #ifdef SHOW_FACES
- for(i=0;i<obj_count;i++)
- {printf("Face %d %5d,%5d,%5d\n",i,object[i]->normal.x,
- object[i]->normal.y,object[i]->normal.z);
- printf(" cent %5d,%5d,%5d\n",object[i]->centre.logical.x,
- object[i]->centre.logical.y,object[i]->centre.logical.z);
- }
- #endif /* SHOW_FACES */
- /* Set up the screen */
- init_screen();
- /* Keep displaying forever, the code calls exit() when its done */
- while(-1)
- {
- trans_view();
- display_object();
- view[0] += rot1;
- view[1] += rot2;
- }
- }
-