teapot now using vertex arrays or vertex attribute arrays, using handwritten Bezier surface evaluation code
in fg_geometry, fixed up normal generation for visualization and added support for drawing texture coordinates (teapot has texture coordinates, other geometric shapes don't) git-svn-id: https://svn.code.sf.net/p/freeglut/code/trunk@1567 7f0cb862-5218-0410-a997-914c9d46530a
This commit is contained in:
parent
fc84854e33
commit
6581072673
@ -49,7 +49,7 @@ static void fghDrawGeometryWire11(GLfloat *vertices, GLfloat *normals,
|
|||||||
GLushort *vertIdxs, GLsizei numParts, GLsizei numVertPerPart, GLenum vertexMode,
|
GLushort *vertIdxs, GLsizei numParts, GLsizei numVertPerPart, GLenum vertexMode,
|
||||||
GLushort *vertIdxs2, GLsizei numParts2, GLsizei numVertPerPart2
|
GLushort *vertIdxs2, GLsizei numParts2, GLsizei numVertPerPart2
|
||||||
);
|
);
|
||||||
static void fghDrawGeometrySolid11(GLfloat *vertices, GLfloat *normals, GLsizei numVertices,
|
static void fghDrawGeometrySolid11(GLfloat *vertices, GLfloat *normals, GLfloat *textcs, GLsizei numVertices,
|
||||||
GLushort *vertIdxs, GLsizei numParts, GLsizei numVertIdxsPerPart);
|
GLushort *vertIdxs, GLsizei numParts, GLsizei numVertIdxsPerPart);
|
||||||
#endif
|
#endif
|
||||||
static void fghDrawGeometryWire20(GLfloat *vertices, GLfloat *normals, GLsizei numVertices,
|
static void fghDrawGeometryWire20(GLfloat *vertices, GLfloat *normals, GLsizei numVertices,
|
||||||
@ -57,12 +57,11 @@ static void fghDrawGeometryWire20(GLfloat *vertices, GLfloat *normals, GLsizei n
|
|||||||
GLushort *vertIdxs2, GLsizei numParts2, GLsizei numVertPerPart2,
|
GLushort *vertIdxs2, GLsizei numParts2, GLsizei numVertPerPart2,
|
||||||
GLint attribute_v_coord, GLint attribute_v_normal
|
GLint attribute_v_coord, GLint attribute_v_normal
|
||||||
);
|
);
|
||||||
static void fghDrawGeometrySolid20(GLfloat *vertices, GLfloat *normals, GLsizei numVertices,
|
static void fghDrawGeometrySolid20(GLfloat *vertices, GLfloat *normals, GLfloat *textcs, GLsizei numVertices,
|
||||||
GLushort *vertIdxs, GLsizei numParts, GLsizei numVertIdxsPerPart,
|
GLushort *vertIdxs, GLsizei numParts, GLsizei numVertIdxsPerPart,
|
||||||
GLint attribute_v_coord, GLint attribute_v_normal);
|
GLint attribute_v_coord, GLint attribute_v_normal, GLint attribute_v_texture);
|
||||||
/* declare function for generating visualization of normals */
|
/* declare function for generating visualization of normals */
|
||||||
static void fghGenerateNormalVisualization(GLfloat *vertices, GLfloat *normals, GLsizei numVertices,
|
static void fghGenerateNormalVisualization(GLfloat *vertices, GLfloat *normals, GLsizei numVertices);
|
||||||
GLushort *vertIdxs, GLsizei numParts, GLsizei numVertIdxsPerPart);
|
|
||||||
#ifndef GL_ES_VERSION_2_0
|
#ifndef GL_ES_VERSION_2_0
|
||||||
static void fghDrawNormalVisualization11();
|
static void fghDrawNormalVisualization11();
|
||||||
#endif
|
#endif
|
||||||
@ -134,7 +133,7 @@ static void fghDrawNormalVisualization20(GLint attribute_v_coord);
|
|||||||
*
|
*
|
||||||
* Feel free to contribute better naming ;)
|
* Feel free to contribute better naming ;)
|
||||||
*/
|
*/
|
||||||
static void fghDrawGeometryWire(GLfloat *vertices, GLfloat *normals, GLsizei numVertices,
|
void fghDrawGeometryWire(GLfloat *vertices, GLfloat *normals, GLsizei numVertices,
|
||||||
GLushort *vertIdxs, GLsizei numParts, GLsizei numVertPerPart, GLenum vertexMode,
|
GLushort *vertIdxs, GLsizei numParts, GLsizei numVertPerPart, GLenum vertexMode,
|
||||||
GLushort *vertIdxs2, GLsizei numParts2, GLsizei numVertPerPart2
|
GLushort *vertIdxs2, GLsizei numParts2, GLsizei numVertPerPart2
|
||||||
)
|
)
|
||||||
@ -159,9 +158,9 @@ static void fghDrawGeometryWire(GLfloat *vertices, GLfloat *normals, GLsizei num
|
|||||||
/* Draw the geometric shape with filled triangles
|
/* Draw the geometric shape with filled triangles
|
||||||
*
|
*
|
||||||
* Arguments:
|
* Arguments:
|
||||||
* GLfloat *vertices, GLfloat *normals, GLsizei numVertices
|
* GLfloat *vertices, GLfloat *normals, GLfloat *textcs, GLsizei numVertices
|
||||||
* The vertex coordinate and normal buffers, and the number of entries in
|
* The vertex coordinate, normal and texture coordinate buffers, and the
|
||||||
* those
|
* number of entries in those
|
||||||
* GLushort *vertIdxs
|
* GLushort *vertIdxs
|
||||||
* a vertex indices buffer, optional (not passed for the polyhedra with
|
* a vertex indices buffer, optional (not passed for the polyhedra with
|
||||||
* triangular faces)
|
* triangular faces)
|
||||||
@ -182,23 +181,23 @@ static void fghDrawGeometryWire(GLfloat *vertices, GLfloat *normals, GLsizei num
|
|||||||
* numParts * numVertPerPart gives the number of entries in the vertex
|
* numParts * numVertPerPart gives the number of entries in the vertex
|
||||||
* array vertIdxs
|
* array vertIdxs
|
||||||
*/
|
*/
|
||||||
static void fghDrawGeometrySolid(GLfloat *vertices, GLfloat *normals, GLsizei numVertices,
|
void fghDrawGeometrySolid(GLfloat *vertices, GLfloat *normals, GLfloat *textcs, GLsizei numVertices,
|
||||||
GLushort *vertIdxs, GLsizei numParts, GLsizei numVertIdxsPerPart)
|
GLushort *vertIdxs, GLsizei numParts, GLsizei numVertIdxsPerPart)
|
||||||
{
|
{
|
||||||
GLint attribute_v_coord = fgStructure.CurrentWindow->Window.attribute_v_coord;
|
GLint attribute_v_coord = fgStructure.CurrentWindow->Window.attribute_v_coord;
|
||||||
GLint attribute_v_normal = fgStructure.CurrentWindow->Window.attribute_v_normal;
|
GLint attribute_v_normal = fgStructure.CurrentWindow->Window.attribute_v_normal;
|
||||||
|
GLint attribute_v_texture = -1; // TODO!!!
|
||||||
|
|
||||||
if (fgStructure.CurrentWindow->State.VisualizeNormals)
|
if (fgStructure.CurrentWindow->State.VisualizeNormals)
|
||||||
/* generate normals for each vertex to be drawn as well */
|
/* generate normals for each vertex to be drawn as well */
|
||||||
fghGenerateNormalVisualization(vertices, normals, numVertices,
|
fghGenerateNormalVisualization(vertices, normals, numVertices);
|
||||||
vertIdxs, numParts, numVertIdxsPerPart);
|
|
||||||
|
|
||||||
if (fgState.HasOpenGL20 && (attribute_v_coord != -1 || attribute_v_normal != -1))
|
if (fgState.HasOpenGL20 && (attribute_v_coord != -1 || attribute_v_normal != -1))
|
||||||
{
|
{
|
||||||
/* User requested a 2.0 draw */
|
/* User requested a 2.0 draw */
|
||||||
fghDrawGeometrySolid20(vertices, normals, numVertices,
|
fghDrawGeometrySolid20(vertices, normals, textcs, numVertices,
|
||||||
vertIdxs, numParts, numVertIdxsPerPart,
|
vertIdxs, numParts, numVertIdxsPerPart,
|
||||||
attribute_v_coord, attribute_v_normal);
|
attribute_v_coord, attribute_v_normal, attribute_v_texture);
|
||||||
|
|
||||||
if (fgStructure.CurrentWindow->State.VisualizeNormals)
|
if (fgStructure.CurrentWindow->State.VisualizeNormals)
|
||||||
/* draw normals for each vertex as well */
|
/* draw normals for each vertex as well */
|
||||||
@ -207,7 +206,7 @@ static void fghDrawGeometrySolid(GLfloat *vertices, GLfloat *normals, GLsizei nu
|
|||||||
#ifndef GL_ES_VERSION_2_0
|
#ifndef GL_ES_VERSION_2_0
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
fghDrawGeometrySolid11(vertices, normals, numVertices,
|
fghDrawGeometrySolid11(vertices, normals, textcs, numVertices,
|
||||||
vertIdxs, numParts, numVertIdxsPerPart);
|
vertIdxs, numParts, numVertIdxsPerPart);
|
||||||
|
|
||||||
if (fgStructure.CurrentWindow->State.VisualizeNormals)
|
if (fgStructure.CurrentWindow->State.VisualizeNormals)
|
||||||
@ -252,7 +251,7 @@ static void fghDrawGeometryWire11(GLfloat *vertices, GLfloat *normals,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void fghDrawGeometrySolid11(GLfloat *vertices, GLfloat *normals, GLsizei numVertices,
|
static void fghDrawGeometrySolid11(GLfloat *vertices, GLfloat *normals, GLfloat *textcs, GLsizei numVertices,
|
||||||
GLushort *vertIdxs, GLsizei numParts, GLsizei numVertIdxsPerPart)
|
GLushort *vertIdxs, GLsizei numParts, GLsizei numVertIdxsPerPart)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
@ -263,6 +262,12 @@ static void fghDrawGeometrySolid11(GLfloat *vertices, GLfloat *normals, GLsizei
|
|||||||
glVertexPointer(3, GL_FLOAT, 0, vertices);
|
glVertexPointer(3, GL_FLOAT, 0, vertices);
|
||||||
glNormalPointer(GL_FLOAT, 0, normals);
|
glNormalPointer(GL_FLOAT, 0, normals);
|
||||||
|
|
||||||
|
if (textcs)
|
||||||
|
{
|
||||||
|
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||||
|
glTexCoordPointer(2, GL_FLOAT, 0, textcs);
|
||||||
|
}
|
||||||
|
|
||||||
if (!vertIdxs)
|
if (!vertIdxs)
|
||||||
glDrawArrays(GL_TRIANGLES, 0, numVertices);
|
glDrawArrays(GL_TRIANGLES, 0, numVertices);
|
||||||
else
|
else
|
||||||
@ -274,6 +279,8 @@ static void fghDrawGeometrySolid11(GLfloat *vertices, GLfloat *normals, GLsizei
|
|||||||
|
|
||||||
glDisableClientState(GL_VERTEX_ARRAY);
|
glDisableClientState(GL_VERTEX_ARRAY);
|
||||||
glDisableClientState(GL_NORMAL_ARRAY);
|
glDisableClientState(GL_NORMAL_ARRAY);
|
||||||
|
if (textcs)
|
||||||
|
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -390,11 +397,11 @@ static void fghDrawGeometryWire20(GLfloat *vertices, GLfloat *normals, GLsizei n
|
|||||||
|
|
||||||
|
|
||||||
/* Version for OpenGL (ES) >= 2.0 */
|
/* Version for OpenGL (ES) >= 2.0 */
|
||||||
static void fghDrawGeometrySolid20(GLfloat *vertices, GLfloat *normals, GLsizei numVertices,
|
static void fghDrawGeometrySolid20(GLfloat *vertices, GLfloat *normals, GLfloat *textcs, GLsizei numVertices,
|
||||||
GLushort *vertIdxs, GLsizei numParts, GLsizei numVertIdxsPerPart,
|
GLushort *vertIdxs, GLsizei numParts, GLsizei numVertIdxsPerPart,
|
||||||
GLint attribute_v_coord, GLint attribute_v_normal)
|
GLint attribute_v_coord, GLint attribute_v_normal, GLint attribute_v_texture)
|
||||||
{
|
{
|
||||||
GLuint vbo_coords = 0, vbo_normals = 0, ibo_elements = 0;
|
GLuint vbo_coords = 0, vbo_normals = 0, vbo_textcs = 0, ibo_elements = 0;
|
||||||
GLsizei numVertIdxs = numParts * numVertIdxsPerPart;
|
GLsizei numVertIdxs = numParts * numVertIdxsPerPart;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
@ -414,6 +421,14 @@ static void fghDrawGeometrySolid20(GLfloat *vertices, GLfloat *normals, GLsizei
|
|||||||
fghBindBuffer(FGH_ARRAY_BUFFER, 0);
|
fghBindBuffer(FGH_ARRAY_BUFFER, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (numVertices > 0 && attribute_v_texture != -1 && textcs) {
|
||||||
|
fghGenBuffers(1, &vbo_textcs);
|
||||||
|
fghBindBuffer(FGH_ARRAY_BUFFER, vbo_textcs);
|
||||||
|
fghBufferData(FGH_ARRAY_BUFFER, numVertices * 2 * sizeof(textcs[0]),
|
||||||
|
textcs, FGH_STATIC_DRAW);
|
||||||
|
fghBindBuffer(FGH_ARRAY_BUFFER, 0);
|
||||||
|
}
|
||||||
|
|
||||||
if (vertIdxs != NULL) {
|
if (vertIdxs != NULL) {
|
||||||
fghGenBuffers(1, &ibo_elements);
|
fghGenBuffers(1, &ibo_elements);
|
||||||
fghBindBuffer(FGH_ELEMENT_ARRAY_BUFFER, ibo_elements);
|
fghBindBuffer(FGH_ELEMENT_ARRAY_BUFFER, ibo_elements);
|
||||||
@ -450,6 +465,20 @@ static void fghDrawGeometrySolid20(GLfloat *vertices, GLfloat *normals, GLsizei
|
|||||||
fghBindBuffer(FGH_ARRAY_BUFFER, 0);
|
fghBindBuffer(FGH_ARRAY_BUFFER, 0);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (vbo_textcs) {
|
||||||
|
fghEnableVertexAttribArray(attribute_v_texture);
|
||||||
|
fghBindBuffer(FGH_ARRAY_BUFFER, vbo_textcs);
|
||||||
|
fghVertexAttribPointer(
|
||||||
|
attribute_v_texture,/* attribute */
|
||||||
|
2, /* number of elements per vertex, here (s,t) */
|
||||||
|
GL_FLOAT, /* the type of each element */
|
||||||
|
GL_FALSE, /* take our values as-is */
|
||||||
|
0, /* no extra data between each position */
|
||||||
|
0 /* offset of first element */
|
||||||
|
);
|
||||||
|
fghBindBuffer(FGH_ARRAY_BUFFER, 0);
|
||||||
|
};
|
||||||
|
|
||||||
if (vertIdxs == NULL) {
|
if (vertIdxs == NULL) {
|
||||||
glDrawArrays(GL_TRIANGLES, 0, numVertices);
|
glDrawArrays(GL_TRIANGLES, 0, numVertices);
|
||||||
} else {
|
} else {
|
||||||
@ -470,11 +499,15 @@ static void fghDrawGeometrySolid20(GLfloat *vertices, GLfloat *normals, GLsizei
|
|||||||
fghDisableVertexAttribArray(attribute_v_coord);
|
fghDisableVertexAttribArray(attribute_v_coord);
|
||||||
if (vbo_normals != 0)
|
if (vbo_normals != 0)
|
||||||
fghDisableVertexAttribArray(attribute_v_normal);
|
fghDisableVertexAttribArray(attribute_v_normal);
|
||||||
|
if (vbo_textcs != 0)
|
||||||
|
fghDisableVertexAttribArray(attribute_v_texture);
|
||||||
|
|
||||||
if (vbo_coords != 0)
|
if (vbo_coords != 0)
|
||||||
fghDeleteBuffers(1, &vbo_coords);
|
fghDeleteBuffers(1, &vbo_coords);
|
||||||
if (vbo_normals != 0)
|
if (vbo_normals != 0)
|
||||||
fghDeleteBuffers(1, &vbo_normals);
|
fghDeleteBuffers(1, &vbo_normals);
|
||||||
|
if (vbo_textcs != 0)
|
||||||
|
fghDeleteBuffers(1, &vbo_textcs);
|
||||||
if (ibo_elements != 0)
|
if (ibo_elements != 0)
|
||||||
fghDeleteBuffers(1, &ibo_elements);
|
fghDeleteBuffers(1, &ibo_elements);
|
||||||
}
|
}
|
||||||
@ -483,25 +516,18 @@ static void fghDrawGeometrySolid20(GLfloat *vertices, GLfloat *normals, GLsizei
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Generate vertex indices for visualizing the normals.
|
* Generate vertex indices for visualizing the normals.
|
||||||
|
* vertices are written into verticesForNormalVisualization.
|
||||||
|
* This must be freed by caller, we do the free at the
|
||||||
|
* end of fghDrawNormalVisualization11/fghDrawNormalVisualization20
|
||||||
*/
|
*/
|
||||||
static GLfloat *verticesForNormalVisualization;
|
static GLfloat *verticesForNormalVisualization;
|
||||||
static GLushort numNormalVertices = 0;
|
static GLsizei numNormalVertices = 0;
|
||||||
static void fghGenerateNormalVisualization(GLfloat *vertices, GLfloat *normals, GLsizei numVertices,
|
static void fghGenerateNormalVisualization(GLfloat *vertices, GLfloat *normals, GLsizei numVertices)
|
||||||
GLushort *vertIdxs, GLsizei numParts, GLsizei numVertIdxsPerPart)
|
|
||||||
{
|
{
|
||||||
GLushort i,j;
|
int i,j;
|
||||||
/* calc number of vertices to generate, allocate. Must be freed by caller
|
|
||||||
* We do the free at the end of fghDrawNormalVisualization11/fghDrawNormalVisualization20
|
|
||||||
*/
|
|
||||||
if (!vertIdxs)
|
|
||||||
numNormalVertices = numVertices * 2;
|
numNormalVertices = numVertices * 2;
|
||||||
else
|
|
||||||
numNormalVertices = numParts * numVertIdxsPerPart * 2;
|
|
||||||
verticesForNormalVisualization = malloc(numNormalVertices*3 * sizeof(GLfloat));
|
verticesForNormalVisualization = malloc(numNormalVertices*3 * sizeof(GLfloat));
|
||||||
|
|
||||||
/* Now generate vertices for lines to draw the normals */
|
|
||||||
if (!vertIdxs)
|
|
||||||
{
|
|
||||||
for (i=0,j=0; i<numNormalVertices*3/2; i+=3, j+=6)
|
for (i=0,j=0; i<numNormalVertices*3/2; i+=3, j+=6)
|
||||||
{
|
{
|
||||||
verticesForNormalVisualization[j+0] = vertices[i+0];
|
verticesForNormalVisualization[j+0] = vertices[i+0];
|
||||||
@ -511,20 +537,6 @@ static void fghGenerateNormalVisualization(GLfloat *vertices, GLfloat *normals,
|
|||||||
verticesForNormalVisualization[j+4] = vertices[i+1] + normals[i+1]/4.f;
|
verticesForNormalVisualization[j+4] = vertices[i+1] + normals[i+1]/4.f;
|
||||||
verticesForNormalVisualization[j+5] = vertices[i+2] + normals[i+2]/4.f;
|
verticesForNormalVisualization[j+5] = vertices[i+2] + normals[i+2]/4.f;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
for (i=0,j=0; i<numNormalVertices/2; i++, j+=6)
|
|
||||||
{
|
|
||||||
GLushort idx = vertIdxs[i]*3;
|
|
||||||
verticesForNormalVisualization[j+0] = vertices[idx+0];
|
|
||||||
verticesForNormalVisualization[j+1] = vertices[idx+1];
|
|
||||||
verticesForNormalVisualization[j+2] = vertices[idx+2];
|
|
||||||
verticesForNormalVisualization[j+3] = vertices[idx+0] + normals[idx+0]/4.f;
|
|
||||||
verticesForNormalVisualization[j+4] = vertices[idx+1] + normals[idx+1]/4.f;
|
|
||||||
verticesForNormalVisualization[j+5] = vertices[idx+2] + normals[idx+2]/4.f;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Version for OpenGL (ES) 1.1 */
|
/* Version for OpenGL (ES) 1.1 */
|
||||||
@ -1507,7 +1519,7 @@ void fghGenerateTorus(
|
|||||||
}\
|
}\
|
||||||
else\
|
else\
|
||||||
{\
|
{\
|
||||||
fghDrawGeometrySolid(name##_verts,name##_norms,nameCaps##_VERT_PER_OBJ,\
|
fghDrawGeometrySolid(name##_verts,name##_norms,NULL,nameCaps##_VERT_PER_OBJ,\
|
||||||
vertIdxs, 1, nameCaps##_VERT_PER_OBJ_TRI); \
|
vertIdxs, 1, nameCaps##_VERT_PER_OBJ_TRI); \
|
||||||
}\
|
}\
|
||||||
}
|
}
|
||||||
@ -1549,7 +1561,7 @@ static void fghCube( GLfloat dSize, GLboolean useWireMode )
|
|||||||
NULL,CUBE_NUM_FACES, CUBE_NUM_EDGE_PER_FACE,GL_LINE_LOOP,
|
NULL,CUBE_NUM_FACES, CUBE_NUM_EDGE_PER_FACE,GL_LINE_LOOP,
|
||||||
NULL,0,0);
|
NULL,0,0);
|
||||||
else
|
else
|
||||||
fghDrawGeometrySolid(vertices, cube_norms, CUBE_VERT_PER_OBJ,
|
fghDrawGeometrySolid(vertices, cube_norms, NULL, CUBE_VERT_PER_OBJ,
|
||||||
cube_vertIdxs, 1, CUBE_VERT_PER_OBJ_TRI);
|
cube_vertIdxs, 1, CUBE_VERT_PER_OBJ_TRI);
|
||||||
|
|
||||||
if (dSize!=1.f)
|
if (dSize!=1.f)
|
||||||
@ -1593,7 +1605,7 @@ static void fghSierpinskiSponge ( int numLevels, double offset[3], GLfloat scale
|
|||||||
NULL,numFace,TETRAHEDRON_NUM_EDGE_PER_FACE,GL_LINE_LOOP,
|
NULL,numFace,TETRAHEDRON_NUM_EDGE_PER_FACE,GL_LINE_LOOP,
|
||||||
NULL,0,0);
|
NULL,0,0);
|
||||||
else
|
else
|
||||||
fghDrawGeometrySolid(vertices,normals,numVert,NULL,1,0);
|
fghDrawGeometrySolid(vertices,normals,NULL,numVert,NULL,1,0);
|
||||||
|
|
||||||
free(vertices);
|
free(vertices);
|
||||||
free(normals );
|
free(normals );
|
||||||
@ -1715,7 +1727,7 @@ static void fghSphere( GLfloat radius, GLint slices, GLint stacks, GLboolean use
|
|||||||
|
|
||||||
|
|
||||||
/* draw */
|
/* draw */
|
||||||
fghDrawGeometrySolid(vertices,normals,nVert,stripIdx,stacks,(slices+1)*2);
|
fghDrawGeometrySolid(vertices,normals,NULL,nVert,stripIdx,stacks,(slices+1)*2);
|
||||||
|
|
||||||
/* cleanup allocated memory */
|
/* cleanup allocated memory */
|
||||||
free(stripIdx);
|
free(stripIdx);
|
||||||
@ -1826,7 +1838,7 @@ static void fghCone( GLfloat base, GLfloat height, GLint slices, GLint stacks, G
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* draw */
|
/* draw */
|
||||||
fghDrawGeometrySolid(vertices,normals,nVert,stripIdx,stacks+1,(slices+1)*2);
|
fghDrawGeometrySolid(vertices,normals,NULL,nVert,stripIdx,stacks+1,(slices+1)*2);
|
||||||
|
|
||||||
/* cleanup allocated memory */
|
/* cleanup allocated memory */
|
||||||
free(stripIdx);
|
free(stripIdx);
|
||||||
@ -1947,7 +1959,7 @@ static void fghCylinder( GLfloat radius, GLfloat height, GLint slices, GLint sta
|
|||||||
stripIdx[idx+1] = nVert-1; /* repeat first slice's idx for closing off shape */
|
stripIdx[idx+1] = nVert-1; /* repeat first slice's idx for closing off shape */
|
||||||
|
|
||||||
/* draw */
|
/* draw */
|
||||||
fghDrawGeometrySolid(vertices,normals,nVert,stripIdx,stacks+2,(slices+1)*2);
|
fghDrawGeometrySolid(vertices,normals,NULL,nVert,stripIdx,stacks+2,(slices+1)*2);
|
||||||
|
|
||||||
/* cleanup allocated memory */
|
/* cleanup allocated memory */
|
||||||
free(stripIdx);
|
free(stripIdx);
|
||||||
@ -2041,7 +2053,7 @@ static void fghTorus( GLfloat dInnerRadius, GLfloat dOuterRadius, GLint nSides,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* draw */
|
/* draw */
|
||||||
fghDrawGeometrySolid(vertices,normals,nVert,stripIdx,nSides,(nRings+1)*2);
|
fghDrawGeometrySolid(vertices,normals,NULL,nVert,stripIdx,nSides,(nRings+1)*2);
|
||||||
|
|
||||||
/* cleanup allocated memory */
|
/* cleanup allocated memory */
|
||||||
free(stripIdx);
|
free(stripIdx);
|
||||||
|
@ -25,171 +25,424 @@
|
|||||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/* notes:
|
||||||
* Original teapot code copyright follows:
|
* the (very little) required math is found here: http://www.gamasutra.com/view/feature/131848/tessellation_of_4x4_bezier_patches_.php?print=1
|
||||||
*/
|
* a much more optimized version is here, didn't bother to implement that: http://www.gamasutra.com/view/feature/131794/an_indepth_look_at_bicubic_bezier_.php?print=1
|
||||||
|
* teacup and teaspoon data: ftp://ftp.funet.fi/pub/sci/graphics/packages/objects/teaset.tar.Z (figure out this sampling scheme)
|
||||||
/*
|
|
||||||
* (c) Copyright 1993, Silicon Graphics, Inc.
|
|
||||||
*
|
|
||||||
* ALL RIGHTS RESERVED
|
|
||||||
*
|
|
||||||
* Permission to use, copy, modify, and distribute this software
|
|
||||||
* for any purpose and without fee is hereby granted, provided
|
|
||||||
* that the above copyright notice appear in all copies and that
|
|
||||||
* both the copyright notice and this permission notice appear in
|
|
||||||
* supporting documentation, and that the name of Silicon
|
|
||||||
* Graphics, Inc. not be used in advertising or publicity
|
|
||||||
* pertaining to distribution of the software without specific,
|
|
||||||
* written prior permission.
|
|
||||||
*
|
|
||||||
* THE MATERIAL EMBODIED ON THIS SOFTWARE IS PROVIDED TO YOU
|
|
||||||
* "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, EXPRESS, IMPLIED OR
|
|
||||||
* OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF
|
|
||||||
* MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. IN NO
|
|
||||||
* EVENT SHALL SILICON GRAPHICS, INC. BE LIABLE TO YOU OR ANYONE
|
|
||||||
* ELSE FOR ANY DIRECT, SPECIAL, INCIDENTAL, INDIRECT OR
|
|
||||||
* CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER,
|
|
||||||
* INCLUDING WITHOUT LIMITATION, LOSS OF PROFIT, LOSS OF USE,
|
|
||||||
* SAVINGS OR REVENUE, OR THE CLAIMS OF THIRD PARTIES, WHETHER OR
|
|
||||||
* NOT SILICON GRAPHICS, INC. HAS BEEN ADVISED OF THE POSSIBILITY
|
|
||||||
* OF SUCH LOSS, HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
|
||||||
* ARISING OUT OF OR IN CONNECTION WITH THE POSSESSION, USE OR
|
|
||||||
* PERFORMANCE OF THIS SOFTWARE.
|
|
||||||
*
|
|
||||||
* US Government Users Restricted Rights
|
|
||||||
*
|
|
||||||
* Use, duplication, or disclosure by the Government is subject to
|
|
||||||
* restrictions set forth in FAR 52.227.19(c)(2) or subparagraph
|
|
||||||
* (c)(1)(ii) of the Rights in Technical Data and Computer
|
|
||||||
* Software clause at DFARS 252.227-7013 and/or in similar or
|
|
||||||
* successor clauses in the FAR or the DOD or NASA FAR
|
|
||||||
* Supplement. Unpublished-- rights reserved under the copyright
|
|
||||||
* laws of the United States. Contractor/manufacturer is Silicon
|
|
||||||
* Graphics, Inc., 2011 N. Shoreline Blvd., Mountain View, CA
|
|
||||||
* 94039-7311.
|
|
||||||
*
|
|
||||||
* OpenGL(TM) is a trademark of Silicon Graphics, Inc.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <GL/freeglut.h>
|
#include <GL/freeglut.h>
|
||||||
#include "fg_internal.h"
|
#include "fg_internal.h"
|
||||||
#include "fg_teapot_data.h"
|
#include "fg_teapot_data.h"
|
||||||
|
|
||||||
|
/* -- STATIC VARS: CACHES ---------------------------------------------------- */
|
||||||
|
|
||||||
|
/* Teapot defs */
|
||||||
|
#define GLUT_TEAPOT_N_PATCHES (6*4 + 4*2) /* 6 patches are reproduced (rotated) 4 times, 4 patches (flipped) 2 times */
|
||||||
|
#define GLUT_SOLID_TEAPOT_N_SUBDIV 10
|
||||||
|
#define GLUT_SOLID_TEAPOT_N_VERT GLUT_SOLID_TEAPOT_N_SUBDIV*GLUT_SOLID_TEAPOT_N_SUBDIV * GLUT_TEAPOT_N_PATCHES /* N_SUBDIV^2 vertices per patch */
|
||||||
|
#define GLUT_SOLID_TEAPOT_N_TRI (GLUT_SOLID_TEAPOT_N_SUBDIV-1)*(GLUT_SOLID_TEAPOT_N_SUBDIV-1) * GLUT_TEAPOT_N_PATCHES * 2 /* if e.g. 7x7 vertices for each patch, there are 6*6 squares for each patch. Each square is decomposed into 2 triangles */
|
||||||
|
|
||||||
|
#define GLUT_WIRE_TEAPOT_N_SUBDIV 7
|
||||||
|
#define GLUT_WIRE_TEAPOT_N_VERT GLUT_WIRE_TEAPOT_N_SUBDIV*GLUT_WIRE_TEAPOT_N_SUBDIV * GLUT_TEAPOT_N_PATCHES /* N_SUBDIV^2 vertices per patch */
|
||||||
|
|
||||||
|
/* Bernstein coefficients only have to be precomputed once (number of patch subdivisions is fixed)
|
||||||
|
* Can thus define arrays for them here, they will be filled upon first use.
|
||||||
|
* 3rd order Bezier surfaces have 4 Bernstein coeffs.
|
||||||
|
* Have separate caches for solid and wire as they use a different number of subdivisions
|
||||||
|
* _0 is for Bernstein polynomials, _1 for their first derivative (which we need for normals)
|
||||||
|
*/
|
||||||
|
static GLfloat bernWire_0 [GLUT_WIRE_TEAPOT_N_SUBDIV] [4];
|
||||||
|
static GLfloat bernWire_1 [GLUT_WIRE_TEAPOT_N_SUBDIV] [4];
|
||||||
|
static GLfloat bernSolid_0[GLUT_SOLID_TEAPOT_N_SUBDIV][4];
|
||||||
|
static GLfloat bernSolid_1[GLUT_SOLID_TEAPOT_N_SUBDIV][4];
|
||||||
|
|
||||||
|
/* Bit of caching:
|
||||||
|
* vertex indices and normals only need to be generated once for
|
||||||
|
* a given number of subdivisions as they don't change with scale.
|
||||||
|
* Vertices can be cached and reused if scale didn't change.
|
||||||
|
*/
|
||||||
|
static GLushort vertIdxsSolid[GLUT_SOLID_TEAPOT_N_TRI*3];
|
||||||
|
static GLfloat normsSolid [GLUT_SOLID_TEAPOT_N_VERT*3];
|
||||||
|
static GLfloat vertsSolid [GLUT_SOLID_TEAPOT_N_VERT*3];
|
||||||
|
static GLfloat texcsSolid [GLUT_SOLID_TEAPOT_N_VERT*2];
|
||||||
|
static GLfloat lastScaleSolid = 0.f;
|
||||||
|
static GLboolean initedSolid = GL_FALSE;
|
||||||
|
|
||||||
|
static GLushort vertIdxsWire [GLUT_WIRE_TEAPOT_N_VERT*2];
|
||||||
|
static GLfloat normsWire [GLUT_WIRE_TEAPOT_N_VERT*3];
|
||||||
|
static GLfloat vertsWire [GLUT_WIRE_TEAPOT_N_VERT*3];
|
||||||
|
static GLfloat lastScaleWire = 0.f;
|
||||||
|
static GLboolean initedWire = GL_FALSE;
|
||||||
|
|
||||||
/* -- PRIVATE FUNCTIONS ---------------------------------------------------- */
|
/* -- PRIVATE FUNCTIONS ---------------------------------------------------- */
|
||||||
|
extern void fghDrawGeometrySolid(GLfloat *vertices, GLfloat *normals, GLfloat *textcs, GLsizei numVertices,
|
||||||
|
GLushort *vertIdxs, GLsizei numParts, GLsizei numVertIdxsPerPart);
|
||||||
|
extern void fghDrawGeometryWire(GLfloat *vertices, GLfloat *normals, GLsizei numVertices,
|
||||||
|
GLushort *vertIdxs, GLsizei numParts, GLsizei numVertPerPart, GLenum vertexMode,
|
||||||
|
GLushort *vertIdxs2, GLsizei numParts2, GLsizei numVertPerPart2);
|
||||||
|
|
||||||
|
/* evaluate 3rd order Bernstein polynomial and its 1st deriv */
|
||||||
static void fghTeapot( GLint grid, GLdouble scale, GLenum type )
|
static void bernstein3(int i, GLfloat x, GLfloat *r0, GLfloat *r1)
|
||||||
{
|
{
|
||||||
#if defined(_WIN32_WCE)
|
float invx = 1.f - x;
|
||||||
int i, numV=sizeof(strip_vertices)/4, numI=sizeof(strip_normals)/4;
|
|
||||||
#else
|
|
||||||
double p[4][4][3], q[4][4][3], r[4][4][3], s[4][4][3];
|
|
||||||
long i, j, k, l;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
glPushAttrib( GL_ENABLE_BIT | GL_EVAL_BIT );
|
/* r0: zero order coeff, r1: first deriv coeff */
|
||||||
glEnable( GL_AUTO_NORMAL );
|
switch (i)
|
||||||
glEnable( GL_NORMALIZE );
|
|
||||||
glEnable( GL_MAP2_VERTEX_3 );
|
|
||||||
glEnable( GL_MAP2_TEXTURE_COORD_2 );
|
|
||||||
|
|
||||||
glPushMatrix();
|
|
||||||
glRotated( 270.0, 1.0, 0.0, 0.0 );
|
|
||||||
glScaled( 0.5 * scale, 0.5 * scale, 0.5 * scale );
|
|
||||||
glTranslated( 0.0, 0.0, -1.5 );
|
|
||||||
|
|
||||||
#if defined(_WIN32_WCE)
|
|
||||||
glRotated( 90.0, 1.0, 0.0, 0.0 );
|
|
||||||
glBegin( GL_TRIANGLE_STRIP );
|
|
||||||
|
|
||||||
for( i = 0; i < numV-1; i++ )
|
|
||||||
{
|
{
|
||||||
int vidx = strip_vertices[i],
|
GLfloat temp;
|
||||||
nidx = strip_normals[i];
|
case 0:
|
||||||
|
temp = invx*invx;
|
||||||
|
*r0 = invx * temp; /* invx * invx * invx */
|
||||||
|
*r1 = -3 * temp; /* -3 * invx * invx */
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
temp = invx*invx;
|
||||||
|
*r0 = 3 * x * temp; /* 3 * x * invx * invx */
|
||||||
|
*r1 = 3 * temp - 6 * x * invx; /* 3 * invx * invx - 6 * x * invx */
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
temp = x*x;
|
||||||
|
*r0 = 3 * temp * invx; /* 3 * x * x * invx */
|
||||||
|
*r1 = 6 * x * invx - 3 * temp; /* 6 * x * invx - 3 * x * x */
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
temp = x*x;
|
||||||
|
*r0 = x * temp; /* x * x * x */
|
||||||
|
*r1 = 3 * temp; /* 3 * x * x */
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
*r0 = *r1 = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if( vidx != -1 )
|
static void pregenBernstein(int nSubDivs, GLfloat (*bern_0)[4], GLfloat (*bern_1)[4])
|
||||||
|
{
|
||||||
|
int s,i;
|
||||||
|
for (s=0; s<nSubDivs; s++)
|
||||||
{
|
{
|
||||||
glNormal3fv( normals[nidx] );
|
GLfloat x = s/(nSubDivs-1.f);
|
||||||
glVertex3fv( vertices[vidx] );
|
for (i=0; i<4; i++) /* 3rd order polynomial */
|
||||||
|
bernstein3(i,x,bern_0[s]+i,bern_1[s]+i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* based on flag either rotate patches around y axis to other 3 quadrants (flag=4) or reflect patch across x-y plane (flag=2) */
|
||||||
|
static void rotOrReflect(int flag, int nVals, int nSubDivs, GLfloat *vals)
|
||||||
|
{
|
||||||
|
int u,i,o;
|
||||||
|
|
||||||
|
if (flag==4)
|
||||||
|
{
|
||||||
|
int i1=nVals, i2=nVals*2, i3=nVals*3;
|
||||||
|
for (o=0; o<nVals; o+=3)
|
||||||
|
{
|
||||||
|
/* 90° rotation */
|
||||||
|
vals[i1+o+0] = vals[o+2];
|
||||||
|
vals[i1+o+1] = vals[o+1];
|
||||||
|
vals[i1+o+2] = -vals[o+0];
|
||||||
|
/* 180° rotation */
|
||||||
|
vals[i2+o+0] = -vals[o+0];
|
||||||
|
vals[i2+o+1] = vals[o+1];
|
||||||
|
vals[i2+o+2] = -vals[o+2];
|
||||||
|
/* 270° rotation */
|
||||||
|
vals[i3+o+0] = -vals[o+2];
|
||||||
|
vals[i3+o+1] = vals[o+1];
|
||||||
|
vals[i3+o+2] = vals[o+0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (flag==2)
|
||||||
|
{
|
||||||
|
/* copy over values, reversing row order to keep winding correct, and negating z to perform the flip */
|
||||||
|
for (u=0; u<nSubDivs; u++) /* per row */
|
||||||
|
{
|
||||||
|
int off = (nSubDivs-u-1)*nSubDivs*3; /* read last row first from the already existing rows */
|
||||||
|
o = nVals + u *nSubDivs*3; /* write last row as first row to output */
|
||||||
|
for (i=0; i<nSubDivs*3; i+=3, o+=3) /* each row has nSubDivs points consisting of three values */
|
||||||
|
{
|
||||||
|
vals[o+0] = vals[off+i+0];
|
||||||
|
vals[o+1] = vals[off+i+1];
|
||||||
|
vals[o+2] = -vals[off+i+2];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* verts array should be initialized to 0! */
|
||||||
|
static int evalBezierWithNorm(GLfloat cp[4][4][3], int nSubDivs, float (*bern_0)[4], float (*bern_1)[4], int flag, int normalFix, GLfloat *verts, GLfloat *norms)
|
||||||
|
{
|
||||||
|
int nVerts = nSubDivs*nSubDivs;
|
||||||
|
int nVertVals = nVerts*3; /* number of values output for one patch, flag (2 or 4) indicates how many times we will write this to output */
|
||||||
|
int u,v,i,j,o;
|
||||||
|
|
||||||
|
/* generate vertices and coordinates for the patch */
|
||||||
|
for (u=0,o=0; u<nSubDivs; u++)
|
||||||
|
{
|
||||||
|
for (v=0; v<nSubDivs; v++, o+=3)
|
||||||
|
{
|
||||||
|
/* for normals, get two tangents at the vertex using partial derivatives of 2D Bezier grid */
|
||||||
|
float tan1[3]={0}, tan2[3]={0}, len;
|
||||||
|
for (i=0; i<=3; i++)
|
||||||
|
{
|
||||||
|
float vert_0[3]={0}, vert_1[3]={0};
|
||||||
|
for (j=0; j<=3; j++)
|
||||||
|
{
|
||||||
|
vert_0[0] += bern_0[v][j] * cp[i][j][0];
|
||||||
|
vert_0[1] += bern_0[v][j] * cp[i][j][1];
|
||||||
|
vert_0[2] += bern_0[v][j] * cp[i][j][2];
|
||||||
|
|
||||||
|
vert_1[0] += bern_1[v][j] * cp[i][j][0];
|
||||||
|
vert_1[1] += bern_1[v][j] * cp[i][j][1];
|
||||||
|
vert_1[2] += bern_1[v][j] * cp[i][j][2];
|
||||||
|
}
|
||||||
|
|
||||||
|
verts[o+0] += bern_0[u][i]*vert_0[0];
|
||||||
|
verts[o+1] += bern_0[u][i]*vert_0[1];
|
||||||
|
verts[o+2] += bern_0[u][i]*vert_0[2];
|
||||||
|
|
||||||
|
tan1[0] += bern_0[u][i]*vert_1[0];
|
||||||
|
tan1[1] += bern_0[u][i]*vert_1[1];
|
||||||
|
tan1[2] += bern_0[u][i]*vert_1[2];
|
||||||
|
tan2[0] += bern_1[u][i]*vert_0[0];
|
||||||
|
tan2[1] += bern_1[u][i]*vert_0[1];
|
||||||
|
tan2[2] += bern_1[u][i]*vert_0[2];
|
||||||
|
}
|
||||||
|
/* get normal through cross product of the two tangents of the vertex */
|
||||||
|
norms[o+0] = tan1[1] * tan2[2] - tan1[2] * tan2[1];
|
||||||
|
norms[o+1] = tan1[2] * tan2[0] - tan1[0] * tan2[2];
|
||||||
|
norms[o+2] = tan1[0] * tan2[1] - tan1[1] * tan2[0];
|
||||||
|
len = (GLfloat)sqrt(norms[o+0] * norms[o+0] + norms[o+1] * norms[o+1] + norms[o+2] * norms[o+2]);
|
||||||
|
norms[o+0] /= len;
|
||||||
|
norms[o+1] /= len;
|
||||||
|
norms[o+2] /= len;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Fix normal vector if needed */
|
||||||
|
if (normalFix)
|
||||||
|
{
|
||||||
|
for (o=0; o<nSubDivs*3; o+=3) /* whole first row (first nSubDivs normals) is broken: replace normals for the whole row */
|
||||||
|
{
|
||||||
|
norms[o+0] = 0.f;
|
||||||
|
norms[o+1] = normalFix==1? 1.f:-1.f;
|
||||||
|
norms[o+2] = 0.f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* now based on flag either rotate patches around y axis to other 3 quadrants (flag=4) or reflect patch across x-y plane (flag=2) */
|
||||||
|
rotOrReflect(flag, nVertVals, nSubDivs, verts);
|
||||||
|
rotOrReflect(flag, nVertVals, nSubDivs, norms);
|
||||||
|
|
||||||
|
return nVertVals*flag;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* verts array should be initialized to 0! */
|
||||||
|
static int evalBezier(GLfloat cp[4][4][3], int nSubDivs, float (*bern_0)[4], int flag, GLfloat *verts)
|
||||||
|
{
|
||||||
|
int nVerts = nSubDivs*nSubDivs;
|
||||||
|
int nVertVals = nVerts*3; /* number of values output for one patch, flag (2 or 4) indicates how many times we will write this to output */
|
||||||
|
int u,v,i,j,o;
|
||||||
|
|
||||||
|
/* generate vertices and coordinates for the patch */
|
||||||
|
for (u=0,o=0; u<nSubDivs; u++)
|
||||||
|
{
|
||||||
|
for (v=0; v<nSubDivs; v++, o+=3)
|
||||||
|
{
|
||||||
|
for (i=0; i<=3; i++)
|
||||||
|
{
|
||||||
|
float vert_0[3]={0};
|
||||||
|
for (j=0; j<=3; j++)
|
||||||
|
{
|
||||||
|
vert_0[0] += bern_0[v][j] * cp[i][j][0];
|
||||||
|
vert_0[1] += bern_0[v][j] * cp[i][j][1];
|
||||||
|
vert_0[2] += bern_0[v][j] * cp[i][j][2];
|
||||||
|
}
|
||||||
|
|
||||||
|
verts[o+0] += bern_0[u][i]*vert_0[0];
|
||||||
|
verts[o+1] += bern_0[u][i]*vert_0[1];
|
||||||
|
verts[o+2] += bern_0[u][i]*vert_0[2];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* now based on flag either rotate patches around y axis to other 3 quadrants (flag=4) or reflect patch across x-y plane (flag=2) */
|
||||||
|
rotOrReflect(flag, nVertVals, nSubDivs, verts);
|
||||||
|
|
||||||
|
return nVertVals*flag;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void fghTeapot( GLfloat scale, GLboolean useWireMode )
|
||||||
|
{
|
||||||
|
/* for internal use */
|
||||||
|
int p,o;
|
||||||
|
GLfloat cp[4][4][3];
|
||||||
|
/* to hold pointers to static vars/arrays */
|
||||||
|
GLfloat (*bern_0)[4], (*bern_1)[4];
|
||||||
|
GLfloat *verts, *norms, *lastScale;
|
||||||
|
GLushort *vertIdxs;
|
||||||
|
GLboolean * inited;
|
||||||
|
int nSubDivs, nVerts;
|
||||||
|
|
||||||
|
/* Get relevant static arrays and variables */
|
||||||
|
bern_0 = useWireMode ? bernWire_0 : bernSolid_0;
|
||||||
|
bern_1 = useWireMode ? bernWire_1 : bernSolid_1;
|
||||||
|
verts = useWireMode ? vertsWire : vertsSolid;
|
||||||
|
norms = useWireMode ? normsWire : normsSolid;
|
||||||
|
lastScale = useWireMode ? &lastScaleWire : &lastScaleSolid;
|
||||||
|
vertIdxs = useWireMode ? vertIdxsWire : vertIdxsSolid;
|
||||||
|
inited = useWireMode ? &initedWire : &initedSolid;
|
||||||
|
nSubDivs = useWireMode ? GLUT_WIRE_TEAPOT_N_SUBDIV : GLUT_SOLID_TEAPOT_N_SUBDIV;
|
||||||
|
nVerts = useWireMode ? GLUT_WIRE_TEAPOT_N_VERT : GLUT_SOLID_TEAPOT_N_VERT;
|
||||||
|
|
||||||
|
/* check if need to generate vertices */
|
||||||
|
if (!*inited || scale != *lastScale)
|
||||||
|
{
|
||||||
|
printf("regen\n");
|
||||||
|
/* set vertex array to all 0 (not necessary for normals and vertex indices) */
|
||||||
|
memset(verts,0,nVerts*3*sizeof(GLfloat));
|
||||||
|
|
||||||
|
/* pregen Berstein polynomials and their first derivatives (for normals) */
|
||||||
|
if (!*inited)
|
||||||
|
pregenBernstein(nSubDivs,bern_0,bern_1);
|
||||||
|
|
||||||
|
/* generate vertices and normals */
|
||||||
|
for (p=0, o=0; p<GLUT_TEAPOT_N_INPUT_PATCHES; p++)
|
||||||
|
{
|
||||||
|
/* set flags for evalBezier function */
|
||||||
|
int flag = p<6?4:2; /* first six patches get 3 copies (rotations), last four get 2 copies (flips) */
|
||||||
|
int normalFix = p==3?1:p==5?2:0; /* Fix normal vectors for vertices on top of lid (patch 4) and on middle of bottom (patch 6). Different flag value as different normal needed */
|
||||||
|
|
||||||
|
/* collect control points */
|
||||||
|
int i;
|
||||||
|
for (i=0; i<16; i++)
|
||||||
|
{
|
||||||
|
/* Original code draw with a 270° rot around X axis, a scaling and a translation along the Z-axis.
|
||||||
|
* Incorporating these in the control points is much cheaper than transforming all the vertices.
|
||||||
|
* Original:
|
||||||
|
* glRotated( 270.0, 1.0, 0.0, 0.0 );
|
||||||
|
* glScaled( 0.5 * scale, 0.5 * scale, 0.5 * scale );
|
||||||
|
* glTranslated( 0.0, 0.0, -1.5 );
|
||||||
|
*/
|
||||||
|
cp[i/4][i%4][0] = cpdata[patchdata[p][i]][0] *scale/2.f;
|
||||||
|
cp[i/4][i%4][1] = (cpdata[patchdata[p][i]][2]-1.5f)*scale/2.f;
|
||||||
|
cp[i/4][i%4][2] = -cpdata[patchdata[p][i]][1] *scale/2.f;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* eval bezier patch */
|
||||||
|
if (!*inited) /* first time, generate normals as well */
|
||||||
|
o += evalBezierWithNorm(cp,nSubDivs,bern_0,bern_1, flag, normalFix, verts+o,norms+o);
|
||||||
|
else /* only need to regen vertices */
|
||||||
|
o += evalBezier(cp,nSubDivs,bern_0, flag, verts+o);
|
||||||
|
}
|
||||||
|
*lastScale = scale;
|
||||||
|
|
||||||
|
if (!*inited)
|
||||||
|
{
|
||||||
|
int r,c;
|
||||||
|
/* generate texture coordinates if solid teapot */
|
||||||
|
if (!useWireMode)
|
||||||
|
{
|
||||||
|
/* generate for first patch */
|
||||||
|
for (r=0,o=0; r<nSubDivs; r++)
|
||||||
|
{
|
||||||
|
GLfloat u = r/(nSubDivs-1.f);
|
||||||
|
for (c=0; c<nSubDivs; c++, o+=2)
|
||||||
|
{
|
||||||
|
GLfloat v = c/(nSubDivs-1.f);
|
||||||
|
texcsSolid[o+0] = u;
|
||||||
|
texcsSolid[o+1] = v;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* copy it over for all the other patches */
|
||||||
|
for (p=1; p<GLUT_TEAPOT_N_PATCHES; p++)
|
||||||
|
memcpy(texcsSolid+p*nSubDivs*nSubDivs*2,texcsSolid,nSubDivs*nSubDivs*2*sizeof(GLfloat));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* build vertex index array */
|
||||||
|
if (useWireMode)
|
||||||
|
{
|
||||||
|
/* build vertex indices to draw teapot as line strips */
|
||||||
|
/* first strips along increasing u, constant v */
|
||||||
|
for (p=0, o=0; p<GLUT_TEAPOT_N_PATCHES; p++)
|
||||||
|
{
|
||||||
|
int idx = nSubDivs*nSubDivs*p;
|
||||||
|
for (c=0; c<nSubDivs; c++)
|
||||||
|
for (r=0; r<nSubDivs; r++, o++)
|
||||||
|
vertIdxs[o] = idx+r*nSubDivs+c;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* then strips along increasing v, constant u */
|
||||||
|
for (p=0; p<GLUT_TEAPOT_N_PATCHES; p++) /* don't reset o, we continue appending! */
|
||||||
|
{
|
||||||
|
int idx = nSubDivs*nSubDivs*p;
|
||||||
|
for (r=0; r<nSubDivs; r++)
|
||||||
|
{
|
||||||
|
int loc = r*nSubDivs;
|
||||||
|
for (c=0; c<nSubDivs; c++, o++)
|
||||||
|
vertIdxs[o] = idx+loc+c;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
glEnd();
|
/* build vertex indices to draw teapot as triangles */
|
||||||
glBegin( GL_TRIANGLE_STRIP );
|
for (p=0,o=0; p<GLUT_TEAPOT_N_PATCHES; p++)
|
||||||
}
|
{
|
||||||
}
|
int idx = nSubDivs*nSubDivs*p;
|
||||||
|
for (r=0; r<nSubDivs-1; r++)
|
||||||
|
{
|
||||||
|
int loc = r*nSubDivs;
|
||||||
|
for (c=0; c<nSubDivs-1; c++, o+=6)
|
||||||
|
{
|
||||||
|
/* ABC ACD, where B and C are one row lower */
|
||||||
|
int row1 = idx+loc+c;
|
||||||
|
int row2 = row1+nSubDivs;
|
||||||
|
|
||||||
glEnd();
|
vertIdxs[o+0] = row1+0;
|
||||||
#else
|
vertIdxs[o+1] = row2+0;
|
||||||
for (i = 0; i < 10; i++) {
|
vertIdxs[o+2] = row2+1;
|
||||||
for (j = 0; j < 4; j++) {
|
|
||||||
for (k = 0; k < 4; k++) {
|
vertIdxs[o+3] = row1+0;
|
||||||
for (l = 0; l < 3; l++) {
|
vertIdxs[o+4] = row2+1;
|
||||||
p[j][k][l] = cpdata[patchdata[i][j * 4 + k]][l];
|
vertIdxs[o+5] = row1+1;
|
||||||
q[j][k][l] = cpdata[patchdata[i][j * 4 + (3 - k)]][l];
|
|
||||||
if (l == 1)
|
|
||||||
q[j][k][l] *= -1.0;
|
|
||||||
if (i < 6) {
|
|
||||||
r[j][k][l] =
|
|
||||||
cpdata[patchdata[i][j * 4 + (3 - k)]][l];
|
|
||||||
if (l == 0)
|
|
||||||
r[j][k][l] *= -1.0;
|
|
||||||
s[j][k][l] = cpdata[patchdata[i][j * 4 + k]][l];
|
|
||||||
if (l == 0)
|
|
||||||
s[j][k][l] *= -1.0;
|
|
||||||
if (l == 1)
|
|
||||||
s[j][k][l] *= -1.0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
glMap2d(GL_MAP2_TEXTURE_COORD_2, 0.0, 1.0, 2, 2, 0.0, 1.0, 4, 2,
|
*inited = GL_TRUE;
|
||||||
&tex[0][0][0]);
|
|
||||||
glMap2d(GL_MAP2_VERTEX_3, 0.0, 1.0, 3, 4, 0.0, 1.0, 12, 4,
|
|
||||||
&p[0][0][0]);
|
|
||||||
glMapGrid2d(grid, 0.0, 1.0, grid, 0.0, 1.0);
|
|
||||||
glEvalMesh2(type, 0, grid, 0, grid);
|
|
||||||
glMap2d(GL_MAP2_VERTEX_3, 0.0, 1.0, 3, 4, 0.0, 1.0, 12, 4,
|
|
||||||
&q[0][0][0]);
|
|
||||||
glEvalMesh2(type, 0, grid, 0, grid);
|
|
||||||
if (i < 6) {
|
|
||||||
glMap2d(GL_MAP2_VERTEX_3, 0.0, 1.0, 3, 4, 0.0, 1.0, 12, 4,
|
|
||||||
&r[0][0][0]);
|
|
||||||
glEvalMesh2(type, 0, grid, 0, grid);
|
|
||||||
glMap2d(GL_MAP2_VERTEX_3, 0.0, 1.0, 3, 4, 0.0, 1.0, 12, 4,
|
|
||||||
&s[0][0][0]);
|
|
||||||
glEvalMesh2(type, 0, grid, 0, grid);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /* defined(_WIN32_WCE) */
|
|
||||||
|
|
||||||
glPopMatrix();
|
/* draw */
|
||||||
glPopAttrib();
|
// TODO: texture coordinates
|
||||||
|
if (useWireMode)
|
||||||
|
fghDrawGeometryWire(verts, norms, nVerts, vertIdxs, GLUT_TEAPOT_N_PATCHES*nSubDivs*2, nSubDivs, GL_LINE_STRIP, NULL,0,0);
|
||||||
|
else
|
||||||
|
fghDrawGeometrySolid(verts,norms,texcsSolid,nVerts,vertIdxs,1,GLUT_SOLID_TEAPOT_N_TRI*3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* -- INTERFACE FUNCTIONS -------------------------------------------------- */
|
/* -- INTERFACE FUNCTIONS -------------------------------------------------- */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Renders a beautiful wired teapot...
|
* Renders a wired teapot...
|
||||||
*/
|
*/
|
||||||
void FGAPIENTRY glutWireTeapot( GLdouble size )
|
void FGAPIENTRY glutWireTeapot( double size )
|
||||||
{
|
{
|
||||||
FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutWireTeapot" );
|
FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutWireTeapot" );
|
||||||
/* We will use the general teapot rendering code */
|
/* We will use the general teapot rendering code */
|
||||||
fghTeapot( 10, size, GL_LINE );
|
fghTeapot( (GLfloat)size, GL_TRUE );
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Renders a beautiful filled teapot...
|
* Renders a filled teapot...
|
||||||
*/
|
*/
|
||||||
void FGAPIENTRY glutSolidTeapot( GLdouble size )
|
void FGAPIENTRY glutSolidTeapot( double size )
|
||||||
{
|
{
|
||||||
FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSolidTeapot" );
|
FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSolidTeapot" );
|
||||||
/* We will use the general teapot rendering code */
|
/* We will use the general teapot rendering code */
|
||||||
fghTeapot( 7, size, GL_FILL );
|
fghTeapot( (GLfloat)size, GL_FALSE );
|
||||||
}
|
}
|
||||||
|
|
||||||
/*** END OF FILE ***/
|
/*** END OF FILE ***/
|
||||||
|
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user