3 #include <msp/gl/technique.h>
12 TrackType3D::TrackType3D(Catalogue3D &c, const TrackType &tt):
18 const TrackAppearance &appearance = tt.get_appearance();
19 const Catalogue &cat = catalogue.get_catalogue();
20 const vector<TrackPart> &parts = tt.get_parts();
22 const Profile &ballast_profile = appearance.get_ballast_profile();
23 const Vector &ballast_min = ballast_profile.get_min_coords();
24 const Vector &ballast_max = ballast_profile.get_max_coords();
25 float ballast_h = ballast_max.y-ballast_min.y;
27 const Profile &rail_profile = appearance.get_rail_profile();
28 const Vector &rail_min = rail_profile.get_min_coords();
29 const Vector &rail_max = rail_profile.get_max_coords();
30 float rail_h = rail_max.y-rail_min.y;
32 const Profile &tie_profile = appearance.get_tie_profile();
33 const Vector &tie_min = tie_profile.get_min_coords();
34 const Vector &tie_max = tie_profile.get_max_coords();
35 float tie_h = tie_max.y-tie_min.y;
37 float gauge = cat.get_gauge();
39 string obj_name = tt.get_object();
41 object = &catalogue.get<GL::Object>(obj_name);
44 mesh = new GL::Mesh((GL::NORMAL3, GL::TEXCOORD2, GL::VERTEX3));
45 mesh->set_winding(&GL::WindingTest::counterclockwise());
46 GL::MeshBuilder bld(*mesh);
49 bld.texcoord(0.17, 0.5);
50 for(vector<TrackPart>::const_iterator i=parts.begin(); i!=parts.end(); ++i)
51 build_part(*i, ballast_profile, Vector(0, 0, -ballast_min.y), false, bld, index);
53 float y = ballast_h-tie_min.y;
54 bld.texcoord(0.83, 0.5);
55 for(vector<TrackPart>::const_iterator i=parts.begin(); i!=parts.end(); ++i)
56 build_ties(*i, tie_profile, appearance.get_tie_length(), appearance.get_tie_spacing(), Vector(0, 0, y), bld, index);
58 bld.texcoord(0.5, 0.5);
59 y = ballast_h+tie_h-rail_min.y;
60 for(vector<TrackPart>::const_iterator i=parts.begin(); i!=parts.end(); ++i)
61 build_part(*i, rail_profile, Vector(0, gauge/2, y), true, bld, index);
62 for(vector<TrackPart>::const_iterator i=parts.begin(); i!=parts.end(); ++i)
63 build_part(*i, rail_profile, Vector(0, -gauge/2, y), false, bld, index);
65 object = new GL::Object;
66 object->set_mesh(mesh);
67 object->set_technique(&catalogue.get<GL::Technique>(appearance.get_technique()));
72 unsigned paths = tt.get_paths();
73 for(int i=-1; i<=1; ++i)
75 // TODO Make profile width configurable
79 float rail_w = (rail_max.x-rail_min.x)*2;
80 profile.append_vertex(Vector(rail_w*-0.5, 0, 0), false);
81 profile.append_vertex(Vector(rail_w*0.5, 0, 0), false);
85 profile.append_vertex(Vector(i*(gauge*0.5+rail_min.x*2), 0, 0), false);
86 profile.append_vertex(Vector(i*(gauge*0.5+rail_max.x*2), 0, 0), false);
89 // TODO Avoid generating redundant meshes for single-path tracks
90 for(int j=-1; j<=4; ++j)
92 if(j>=0 && !((paths>>j)&1))
95 GL::Mesh *m = new GL::Mesh(GL::VERTEX3);
96 GL::MeshBuilder bld(*m);
98 for(vector<TrackPart>::const_iterator k=parts.begin(); k!=parts.end(); ++k)
99 if(j<0 || k->get_path()==static_cast<unsigned>(j))
100 build_part(*k, profile, Vector(0, 0, ballast_h+1.5*rail_h), false, bld, index);
101 path_meshes[(j&0xFF)|((i&3)<<8)] = m;
106 TrackType3D::~TrackType3D()
108 for(map<unsigned, GL::Mesh *>::iterator i=path_meshes.begin(); i!=path_meshes.end(); ++i)
117 const GL::Mesh &TrackType3D::get_path_mesh(int p, int s) const
119 unsigned key = (p<0 ? 0xFF : p) | ((s&3)<<8);
120 return *get_item(path_meshes, key);
123 void TrackType3D::build_part(const TrackPart &part, const Profile &profile, const Vector &offset, bool mirror, GL::MeshBuilder &bld, unsigned &base_index)
125 float plen = part.get_length();
126 unsigned nsegs = (part.is_curved() ? static_cast<unsigned>(plen*32)+1 : 1);
128 unsigned n_vertices = profile.get_n_vertices();
129 for(unsigned i=0; i<=nsegs; ++i)
131 OrientedPoint basep = part.get_point(i*plen/nsegs);
132 Transform trans = Transform::rotation(basep.rotation, Vector(0, 0, 1));
134 for(unsigned j=0; j<n_vertices; ++j)
136 const Profile::Vertex &v = profile.get_vertex(mirror ? n_vertices-1-j : j);
137 Vector p(0, -v.pos.x, v.pos.y);
140 p = basep.position+trans.transform(offset+p);
142 Vector n(0, -v.normal.x, v.normal.y);
145 n = trans.transform(n);
147 bld.normal(n.x, n.y, n.z);
148 bld.vertex(p.x, p.y, p.z);
152 for(unsigned i=0; i+1<n_vertices; )
154 bld.begin(GL::TRIANGLE_STRIP);
155 for(unsigned j=0; j<=nsegs; ++j)
157 unsigned k = j*n_vertices+i;
158 bld.element(base_index+k+1);
159 bld.element(base_index+k);
164 if(!profile.get_vertex(i).smooth)
168 base_index += (nsegs+1)*n_vertices;
171 void TrackType3D::build_ties(const TrackPart &part, const Profile &profile, float length, float spacing, const Vector &offset, GL::MeshBuilder &bld, unsigned &base_index)
173 float plen = part.get_length();
174 unsigned count = plen/spacing+0.5;
179 unsigned n_vertices = profile.get_n_vertices();
180 float min_y = profile.get_min_coords().y;
181 vector<Vector> cap_vertices;
182 for(unsigned i=0; i+1<n_vertices; )
184 const Profile::Vertex &v = profile.get_vertex(i);
185 if(cap_vertices.size()>=2)
188 cap_vertices.push_back(Vector(v.pos.x, min_y, 0));
190 cap_vertices.push_back(profile.get_vertex(n_vertices-1).pos);
192 cap_vertices.push_back(v.pos);
195 if(!profile.get_vertex(i).smooth)
199 for(unsigned i=0; i<count; ++i)
201 OrientedPoint basep = part.get_point((i+0.5)*plen/count);
202 Transform trans = Transform::rotation(basep.rotation, Vector(0, 0, 1));
205 for(unsigned j=0; j<n_vertices; ++j)
207 const Profile::Vertex &v = profile.get_vertex(j);
209 Vector n = trans.transform(Vector(0, -v.normal.x, v.normal.y));
210 bld.normal(n.x, n.y, n.z);
213 bld.begin(GL::TRIANGLE_STRIP);
215 for(unsigned k=0; k<2; ++k)
217 Vector p((k-0.5)*length, -v.pos.x, v.pos.y);
218 p = basep.position+trans.transform(offset+p);
219 bld.vertex(p.x, p.y, p.z);
222 if(++strip>=2 && !profile.get_vertex(j).smooth)
231 for(unsigned j=0; j<2; ++j)
233 Vector n = trans.transform(Vector(j*2.0-1, 0, 0));
234 bld.normal(n.x, n.y, n.z);
236 bld.begin(GL::TRIANGLE_STRIP);
237 for(unsigned k=0; k<cap_vertices.size(); ++k)
239 const Vector &v = cap_vertices[k^j];
240 Vector p((j-0.5)*length, -v.x, v.y);
241 p = basep.position+trans.transform(offset+p);
242 bld.vertex(p.x, p.y, p.z);
247 base_index += 2*(n_vertices+cap_vertices.size());