From: Mikko Rasa Date: Sun, 7 Nov 2010 14:27:40 +0000 (+0000) Subject: Add framework for generating simple meshes for vehicles X-Git-Url: http://git.tdb.fi/?a=commitdiff_plain;h=30df355287abd0bfe1189e616056335505287e9a;p=r2c2.git Add framework for generating simple meshes for vehicles --- diff --git a/source/3d/vehicletype.cpp b/source/3d/vehicletype.cpp index be6b985..b283edd 100644 --- a/source/3d/vehicletype.cpp +++ b/source/3d/vehicletype.cpp @@ -6,6 +6,8 @@ Distributed under the GPL */ #include +#include +#include #include #include "catalogue.h" #include "vehicletype.h" @@ -13,19 +15,35 @@ Distributed under the GPL using namespace std; using namespace Msp; +namespace { + +template +T get(const map ¶ms, const string &key, T def = T()) +{ + map::const_iterator i = params.find(key); + if(i==params.end()) + return def; + + return lexical_cast(i->second); +} + +} + namespace Marklin { -VehicleType3D::VehicleType3D(Catalogue3D &, const VehicleType &vt): +VehicleType3D::VehicleType3D(const Catalogue3D &c, const VehicleType &t): + catalogue(c), + type(t), body_object(0), axle_objects(1) { - body_object = get_object(vt.get_object()); + body_object = get_object(type.get_object()); - const vector &axles = vt.get_axles(); + const vector &axles = type.get_axles(); for(vector::const_iterator i=axles.begin(); i!=axles.end(); ++i) axle_objects[0].push_back(get_object(i->object)); - const vector &bogies = vt.get_bogies(); + const vector &bogies = type.get_bogies(); for(vector::const_iterator i=bogies.begin(); i!=bogies.end(); ++i) { bogie_objects.push_back(get_object(i->object)); @@ -72,10 +90,256 @@ GL::Object *VehicleType3D::get_object(const string &name) GL::Object *&ptr = objects[name]; if(!ptr) { - ptr = new GL::Object; - DataFile::load(*ptr, name); + if(name[0]==':') + { + string::size_type colon = name.find(':', 1); + string kind = name.substr(1, colon-1); + + map params; + params["length"] = lexical_cast(type.get_length()*1000); + params["width"] = lexical_cast(type.get_width()*1000); + params["height"] = lexical_cast(type.get_height()*1000); + if(colon!=string::npos) + { + string::size_type start = colon+1; + while(1) + { + string::size_type equals = name.find('=', start); + string::size_type comma = name.find(',', start); + if(equalsset_mesh(mesh); + ptr->set_technique(create_technique(params)); + } + } + else + { + ptr = new GL::Object; + DataFile::load(*ptr, name); + } } return ptr; } +GL::Technique *VehicleType3D::create_technique(const map ¶ms) +{ + string color_str = get(params, "color", "808080"); + unsigned color = lexical_cast(color_str, "x"); + string color2_str = get(params, "color2", color_str); + unsigned color2 = lexical_cast(color2_str, "x"); + + GL::Technique *tech = new GL::Technique; + GL::RenderPass &pass = tech->add_pass(GL::Tag()); + GL::Material *mat = new GL::Material; + mat->set_diffuse(GL::Color(1)); + pass.set_material(mat); + GL::Texture2D *tex = new GL::Texture2D; + tex->storage(GL::RGB, 2, 1, 0); + tex->set_min_filter(GL::NEAREST); + tex->set_mag_filter(GL::NEAREST); + unsigned char data[6] = { color>>16, color>>8, color, color2>>16, color2>>8, color2 }; + tex->image(0, GL::RGB, GL::UNSIGNED_BYTE, data); + pass.set_texture(0, tex); + + return tech; +} + +GL::Mesh *VehicleType3D::create_open_wagon(const map ¶ms) +{ + float length = get(params, "length")/1000; + float width = get(params, "width")/1000; + float height = get(params, "height")/1000; + float clearance = get(params, "clearance", 900*catalogue.get_catalogue().get_scale())/1000; + float border = get(params, "border", 40*catalogue.get_catalogue().get_scale())/1000; + + GL::Mesh *mesh = new GL::Mesh((GL::NORMAL3, GL::TEXCOORD2, GL::VERTEX3)); + GL::MeshBuilder bld(*mesh); + + for(unsigned i=0; i<16; ++i) + { + float x = length/2; + float y = width/2; + if(i>=8) + { + x -= border; + y -= border; + } + if((i+1)%4<2) + x = -x; + if(i%4<2) + y = -y; + + float z = height; + if(i<4) + z = clearance; + else if(i>=12) + z = clearance+0.1*catalogue.get_catalogue().get_scale(); + + bld.texcoord((i>=12 ? 0.75 : 0.25), 0.5); + bld.normal(0, 0, (i<4 ? -1 : 1)); + bld.vertex(x, y, z); + bld.texcoord((i>=8 ? 0.75 : 0.25), 0.5); + bld.normal(((x<0)==(i<8) ? -1 : 1), 0, 0); + bld.vertex(x, y, z); + bld.normal(0, ((y<0)==(i<8) ? -1 : 1), 0); + bld.vertex(x, y, z); + } + + bld.begin(GL::QUADS); + for(unsigned i=0; i<3; ++i) + for(unsigned j=0; j<4; ++j) + { + unsigned k = (i==1 ? 0 : 2-j%2); + bld.element((i*4+j)*3+k); + bld.element((i*4+(j+1)%4)*3+k); + bld.element(((i+1)*4+(j+1)%4)*3+k); + bld.element(((i+1)*4+j)*3+k); + } + for(unsigned i=4; i--;) + bld.element(i*3); + for(unsigned i=0; i<4; ++i) + bld.element((12+i)*3); + bld.end(); + + return mesh; +} + +GL::Mesh *VehicleType3D::create_covered_wagon(const map ¶ms) +{ + float length = get(params, "length")/1000; + float width = get(params, "width")/1000; + float height = get(params, "height")/1000; + float clearance = get(params, "clearance", 900*catalogue.get_catalogue().get_scale())/1000; + float roof = get(params, "roof", width*250)/1000; + + GL::Mesh *mesh = new GL::Mesh((GL::NORMAL3, GL::TEXCOORD2, GL::VERTEX3)); + GL::MeshBuilder bld(*mesh); + + for(unsigned i=0; i<12; ++i) + { + float x = length/2; + float y = width/2; + if(i>=8) + y /= 3; + if((i+1)%4<2) + x = -x; + if(i%4<2) + y = -y; + + float z = height; + if(i<4) + z = clearance; + else if(i<8) + z -= roof; + + if(i<4) + { + bld.normal(0, 0, -1); + bld.texcoord(0.25, 0.5); + } + else + { + float a = atan2(roof/(i>=8 ? 3 : 1), width/2); + if(y<0) + a = -a; + bld.normal(0, sin(a), cos(a)); + bld.texcoord(0.75, 0.5); + } + bld.vertex(x, y, z); + + bld.texcoord(0.25, 0.5); + bld.normal((x<0 ? -1 : 1), 0, 0); + bld.vertex(x, y, z); + bld.normal(0, (y<0 ? -1 : 1), 0); + bld.vertex(x, y, z); + } + + bld.begin(GL::QUADS); + for(unsigned i=0; i<2; ++i) + for(unsigned j=0; j<4; ++j) + { + unsigned k = ((i==1 && j%2==0) ? 0 : 2-j%2); + bld.element((i*4+j)*3+k); + bld.element((i*4+(j+1)%4)*3+k); + bld.element(((i+1)*4+(j+1)%4)*3+k); + bld.element(((i+1)*4+j)*3+k); + } + for(unsigned i=4; i--;) + bld.element(i*3); + for(unsigned i=0; i<4; ++i) + bld.element((8+i)*3); + bld.end(); + + return mesh; +} + +GL::Mesh *VehicleType3D::create_flat_wagon(const map ¶ms) +{ + float length = get(params, "length")/1000; + float width = get(params, "width")/1000; + float height = get(params, "height")/1000; + float clearance = get(params, "clearance", 900*catalogue.get_catalogue().get_scale())/1000; + + GL::Mesh *mesh = new GL::Mesh((GL::NORMAL3, GL::TEXCOORD2, GL::VERTEX3)); + GL::MeshBuilder bld(*mesh); + + for(unsigned i=0; i<8; ++i) + { + float x = length/2; + float y = width/2; + if((i+1)%4<2) + x = -x; + if(i%4<2) + y = -y; + + float z = (i<4 ? clearance : height); + + bld.texcoord((i>=4 ? 0.75 : 0.25), 0.5); + bld.normal(0, 0, (i<4 ? -1 : 1)); + bld.vertex(x, y, z); + bld.texcoord(0.25, 0.5); + bld.normal(((x<0)==(i<8) ? -1 : 1), 0, 0); + bld.vertex(x, y, z); + bld.normal(0, ((y<0)==(i<8) ? -1 : 1), 0); + bld.vertex(x, y, z); + } + + bld.begin(GL::QUADS); + for(unsigned i=0; i<4; ++i) + { + unsigned j = 2-i%2; + bld.element(i*3+j); + bld.element(((i+1)%4)*3+j); + bld.element((4+(i+1)%4)*3+j); + bld.element((4+i)*3+j); + } + for(unsigned i=4; i--;) + bld.element(i*3); + for(unsigned i=0; i<4; ++i) + bld.element((4+i)*3); + bld.end(); + + return mesh; +} + } // namespace Marklin diff --git a/source/3d/vehicletype.h b/source/3d/vehicletype.h index faa34ac..f38f02d 100644 --- a/source/3d/vehicletype.h +++ b/source/3d/vehicletype.h @@ -19,13 +19,15 @@ class Catalogue3D; class VehicleType3D { private: + const Catalogue3D &catalogue; + const VehicleType &type; std::map objects; Msp::GL::Object *body_object; std::vector bogie_objects; std::vector > axle_objects; public: - VehicleType3D(Catalogue3D &, const VehicleType &); + VehicleType3D(const Catalogue3D &, const VehicleType &); ~VehicleType3D(); const Msp::GL::Object *get_body_object() const { return body_object; } @@ -34,6 +36,10 @@ public: const Msp::GL::Object *get_bogie_axle_object(unsigned, unsigned) const; private: Msp::GL::Object *get_object(const std::string &); + Msp::GL::Technique *create_technique(const std::map &); + Msp::GL::Mesh *create_open_wagon(const std::map &); + Msp::GL::Mesh *create_covered_wagon(const std::map &); + Msp::GL::Mesh *create_flat_wagon(const std::map &); }; } // namespace Marklin