can now also draw the normal vectors (seems very useful for instructive
authorDiederick Niehorster <dcnieho@gmail.com>
Sun, 18 Nov 2012 15:41:03 +0000 (15:41 +0000)
committerDiederick Niehorster <dcnieho@gmail.com>
Sun, 18 Nov 2012 15:41:03 +0000 (15:41 +0000)
programs, something which FreeGLUT often gets used for). use the 'n' key
in the shapes demo

git-svn-id: svn+ssh://svn.code.sf.net/p/freeglut/code/trunk/freeglut/freeglut@1403 7f0cb862-5218-0410-a997-914c9d46530a

include/GL/freeglut_ext.h
progs/demos/shapes/shapes.c
src/fg_geometry.c
src/fg_internal.h
src/fg_state.c
src/fg_structure.c

index 98bb9d7..da6c7ee 100644 (file)
@@ -86,6 +86,8 @@
 
 #define  GLUT_SKIP_STALE_MOTION_EVENTS      0x0204
 
+#define  GLUT_OBJECTS_VISUALIZE_NORMALS     0x0205
+
 /*
  * New tokens for glutInitDisplayMode.
  * Only one GLUT_AUXn bit may be used at a time.
index 6942c77..b2da232 100644 (file)
@@ -420,6 +420,7 @@ static float ar;
 static GLboolean persProject = GL_TRUE;
 static GLboolean animateXRot = GL_FALSE;
 static GLboolean useShader   = GL_FALSE;
+static GLboolean visNormals  = GL_FALSE;
 
 /*
  * These one-liners draw particular objects, fetching appropriate
@@ -541,7 +542,7 @@ static const entry table [] =
     ENTRY (Sphere),
     ENTRY (Cone),
     ENTRY (Cylinder),
-    ENTRY (Cuboctahedron)
+    ENTRY (Cuboctahedron)   /* This one doesn't work when in shader mode and is then skipped */
 };
 #undef ENTRY
 
@@ -659,6 +660,7 @@ static void display(void)
     else
     {
         /* fixed function pipeline */
+        glutSetOption(GLUT_OBJECTS_VISUALIZE_NORMALS,visNormals);   /* Normals visualized or not? */
         glMatrixMode(GL_PROJECTION);
         glLoadIdentity();
         if (persProject)
@@ -709,6 +711,8 @@ static void display(void)
             shapesPrintf (9, 1, "2D rotation (r)");
         else
             shapesPrintf (9, 1, "1D rotation (r)");
+        if (!useShader)
+            shapesPrintf (10, 1, "visualizing normals: %i (n)",visNormals);
     } else {
         /* print to command line instead */
         printf ( "Shape %d slides %d stacks %d\n", function_index, slices, stacks ) ;
@@ -757,6 +761,9 @@ key(unsigned char key, int x, int y)
     case 'S':
     case 's': useShader=!useShader;       break;
 
+    case 'N':
+    case 'n': visNormals=!visNormals;     break;
+
     default:
         break;
     }
index 3e50e79..066a0d3 100644 (file)
    have a nice code order below */
 #ifndef GL_ES_VERSION_2_0
 static void fghDrawGeometryWire11(GLfloat *vertices, GLfloat *normals,
-    GLushort *vertIdxs, GLsizei numParts, GLsizei numVertPerPart, GLenum vertexMode,
-    GLushort *vertIdxs2, GLsizei numParts2, GLsizei numVertPerPart2
+                                  GLushort *vertIdxs, GLsizei numParts, GLsizei numVertPerPart, GLenum vertexMode,
+                                  GLushort *vertIdxs2, GLsizei numParts2, GLsizei numVertPerPart2
     );
 static void fghDrawGeometrySolid11(GLfloat *vertices, GLfloat *normals, GLsizei numVertices,
-    GLushort *vertIdxs, GLsizei numParts, GLsizei numVertIdxsPerPart);
+                                   GLushort *vertIdxs, GLsizei numParts, GLsizei numVertIdxsPerPart);
 #endif
 static void fghDrawGeometryWire20(GLfloat *vertices, GLfloat *normals, GLsizei numVertices,
-    GLushort *vertIdxs, GLsizei numParts, GLsizei numVertPerPart, GLenum vertexMode,
-    GLushort *vertIdxs2, GLsizei numParts2, GLsizei numVertPerPart2,
-    GLint attribute_v_coord, GLint attribute_v_normal
+                                  GLushort *vertIdxs, GLsizei numParts, GLsizei numVertPerPart, GLenum vertexMode,
+                                  GLushort *vertIdxs2, GLsizei numParts2, GLsizei numVertPerPart2,
+                                  GLint attribute_v_coord, GLint attribute_v_normal
     );
 static void fghDrawGeometrySolid20(GLfloat *vertices, GLfloat *normals, GLsizei numVertices,
-    GLushort *vertIdxs, GLsizei numParts, GLsizei numVertIdxsPerPart,
-    GLint attribute_v_coord, GLint attribute_v_normal);
+                                   GLushort *vertIdxs, GLsizei numParts, GLsizei numVertIdxsPerPart,
+                                   GLint attribute_v_coord, GLint attribute_v_normal);
+/* declare function for generating visualization of normals */
+static void fghGenerateNormalVisualization(GLfloat *vertices, GLfloat *normals, GLsizei numVertices,
+                                           GLushort *vertIdxs, GLsizei numParts, GLsizei numVertIdxsPerPart);
+static void fghDrawNormalVisualization();
 
 /* Drawing geometry:
  * Explanation of the functions has to be separate for the polyhedra and
@@ -116,8 +120,8 @@ static void fghDrawGeometrySolid20(GLfloat *vertices, GLfloat *normals, GLsizei
  * Feel free to contribute better naming ;)
  */
 static void fghDrawGeometryWire(GLfloat *vertices, GLfloat *normals, GLsizei numVertices,
-    GLushort *vertIdxs, GLsizei numParts, GLsizei numVertPerPart, GLenum vertexMode,
-    GLushort *vertIdxs2, GLsizei numParts2, GLsizei numVertPerPart2
+                                GLushort *vertIdxs, GLsizei numParts, GLsizei numVertPerPart, GLenum vertexMode,
+                                GLushort *vertIdxs2, GLsizei numParts2, GLsizei numVertPerPart2
     )
 {
     GLint attribute_v_coord  = fgStructure.CurrentWindow->Window.attribute_v_coord;
@@ -176,8 +180,19 @@ static void fghDrawGeometrySolid(GLfloat *vertices, GLfloat *normals, GLsizei nu
                                attribute_v_coord, attribute_v_normal);
 #ifndef GL_ES_VERSION_2_0
     else
+    {
         fghDrawGeometrySolid11(vertices, normals, numVertices,
                                vertIdxs, numParts, numVertIdxsPerPart);
+
+        if (fgStructure.CurrentWindow->State.VisualizeNormals)
+        {
+            /* generate normals for each vertex to be drawn as well */
+            fghGenerateNormalVisualization(vertices, normals, numVertices,
+                                           vertIdxs, numParts, numVertIdxsPerPart);
+            /* draw normals for each vertex as well */
+            fghDrawNormalVisualization();
+        }
+    }
 #endif
 }
 
@@ -186,8 +201,8 @@ static void fghDrawGeometrySolid(GLfloat *vertices, GLfloat *normals, GLsizei nu
 /* Version for OpenGL (ES) 1.1 */
 #ifndef GL_ES_VERSION_2_0
 static void fghDrawGeometryWire11(GLfloat *vertices, GLfloat *normals,
-    GLushort *vertIdxs, GLsizei numParts, GLsizei numVertPerPart, GLenum vertexMode,
-    GLushort *vertIdxs2, GLsizei numParts2, GLsizei numVertPerPart2
+                                  GLushort *vertIdxs, GLsizei numParts, GLsizei numVertPerPart, GLenum vertexMode,
+                                  GLushort *vertIdxs2, GLsizei numParts2, GLsizei numVertPerPart2
     )
 {
     int i;
@@ -217,7 +232,7 @@ static void fghDrawGeometryWire11(GLfloat *vertices, GLfloat *normals,
 
 
 static void fghDrawGeometrySolid11(GLfloat *vertices, GLfloat *normals, GLsizei numVertices,
-    GLushort *vertIdxs, GLsizei numParts, GLsizei numVertIdxsPerPart)
+                                   GLushort *vertIdxs, GLsizei numParts, GLsizei numVertIdxsPerPart)
 {
     int i;
 
@@ -243,10 +258,9 @@ static void fghDrawGeometrySolid11(GLfloat *vertices, GLfloat *normals, GLsizei
 
 /* Version for OpenGL (ES) >= 2.0 */
 static void fghDrawGeometryWire20(GLfloat *vertices, GLfloat *normals, GLsizei numVertices,
-    GLushort *vertIdxs, GLsizei numParts, GLsizei numVertPerPart, GLenum vertexMode,
-    GLushort *vertIdxs2, GLsizei numParts2, GLsizei numVertPerPart2,
-    GLint attribute_v_coord, GLint attribute_v_normal
-    )
+                                  GLushort *vertIdxs, GLsizei numParts, GLsizei numVertPerPart, GLenum vertexMode,
+                                  GLushort *vertIdxs2, GLsizei numParts2, GLsizei numVertPerPart2,
+                                  GLint attribute_v_coord, GLint attribute_v_normal)
 {
     GLuint vbo_coords = 0, vbo_normals = 0,
         ibo_elements = 0, ibo_elements2 = 0;
@@ -447,6 +461,71 @@ static void fghDrawGeometrySolid20(GLfloat *vertices, GLfloat *normals, GLsizei
 
 
 /**
+ * Generate vertex indices for visualizing the normals.
+ */
+static GLfloat *verticesForNormalVisualization;
+static GLushort numNormalVertices = 0;
+static void fghGenerateNormalVisualization(GLfloat *vertices, GLfloat *normals, GLsizei numVertices,
+                                           GLushort *vertIdxs, GLsizei numParts, GLsizei numVertIdxsPerPart)
+{
+    GLushort i,j;
+    /* calc number of vertices to generate, allocate. TODO: FREE again after draw!
+     * two for each vertex in the input shape
+     */
+    if (!vertIdxs)
+        numNormalVertices = numVertices * 2;
+    else
+        numNormalVertices = numParts * numVertIdxsPerPart * 2;
+    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)
+        {
+            verticesForNormalVisualization[j+0] = vertices[i+0];
+            verticesForNormalVisualization[j+1] = vertices[i+1];
+            verticesForNormalVisualization[j+2] = vertices[i+2];
+            verticesForNormalVisualization[j+3] = vertices[i+0] + normals[i+0]/4.f;
+            verticesForNormalVisualization[j+4] = vertices[i+1] + normals[i+1]/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;
+        }
+    }
+}
+
+static void fghDrawNormalVisualization()
+{
+    GLfloat currentColor[4];
+    /* Setup draw color: (1,1,1)-shape's color */
+    glGetFloatv(GL_CURRENT_COLOR,currentColor);
+    glColor4f(1-currentColor[0],1-currentColor[1],1-currentColor[2],currentColor[3]);
+
+    glEnableClientState(GL_VERTEX_ARRAY);
+
+    glVertexPointer(3, GL_FLOAT, 0, verticesForNormalVisualization);
+    glDrawArrays(GL_LINES, 0, numNormalVertices);
+
+    glDisableClientState(GL_VERTEX_ARRAY);
+
+    /* Done, free memory, reset color */
+    free(verticesForNormalVisualization);
+    glColor4fv(currentColor);
+}
+
+/**
  * Generate all combinations of vertices and normals needed to draw object.
  * Optional shape decomposition to triangles:
  * We'll use glDrawElements to draw all shapes that are not naturally
index 129654a..370f176 100644 (file)
@@ -402,7 +402,9 @@ struct tagSFG_WindowState
 
     GLboolean       IsFullscreen;       /* is the window fullscreen? */
 
-    GLboolean       NeedToInitContext; /* are OpenGL context/resources loaded? */
+    GLboolean       NeedToInitContext;  /* are OpenGL context/resources loaded? */
+
+    GLboolean       VisualizeNormals;   /* When drawing objects, draw vectors representing the normals as well? */
 };
 
 
index 734a57c..4f369d4 100644 (file)
@@ -115,6 +115,11 @@ void FGAPIENTRY glutSetOption( GLenum eWhat, int value )
       fgState.SkipStaleMotion = value;
       break;
 
+    case GLUT_OBJECTS_VISUALIZE_NORMALS:
+      if( fgStructure.CurrentWindow != NULL )
+        fgStructure.CurrentWindow->State.VisualizeNormals = value;
+      break;
+
     default:
         fgWarning( "glutSetOption(): missing enum handle %d", eWhat );
         break;
@@ -205,6 +210,11 @@ int FGAPIENTRY glutGet( GLenum eWhat )
     case GLUT_SKIP_STALE_MOTION_EVENTS:
       return fgState.SkipStaleMotion;
 
+    case GLUT_OBJECTS_VISUALIZE_NORMALS:
+      if( fgStructure.CurrentWindow == NULL )
+        return GL_FALSE;
+      return fgStructure.CurrentWindow->State.VisualizeNormals;
+
     default:
         return fgPlatformGlutGet ( eWhat );
         break;
index 7c2c143..8a5b4f5 100644 (file)
@@ -98,6 +98,7 @@ SFG_Window* fgCreateWindow( SFG_Window* parent, const char* title,
     window->State.IgnoreKeyRepeat = GL_FALSE;
     window->State.KeyRepeating    = GL_FALSE;
     window->State.IsFullscreen    = GL_FALSE;
+    window->State.VisualizeNormals= GL_FALSE;
 
     /*
      * Open the window now. The fgOpenWindow() function is system