]> git.tdb.fi Git - r2c2.git/blob - source/3d/tracktype.cpp
Plug several memory leaks
[r2c2.git] / source / 3d / tracktype.cpp
1 #include <algorithm>
2 #include <cmath>
3 #include <msp/gl/technique.h>
4 #include "catalogue.h"
5 #include "tracktype.h"
6
7 using namespace std;
8 using namespace Msp;
9
10 namespace R2C2 {
11
12 TrackType3D::TrackType3D(Catalogue3D &cat3d, const TrackType &tt):
13         catalogue(cat3d),
14         mesh(0),
15         object(0),
16         own_data(false)
17 {
18         const Catalogue &cat = cat3d.get_catalogue();
19         const vector<TrackPart> &parts = tt.get_parts();
20
21         const Profile &ballast_profile = cat.get_ballast_profile();
22         const Vector &ballast_min = ballast_profile.get_min_coords();
23         const Vector &ballast_max = ballast_profile.get_max_coords();
24         float ballast_h = ballast_max.y-ballast_min.y;
25
26         const Profile &rail_profile = cat.get_rail_profile();
27         const Vector &rail_min = rail_profile.get_min_coords();
28         const Vector &rail_max = rail_profile.get_max_coords();
29         float rail_h = rail_max.y-rail_min.y;
30
31         float gauge = cat.get_gauge();
32
33         string obj_name = tt.get_object();
34         if(!obj_name.empty())
35                 object = &catalogue.get<GL::Object>(obj_name);
36         else
37         {
38                 mesh = new GL::Mesh((GL::NORMAL3, GL::TEXCOORD2, GL::VERTEX3));
39                 mesh->set_winding(&GL::WindingTest::counterclockwise());
40                 GL::MeshBuilder bld(*mesh);
41
42                 unsigned index = 0;
43                 bld.texcoord(0.25, 0.5);
44                 for(vector<TrackPart>::const_iterator i=parts.begin(); i!=parts.end(); ++i)
45                         build_part(*i, ballast_profile, Vector(0, -ballast_min.y, 0), false, bld, index);
46
47                 bld.texcoord(0.75, 0.5);
48                 float y = ballast_h-rail_min.y;
49                 for(vector<TrackPart>::const_iterator i=parts.begin(); i!=parts.end(); ++i)
50                         build_part(*i, rail_profile, Vector(0, gauge/2, y), true, bld, index);
51                 for(vector<TrackPart>::const_iterator i=parts.begin(); i!=parts.end(); ++i)
52                         build_part(*i, rail_profile, Vector(0, -gauge/2, y), false, bld, index);
53
54                 object = new GL::Object;
55                 object->set_mesh(mesh);
56                 object->set_technique(&catalogue.get<GL::Technique>(cat.get_track_technique()));
57
58                 own_data = true;
59         }
60  
61         unsigned paths = tt.get_paths();
62         for(unsigned i=0; paths; ++i, paths>>=1)
63         {
64                 GL::Mesh *m = 0;
65                 if(paths&1)
66                 {
67                         m = new GL::Mesh(GL::VERTEX3);
68                         GL::MeshBuilder bld(*m);
69                         unsigned index = 0;
70                         for(vector<TrackPart>::const_iterator j=parts.begin(); j!=parts.end(); ++j)
71                                 if(j->get_path()==i)
72                                         build_part(*j, cat.get_path_profile(), Vector(0, 0, ballast_h+1.5*rail_h), false, bld, index);
73                 }
74                 path_meshes.push_back(m);
75         }
76 }
77
78 TrackType3D::~TrackType3D()
79 {
80         for(vector<GL::Mesh *>::iterator i=path_meshes.begin(); i!=path_meshes.end(); ++i)
81                 delete *i;
82         if(own_data)
83         {
84                 delete object;
85                 delete mesh;
86         }
87 }
88
89 const GL::Mesh &TrackType3D::get_path_mesh(unsigned p) const
90 {
91         if(p>=path_meshes.size())
92                 throw out_of_range("TrackType3D::get_path_mesh");
93         if(!path_meshes[p])
94                 throw invalid_argument("TrackType3D::get_path_mesh");
95         return *path_meshes[p];
96 }
97
98 void TrackType3D::build_part(const TrackPart &part, const Profile &profile, const Vector &offset, bool mirror, GL::MeshBuilder &bld, unsigned &base_index)
99 {
100         float plen = part.get_length();
101         unsigned nsegs = (part.is_curved() ? static_cast<unsigned>(plen*32)+1 : 1);
102
103         unsigned n_vertices = profile.get_n_vertices();
104         for(unsigned i=0; i<=nsegs; ++i)
105         {
106                 TrackPoint basep = part.get_point(i*plen/nsegs);
107                 Transform trans = Transform::rotation(basep.dir, Vector(0, 0, 1));
108
109                 for(unsigned j=0; j<n_vertices; ++j)
110                 {
111                         const Profile::Vertex &v = profile.get_vertex(mirror ? n_vertices-1-j : j);
112                         Vector p(0, -v.pos.x, v.pos.y);
113                         if(mirror)
114                                 p.y = -p.y;
115                         p = basep.pos+trans.transform(offset+p);
116
117                         Vector n(0, -v.normal.x, v.normal.y);
118                         if(mirror)
119                                 n.y = -n.y;
120                         n = trans.transform(n);
121
122                         bld.normal(n.x, n.y, n.z);
123                         bld.vertex(p.x, p.y, p.z);
124                 }
125         }
126
127         for(unsigned i=0; i+1<n_vertices; )
128         {
129                 bld.begin(GL::TRIANGLE_STRIP);
130                 for(unsigned j=0; j<=nsegs; ++j)
131                 {
132                         unsigned k = j*n_vertices+i;
133                         bld.element(base_index+k+1);
134                         bld.element(base_index+k);
135                 }
136                 bld.end();
137
138                 ++i;
139                 if(!profile.get_vertex(i).smooth)
140                         ++i;
141         }
142
143         base_index += (nsegs+1)*n_vertices;
144 }
145
146 } // namespace R2C2