+ fghDrawGeometrySolid(vertices,normals,NULL,numVert,NULL,1,0);
+
+ free(vertices);
+ free(normals );
+ }
+}
+
+
+static void fghSphere( GLfloat radius, GLint slices, GLint stacks, GLboolean useWireMode )
+{
+ int i,j,idx, nVert;
+ GLfloat *vertices, *normals;
+
+ /* Generate vertices and normals */
+ fghGenerateSphere(radius,slices,stacks,&vertices,&normals,&nVert);
+
+ if (nVert==0)
+ /* nothing to draw */
+ return;
+
+ if (useWireMode)
+ {
+ GLushort *sliceIdx, *stackIdx;
+ /* First, generate vertex index arrays for drawing with glDrawElements
+ * We have a bunch of line_loops to draw for each stack, and a
+ * bunch for each slice.
+ */
+
+ sliceIdx = malloc(slices*(stacks+1)*sizeof(GLushort));
+ stackIdx = malloc(slices*(stacks-1)*sizeof(GLushort));
+ if (!(stackIdx) || !(sliceIdx))
+ {
+ free(stackIdx);
+ free(sliceIdx);
+ fgError("Failed to allocate memory in fghSphere");
+ }
+
+ /* generate for each stack */
+ for (i=0,idx=0; i<stacks-1; i++)
+ {
+ GLushort offset = 1+i*slices; /* start at 1 (0 is top vertex), and we advance one stack down as we go along */
+ for (j=0; j<slices; j++, idx++)
+ {
+ stackIdx[idx] = offset+j;
+ }
+ }
+
+ /* generate for each slice */
+ for (i=0,idx=0; i<slices; i++)
+ {
+ GLushort offset = 1+i; /* start at 1 (0 is top vertex), and we advance one slice as we go along */
+ sliceIdx[idx++] = 0; /* vertex on top */
+ for (j=0; j<stacks-1; j++, idx++)
+ {
+ sliceIdx[idx] = offset+j*slices;
+ }
+ sliceIdx[idx++] = nVert-1; /* zero based index, last element in array... */
+ }
+
+ /* draw */
+ fghDrawGeometryWire(vertices,normals,nVert,
+ sliceIdx,slices,stacks+1,GL_LINE_STRIP,
+ stackIdx,stacks-1,slices);
+
+ /* cleanup allocated memory */
+ free(sliceIdx);
+ free(stackIdx);
+ }
+ else
+ {
+ /* First, generate vertex index arrays for drawing with glDrawElements
+ * All stacks, including top and bottom are covered with a triangle
+ * strip.
+ */
+ GLushort *stripIdx;
+ /* Create index vector */
+ GLushort offset;
+
+ /* Allocate buffers for indices, bail out if memory allocation fails */
+ stripIdx = malloc((slices+1)*2*(stacks)*sizeof(GLushort));
+ if (!(stripIdx))
+ {
+ free(stripIdx);
+ fgError("Failed to allocate memory in fghSphere");
+ }
+
+ /* top stack */
+ for (j=0, idx=0; j<slices; j++, idx+=2)
+ {
+ stripIdx[idx ] = j+1; /* 0 is top vertex, 1 is first for first stack */
+ stripIdx[idx+1] = 0;
+ }
+ stripIdx[idx ] = 1; /* repeat first slice's idx for closing off shape */
+ stripIdx[idx+1] = 0;
+ idx+=2;
+
+ /* middle stacks: */
+ /* Strip indices are relative to first index belonging to strip, NOT relative to first vertex/normal pair in array */
+ for (i=0; i<stacks-2; i++, idx+=2)
+ {
+ offset = 1+i*slices; /* triangle_strip indices start at 1 (0 is top vertex), and we advance one stack down as we go along */
+ for (j=0; j<slices; j++, idx+=2)
+ {
+ stripIdx[idx ] = offset+j+slices;
+ stripIdx[idx+1] = offset+j;
+ }
+ stripIdx[idx ] = offset+slices; /* repeat first slice's idx for closing off shape */
+ stripIdx[idx+1] = offset;
+ }
+
+ /* bottom stack */
+ offset = 1+(stacks-2)*slices; /* triangle_strip indices start at 1 (0 is top vertex), and we advance one stack down as we go along */
+ for (j=0; j<slices; j++, idx+=2)
+ {
+ stripIdx[idx ] = nVert-1; /* zero based index, last element in array (bottom vertex)... */
+ stripIdx[idx+1] = offset+j;
+ }
+ stripIdx[idx ] = nVert-1; /* repeat first slice's idx for closing off shape */
+ stripIdx[idx+1] = offset;
+
+
+ /* draw */
+ fghDrawGeometrySolid(vertices,normals,NULL,nVert,stripIdx,stacks,(slices+1)*2);
+
+ /* cleanup allocated memory */
+ free(stripIdx);
+ }
+
+ /* cleanup allocated memory */
+ free(vertices);
+ free(normals);
+}
+
+static void fghCone( GLfloat base, GLfloat height, GLint slices, GLint stacks, GLboolean useWireMode )
+{
+ int i,j,idx, nVert;
+ GLfloat *vertices, *normals;
+
+ /* Generate vertices and normals */
+ /* Note, (stacks+1)*slices vertices for side of object, slices+1 for top and bottom closures */
+ fghGenerateCone(base,height,slices,stacks,&vertices,&normals,&nVert);
+
+ if (nVert==0)
+ /* nothing to draw */
+ return;
+
+ if (useWireMode)
+ {
+ GLushort *sliceIdx, *stackIdx;
+ /* First, generate vertex index arrays for drawing with glDrawElements
+ * We have a bunch of line_loops to draw for each stack, and a
+ * bunch for each slice.
+ */
+
+ stackIdx = malloc(slices*stacks*sizeof(GLushort));
+ sliceIdx = malloc(slices*2 *sizeof(GLushort));
+ if (!(stackIdx) || !(sliceIdx))
+ {
+ free(stackIdx);
+ free(sliceIdx);
+ fgError("Failed to allocate memory in fghCone");
+ }
+
+ /* generate for each stack */
+ for (i=0,idx=0; i<stacks; i++)
+ {
+ GLushort offset = 1+(i+1)*slices; /* start at 1 (0 is top vertex), and we advance one stack down as we go along */
+ for (j=0; j<slices; j++, idx++)
+ {
+ stackIdx[idx] = offset+j;
+ }
+ }
+
+ /* generate for each slice */
+ for (i=0,idx=0; i<slices; i++)
+ {
+ GLushort offset = 1+i; /* start at 1 (0 is top vertex), and we advance one slice as we go along */
+ sliceIdx[idx++] = offset+slices;
+ sliceIdx[idx++] = offset+(stacks+1)*slices;
+ }
+
+ /* draw */
+ fghDrawGeometryWire(vertices,normals,nVert,
+ sliceIdx,1,slices*2,GL_LINES,
+ stackIdx,stacks,slices);
+
+ /* cleanup allocated memory */
+ free(sliceIdx);
+ free(stackIdx);
+ }
+ else
+ {
+ /* First, generate vertex index arrays for drawing with glDrawElements
+ * All stacks, including top and bottom are covered with a triangle
+ * strip.
+ */
+ GLushort *stripIdx;
+ /* Create index vector */
+ GLushort offset;
+
+ /* Allocate buffers for indices, bail out if memory allocation fails */
+ stripIdx = malloc((slices+1)*2*(stacks+1)*sizeof(GLushort)); /*stacks +1 because of closing off bottom */
+ if (!(stripIdx))
+ {
+ free(stripIdx);
+ fgError("Failed to allocate memory in fghCone");
+ }
+
+ /* top stack */
+ for (j=0, idx=0; j<slices; j++, idx+=2)
+ {
+ stripIdx[idx ] = 0;
+ stripIdx[idx+1] = j+1; /* 0 is top vertex, 1 is first for first stack */
+ }
+ stripIdx[idx ] = 0; /* repeat first slice's idx for closing off shape */
+ stripIdx[idx+1] = 1;
+ idx+=2;
+
+ /* middle stacks: */
+ /* Strip indices are relative to first index belonging to strip, NOT relative to first vertex/normal pair in array */
+ for (i=0; i<stacks; i++, idx+=2)
+ {
+ offset = 1+(i+1)*slices; /* triangle_strip indices start at 1 (0 is top vertex), and we advance one stack down as we go along */
+ for (j=0; j<slices; j++, idx+=2)
+ {
+ stripIdx[idx ] = offset+j;
+ stripIdx[idx+1] = offset+j+slices;
+ }
+ stripIdx[idx ] = offset; /* repeat first slice's idx for closing off shape */
+ stripIdx[idx+1] = offset+slices;
+ }
+
+ /* draw */
+ fghDrawGeometrySolid(vertices,normals,NULL,nVert,stripIdx,stacks+1,(slices+1)*2);
+
+ /* cleanup allocated memory */
+ free(stripIdx);
+ }
+
+ /* cleanup allocated memory */
+ free(vertices);
+ free(normals);
+}
+
+static void fghCylinder( GLfloat radius, GLfloat height, GLint slices, GLint stacks, GLboolean useWireMode )
+{
+ int i,j,idx, nVert;
+ GLfloat *vertices, *normals;
+
+ /* Generate vertices and normals */
+ /* Note, (stacks+1)*slices vertices for side of object, 2*slices+2 for top and bottom closures */
+ fghGenerateCylinder(radius,height,slices,stacks,&vertices,&normals,&nVert);
+
+ if (nVert==0)
+ /* nothing to draw */
+ return;
+
+ if (useWireMode)
+ {
+ GLushort *sliceIdx, *stackIdx;
+ /* First, generate vertex index arrays for drawing with glDrawElements
+ * We have a bunch of line_loops to draw for each stack, and a
+ * bunch for each slice.
+ */
+
+ stackIdx = malloc(slices*(stacks+1)*sizeof(GLushort));
+ sliceIdx = malloc(slices*2 *sizeof(GLushort));
+ if (!(stackIdx) || !(sliceIdx))
+ {
+ free(stackIdx);
+ free(sliceIdx);
+ fgError("Failed to allocate memory in fghCylinder");
+ }
+
+ /* generate for each stack */
+ for (i=0,idx=0; i<stacks+1; i++)
+ {
+ GLushort offset = 1+(i+1)*slices; /* start at 1 (0 is top vertex), and we advance one stack down as we go along */
+ for (j=0; j<slices; j++, idx++)
+ {
+ stackIdx[idx] = offset+j;
+ }
+ }
+
+ /* generate for each slice */
+ for (i=0,idx=0; i<slices; i++)
+ {
+ GLushort offset = 1+i; /* start at 1 (0 is top vertex), and we advance one slice as we go along */
+ sliceIdx[idx++] = offset+slices;
+ sliceIdx[idx++] = offset+(stacks+1)*slices;
+ }
+
+ /* draw */
+ fghDrawGeometryWire(vertices,normals,nVert,
+ sliceIdx,1,slices*2,GL_LINES,
+ stackIdx,stacks+1,slices);
+
+ /* cleanup allocated memory */
+ free(sliceIdx);
+ free(stackIdx);
+ }
+ else
+ {
+ /* First, generate vertex index arrays for drawing with glDrawElements
+ * All stacks, including top and bottom are covered with a triangle
+ * strip.
+ */
+ GLushort *stripIdx;
+ /* Create index vector */
+ GLushort offset;