home *** CD-ROM | disk | FTP | other *** search
- /* Generates the vertices for a ball approximated with polygonal
- facets, in a form suitable for including into a C module. Vertices,
- faces, and supporting info is generated, in the following format:
-
- ----------------------------start------------------------------
- #define NUM_FACES <number of faces in object>
- #define NUM_VERTS <number of vertices in object>
- #define NUM_REAL_VERTS <number of vertices in object, excluding unit normal
- endpoints>
-
- Point3 Verts[] = { <vertices in object, with unit normal endpoints coming
- last> };
-
- static int Face0[] = { <unit normal endpoint index, followed by vertex
- indexes for face, clockwise> };
- static int Face1[] = { <unit normal endpoint index, followed by vertex
- indexes for face, clockwise> };
- :
- static int Face<n>[] = { <unit normal endpoint index, followed by vertex
- indexes for face, clockwise> };
-
- static int *VertNumList[] = { <ptr to vertex index list per face> };
- static int VertsInFace[] = { <# vertices in each face> };
-
- ***Note: the first two vertices in the vertex list for each face are always
- the end and start points of a unit normal vector for the face, pointing in
- the direction from which the face can be seen; these are used for shading.
- The second point is also an active vertex***
- ----------------------------end--------------------------------
- */
-
- #include <stdio.h>
- #include <conio.h>
- #include <math.h>
- #include <string.h>
- #include "polygon.h"
-
- #define PI 3.14159265358979323846
- #define DOUBLE_TO_FIXED(x) ((long) (x * 65536.0 + 0.5))
-
- void main(void);
- void PrintVertex(struct Point3 *);
- void Print4Indexes(int, int, int, int, int);
- void Print5Indexes(int, int, int, int, int, int);
- void UnitNormal(struct Point3 * Vec, int BaseIndex, int Vec0EndIndex,
- int Vec1EndIndex);
-
- /* Used to rotate around the Y axis by one band's width */
- static double YXform[4][4] = {
- {1.0, 0.0, 0.0, 0.0},
- {0.0, 1.0, 0.0, 0.0},
- {0.0, 0.0, 1.0, 0.0},
- {0.0, 0.0, 0.0, 1.0}
- };
-
- /* Used to rotate around the Z axis by one band's width */
- static double ZXform[4][4] = {
- {1.0, 0.0, 0.0, 0.0},
- {0.0, 1.0, 0.0, 0.0},
- {0.0, 0.0, 1.0, 0.0},
- {0.0, 0.0, 0.0, 1.0}
- };
-
- struct Point3 Pointlist[1000];
- int NumPoints = 0;
-
- static FILE *OutputFile; /* where we'll write to */
-
- int FirstUnitNormalIndex;
-
- void main()
- {
- int Radius, Bands, i, j, LastIndex, BandsX2, LastBandStartIndex;
- int TopBandStartIndex, BottomBandStartIndex, FaceNum;
- struct Point3 BaseVec, BandVec, WorkingVec, TempVec;
- char OutputFilename[130];
- char Description[130];
-
- printf("Radius: ");
- scanf("%d",&Radius);
- printf("Bands: ");
- scanf("%d",&Bands);
- printf("Output file: ");
- OutputFilename[0] = 127;
- cgets(OutputFilename);
- printf("\nBrief description: ");
- Description[0] = 127;
- cgets(Description);
- printf("\n");
-
- BandsX2 = Bands*2;
-
- if ((OutputFile = fopen(&OutputFilename[2], "w")) == NULL) {
- printf("Error\n");
- exit(1);
- }
-
- /* Descriptive comments */
- fprintf(OutputFile, "/* %s */\n", &Description[2]);
- fprintf(OutputFile, "/* Created with radius = %d, bands = %d */\n",
- Radius, Bands);
-
- /* Defines for # of faces and vertices */
- fprintf(OutputFile, "#define NUM_FACES %d\n", BandsX2*Bands);
- fprintf(OutputFile, "#define NUM_VERTS %d\n\n",
- 2+1+BandsX2*(Bands-1)+1+ (BandsX2*Bands));
- /* # of vertices excluding unit normal endpoints */
- fprintf(OutputFile, "#define NUM_REAL_VERTS %d\n\n",
- 2+1+BandsX2*(Bands-1)+1);
-
- /* Do the polygon vertices */
- fprintf(OutputFile, "Point3 Verts[] = {\n");
-
- /* Generate the rotation matrices */
- AppendRotationY(YXform, PI / Bands);
- AppendRotationZ(ZXform, PI / Bands);
-
- /* Do the point at the top */
- BaseVec.X = 0.0;
- BaseVec.Y = Radius;
- BaseVec.Z = 0.0;
- BaseVec.W = 1.0;
- PrintVertex(&BaseVec);
-
- BandVec = BaseVec;
-
- /* Do the vertices in each band in turn */
- for (i=1; i<Bands; i++) {
- /* Rotate around Z to the next band's latitude */
- XformVec(ZXform, (double *)&BandVec, (double *)&TempVec);
- WorkingVec = BandVec = TempVec;
- /* Do the vertices in this band */
- for (j=0; j<BandsX2; j++) {
- WorkingVec = TempVec;
- PrintVertex(&WorkingVec);
- /* Now rotate around Y to the next vertex's longitude */
- XformVec(YXform, (double *)&WorkingVec, (double *)&TempVec);
- }
- }
-
- /* Do the point at the bottom */
- BaseVec.Y = -Radius;
- PrintVertex(&BaseVec);
-
- /* Now generate the unit normal endpoint for each face, as the last
- entries in the vertex list */
- /* Index in overall vertex list of first unit normal endpoint we'll
- create; remember where we can find it */
- FirstUnitNormalIndex = NumPoints;
-
- FaceNum = 0;
-
- /* Unit normal endpoints in top band */
- for (i=0; i<BandsX2; i++) {
- UnitNormal(&BaseVec, 0, ((i+1)%BandsX2)+1, i+1);
- PrintVertex(&BaseVec);
- FaceNum++;
- }
-
- /* Unit normal endpoints in middle bands */
- for (j=0; j<(Bands-2); j++) {
- TopBandStartIndex = j*BandsX2 + 1;
- BottomBandStartIndex = (j+1)*BandsX2 + 1;
- /* Indexes in this band */
- for (i=0; i<BandsX2; i++) {
- UnitNormal(&BaseVec, i+TopBandStartIndex,
- ((i+1)%BandsX2)+TopBandStartIndex,
- i+BottomBandStartIndex);
- PrintVertex(&BaseVec);
- FaceNum++;
- }
- }
-
- /* Unit normal endpoints in bottom band */
- LastIndex = BandsX2*(Bands-1)+1;
- LastBandStartIndex = BandsX2*(Bands-2)+1;
- for (i=0; i<BandsX2; i++) {
- UnitNormal(&BaseVec, LastBandStartIndex+i,
- LastBandStartIndex+((i+1)%BandsX2), LastIndex);
- PrintVertex(&BaseVec);
- FaceNum++;
- }
-
- /* Done generating points, including both polygon vertices and unit
- normals */
- fprintf(OutputFile, "};\n\n");
-
-
- /* Do the vertex indexes for each face in each band */
- FaceNum = 0;
-
- /* Vertex indexes in top band, with unit normal endpoint first */
- for (i=0; i<BandsX2; i++) {
- Print4Indexes(FaceNum++, FirstUnitNormalIndex++, 0,
- ((i+1)%BandsX2)+1, i+1);
- }
-
- /* Vertex indexes in middle bands, with unit normal endpoints first */
- for (j=0; j<(Bands-2); j++) {
- TopBandStartIndex = j*BandsX2 + 1;
- BottomBandStartIndex = (j+1)*BandsX2 + 1;
- /* Indexes in this band */
- for (i=0; i<BandsX2; i++) {
- Print5Indexes(FaceNum++, FirstUnitNormalIndex++,
- i+TopBandStartIndex,
- ((i+1)%BandsX2)+TopBandStartIndex,
- ((i+1)%BandsX2)+BottomBandStartIndex,
- i+BottomBandStartIndex);
- }
- }
-
- /* Vertex indexes in bottom band, with unit normal endpoint first */
- LastIndex = BandsX2*(Bands-1)+1;
- LastBandStartIndex = BandsX2*(Bands-2)+1;
- for (i=0; i<BandsX2; i++) {
- Print4Indexes(FaceNum++, FirstUnitNormalIndex++,
- LastBandStartIndex+i,
- LastBandStartIndex+((i+1)%BandsX2), LastIndex);
- }
-
- /* Do the list of pointers to index arrays for each face */
- fprintf(OutputFile, "\nstatic int *VertNumList[] = {\n");
- for (i=0; i<(BandsX2*Bands); i++) {
- fprintf(OutputFile, "Face%d,\n", i);
- }
- fprintf(OutputFile, "};\n");
-
- /* Do the # of vertices in each face (3 for the top and bottom
- bands, 4 for the rest) */
- fprintf(OutputFile, "\nstatic int VertsInFace[] = {\n");
- for (i=0; i<BandsX2; i++) fprintf(OutputFile, "3,\n");
- for (i=0; i<(BandsX2*(Bands-2)); i++) fprintf(OutputFile, "4,\n");
- for (i=0; i<BandsX2; i++) fprintf(OutputFile, "3,\n");
- fprintf(OutputFile, "};\n");
-
- exit(0);
- }
-
- /* Prints the array of indexes for a 5-vertex face (generally four vertices
- plus the unit normal endpoint, actually). */
- void Print5Indexes(int FaceNum, int V1, int V2, int V3, int V4, int V5)
- {
- fprintf(OutputFile, "static int Face%d[] = {%d,%d,%d,%d,%d};\n",
- FaceNum, V1, V2, V3, V4, V5);
- }
-
- /* Prints the array of indexes for a 4-vertex face (generally three vertices
- plus the unit normal endpoint, actually). */
- void Print4Indexes(int FaceNum, int V1, int V2, int V3, int V4)
- {
- fprintf(OutputFile, "static int Face%d[] = {%d,%d,%d,%d};\n",
- FaceNum, V1, V2, V3, V4);
- }
-
- /* Prints a vertex, in 16.16 fixed-point form */
- void PrintVertex(struct Point3 *Vec)
- {
- long X = DOUBLE_TO_FIXED(Vec->X);
- long Y = DOUBLE_TO_FIXED(Vec->Y);
- long Z = DOUBLE_TO_FIXED(Vec->Z);
- Pointlist[NumPoints++] = *Vec; /* remember this point */
-
- fprintf(OutputFile, "{%ld, %ld, %ld},\n", X, Y, Z);
- }
-
- /* Calculates the end of the unit normal by calculating the cross-product of
- the first and last vectors, and normalizing it to 1 unit in length */
- void UnitNormal(struct Point3 * Vec, int BaseIndex, int Vec0EndIndex,
- int Vec1EndIndex)
- {
- double v1, v2, v3, w1, w2, w3, Xlen, Ylen, Zlen, Length;
-
- v1 = Pointlist[Vec0EndIndex].X - Pointlist[BaseIndex].X;
- v2 = Pointlist[Vec0EndIndex].Y - Pointlist[BaseIndex].Y;
- v3 = Pointlist[Vec0EndIndex].Z - Pointlist[BaseIndex].Z;
- w1 = Pointlist[Vec1EndIndex].X - Pointlist[BaseIndex].X;
- w2 = Pointlist[Vec1EndIndex].Y - Pointlist[BaseIndex].Y;
- w3 = Pointlist[Vec1EndIndex].Z - Pointlist[BaseIndex].Z;
- /* Calculate perpendicular relative to the BaseIndex point in Vec */
- Vec->X = v2*w3 - v3*w2;
- Vec->Y = v3*w1 - v1*w3;
- Vec->Z = v1*w2 - v2*w1;
- /* Calculate the length of the normal, and reverse its direction so that
- a positive normal points toward the screen, negative points away */
- Xlen = -(Vec->X - Pointlist[BaseIndex].X);
- Ylen = -(Vec->Y - Pointlist[BaseIndex].Y);
- Zlen = -(Vec->Z - Pointlist[BaseIndex].Z);
- Length = sqrt(Xlen*Xlen + Ylen*Ylen + Zlen*Zlen);
- /* Scale it to a unit normal and offset it from the start point */
- Vec->X = Pointlist[BaseIndex].X + (Xlen / Length);
- Vec->Y = Pointlist[BaseIndex].Y + (Ylen / Length);
- Vec->Z = Pointlist[BaseIndex].Z + (Zlen / Length);
- }
-