#include <msp/core/maputils.h>
#include <msp/geometry/box.h>
#include <msp/geometry/transformedshape.h>
+#include <msp/strings/regex.h>
#include <msp/strings/format.h>
#include "vehicletype.h"
VehicleType::Rod::Rod():
- pivot(BODY),
- pivot_index(0),
- pivot_index2(0),
- limit(ROTATE),
- connect_index(-1),
mirror_object(false)
{ }
add("height", &Loader::height);
add("length", &Loader::length);
add("locomotive", &VehicleType::locomotive);
+ add("mirror_rods", &Loader::mirror_rods);
add("object", &VehicleType::object);
add("rod", &Loader::rod);
add("rotate_object", &VehicleType::rotate_object);
obj.fixed_axles.push_back(&obj.axles[i]);
}
+ for(TagMap::const_iterator i=rod_tags.begin(); i!=rod_tags.end(); ++i)
+ if(i->second>=0x10000)
+ throw runtime_error(format("unresolved reference to %s\n", i->first));
+
obj.shape = new Geometry::TransformedShape<float, 3>(
Geometry::Box<float>(obj.length, obj.width, obj.height),
Transform::translation(Vector(0, 0, obj.height/2)));
obj.length = l/1000;
}
-void VehicleType::Loader::rod()
+void VehicleType::Loader::mirror_rods()
+{
+ MirrorParametersLoader params;
+ load_sub_with(params);
+ Regex r_filter(params.filter);
+
+ vector<unsigned> mirror_indices(obj.rods.size(), 0);
+ for(TagMap::const_iterator i=rod_tags.begin(); i!=rod_tags.end(); ++i)
+ if(i->second<0x10000 && r_filter.match(i->first))
+ mirror_indices[i->second] = 1;
+
+ for(unsigned i=0, j=obj.rods.size(); i<mirror_indices.size(); ++i)
+ if(mirror_indices[i])
+ mirror_indices[i] = j++;
+
+ Transform axle_trans = Transform::rotation(params.phase_offset, Vector(0, 1, 0));
+
+ for(unsigned i=0; i<mirror_indices.size(); ++i)
+ {
+ if(!mirror_indices[i])
+ continue;
+
+ Rod mr = obj.rods[i];
+ mr.initial_position.y = -mr.initial_position.y;
+ mr.mirror_object = !mr.mirror_object;
+ for(vector<RodConstraint>::iterator j=mr.constraints.begin(); j!=mr.constraints.end(); ++j)
+ {
+ j->target_position.y = -j->target_position.y;
+ j->local_position.y = -j->local_position.y;
+ j->axis.y = -j->axis.y;
+ if(j->target==RodConstraint::ROD && mirror_indices[j->target_index])
+ j->target_index = mirror_indices[j->target_index];
+ else if(j->target==RodConstraint::AXLE)
+ j->target_position = axle_trans.transform(j->target_position);
+ }
+
+ obj.rods.push_back(mr);
+ }
+}
+
+void VehicleType::Loader::rod(const string &t)
{
Rod rd;
Rod::Loader ldr(rd, rod_tags);
load_sub_with(ldr);
+
+ unsigned n = obj.rods.size();
+ if(rod_tags.count(t))
+ {
+ unsigned p = rod_tags[t];
+ for(vector<Rod>::iterator i=obj.rods.begin(); i!=obj.rods.end(); ++i)
+ for(vector<RodConstraint>::iterator j=i->constraints.begin(); j!=i->constraints.end(); ++j)
+ if(j->target_index==p)
+ j->target_index = n;
+ }
+ rod_tags[t] = n;
obj.rods.push_back(rd);
- if(!ldr.get_tag().empty())
- rod_tags[ldr.get_tag()] = obj.rods.size()-1;
- rod_tags["previous"] = obj.rods.size()-1;
}
void VehicleType::Loader::width(float w)
}
-VehicleType::Rod::Loader::Loader(Rod &r, const map<string, unsigned> &t):
- DataFile::ObjectLoader<Rod>(r),
+VehicleType::RodConstraint::RodConstraint():
+ type(MOVE),
+ target(BODY),
+ target_index(0)
+{ }
+
+
+VehicleType::RodConstraint::Loader::Loader(RodConstraint &c, TagMap &t):
+ DataFile::ObjectLoader<RodConstraint>(c),
tags(t)
{
- add("connect", &Loader::connect);
- add("limit", &Rod::limit);
- add("mirror_object", &Rod::mirror_object);
- add("object", &Rod::object);
- add("pivot_body", &Loader::pivot_body);
- add("pivot_axle", &Loader::pivot_axle);
- add("pivot_axle", &Loader::pivot_bogie_axle);
- add("pivot_rod", &Loader::pivot_rod);
- add("position", &Loader::position);
- add("tag", &Loader::set_tag);
+ add("axis", &Loader::axis);
+ add("local_position", &Loader::local_position);
+ add("target_axle", &Loader::target_axle);
+ add("target_position", &Loader::target_position);
+ add("target_rod", &Loader::target_rod);
+}
+
+void VehicleType::RodConstraint::Loader::axis(float x, float y, float z)
+{
+ obj.axis = Vector(x, y, z);
+ obj.axis.normalize();
}
-void VehicleType::Rod::Loader::connect(const string &t, float px, float pz, float ox, float oz)
+void VehicleType::RodConstraint::Loader::local_position(float x, float y, float z)
{
- obj.connect_index = get_item(tags, t);
- obj.connect_point = Vector(px/1000, 0, pz/1000);
- obj.connect_offset = Vector(ox/1000, 0, oz/1000);
+ obj.local_position = Vector(x/1000, y/1000, z/1000);
}
-void VehicleType::Rod::Loader::pivot_body()
+void VehicleType::RodConstraint::Loader::target_axle(unsigned i)
{
- obj.pivot = BODY;
+ obj.target = AXLE;
+ obj.target_index = i;
+ // TODO check range
}
-void VehicleType::Rod::Loader::pivot_axle(unsigned i)
+void VehicleType::RodConstraint::Loader::target_position(float x, float y, float z)
{
- obj.pivot = AXLE;
- obj.pivot_index = i;
+ obj.target_position = Vector(x/1000, y/1000, z/1000);
+}
+
+void VehicleType::RodConstraint::Loader::target_rod(const string &n)
+{
+ obj.target = ROD;
+ TagMap::iterator i = tags.find(n);
+ if(i!=tags.end())
+ obj.target_index = i->second;
+ else
+ {
+ obj.target_index = 0x10000+tags.size();
+ tags[n] = obj.target_index;
+ }
}
-void VehicleType::Rod::Loader::pivot_bogie_axle(unsigned i, unsigned j)
+
+VehicleType::Rod::Loader::Loader(Rod &r, TagMap &t):
+ DataFile::ObjectLoader<Rod>(r),
+ tags(t)
{
- obj.pivot = BOGIE_AXLE;
- obj.pivot_index = i;
- obj.pivot_index2 = j;
+ add("initial_position", &Loader::initial_position);
+ add("mirror_object", &Rod::mirror_object);
+ add("move", &Loader::constraint<RodConstraint::MOVE>);
+ add("object", &Rod::object);
+ add("rotate", &Loader::constraint<RodConstraint::ROTATE>);
+ add("slide", &Loader::constraint<RodConstraint::SLIDE>);
}
-void VehicleType::Rod::Loader::pivot_rod(const string &t)
+template<VehicleType::RodConstraint::Type t>
+void VehicleType::Rod::Loader::constraint()
{
- obj.pivot_index = get_item(tags, t);
- obj.pivot = ROD;
+ RodConstraint cns;
+ cns.type = t;
+ load_sub(cns, tags);
+ obj.constraints.push_back(cns);
}
-void VehicleType::Rod::Loader::position(float x, float y, float z)
+void VehicleType::Rod::Loader::initial_position(float x, float y, float z)
{
- obj.pivot_point = Vector(x/1000, y/1000, z/1000);
+ obj.initial_position = Vector(x/1000, y/1000, z/1000);
}
-void VehicleType::Rod::Loader::set_tag(const string &t)
+
+VehicleType::MirrorParametersLoader::MirrorParametersLoader()
{
- tag = t;
+ add("filter", &MirrorParametersLoader::filt);
+ add("phase_offset", &MirrorParametersLoader::phase_offs);
}
+void VehicleType::MirrorParametersLoader::filt(const string &f)
+{
+ filter = f;
+}
-void operator>>(const LexicalConverter &c, VehicleType::Rod::Limit &l)
+void VehicleType::MirrorParametersLoader::phase_offs(float o)
{
- const string &s = c.get();
- if(s=="FIXED")
- l = VehicleType::Rod::FIXED;
- else if(s=="ROTATE")
- l = VehicleType::Rod::ROTATE;
- else if(s=="SLIDE_X")
- l = VehicleType::Rod::SLIDE_X;
- else
- throw lexical_error(format("conversion of '%s' to Rod::Limit", s));
+ phase_offset = Angle::from_degrees(o);
}
} // namespace R2C2