/* 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 #define NUM_VERTS #define NUM_REAL_VERTS Point3 Verts[] = { }; static int Face0[] = { }; static int Face1[] = { }; : static int Face[] = { }; static int *VertNumList[] = { }; 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 #include #include #include #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; iX); 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); }