Use meshes for curved rails
authorNick Gasson <nick@nickg.me.uk>
Sun, 24 May 2009 20:11:50 +0000 (21:11 +0100)
committerNick Gasson <nick@nickg.me.uk>
Sun, 24 May 2009 20:11:50 +0000 (21:11 +0100)
include/IMesh.hpp
src/Mesh.cpp
src/TrackCommon.cpp

index acdbd07444a3e7591059c82188b4ac7f5a3f3ec0..e225136e908dca645f8d2799064b8b7efaa68974 100644 (file)
@@ -55,6 +55,9 @@ struct IMeshBuffer {
    // Convenience functions
    virtual void addQuad(Vertex a, Vertex b, Vertex c, Vertex d,
                         Colour aColour) = 0;
+   virtual void addQuad(Vertex a, Vertex b, Vertex c, Vertex d,
+                        Normal na, Normal nb, Normal nc, Normal nd,
+                        Colour aColour) = 0;
 
    virtual void bindMaterial(const Material& aMaterial) = 0;
    
index bef493b4ea3b5c7cb9e90e61cffa7b014cea5ee6..2c32d4d588a06213a302ab615ef683a8d702917a 100644 (file)
@@ -41,6 +41,9 @@ struct MeshBuffer : IMeshBuffer {
 
    void addQuad(Vertex a, Vertex b, Vertex c, Vertex d,
                 Colour aColour);
+   void addQuad(Vertex a, Vertex b, Vertex c, Vertex d,
+                Normal na, Normal nb, Normal nc, Normal nd,
+                Colour aColour);
       
    void bindMaterial(const Material& aMaterial);
    
@@ -196,6 +199,20 @@ void MeshBuffer::addQuad(Vertex a, Vertex b, Vertex c, Vertex d, Colour aColour)
    add(b, n2, aColour);
 }
 
+void MeshBuffer::addQuad(Vertex a, Vertex b, Vertex c, Vertex d,
+                         Normal na, Normal nb, Normal nc, Normal nd,
+                         Colour aColour)
+{
+   
+   add(b, na, aColour);
+   add(c, nb, aColour);
+   add(d, nc, aColour);
+
+   add(d, nd, aColour);
+   add(a, na, aColour);
+   add(b, nb, aColour);
+}
+
 // Default material
 Material::Material()
   : diffuseR(1.0f), diffuseG(1.0f), diffuseB(1.0f),
index c6e9ccc247885e91fbae308e3219ce35b8abb082..af2c73de63a3eeb1bbfce658095aaba2ace07b56 100644 (file)
@@ -21,6 +21,7 @@
 #include "IMesh.hpp"
 
 #include <cmath>
+#include <map>
 
 #include <GL/gl.h>
 
@@ -36,6 +37,9 @@ namespace {
 
    IMeshPtr theSleeperMesh, theRailMesh;
 
+   typedef map<int, IMeshPtr> CurvedRailMeshMap;
+   CurvedRailMeshMap theCurvedRailMeshes;
+   
    void generateSleeperMesh()
    {
       IMeshBufferPtr buf = makeMeshBuffer();
@@ -115,6 +119,94 @@ namespace {
       
       theRailMesh = makeMesh(buf);
    }
+
+   enum RailType {
+      InnerRail, OuterRail
+   };
+   
+   IMeshPtr generateCurvedRailMesh(IMeshBufferPtr buf, int baseRadius, RailType type)
+   {
+      const float edgeWidth = (1 - GAUGE - RAIL_WIDTH)/2.0;
+      const float R = static_cast<float>(baseRadius) - edgeWidth
+      - (type == OuterRail ? 0 : GAUGE);
+      const float r = R - RAIL_WIDTH;
+      
+      const float step = 0.1f;
+
+      const IMeshBuffer::Colour metal = make_tuple(0.7f, 0.7f, 0.7f);
+      
+      // Top of rail
+      for (float theta = 0; theta < M_PI / 2.0f; theta += step) {
+         buf->addQuad(makeVector(r * cos(theta), 0.1f, r * sin(theta)), 
+                      makeVector(r * cos(theta + step), 0.1f, r * sin(theta + step)),
+                      makeVector(R * cos(theta + step), 0.1f, R * sin(theta + step)),
+                      makeVector(R * cos(theta), 0.1f, R * sin(theta)),
+                      metal);
+      }
+      
+      // Outer edge
+      for (float theta = 0; theta < M_PI / 2.0f; theta += step) {
+         const float sinT = sin(theta);
+         const float cosT = cos(theta);
+         const float sinT1 = sin(theta + step);
+         const float cosT1 = cos(theta + step);
+
+         buf->addQuad(// Vertices
+                      makeVector(R * cosT1, 0.1f, R * sinT1),
+                      makeVector(R * cosT1, 0.0f, R * sinT1),
+                      makeVector(R * cosT, 0.0f, R * sinT),
+                      makeVector(R * cosT, 0.1f, R * sinT),
+
+                      // Normals
+                      makeVector(cosT1, 0.0f, sinT1),
+                      makeVector(cosT1, 0.0f, sinT1),
+                      makeVector(cosT, 0.0f, sinT),
+                      makeVector(cosT, 0.0f, sinT),
+
+                      metal);
+      }
+      
+      // Inner edge
+      for (float theta = 0; theta < M_PI / 2.0f; theta += step) {
+         const float sinT = sin(theta);
+         const float cosT = cos(theta);
+         const float sinT1 = sin(theta + step);
+         const float cosT1 = cos(theta + step);
+
+         buf->addQuad(// Vertices
+                      makeVector(r * cosT, 0.1f, r * sinT),
+                      makeVector(r * cosT, 0.0f, r * sinT),
+                      makeVector(r * cosT1, 0.0f, r * sinT1),
+                      makeVector(r * cosT1, 0.1f, r * sinT1),
+
+                      // Normals
+                      makeVector(-cosT, 0.0f, -sinT),
+                      makeVector(-cosT, 0.0f, -sinT),
+                      makeVector(-cosT1, 0.0f, -sinT1),
+                      makeVector(-cosT1, 0.0f, -sinT1),
+
+                      metal);
+      }
+
+      return makeMesh(buf);
+   }
+   
+   IMeshPtr getCurvedRailMesh(int baseRadius)
+   {      
+      CurvedRailMeshMap::iterator it = theCurvedRailMeshes.find(baseRadius);
+      if (it != theCurvedRailMeshes.end())
+         return (*it).second;
+      else {
+         IMeshBufferPtr buf = makeMeshBuffer();
+         
+         generateCurvedRailMesh(buf, baseRadius, InnerRail);
+         generateCurvedRailMesh(buf, baseRadius, OuterRail);
+            
+         IMeshPtr ptr = makeMesh(buf);
+         theCurvedRailMeshes[baseRadius] = ptr;
+         return ptr;
+      }         
+   }
 }
 
 // Draw a sleeper in the current maxtrix location
@@ -147,92 +239,15 @@ void renderStraightRail()
    glPopMatrix();
 }
 
-enum RailType {
-   InnerRail, OuterRail
-};
-
 static void makeCurveRail(int baseRadius, track::Angle startAngle,
                           track::Angle finishAngle, RailType type)
 {
-   const float edgeWidth = (1 - GAUGE - RAIL_WIDTH)/2.0;
-   const float R = static_cast<float>(baseRadius) - edgeWidth
-      - (type == OuterRail ? 0 : GAUGE);
-   const float r = R - RAIL_WIDTH;
-
-   const float step = 0.1;
-
-   glPushAttrib(GL_ENABLE_BIT);
-   glDisable(GL_TEXTURE_2D);
-   glDisable(GL_BLEND);
-
    glPushMatrix();
    
    glRotatef(static_cast<float>(startAngle), 0.0f, 1.0f, 0.0f);
-
-   glColor3f(0.7, 0.7, 0.7);
-
-   const float startAngleR = degToRad(startAngle);
-   const float finishAngleR = degToRad(finishAngle);
-
-   // Top of rail
-   glBegin(GL_QUADS);
-   for (float theta = 0; theta < finishAngleR - startAngleR; theta += step) {
-      glNormal3f(0.0f, 1.0f, 0.0f);
-      glVertex3f(r * cos(theta), 0.1f, r * sin(theta)); 
-      glVertex3f(r * cos(theta + step), 0.1f, r * sin(theta + step));
-      glVertex3f(R * cos(theta + step), 0.1f, R * sin(theta + step));
-      glVertex3f(R * cos(theta), 0.1f, R * sin(theta));
-   }
-   glEnd();
-
-   // Outer edge
-   for (float theta = 0; theta < finishAngleR - startAngleR; theta += step) {
-      const float sinT = sin(theta);
-      const float cosT = cos(theta);
-      const float sinT1 = sin(theta + step);
-      const float cosT1 = cos(theta + step);
-      
-      glBegin(GL_QUADS);
-   
-      glNormal3f(cosT1, 0.0f, sinT1);
-      glVertex3f(R * cosT1, 0.1f, R * sinT1);
-      
-      glNormal3f(cosT1, 0.0f, sinT1);
-      glVertex3f(R * cosT1, 0.0f, R * sinT1);
-      
-      glNormal3f(cosT, 0.0f, sinT);
-      glVertex3f(R * cosT, 0.0f, R * sinT);
-      
-      glNormal3f(cosT, 0.0f, sinT);
-      glVertex3f(R * cosT, 0.1f, R * sinT);
-      
-      glEnd();
-   }
-
-   // Inner edge
-   glBegin(GL_QUADS);
-   for (float theta = 0; theta < finishAngleR - startAngleR; theta += step) {
-      const float sinT = sin(theta);
-      const float cosT = cos(theta);
-      const float sinT1 = sin(theta + step);
-      const float cosT1 = cos(theta + step);
-      
-      glNormal3f(-cosT, 0.0f, -sinT);
-      glVertex3f(r * cosT, 0.1f, r * sinT);
-      
-      glNormal3f(-cosT, 0.0f, -sinT);
-      glVertex3f(r * cosT, 0.0f, r * sinT);
-      
-      glNormal3f(-cosT1, 0.0f, -sinT1);
-      glVertex3f(r * cosT1, 0.0f, r * sinT1);
-      
-      glNormal3f(-cosT1, 0.0f, -sinT1);
-      glVertex3f(r * cosT1, 0.1f, r * sinT1);
-   }
-   glEnd();
+   getCurvedRailMesh(baseRadius)->render();
 
    glPopMatrix();
-   glPopAttrib();
 }
 
 // Move to the origin of a curved section of track