home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / src / demos / VGX / shadows / glo_obj.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-08-02  |  11.7 KB  |  454 lines

  1. /*
  2.  * Copyright 1991, 1992, 1993, 1994, Silicon Graphics, Inc.
  3.  * All Rights Reserved.
  4.  *
  5.  * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
  6.  * the contents of this file may not be disclosed to third parties, copied or
  7.  * duplicated in any form, in whole or in part, without the prior written
  8.  * permission of Silicon Graphics, Inc.
  9.  *
  10.  * RESTRICTED RIGHTS LEGEND:
  11.  * Use, duplication or disclosure by the Government is subject to restrictions
  12.  * as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
  13.  * and Computer Software clause at DFARS 252.227-7013, and/or in similar or
  14.  * successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
  15.  * rights reserved under the Copyright Laws of the United States.
  16.  */
  17. /*
  18.     glo_obj.c - Code to support GL based 3D objects.
  19.  
  20.     Tim Heidmann, Silicon Graphics
  21.     Created    Oct 5, 1988
  22.     Last Edit  July 22, 1991
  23. */
  24.  
  25. #include <stdio.h>
  26. #include <gl.h>
  27. #include "glo_obj.h"
  28.  
  29. /* A cube:
  30.   5----6
  31.   |\   |\
  32.   | 1----2
  33.   | |  | |
  34.   4-|--7 |
  35.    \|   \|
  36.     0----3
  37. */
  38. int cube_list[] = {
  39.     NPERP,
  40.     BGNPOLY,  8,  4,  5,  6,  7, ENDPOLY, /* Back   */
  41.     BGNPOLY,  9,  3,  2,  1,  0, ENDPOLY, /* Front  */
  42.     BGNPOLY, 10,  0,  4,  7,  3, ENDPOLY, /* Bottom */
  43.     BGNPOLY, 11,  1,  2,  6,  5, ENDPOLY, /* Top    */
  44.     BGNPOLY, 12,  0,  1,  5,  4, ENDPOLY, /* Left   */
  45.     BGNPOLY, 13,  2,  3,  7,  6, ENDPOLY, /* Right  */
  46.     ENDLIST
  47. };
  48. float cube_t[][3] = {
  49.     -0.5, -0.5,  0.5, /*  0 - Front Face */
  50.     -0.5,  0.5,  0.5, /*  1 */
  51.      0.5,  0.5,  0.5, /*  2 */
  52.      0.5, -0.5,  0.5, /*  3 */
  53.     -0.5, -0.5, -0.5, /*  4 - Back Face */
  54.     -0.5,  0.5, -0.5, /*  5 */
  55.      0.5,  0.5, -0.5, /*  6 */
  56.      0.5, -0.5, -0.5, /*  7 */
  57.      0.0,  0.0, -1.0, /*  8 - Back Normal */
  58.      0.0,  0.0,  1.0, /*  9 - Front Normal */
  59.      0.0, -1.0,  0.0, /* 10 - Bottom Normal */
  60.      0.0,  1.0,  0.0, /* 11 - Top Normal */
  61.     -1.0,  0.0,  0.0, /* 12 - Left Normal */
  62.      1.0,  0.0,  0.0  /* 13 - Right Normal */
  63. };
  64. glo_ObjTyp glo_cube = {cube_list, cube_t};
  65.  
  66. struct glo_lnl {
  67.     int cmd;
  68.     char *name;
  69. } glo_ListNameList[] = {
  70.     {ENDLIST,  "ENDLIST"},
  71.     {BGNTMSH,  "BGNTMSH"},
  72.     {ENDTMSH,  "ENDTMSH"},
  73.     {SWAPTMSH, "SWAPTMSH"},
  74.     {BGNPOLY,  "BGNPOLY"},
  75.     {ENDPOLY,  "ENDPOLY"},
  76.     {BGNLINE,  "BGNLINE"},
  77.     {ENDLINE,  "ENDLINE"},
  78.     {NPERV,    "NPERV"},
  79.     {NPERP,    "NPERP"},
  80.     {NONORM,   "NONORM"}
  81. };
  82. int glo_ListNameListLen = (sizeof(glo_ListNameList)/sizeof(struct glo_lnl));
  83.  
  84. /* Useful function prototypes */
  85. char *
  86. glo_ListName(int listItem);
  87. int
  88. glo_ParseCmd(char name[]);
  89. Boolean
  90. glo_FileLine(FILE *fd, char buffer[]);
  91.  
  92.  
  93. void
  94. glo_DrawObj(glo_ObjPtr glop)
  95. {
  96.     int *lip, mode;
  97.  
  98.     if (glop == NULL) return;
  99.  
  100.     mode = NONORM;
  101.     lip = glop->list;
  102.     for (;;) {
  103.         switch (*lip++) {
  104.         case ENDLIST: return;
  105.         case NPERP: mode = NPERP; break;
  106.         case NPERV: mode = NPERV; break;
  107.         case NONORM: mode = NONORM; break;
  108.         case BGNPOLY: bgnpolygon();
  109.             switch (mode) {
  110.             case NPERP: /* Normal per polygon */
  111.                 if (*lip < 0) break;
  112.                 n3f(glop->t + *lip++);
  113.                 for (;;) {
  114.                     if (*lip < 0) break;
  115.                     v3f(glop->t + *lip++);
  116.                 }
  117.                 break;
  118.             case NPERV: /* Normal per vertex */
  119.                 for (;;) {
  120.                     if (*lip < 0) break;
  121.                     n3f(glop->t + *lip++);
  122.                     v3f(glop->t + *lip++);
  123.                 }
  124.                 break;
  125.             case NONORM: /* No Normals */
  126.                 for (;;) {
  127.                     if (*lip < 0) break;
  128.                     v3f(glop->t + *lip++);
  129.                 }
  130.                 break;
  131.             default: ; }
  132.             break;
  133.  
  134.         case ENDPOLY: endpolygon(); break;
  135.         default:
  136.         if (lip[-1] >= USEMATL && lip[-1] < 0) {
  137.         lmbind(MATERIAL, lip[-1] - USEMATL);
  138.         }
  139.         break;
  140.         }
  141.     }
  142. }
  143.  
  144.  
  145. void
  146. glo_DrawGeometry(glo_ObjPtr glop)
  147. {
  148.     /* Draw the object - geometry only, no lmbind()'s or n3f()'s */
  149.     int *lip, mode;
  150.  
  151.     if (glop == NULL) return;
  152.  
  153.     mode = NONORM;
  154.     lip = glop->list;
  155.     for (;;) {
  156.         switch (*lip++) {
  157.         case ENDLIST: return;
  158.         case NPERP: mode = NPERP; break;
  159.         case NPERV: mode = NPERV; break;
  160.         case NONORM: mode = NONORM; break;
  161.         case BGNPOLY: bgnpolygon();
  162.             switch (mode) {
  163.             case NPERP: /* Normal per polygon */
  164.                 if (*lip < 0) break;
  165.                 lip++; /* Skip the normal */
  166.                 for (;;) {
  167.                     if (*lip < 0) break;
  168.                     v3f(glop->t + *lip++);
  169.                 }
  170.                 break;
  171.             case NPERV: /* Normal per vertex */
  172.                 for (;;) {
  173.                     if (*lip < 0) break;
  174.             lip++; /* Skip the normal */
  175.                     v3f(glop->t + *lip++);
  176.                 }
  177.                 break;
  178.             case NONORM: /* No Normals */
  179.                 for (;;) {
  180.                     if (*lip < 0) break;
  181.                     v3f(glop->t + *lip++);
  182.                 }
  183.                 break;
  184.             default: ; }
  185.             break;
  186.  
  187.         case ENDPOLY: endpolygon(); break;
  188.         default:
  189.         /* Ignore material changes */
  190.         break;
  191.         }
  192.     }
  193. }
  194.  
  195.  
  196. void
  197. glo_DrawNormals(glo_ObjPtr glop)
  198. {
  199.     /* Draw just the normals as yellow vectors */
  200.     int *lip, mode;
  201.     float lastNormal[3];
  202.  
  203.     if (glop == NULL) return;
  204.  
  205.     mode = NONORM;
  206.     lip = glop->list;
  207.     for (;;) {
  208.         switch (*lip++) {
  209.         case ENDLIST: return;
  210.         case NPERP: mode = NPERP; break;
  211.         case NPERV: mode = NPERV; break;
  212.         case NONORM: mode = NONORM; break;
  213.         case BGNPOLY:
  214.         cpack(0xff00ffff);
  215.             switch (mode) {
  216.             case NPERP: /* Normal per polygon */
  217.                 if (*lip < 0) break;
  218.                 vcopy(glop->t + *lip++, lastNormal);
  219.         bgnline();
  220.         v3f(glop->t + *lip);
  221.         vadd(glop->t + *lip++, lastNormal, lastNormal);
  222.         v3f(lastNormal);
  223.         endline();
  224.                 for (;;) {
  225.                     if (*lip++ < 0) break;
  226.                 }
  227.                 break;
  228.             case NPERV: /* Normal per vertex */
  229.                 for (;;) {
  230.                     if (*lip < 0) break;
  231.             vcopy(glop->t + *lip++, lastNormal);
  232.             bgnline();
  233.                     v3f(glop->t + *lip);
  234.                     vadd(glop->t + *lip++, lastNormal, lastNormal);
  235.             v3f(lastNormal);
  236.             endline();
  237.                 }
  238.                 break;
  239.             case NONORM: /* No Normals */
  240.                 for (;;) {
  241.                     if (*lip++ < 0) break;
  242.                 }
  243.                 break;
  244.             default: ; }
  245.             break;
  246.  
  247.         case ENDPOLY:
  248.         break;
  249.         default:
  250.         break;
  251.         }
  252.     }
  253. }
  254.  
  255. glo_ObjPtr
  256. glo_NewObj(int nList, int nTriplets) {
  257.     glo_ObjPtr myObj;
  258.  
  259.     myObj = (glo_ObjPtr) malloc(sizeof(glo_ObjTyp));
  260.     myObj->list = (int *) malloc(sizeof(int) * nList);
  261.     myObj->t = (float (*)[3]) malloc(sizeof(float) * 3 * nTriplets);
  262.     myObj->list[0] = ENDLIST;
  263.     return myObj;
  264. }
  265.  
  266.  
  267. glo_ObjPtr
  268. glo_ReadObj(char filename[]) {
  269.     int i, j, iList, iTrip, nList, nTriplets, count, maxRef;
  270.     FILE *inf;
  271.     glo_ObjPtr myObj;
  272.     int *pList, l[16];
  273.     float *pTriplet, fileVersion;
  274.     char buf[256], cmd[60], fileType[60];
  275.  
  276.     if ((inf = fopen(filename, "r")) == NULL) {
  277.     fprintf(stderr, "Cannot open file %s for reading.\n", filename);
  278.     return NULL;
  279.     }
  280.  
  281.     /* Check file type.  Allocate space for lists. */
  282.     if (!glo_FileLine(inf, buf)) return NULL;
  283.     if (sscanf(buf,"%s %f", fileType, &fileVersion) != 2 ||
  284.         strcmp(fileType, "glo_obj") != 0) {
  285. /*
  286.     fprintf(stderr, "File %s is not a glo_obj file.\n", filename);
  287. */
  288.     return NULL;
  289.     }
  290.     if (!glo_FileLine(inf, buf)) {
  291.     fprintf(stderr, "Unexpected end of glo_obj file %s\n", filename);
  292.     return NULL;
  293.     }
  294.     sscanf(buf, "%d %d", &nList, &nTriplets);
  295.     myObj = glo_NewObj(nList, nTriplets);
  296.  
  297.     /* Read the command list */
  298.     maxRef = -1;
  299.     for (pList=myObj->list, iList=0; iList<nList; pList++, iList++) {
  300.     if (!glo_FileLine(inf, buf)) {
  301.         fprintf(stderr, "Unexpected end of glo_obj file %s\n", filename);
  302.         goto bail;
  303.     }
  304.     sscanf(buf, "%s", cmd);
  305.     if (cmd[0]>='0' && cmd[0]<='9') {
  306.         /* Read a list of indices */
  307.         count = sscanf(buf,
  308.         "%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d",
  309.         l, l+1, l+2, l+3, l+4, l+5, l+6, l+7, l+8, l+9,
  310.         l+10, l+11, l+12, l+13, l+14, l+15);
  311.         for (j=0; j<count; j++) {
  312.         pList[j] = l[j];
  313.         if (l[j] > maxRef) maxRef = l[j];
  314.         }
  315.         pList += j-1;
  316.         iList += j-1;
  317.     }
  318.     else {
  319.         /* Read and parse a command */
  320.         if (strcmp(cmd, "USEMATL")==0) {
  321.             /* Parse a USEMATL <matl #> command */
  322.             sscanf(buf, "%*s %d", &i);
  323.             *pList = USEMATL+i;
  324.         }
  325.         else {
  326.         /* Find a simple command */
  327.         if ((*pList = glo_ParseCmd(cmd)) == 0) {
  328.             fprintf(stderr, "Unknown keyword: %s\n", cmd);
  329.             goto bail;
  330.         }
  331.         if (*pList == ENDLIST) break;
  332.         }
  333.     }
  334.     }
  335.  
  336.     /* Read the triplet list */
  337.     for (iTrip=0, pTriplet= *myObj->t; iTrip<nTriplets; iTrip++, pTriplet+=3) {
  338.     if (!glo_FileLine(inf, buf) && iTrip <= maxRef) {
  339.         fprintf(stderr, "Unexpected end of glo_obj file %s\n", filename);
  340.         goto bail;
  341.     }
  342.     sscanf(buf, "%f %f %f", pTriplet, pTriplet+1, pTriplet+2);
  343.     }
  344.  
  345.     /* Finish up */
  346.     fclose(inf);
  347.     return myObj;
  348.  
  349.  
  350.     /* Free allocated memory and return failure */
  351. bail:
  352.     free(myObj->list);
  353.     free(myObj->t);
  354.     free(myObj);
  355.     return NULL;
  356. }
  357.  
  358. void
  359. glo_WriteObj(glo_ObjPtr theObj, char filename[]) {
  360.     int i, nList, nTriplets, iVerts;
  361.     FILE *outf;
  362.     int *pList;
  363.     float (*tList)[3];
  364.  
  365.     if ((outf = fopen(filename, "w")) == NULL) {
  366.     fprintf(stderr, "Cannot open file %s for writing.\n", filename);
  367. /* 3/25/93   ratman--trying to make compile on sherwood
  368.         return FALSE;
  369. */
  370.     exit(-1);
  371.     }
  372.  
  373.     /* Write the header: File type and Version,
  374.        then command list and triplet array lengths */
  375.     fprintf(outf, "glo_obj 1.0\n");
  376.     glo_GetLengths(theObj, &nList, &nTriplets);
  377.     fprintf(outf, "%d %d\n", nList, nTriplets);
  378.  
  379.     /* Write the command list */
  380.     for (pList = theObj->list;;)
  381.     if (*pList < 0) {
  382.         if (*pList >= USEMATL)
  383.         fprintf(outf, "USEMATL %d\n", *pList - USEMATL);
  384.         else
  385.         fprintf(outf, "%s\n", glo_ListName(*pList));
  386.         if (*pList == ENDLIST) break;
  387.         pList++;
  388.     } else {
  389.         for (iVerts=0; *pList >= 0; pList++, iVerts++) {
  390.         if (iVerts >= 16) {
  391.             /* Keep the output to 16 indices per line */
  392.             fprintf(outf, "\n");
  393.             iVerts = 0;
  394.         }
  395.         fprintf(outf, " %d", *pList);
  396.         }
  397.         fprintf(outf, "\n");
  398.     }
  399.     
  400.     /* Write the triplet list */
  401.     for (i=0, tList=theObj->t; i<nTriplets; i++,tList++)
  402.     fprintf(outf, "%12.6f %12.6f %12.6f\n",
  403.         (*tList)[0], (*tList)[1], (*tList)[2]);
  404.     
  405.     /* Finish up */
  406.     fclose(outf);
  407. /* 3/25/93   ratman--trying to make compile on sherwood
  408.     return TRUE;
  409. */
  410. }
  411.  
  412. void
  413. glo_GetLengths(glo_ObjPtr theObj, int *listLen, int *tripletLen) {
  414.     /* Return length of command and triplet lists,
  415.        based on the appearance of ENDLIST,
  416.        and the highest referenced triplet index. */
  417.     int i, highestTriplet;
  418.  
  419.     highestTriplet = -1;
  420.     for (i=0; theObj->list[i] != ENDLIST; i++)
  421.     if (theObj->list[i] > highestTriplet)
  422.         highestTriplet = theObj->list[i];
  423.     *listLen = i + 1;
  424.     *tripletLen = highestTriplet + 1;
  425. }
  426.  
  427. char *
  428. glo_ListName(int listItem) {
  429.     int i;
  430.     for (i=0; i<glo_ListNameListLen; i++)
  431.     if (listItem == glo_ListNameList[i].cmd)
  432.         return glo_ListNameList[i].name;
  433.     return NULL;
  434. }
  435.  
  436. int
  437. glo_ParseCmd(char name[]) {
  438.     int i;
  439.     for (i=0; i<glo_ListNameListLen; i++)
  440.     if (strcmp(name, glo_ListNameList[i].name)==0)
  441.         return glo_ListNameList[i].cmd;
  442.     return 0;
  443. }
  444.  
  445. Boolean
  446. glo_FileLine(FILE *fd, char buffer[]) {
  447.     /* Read a line from fd, skipping over comments */
  448.     do
  449.     if (fgets(buffer, 256, fd) == NULL) return FALSE;
  450.     while (buffer[0] == '#');
  451.     return TRUE;
  452. }
  453.  
  454.