home *** CD-ROM | disk | FTP | other *** search
/ The Fred Fish Collection 1.5 / ffcollection-1-5-1992-11.iso / ff_disks / 300-399 / ff384.lzh / NorthC / Example1.LZH / cRender / render.c < prev    next >
C/C++ Source or Header  |  1990-09-09  |  10KB  |  329 lines

  1. /*
  2.   (c) 1990 S.Hawtin.
  3.   Permission is granted to copy this file provided
  4.    1) It is not used for commercial gain
  5.    2) This notice is included in all copies
  6.    3) Altered copies are marked as such
  7.  
  8.   No liability is accepted for the contents of the file.
  9.  
  10.     render.c    within        NorthC render
  11. */
  12.  
  13. /*
  14.  Quick hack to play with transforms for three dimensional objects
  15. */
  16.  
  17. #include <stdio.h>
  18. #include <stddef.h>
  19. #include <math.h>
  20.  
  21. #include "3d.h"
  22.  
  23. /* Controlling variables */
  24. int solid_fill = -1;
  25. double rot1 = 0.120;
  26. double rot2 = 0.011;
  27.  
  28. /* The position of the lights, they are fixed relative to the viewer */
  29.  
  30. #define LCOUNT 5
  31.  
  32. long lights[LCOUNT][3] =
  33.    {
  34.     { 278, 356, 634},
  35.     {  500,-1000,-250},
  36.     {-2000,    0, 1000},
  37.     {0,0,0},
  38.     {0,0,0},
  39.     };
  40.  
  41. char object_name[32] = "objects/boat.dat";
  42.  
  43. /* The object is made of an array of triangles */
  44.  
  45. Triangle **object;
  46. int obj_count;
  47.  
  48. Vertex **vertices;
  49. int    vertex_count;
  50.  
  51. /* Here are the triangles we must draw */
  52. Triangle **draw_list;
  53. int draw_count;
  54.  
  55. /* Angle object is being viewed from */
  56. double view[2] =
  57.    {0.3,4.0};
  58.  
  59. /* Transformation matrix in 1024th */
  60.  
  61. static int scale_factor = 1024;
  62.  
  63. long transform[4][4] =
  64.    {{ -512, -737, -737,    0},
  65.     {  870, -431, -256,    0},
  66.     {    0,  512, -870,    0},
  67.     {    0,    0,    0, 1024}
  68.     };
  69.  
  70. trans_vertex(vtex)
  71.     Vertex *vtex;
  72.    {/* Transform a single vertex */
  73.     register long temp;
  74.     if(vtex->is_done==0)
  75.        {/* This vertex has not yet been done, do it */
  76.         temp = (transform[0][0] * vtex->logical.x +
  77.                 transform[0][1] * vtex->logical.y +
  78.                 transform[0][2] * vtex->logical.z)/(1024*SCALE);
  79.     vtex->screen.x = (int)temp;
  80.         temp = (transform[1][0] * vtex->logical.x +
  81.                 transform[1][1] * vtex->logical.y +
  82.                 transform[1][2] * vtex->logical.z)/(1024*SCALE);
  83.     vtex->screen.y = (int)temp;
  84.         temp = (transform[2][0] * vtex->logical.x +
  85.                 transform[2][1] * vtex->logical.y +
  86.                 transform[2][2] * vtex->logical.z)/(1024*SCALE);
  87.     vtex->screen.z = (int)temp;
  88.     vtex->is_done = -1;
  89.         }
  90.     }
  91.  
  92. int
  93. illuminate(vect)
  94.     Vector *vect;
  95.    {/* Work out the ammount of illumination from the normal to the
  96.        surface */
  97.     long tx,ty,tz;
  98.     long i,factor,add;
  99.     long sum = 0;
  100.     tx = (transform[0][0] * vect->x + transform[0][1] * vect->y +
  101.                           transform[0][2] * vect->z)/1024;
  102.     ty = (transform[1][0] * vect->x + transform[1][1] * vect->y +
  103.                           transform[1][2] * vect->z)/1024;
  104.     tz = (transform[2][0] * vect->x + transform[2][1] * vect->y +
  105.                           transform[2][2] * vect->z)/1024;
  106.     for(i=0;i<LCOUNT;i++)
  107.        {/* Sum the illumination from each light */
  108.         add = (tx * lights[i][0] + ty * lights[i][1] + tz * lights[i][2]);
  109.         if(add>0)
  110.         sum += add;
  111.         }
  112.     sum = sum/(LCOUNT*1024);
  113.     if(sum>1023)
  114.         return(1023);
  115.       else
  116.         return((int)sum);
  117.     }
  118.  
  119. int
  120. cmpz(tri1,tri2)
  121.     Triangle **tri1;
  122.     Triangle **tri2;
  123.    {/* Compare the z values of the triangle centres */
  124. #ifndef TEST_LIGHTS
  125.     if(tri1[0]->centre.screen.z > tri2[0]->centre.screen.z)
  126.         return(1);
  127.       else if(tri1[0]->centre.screen.z == tri2[0]->centre.screen.z)
  128. #else
  129.     if(tri1[0]->centre.logical.z > tri2[0]->centre.logical.z)
  130.         return(1);
  131.       else if(tri1[0]->centre.logical.z == tri2[0]->centre.logical.z)
  132. #endif
  133.         return(0);
  134.       else
  135.         return(-1);
  136.     }
  137.  
  138. display_object()
  139.    {/* Display the object, first work out all the points */
  140.     int i;
  141.     draw_count = 0;
  142.     for(i=0;i<obj_count;i++)
  143.        {/* Work out the real points for the whole object */
  144. #ifndef TEST_LIGHTS
  145.         if((transform[2][0] * object[i]->normal.x +
  146.             transform[2][1] * object[i]->normal.y +
  147.             transform[2][2] * object[i]->normal.z)>0)
  148. #else
  149.         if((object[i]->normal.z)>0)
  150. #endif
  151.            {trans_vertex(object[i]->v1);
  152.             trans_vertex(object[i]->v2);
  153.             trans_vertex(object[i]->v3);
  154.             trans_vertex(&(object[i]->centre));
  155.             /* Work out the brightness of the lights */
  156.             object[i]->shade = illuminate(&(object[i]->normal));
  157.             draw_list[draw_count++] = object[i];
  158.             }
  159.         }
  160.     qsort(draw_list,draw_count,sizeof(Triangle *),cmpz);
  161.     clear_screen();
  162.     for(i=0;i<draw_count;i++)
  163.         draw_tri((int)((draw_list[i]->shade)/64),
  164.                  (int)(draw_list[i]->v1->screen.x),
  165.                  (int)(draw_list[i]->v1->screen.y),
  166.                  (int)(draw_list[i]->v2->screen.x),
  167.                  (int)(draw_list[i]->v2->screen.y),
  168.                  (int)(draw_list[i]->v3->screen.x),
  169.                  (int)(draw_list[i]->v3->screen.y));
  170.     }
  171.  
  172. /* Read the object description, */
  173.  
  174. init_triangle(tri)
  175.     Triangle *tri;
  176.    {long nx,ny,nz,length;
  177.     /* Initialise the triangle once the corners are set up */
  178.     tri->centre.logical.x = (tri->v1->logical.x + tri->v2->logical.x + 
  179.                              tri->v3->logical.x)/3;
  180.     tri->centre.logical.y = (tri->v1->logical.y + tri->v2->logical.y + 
  181.                              tri->v3->logical.y)/3;
  182.     tri->centre.logical.z = (tri->v1->logical.z + tri->v2->logical.z + 
  183.                              tri->v3->logical.z)/3;
  184.  
  185.     nx=(tri->v1->logical.y * (tri->v3->logical.z - tri->v2->logical.z)
  186.         +  tri->v2->logical.y * (tri->v1->logical.z - tri->v3->logical.z)
  187.         +  tri->v3->logical.y * (tri->v2->logical.z - tri->v1->logical.z));
  188.     ny=(tri->v1->logical.z * (tri->v3->logical.x - tri->v2->logical.x)
  189.         +  tri->v2->logical.z * (tri->v1->logical.x - tri->v3->logical.x)
  190.         +  tri->v3->logical.z * (tri->v2->logical.x - tri->v1->logical.x));
  191.     nz=(tri->v1->logical.x * (tri->v3->logical.y - tri->v2->logical.y)
  192.         +  tri->v2->logical.x * (tri->v1->logical.y - tri->v3->logical.y)
  193.         +  tri->v3->logical.x * (tri->v2->logical.y - tri->v1->logical.y));
  194.     /* Now make the vector 1024 units long */
  195.     length = (long)sqrt((double)(nx*nx+ny*ny+nz*nz));
  196.     tri->normal.x = (nx*1024)/length;
  197.     tri->normal.y = (ny*1024)/length;
  198.     tri->normal.z = (nz*1024)/length;
  199.     }
  200.  
  201. read_file(fptr)
  202.     FILE *fptr;
  203.    {/* First a count of the vertex list */
  204.     Vertex   *vdata;
  205.     Triangle *tdata;
  206.     int i,n1,n2,n3;
  207.     char next;
  208.  
  209.     fscanf(fptr,"%d",&vertex_count);
  210.     if(vertex_count<=0)
  211.         printf("No vertices in object\n");
  212.     vertices = (Vertex **)calloc(sizeof(Vertex *),vertex_count);
  213.     vdata    = (Vertex *)calloc(sizeof(Vertex),vertex_count);
  214.     if(vertices==NULL || vdata==NULL)
  215.        {printf("Failed to malloc space\n");
  216.         exit(EXIT_FAILURE);
  217.         }
  218.     for(i=0;i<vertex_count;i++)
  219.        {/* Set up the vertex stuff */
  220.         vertices[i] = vdata;
  221.         fscanf(fptr,"%d %d %d",&(vdata->logical.x),
  222.                           &(vdata->logical.y),&vdata->logical.z);
  223.         next = fgetc(fptr);
  224.         while(next!='\n')
  225.             next = fgetc(fptr);
  226.         vdata++;
  227.         }
  228.     fscanf(fptr,"%d",&obj_count);
  229.     if(obj_count<=0)
  230.         printf("No triangles in object\n");
  231.     object  = (Triangle **)calloc(sizeof(Triangle *),obj_count);
  232.     draw_list = (Triangle **)calloc(sizeof(Triangle *),obj_count);
  233.     tdata   = (Triangle *)calloc(sizeof(Triangle),obj_count);
  234.     if(object==NULL || draw_list==NULL || tdata==NULL)
  235.        {printf("Failed to malloc space\n");
  236.         exit(EXIT_FAILURE);
  237.         }
  238.     for(i=0;i<obj_count;i++)
  239.        {/* Set up the triangle stuff */
  240.         object[i] = tdata;
  241.         fscanf(fptr,"%d %d %d",&n1,&n2,&n3);
  242.         tdata->v1 = vertices[n1];
  243.         tdata->v2 = vertices[n2];
  244.         tdata->v3 = vertices[n3];
  245.         next = fgetc(fptr);
  246.         while(next!='\n')
  247.             next = fgetc(fptr);
  248.         init_triangle(tdata);
  249.         tdata++;
  250.         }
  251.     }
  252.  
  253. /* Transform the view into a transform */
  254.  
  255. trans_view()
  256.    {/* Constructthe transformation matrix */
  257.     int i;
  258.     double sinth,costh,sinph,cosph;
  259.  
  260.     sinth = sin(view[0]);
  261.     costh = cos(view[0]);
  262.     sinph = sin(view[1]);
  263.     cosph = cos(view[1]);
  264.  
  265.     transform[0][0] = (long)(-sinth*scale_factor);    /* -sin(th) */
  266.     transform[2][0] = (long)(costh*scale_factor);    /* cos(th)  */
  267.     transform[1][0] = (long)0;                /* 0 */
  268.  
  269.     transform[0][1] = (long)(-costh*cosph*scale_factor);/* -cos(th)cos(ph) */
  270.     transform[2][1] = (long)(-sinth*cosph*scale_factor);/* -sin(th)cos(ph) */
  271.     transform[1][1] = (long)(sinph*scale_factor);    /* sin(ph) */
  272.  
  273.     transform[0][2] = (long)(-costh*sinph*scale_factor);/* -cos(th)sin(ph) */
  274.     transform[2][2] = (long)(-sinth*sinph*scale_factor);/* -sin(th)sin(ph) */
  275.     transform[1][2] = (long)(-cosph*scale_factor);    /* -cos(ph) */
  276.  
  277.     /* Note that we havent done any of the transforms yet */
  278.     for(i=0;i<obj_count;i++)
  279.        {object[i]->centre.is_done = 0;
  280.         }
  281.     for(i=0;i<vertex_count;i++)
  282.        {vertices[i]->is_done = 0;
  283.         }
  284.     }
  285.  
  286. /* SHOW_FACES is set when creating objects */
  287. /* #define SHOW_FACES */
  288.  
  289. main(argc,argv)
  290.     int argc;
  291.     char **argv;
  292.    {
  293.     FILE *fptr;
  294.     int i;
  295.  
  296.     /* Read the object file */
  297.     if(argc>=2)
  298.        {strcpy(object_name,argv[argc-1]);
  299.         }
  300.       else
  301.         scale_factor = 1500;
  302.     fptr = fopen(object_name,"r");
  303.     if(fptr==NULL)
  304.        {printf("Cannot open %s\n",object_name);
  305.         exit(EXIT_FAILURE);
  306.         }
  307.     read_file(fptr);
  308.     /* Set SHOW_FACES to get a print out of the centres and normals of
  309.        all the faces, very useful when defining objects */
  310. #ifdef SHOW_FACES
  311.     for(i=0;i<obj_count;i++)
  312.        {printf("Face %d %5d,%5d,%5d\n",i,object[i]->normal.x,
  313.          object[i]->normal.y,object[i]->normal.z);
  314.         printf("  cent  %5d,%5d,%5d\n",object[i]->centre.logical.x,
  315.          object[i]->centre.logical.y,object[i]->centre.logical.z);
  316.         }
  317. #endif /* SHOW_FACES */
  318.     /* Set up the screen */
  319.     init_screen();
  320.     /* Keep displaying forever, the code calls exit() when its done */
  321.     while(-1)
  322.        {
  323.         trans_view();
  324.     display_object();
  325.     view[0] += rot1;
  326.     view[1] += rot2;
  327.     }
  328.     }
  329.