]> git.tdb.fi Git - r2c2.git/blobdiff - source/3d/tracktype.cpp
Render ties between rails on tracks
[r2c2.git] / source / 3d / tracktype.cpp
index d664c3948ef7a1c9bf54998a4abe661c45b2568e..aad2ca898d1bc5ca9126ad5474a0c3bd3f2a52c6 100644 (file)
@@ -29,6 +29,11 @@ TrackType3D::TrackType3D(Catalogue3D &c, const TrackType &tt):
        const Vector &rail_max = rail_profile.get_max_coords();
        float rail_h = rail_max.y-rail_min.y;
 
+       const Profile &tie_profile = appearance.get_tie_profile();
+       const Vector &tie_min = tie_profile.get_min_coords();
+       const Vector &tie_max = tie_profile.get_max_coords();
+       float tie_h = tie_max.y-tie_min.y;
+
        float gauge = cat.get_gauge();
 
        string obj_name = tt.get_object();
@@ -41,12 +46,17 @@ TrackType3D::TrackType3D(Catalogue3D &c, const TrackType &tt):
                GL::MeshBuilder bld(*mesh);
 
                unsigned index = 0;
-               bld.texcoord(0.25, 0.5);
+               bld.texcoord(0.17, 0.5);
+               for(vector<TrackPart>::const_iterator i=parts.begin(); i!=parts.end(); ++i)
+                       build_part(*i, ballast_profile, Vector(0, 0, -ballast_min.y), false, bld, index);
+
+               float y = ballast_h-tie_min.y;
+               bld.texcoord(0.83, 0.5);
                for(vector<TrackPart>::const_iterator i=parts.begin(); i!=parts.end(); ++i)
-                       build_part(*i, ballast_profile, Vector(0, -ballast_min.y, 0), false, bld, index);
+                       build_ties(*i, tie_profile, appearance.get_tie_length(), appearance.get_tie_spacing(), Vector(0, 0, y), bld, index);
 
-               bld.texcoord(0.75, 0.5);
-               float y = ballast_h-rail_min.y;
+               bld.texcoord(0.5, 0.5);
+               y = ballast_h+tie_h-rail_min.y;
                for(vector<TrackPart>::const_iterator i=parts.begin(); i!=parts.end(); ++i)
                        build_part(*i, rail_profile, Vector(0, gauge/2, y), true, bld, index);
                for(vector<TrackPart>::const_iterator i=parts.begin(); i!=parts.end(); ++i)
@@ -158,4 +168,84 @@ void TrackType3D::build_part(const TrackPart &part, const Profile &profile, cons
        base_index += (nsegs+1)*n_vertices;
 }
 
+void TrackType3D::build_ties(const TrackPart &part, const Profile &profile, float length, float spacing, const Vector &offset, GL::MeshBuilder &bld, unsigned &base_index)
+{
+       float plen = part.get_length();
+       unsigned count = plen/spacing+0.5;
+       (void)length;
+       (void)offset;
+       (void)profile;
+
+       unsigned n_vertices = profile.get_n_vertices();
+       float min_y = profile.get_min_coords().y;
+       vector<Vector> cap_vertices;
+       for(unsigned i=0; i+1<n_vertices; )
+       {
+               const Profile::Vertex &v = profile.get_vertex(i);
+               if(cap_vertices.size()>=2)
+               {
+                       if(i+2<n_vertices)
+                               cap_vertices.push_back(Vector(v.pos.x, min_y, 0));
+                       else
+                               cap_vertices.push_back(profile.get_vertex(n_vertices-1).pos);
+               }
+               cap_vertices.push_back(v.pos);
+
+               ++i;
+               if(!profile.get_vertex(i).smooth)
+                       ++i;
+       }
+
+       for(unsigned i=0; i<count; ++i)
+       {
+               OrientedPoint basep = part.get_point((i+0.5)*plen/count);
+               Transform trans = Transform::rotation(basep.rotation, Vector(0, 0, 1));
+
+               unsigned strip = 0;
+               for(unsigned j=0; j<n_vertices; ++j)
+               {
+                       const Profile::Vertex &v = profile.get_vertex(j);
+
+                       Vector n = trans.transform(Vector(0, -v.normal.x, v.normal.y));
+                       bld.normal(n.x, n.y, n.z);
+
+                       if(!strip)
+                               bld.begin(GL::TRIANGLE_STRIP);
+
+                       for(unsigned k=0; k<2; ++k)
+                       {
+                               Vector p((k-0.5)*length, -v.pos.x, v.pos.y);
+                               p = basep.position+trans.transform(offset+p);
+                               bld.vertex(p.x, p.y, p.z);
+                       }
+
+                       if(++strip>=2 && !profile.get_vertex(j).smooth)
+                       {
+                               bld.end();
+                               strip = 0;
+                       }
+               }
+               if(strip)
+                       bld.end();
+
+               for(unsigned j=0; j<2; ++j)
+               {
+                       Vector n = trans.transform(Vector(j*2.0-1, 0, 0));
+                       bld.normal(n.x, n.y, n.z);
+
+                       bld.begin(GL::TRIANGLE_STRIP);
+                       for(unsigned k=0; k<cap_vertices.size(); ++k)
+                       {
+                               const Vector &v = cap_vertices[k^j];
+                               Vector p((j-0.5)*length, -v.x, v.y);
+                               p = basep.position+trans.transform(offset+p);
+                               bld.vertex(p.x, p.y, p.z);
+                       }
+                       bld.end();
+               }
+
+               base_index += 2*(n_vertices+cap_vertices.size());
+       }
+}
+
 } // namespace R2C2