1 #include <msp/gl/material.h>
2 #include <msp/gl/meshbuilder.h>
3 #include <msp/gl/technique.h>
4 #include <msp/gl/texture2d.h>
5 #include <msp/gl/vector.h>
7 #include "vehicletype.h"
15 T get(const map<string, string> ¶ms, const string &key, T def = T())
17 map<string, string>::const_iterator i = params.find(key);
21 return lexical_cast<T>(i->second);
28 VehicleType3D::VehicleType3D(Catalogue3D &c, const VehicleType &t):
33 body_object = get_object(type.get_object());
35 const vector<VehicleType::Axle> &axles = type.get_axles();
36 for(vector<VehicleType::Axle>::const_iterator i=axles.begin(); i!=axles.end(); ++i)
37 axle_objects.push_back(get_object(i->object));
39 const vector<VehicleType::Bogie> &bogies = type.get_bogies();
40 for(vector<VehicleType::Bogie>::const_iterator i=bogies.begin(); i!=bogies.end(); ++i)
41 bogie_objects.push_back(get_object(i->object));
43 const vector<VehicleType::Rod> &rods = type.get_rods();
44 for(vector<VehicleType::Rod>::const_iterator i=rods.begin(); i!=rods.end(); ++i)
45 rod_objects.push_back(get_object(i->object));
48 VehicleType3D::~VehicleType3D()
50 for(map<string, GL::Object *>::iterator i=objects.begin(); i!=objects.end(); ++i)
54 const GL::Object *VehicleType3D::get_axle_object(unsigned i) const
56 if(i>=axle_objects.size())
57 throw out_of_range("VehicleType3D::get_fixed_axle_object");
58 return axle_objects[i];
61 const GL::Object *VehicleType3D::get_bogie_object(unsigned i) const
63 if(i>=bogie_objects.size())
64 throw out_of_range("VehicleType3D::get_bogie_object");
65 return bogie_objects[i];
68 const GL::Object *VehicleType3D::get_rod_object(unsigned i) const
70 if(i>=rod_objects.size())
71 throw out_of_range("VehicleType3D::get_rod_object");
72 return rod_objects[i];
75 GL::Object *VehicleType3D::get_object(const string &name)
80 GL::Object *&ptr = objects[name];
85 string::size_type colon = name.find(':', 1);
86 string kind = name.substr(1, colon-1);
88 map<string, string> params;
89 params["length"] = lexical_cast<string>(type.get_length()*1000);
90 params["width"] = lexical_cast<string>(type.get_width()*1000);
91 params["height"] = lexical_cast<string>(type.get_height()*1000);
92 if(colon!=string::npos)
94 string::size_type start = colon+1;
97 string::size_type equals = name.find('=', start);
98 string::size_type comma = name.find(',', start);
100 params[name.substr(start, equals-start)] = name.substr(equals+1, comma-equals-1);
102 params[name.substr(start, comma-start)] = string();
104 if(comma==string::npos)
111 if(kind=="openwagon")
112 mesh = create_open_wagon(params);
113 else if(kind=="coveredwagon")
114 mesh = create_covered_wagon(params);
115 else if(kind=="flatwagon")
116 mesh = create_flat_wagon(params);
120 ptr = new GL::Object;
122 ptr->set_technique(create_technique(params));
126 return &catalogue.get<GL::Object>(name);
131 GL::Technique *VehicleType3D::create_technique(const map<string, string> ¶ms)
133 string color_str = get<string>(params, "color", "808080");
134 unsigned color = lexical_cast<unsigned>(color_str, "x");
135 string color2_str = get<string>(params, "color2", color_str);
136 unsigned color2 = lexical_cast<unsigned>(color2_str, "x");
138 GL::Technique *tech = new GL::Technique;
139 GL::RenderPass &pass = tech->add_pass(GL::Tag());
140 GL::Material *mat = new GL::Material;
141 mat->set_diffuse(GL::Color(1));
142 pass.set_material(mat);
143 GL::Texture2D *tex = new GL::Texture2D;
144 tex->storage(GL::RGB, 2, 1);
145 tex->set_min_filter(GL::NEAREST);
146 tex->set_mag_filter(GL::NEAREST);
147 unsigned char data[6];
148 data[0] = color>>16; data[1] = color>>8; data[2] = color;
149 data[3] = color2>>16; data[4] = color2>>8; data[5] = color2;
150 tex->image(0, GL::RGB, GL::UNSIGNED_BYTE, data);
151 pass.set_texture(0, tex);
156 GL::Mesh *VehicleType3D::create_open_wagon(const map<string, string> ¶ms)
158 float length = get<float>(params, "length")/1000;
159 float width = get<float>(params, "width")/1000;
160 float height = get<float>(params, "height")/1000;
161 float clearance = get<float>(params, "clearance", 900*catalogue.get_catalogue().get_scale())/1000;
162 float border = get<float>(params, "border", 40*catalogue.get_catalogue().get_scale())/1000;
164 GL::Mesh *mesh = new GL::Mesh((GL::NORMAL3, GL::TEXCOORD2, GL::VERTEX3));
165 GL::MeshBuilder bld(*mesh);
167 for(unsigned i=0; i<16; ++i)
185 z = clearance+0.1*catalogue.get_catalogue().get_scale();
187 bld.texcoord((i>=12 ? 0.75 : 0.25), 0.5);
188 bld.normal(0, 0, (i<4 ? -1 : 1));
190 bld.texcoord((i>=8 ? 0.75 : 0.25), 0.5);
191 bld.normal(((x<0)==(i<8) ? -1 : 1), 0, 0);
193 bld.normal(0, ((y<0)==(i<8) ? -1 : 1), 0);
197 bld.begin(GL::QUADS);
198 for(unsigned i=0; i<3; ++i)
199 for(unsigned j=0; j<4; ++j)
201 unsigned k = (i==1 ? 0 : 2-j%2);
202 bld.element((i*4+j)*3+k);
203 bld.element((i*4+(j+1)%4)*3+k);
204 bld.element(((i+1)*4+(j+1)%4)*3+k);
205 bld.element(((i+1)*4+j)*3+k);
207 for(unsigned i=4; i--;)
209 for(unsigned i=0; i<4; ++i)
210 bld.element((12+i)*3);
216 GL::Mesh *VehicleType3D::create_covered_wagon(const map<string, string> ¶ms)
218 float length = get<float>(params, "length")/1000;
219 float width = get<float>(params, "width")/1000;
220 float height = get<float>(params, "height")/1000;
221 float clearance = get<float>(params, "clearance", 900*catalogue.get_catalogue().get_scale())/1000;
222 float roof = get<float>(params, "roof", width*250)/1000;
224 GL::Mesh *mesh = new GL::Mesh((GL::NORMAL3, GL::TEXCOORD2, GL::VERTEX3));
225 GL::MeshBuilder bld(*mesh);
227 for(unsigned i=0; i<12; ++i)
246 bld.normal(0, 0, -1);
247 bld.texcoord(0.25, 0.5);
251 float a = atan2(roof/(i>=8 ? 3 : 1), width/2);
254 bld.normal(0, sin(a), cos(a));
255 bld.texcoord(0.75, 0.5);
259 bld.texcoord(0.25, 0.5);
260 bld.normal((x<0 ? -1 : 1), 0, 0);
262 bld.normal(0, (y<0 ? -1 : 1), 0);
266 bld.begin(GL::QUADS);
267 for(unsigned i=0; i<2; ++i)
268 for(unsigned j=0; j<4; ++j)
270 unsigned k = ((i==1 && j%2==0) ? 0 : 2-j%2);
271 bld.element((i*4+j)*3+k);
272 bld.element((i*4+(j+1)%4)*3+k);
273 bld.element(((i+1)*4+(j+1)%4)*3+k);
274 bld.element(((i+1)*4+j)*3+k);
276 for(unsigned i=4; i--;)
278 for(unsigned i=0; i<4; ++i)
279 bld.element((8+i)*3);
285 GL::Mesh *VehicleType3D::create_flat_wagon(const map<string, string> ¶ms)
287 float length = get<float>(params, "length")/1000;
288 float width = get<float>(params, "width")/1000;
289 float height = get<float>(params, "height")/1000;
290 float clearance = get<float>(params, "clearance", 900*catalogue.get_catalogue().get_scale())/1000;
292 GL::Mesh *mesh = new GL::Mesh((GL::NORMAL3, GL::TEXCOORD2, GL::VERTEX3));
293 GL::MeshBuilder bld(*mesh);
295 for(unsigned i=0; i<8; ++i)
304 float z = (i<4 ? clearance : height);
306 bld.texcoord((i>=4 ? 0.75 : 0.25), 0.5);
307 bld.normal(0, 0, (i<4 ? -1 : 1));
309 bld.texcoord(0.25, 0.5);
310 bld.normal(((x<0)==(i<8) ? -1 : 1), 0, 0);
312 bld.normal(0, ((y<0)==(i<8) ? -1 : 1), 0);
316 bld.begin(GL::QUADS);
317 for(unsigned i=0; i<4; ++i)
321 bld.element(((i+1)%4)*3+j);
322 bld.element((4+(i+1)%4)*3+j);
323 bld.element((4+i)*3+j);
325 for(unsigned i=4; i--;)
327 for(unsigned i=0; i<4; ++i)
328 bld.element((4+i)*3);