/****************************************************************
 * File: legogen.c
 * 
 * Description:
 *    Creates a triangle mesh file describing a LEGO(R) building
 *    brick, in a variety of graphics formats.
 * 
 * Calling Syntax:
 *    legogen -[t|r|o|a] > filename.ext
 *
 * Examples:
 *    To generate a TAGL format triangle mesh:
 *       legogen -t > legomesh.tagl
 *    To generate a Rayshade format triangle mesh:
 *       legogen -r > legomesh.ray
 *    To generate an OFF format triangle mesh:
 *       legogen -o > legomesh.off
 *    To generate an AC3D  format triangle mesh:
 *       legogen -t > legomesh.tri
 *    To generate a VRML world file triangle mesh:
 *       legogen -v > legomesh.wrl
 *
 * History:
 * 1.0 July 24, 1996 pjg
 *    Initial Release
 *  
 ***************************************************************/

#include "stdio.h"
#include "stdlib.h"
#include "math.h"

#define TAGL_OUTPUT     1
#define RAYSHADE_OUTPUT 2
#define OFF_OUTPUT      3
#define AC3D_OUTPUT     4
#define VRML_OUTPUT     5

/*
 * Define the geometry of a LEGO brick.
 *
 * These are the x,y,z coordinates of each point in the mesh,
 * measured in centimeters.
*/
#define NUM_POINTS 180
#define NUM_FACES 320
float npoints[NUM_POINTS][3] = {
{0.0  ,	  0.0  ,  0.0 }, {3.2  ,   0.0,	    0.0 }, {3.2,     0.0,   0.96},
{0.0  ,	  0.0  ,  0.96}, {0.0  ,   1.6,	    0.0 }, {3.2,     1.6,   0.0},
{3.2  ,	  1.6  ,  0.96}, {0.0  ,   1.6,	    0.96}, {0.125,   0.125, 0},
{3.075,   0.125,  0   }, {3.075,   1.475,   0   }, {0.125,   1.475, 0},
{0.125,   0.125,   0.835},{3.075,   0.125,   0.835},{3.075,  1.475, 0.835},
{0.125,   1.475,   0.835},{0.23, 1.37, 0.96},{0.4,  1.44, 0.96},
{0.57, 1.37, 0.96},{0.64, 1.2, 0.96},{0.57, 1.03, 0.96},
{0.4,  0.96, 0.96},{0.23, 1.03, 0.96},{0.16, 1.2, 0.96},
{0.4,  1.2, 0.96},{1.2,  1.44, 0.96},{1.37, 1.37, 0.96},
{1.44, 1.2, 0.96},{1.37, 1.03, 0.96},{1.2,  0.96, 0.96},
{1.03, 1.03, 0.96},{0.96, 1.2, 0.96},{1.03, 1.37, 0.96},
{1.2,  1.2, 0.96},{2,    1.44, 0.96},{2.17, 1.37, 0.96},
{2.24, 1.2, 0.96},{2.17, 1.03, 0.96},{2,    0.96, 0.96},
{1.83, 1.03, 0.96},{1.76, 1.2, 0.96},{1.83, 1.37, 0.96},
{2,    1.2, 0.96},{2.8,  1.44, 0.96},{2.97, 1.37, 0.96},
{3.04, 1.2, 0.96},{2.97, 1.03, 0.96},{2.8,  0.96, 0.96},
{2.63, 1.03, 0.96},{2.56, 1.2, 0.96},{2.63, 1.37, 0.96},
{2.8,  1.2, 0.96},{0.4,  0.64, 0.96},{0.57, 0.57, 0.96},
{0.64, 0.4, 0.96},{0.57, 0.23, 0.96},{0.4,  0.16, 0.96},
{0.23, 0.23, 0.96},{0.16, 0.4, 0.96},{0.23, 0.57, 0.96},
{0.4,  0.4, 0.96},{1.2,  0.64, 0.96},{1.37, 0.57, 0.96},
{1.44, 0.4, 0.96},{1.37, 0.23, 0.96},{1.2,  0.16, 0.96},
{1.03, 0.23, 0.96},{0.96, 0.4, 0.96},{1.03, 0.57, 0.96},
{1.2,  0.4, 0.96},{2,    0.64, 0.96},{2.17, 0.57, 0.96},
{2.24, 0.4, 0.96},{2.17, 0.23, 0.96},{2,    0.16, 0.96},
{1.83, 0.23, 0.96},{1.76, 0.4, 0.96},{1.83, 0.57, 0.96},
{2,    0.4, 0.96},{2.8,  0.64, 0.96},{2.97, 0.57, 0.96},
{3.04, 0.4, 0.96},{2.97, 0.23, 0.96},{2.8,  0.16, 0.96},
{2.63, 0.23, 0.96},{2.56, 0.4, 0.96},{2.63, 0.57, 0.96},
{2.8, 0.4, 0.96},{0.4, 1.6, 0.96},{0.8, 1.6, 0.96},
{1.2, 1.6, 0.96},{1.6, 1.6, 0.96},{2.0, 1.6, 0.96},
{2.4, 1.6, 0.96},{2.8, 1.6, 0.96},{3.2, 1.2, 0.96},
{3.2, 0.8, 0.96},{3.2, 0.4, 0.96},{2.8, 0.0, 0.96},
{2.4, 0.0, 0.96},{2.0, 0.0, 0.96},{1.6, 0.0, 0.96},
{1.2, 0.0, 0.96},{0.8, 0.0, 0.96},{0.4, 0.0, 0.96},
{0,   0.4, 0.96},{0,   0.8, 0.96},{0,   1.2, 0.96},
{0.23, 1.37, 1.12},{0.4,  1.44, 1.12},{0.57, 1.37, 1.12},
{0.64, 1.2, 1.12},{0.57, 1.03, 1.12},{0.4,  0.96, 1.12},
{0.23, 1.03, 1.12},{0.16, 1.2, 1.12},{0.4,  1.2, 1.12},
{1.2,  1.44, 1.12},{1.37, 1.37, 1.12},{1.44, 1.2, 1.12},
{1.37, 1.03, 1.12},{1.2,  0.96, 1.12},{1.03, 1.03, 1.12},
{0.96, 1.2, 1.12},{1.03, 1.37, 1.12},{1.2,  1.2, 1.12},
{2,    1.44, 1.12},{2.17, 1.37, 1.12},{2.24, 1.2, 1.12},
{2.17, 1.03, 1.12},{2,    0.96, 1.12},{1.83, 1.03, 1.12},
{1.76, 1.2, 1.12},{1.83, 1.37, 1.12},{2,    1.2, 1.12},
{2.8,  1.44, 1.12},{2.97, 1.37, 1.12},{3.04, 1.2, 1.12},
{2.97, 1.03, 1.12},{2.8,  0.96, 1.12},{2.63, 1.03, 1.12},
{2.56, 1.2, 1.12},{2.63, 1.37, 1.12},{2.8,  1.2, 1.12},
{0.4,  0.64, 1.12},{0.57, 0.57, 1.12},{0.64, 0.4, 1.12},
{0.57, 0.23, 1.12},{0.4,  0.16, 1.12},{0.23, 0.23, 1.12},
{0.16, 0.4, 1.12},{0.23, 0.57, 1.12},{0.4,  0.4, 1.12},
{1.2,  0.64, 1.12},{1.37, 0.57, 1.12},{1.44, 0.4, 1.12},
{1.37, 0.23, 1.12},{1.2,  0.16, 1.12},{1.03, 0.23, 1.12},
{0.96, 0.4, 1.12},{1.03, 0.57, 1.12},{1.2,  0.4, 1.12},
{2,    0.64, 1.12},{2.17, 0.57, 1.12},{2.24, 0.4, 1.12},
{2.17, 0.23, 1.12},{2,    0.16, 1.12},{1.83, 0.23, 1.12},
{1.76, 0.4, 1.12},{1.83, 0.57, 1.12},{2,    0.4, 1.12},
{2.8,  0.64, 1.12},{2.97, 0.57, 1.12},{3.04, 0.4, 1.12},
{2.97, 0.23, 1.12},{2.8,  0.16, 1.12},{2.63, 0.23, 1.12},
{2.56, 0.4, 1.12},{2.63, 0.57, 1.12},{2.8,  0.4, 1.12}
};
/*
 *  These define the faces of the mesh. Since this is a triangle
 *  mesh, each entry has three vertices.  Start numbering the
 * vertices with "1", not "0".
*/
int nfaces[NUM_FACES][3] = {
{4, 3, 2},{4, 2, 1},{3, 7, 6},
{3, 6, 2},{7, 8, 5},{7, 5, 6},
{8, 4, 1},{8, 1, 5},{1, 2, 10},
{1, 10, 9},{12, 5, 1},{12, 1, 9},
{12, 11, 6},{12, 6, 5},{2, 6, 11},
{2, 11, 10},{13, 16, 12},{13, 12, 9},
{16, 15, 11},{16, 11, 12},{15, 14, 10},
{15, 10, 11},{14, 13, 9},{14, 9, 10},
{13, 14, 15},{13, 15, 16},{8, 89, 17},
{89, 18, 17},{89, 90, 18},{90, 19, 18},
{90, 33, 19},{90, 91, 33},{91, 26, 33},
{91, 92, 26},{92, 27, 26},{92, 42, 27},
{92, 93, 42},{93, 35, 42},{93, 94, 35},
{94, 36, 35},{94, 51, 36},{94, 95, 51},
{95, 44, 51},{95, 45, 44},{95, 7, 45},
{7, 96, 45},{96, 46, 45},{96, 47, 46},
{96, 97, 47},{97, 81, 47},{97, 98, 81},
{98, 82, 81},{98, 83, 82},{98, 3, 83},
{3, 99, 83},{99, 84, 83},{99, 85, 84},
{99, 100, 85},{100, 74, 85},{100, 101, 74},
{101, 75, 74},{101, 76, 75},{101, 102, 76},
{102, 65, 76},{102, 103, 65},{103, 66, 65},
{103, 67, 66},{103, 104, 67},{104, 56, 67},
{104, 105, 56},{105, 57, 56},{105, 58, 57},
{105, 4, 58},{4, 106, 58},{106, 59, 58},
{106, 60, 59},{106, 107, 60},{107, 23, 60},
{107, 108, 23},{108, 24, 23},{108, 17, 24},
{108, 8, 17},{19, 33, 20},{33, 32, 20},
{20, 32, 21},{32, 31, 21},{23, 22, 60},
{22, 53, 60},{22, 21, 53},{21, 54, 53},
{21, 31, 54},{31, 69, 54},{54, 69, 55},
{55, 69, 68},{55, 68, 56},{56, 68, 67},
{31, 30, 69},{30, 62, 69},{30, 29, 62},
{29, 63, 62},{27, 42, 28},{28, 42, 41},
{28, 41, 29},{41, 40, 29},{29, 40, 63},
{40, 78, 63},{63, 78, 64},{78, 77, 64},
{77, 76, 64},{64, 76, 65},{40, 39, 78},
{39, 71, 78},{39, 38, 71},{71, 38, 72},
{36, 51, 37},{51, 50, 37},{37, 50, 38},
{50, 49, 38},{38, 49, 72},{49, 87, 72},
{72, 87, 73},{87, 86, 73},{73, 86, 74},
{86, 85, 74},{49, 48, 87},{48, 80, 87},
{48, 47, 80},{47, 81, 80},{109, 110, 117},
{110, 111, 117},{111, 112, 117},{112, 113, 117},
{113, 114, 117},{114, 115, 117},{115, 116, 117},
{116, 109, 117},{17, 18, 109},{18, 110, 109},
{18, 19, 110},{19, 111, 110},{19, 20, 111},
{20, 112, 111},{20, 21, 112},{21, 113, 112},
{21, 22, 113},{22, 114, 113},{22, 23, 114},
{23, 115, 114},{23, 24, 115},{24, 116, 115},
{24, 17, 116},{17, 109, 116},{118, 119, 126},
{119, 120, 126},{120, 121, 126},{121, 122, 126},
{122, 123, 126},{123, 124, 126},{124, 125, 126},
{125, 118, 126},{26, 27, 118},{27, 119, 118},
{27, 28, 119},{28, 120, 119},{28, 29, 120},
{29, 121, 120},{29, 30, 121},{30, 122, 121},
{30, 31, 122},{31, 123, 122},{31, 32, 123},
{32, 124, 123},{32, 33, 124},{33, 125, 124},
{33, 26, 125},{26, 118, 125},{127, 128, 135},
{128, 129, 135},{129, 130, 135},{130, 131, 135},
{131, 132, 135},{132, 133, 135},{133, 134, 135},
{134, 127, 135},{35, 36, 127},{36, 128, 127},
{36, 37, 128},{37, 129, 128},{37, 38, 129},
{38, 130, 129},{38, 39, 130},{39, 131, 130},
{39, 40, 131},{40, 132, 131},{40, 41, 132},
{41, 133, 132},{41, 42, 133},{42, 134, 133},
{42, 35, 134},{35, 127, 134},{136, 137, 144},
{137, 138, 144},{138, 139, 144},{139, 140, 144},
{140, 141, 144},{141, 142, 144},{142, 143, 144},
{143, 136, 144},{44, 45, 136},{45, 137, 136},
{45, 46, 137},{46, 138, 137},{46, 47, 138},
{47, 139, 138},{47, 48, 139},{48, 140, 139},
{48, 49, 140},{49, 141, 140},{49, 50, 141},
{50, 142, 141},{50, 51, 142},{51, 143, 142},
{51, 44, 143},{44, 136, 143},{145, 146, 153},
{146, 147, 153},{147, 148, 153},{148, 149, 153},
{149, 150, 153},{150, 151, 153},{151, 152, 153},
{152, 145, 153},{53, 54, 145},{54, 146, 145},
{54, 55, 146},{55, 147, 146},{55, 56, 147},
{56, 148, 147},{56, 57, 148},{57, 149, 148},
{57, 58, 149},{58, 150, 149},{58, 59, 150},
{59, 151, 150},{59, 60, 151},{60, 152, 151},
{60, 53, 152},{53, 145, 152},{154, 155, 162},
{155, 156, 162},{156, 157, 162},{157, 158, 162},
{158, 159, 162},{159, 160, 162},{160, 161, 162},
{161, 154, 162},{62, 63, 154},{63, 155, 154},
{63, 64, 155},{64, 156, 155},{64, 65, 156},
{65, 157, 156},{65, 66, 157},{66, 158, 157},
{66, 67, 158},{67, 159, 158},{67, 68, 159},
{68, 160, 159},{68, 69, 160},{69, 161, 160},
{69, 62, 161},{62, 154, 161},{163, 164, 171},
{164, 165, 171},{165, 166, 171},{166, 167, 171},
{167, 168, 171},{168, 169, 171},{169, 170, 171},
{170, 163, 171},{71, 72, 163},{72, 164, 163},
{72, 73, 164},{73, 165, 164},{73, 74, 165},
{74, 166, 165},{74, 75, 166},{75, 167, 166},
{75, 76, 167},{76, 168, 167},{76, 77, 168},
{77, 169, 168},{77, 78, 169},{78, 170, 169},
{78, 71, 170},{71, 163, 170},{172, 173, 180},
{173, 174, 180},{174, 175, 180},{175, 176, 180},
{176, 177, 180},{177, 178, 180},{178, 179, 180},
{179, 172, 180},{80, 81, 172},{81, 173, 172},
{81, 82, 173},{82, 174, 173},{82, 83, 174},
{83, 175, 174},{83, 84, 175},{84, 176, 175},
{84, 85, 176},{85, 177, 176},{85, 86, 177},
{86, 178, 177},{86, 87, 178},{87, 179, 178},
{87, 80, 179},{80, 172, 179}
};

main(int argc, char *argv[]) 
{
  int i,j,k;
  int fmt;
  
  if (argc !=2) {
    fprintf(stderr,"legogen prints a triangle mesh to stdout\n");
    fprintf(stderr,"Syntax: legogen -[t|r|o|a|v]\n");
    fprintf(stderr,"Use -t to generate a TAGL format (*.tagl) triangle mesh\n");
    fprintf(stderr,"Use -r to generate a Rayshade format (*.ray) triangle mesh\n");
    fprintf(stderr,"Use -o to generate an OFF format (*.off) triangle mesh\n");
    fprintf(stderr,"Use -a to generate a AC3D format (*.tri) triangle mesh\n");
    fprintf(stderr,"Use -v to generate a VRML format (*.wrl) triangle mesh\n");
    exit(-1);
  }
  switch(argv[1][1]) {
  case 't': 
    fmt = TAGL_OUTPUT;
    break;
  case 'r':
    fmt=RAYSHADE_OUTPUT;
    break;
  case 'o':
    fmt=OFF_OUTPUT;
    break;
  case 'a':
    fmt=AC3D_OUTPUT;
    break;
  case 'v':
    fmt=VRML_OUTPUT;
    break;
  default:
    fprintf(stderr,"legogen prints a triangle mesh to stdout\n");
    fprintf(stderr,"Syntax: legogen -[t|r|o|a|v]\n");
    fprintf(stderr,"Use -t to generate a TAGL format (*.tagl) triangle mesh\n");
    fprintf(stderr,"Use -r to generate a Rayshade format (*.ray) triangle mesh\n");
    fprintf(stderr,"Use -o to generate an OFF format (*.off) triangle mesh\n");
    fprintf(stderr,"Use -a to generate a AC3D format (*.tri) triangle mesh\n");
    fprintf(stderr,"Use -v to generate a VRML format (*.wrl) triangle mesh\n");
    exit(-1);
  }

  switch (fmt) {
  case TAGL_OUTPUT:
    printf("%d %d %d\n",NUM_POINTS, NUM_FACES, 0);
    for (i=0; i<NUM_POINTS; i++) {
      printf("%f %f %f\n",npoints[i][0],
	     npoints[i][1],npoints[i][2]);
    };
    for (i=0; i<NUM_FACES; i++) {
      printf("3 %d %d %d\n",nfaces[i][0],
	     nfaces[i][1],nfaces[i][2]);
    }
    break;
  case  RAYSHADE_OUTPUT:
    printf("name brick\n\tlist\n");
    for (i=0; i<NUM_FACES; i++) {
      printf("\ttriangle  /* %d */\n",i);
      for (j=0; j< 3; j++) {
	k = nfaces[i][j] - 1;
	printf("\t\t%f %f %f  /* point %d */\n",npoints[k][0],
	       npoints[k][1],npoints[k][2], k+1);
      };
    }
    printf("\tend\n");
    break;
  case OFF_OUTPUT:
    printf("OFF\n");
    printf("%d %d %d\n",NUM_POINTS, NUM_FACES, 0);
    for (i=0; i<NUM_POINTS; i++) {
      printf("%f %f %f\n",npoints[i][0],
	     npoints[i][1],npoints[i][2]);
    };
    for (i=0; i<NUM_FACES; i++) {
      /* red color */
      printf("3 %d %d %d  0.9 0.1 0.1\n",nfaces[i][0]-1,
	     nfaces[i][1]-1,nfaces[i][2]-1);
    }
    
    break;
  case AC3D_OUTPUT:
    for (i=0; i<NUM_FACES; i++) {
      /* red color */
      printf("%f %f %f %f %f %f %f %f %f ff0000\n",
	     npoints[nfaces[i][0]-1][0], npoints[nfaces[i][0]-1][1], npoints[nfaces[i][0]-1][2],
	     npoints[nfaces[i][1]-1][0], npoints[nfaces[i][1]-1][1], npoints[nfaces[i][1]-1][2],
	     npoints[nfaces[i][2]-1][0], npoints[nfaces[i][2]-1][1], npoints[nfaces[i][2]-1][2]);
    }
    break;
  case VRML_OUTPUT:
    printf("#VRML V1.0 ascii\n");
    printf("#generated by legogen\n");
    printf("\n");
    printf("Separator {\nShapeHints {\nvertexOrdering  COUNTERCLOCKWISE\n");
    printf("shapeType UNKNOWN_SHAPE_TYPE\nfaceType UNKNOWN_FACE_TYPE\n}\n");
    printf("\nSeparator {\nCoordinate3 {\npoint [\n");
    for (i=0; i<NUM_POINTS-1; i++) {
      printf("%f %f %f,\n",npoints[i][0],
	     npoints[i][1],npoints[i][2]);
    };
    printf("%f %f %f]\n",npoints[NUM_POINTS-1][0],
	     npoints[NUM_POINTS-1][1],npoints[NUM_POINTS-1][2]);
    printf("}\n");
    printf("Material { diffuseColor 1.000000 0.000000 0.000000   ambientColor 0.200000 0.200000 0.200000  emissiveColor 0.000000 0.000000 0.000000  specularColor 0.500000 0.500000 0.500000  shininess 10.000000  transparency 0.000000 }\n");
    printf("\nIndexedFaceSet {\n    coordIndex [\n");
    for (i=0; i<NUM_FACES; i++) {
      printf("%d, %d, %d, -1,\n",nfaces[i][0]-1,
	     nfaces[i][1]-1,nfaces[i][2]-1);
    }
    printf("\n]\n}\n}\n}\n");
    break;
  }
}


