in roboschool/cpp-household/random-world-tools.cpp [420:576]
shared_ptr<Thingy> World::tool_quad_prism(
float tex1, float tex_v_zero,
std::vector<btScalar>& path,
btScalar low,
btScalar high,
const std::string& side_tex_,
const std::string& top_tex_,
const std::string& bottom_tex_)
{
shared_ptr<ThingyClass> klass(new ThingyClass);
klass->class_name = "PrismTool";
klass->metaclass = METACLASS_FLOOR;
shared_ptr<Household::ShapeDetailLevels> shapeset(new Household::ShapeDetailLevels);
shared_ptr<Household::Shape> side_shape;
shared_ptr<Household::Shape> side_cshape;
if (!side_tex_.empty()) {
side_shape.reset(new Household::Shape);
side_shape->material = texture_from_file_cached(side_tex_);
side_cshape.reset(new Household::Shape);
side_cshape->primitive_type = Household::Shape::STATIC_MESH;
}
shared_ptr<Household::Shape> top_shape;
shared_ptr<Household::Shape> top_cshape;
if (!top_tex_.empty()) {
top_shape.reset(new Household::Shape);
top_shape->material = texture_from_file_cached(top_tex_);
top_cshape.reset(new Household::Shape);
top_cshape->primitive_type = Household::Shape::STATIC_MESH;
}
shared_ptr<Household::Shape> bot_shape;
shared_ptr<Household::Shape> bot_cshape;
if (!bottom_tex_.empty()) {
bot_shape.reset(new Household::Shape);
bot_shape->material = texture_from_file_cached(bottom_tex_);
bot_cshape.reset(new Household::Shape);
bot_cshape->primitive_type = Household::Shape::STATIC_MESH;
}
int cnt = path.size()/2;
assert((cnt==4 || cnt==3) && "should be quad or triangle");
std::vector<btVector3> normals;
btVector3 center(0,0,0);
for (int c=0; c<cnt; c++) {
int c1 = (c+0) % cnt;
int c2 = (c+1) % cnt;
btVector3 hor1(path[2*c2+0] - path[2*c1+0], path[2*c2+1] - path[2*c1+1], 0);
btVector3 ver(0, 0, -1);
btVector3 norm1 = hor1.cross(ver);
norm1.normalize();
normals.push_back(norm1);
center += btVector3(path[2*c+0], path[2*c+1], 0);
}
center /= cnt;
center.setZ(0.5*(low+high));
for (int c=0; c<cnt; c++) {
path[2*c+0] -= center.x();
path[2*c+1] -= center.y();
}
low -= center.z();
high -= center.z();
float side_tex_spent = 0;
if (side_shape)
for (int c=0; c<cnt; c++) {
int c1 = (c+0) % cnt;
int c2 = (c+1) % cnt;
btVector3 norm = normals[c1];
btVector3 p1(path[2*c1+0], path[2*c1+1], low);
btVector3 p2(path[2*c2+0], path[2*c2+1], low);
btVector3 p3(path[2*c2+0], path[2*c2+1], high);
btVector3 p4(path[2*c1+0], path[2*c1+1], high);
side_shape->push_vertex(p1.x(), p1.y(), p1.z());
side_shape->push_vertex(p2.x(), p2.y(), p2.z());
side_shape->push_vertex(p3.x(), p3.y(), p3.z());
side_shape->push_vertex(p4.x(), p4.y(), p4.z());
side_cshape->push_vertex(p1.x(), p1.y(), p1.z());
side_cshape->push_vertex(p2.x(), p2.y(), p2.z());
side_cshape->push_vertex(p3.x(), p3.y(), p3.z());
side_cshape->push_vertex(p1.x(), p1.y(), p1.z());
side_cshape->push_vertex(p3.x(), p3.y(), p3.z());
side_cshape->push_vertex(p4.x(), p4.y(), p4.z());
for (int c=0; c<4; c++)
side_shape->push_normal(norm.x(), norm.y(), norm.z());
for (int c=0; c<6; c++)
side_cshape->push_normal(norm.x(), norm.y(), norm.z());
float next_side_tex_spent = side_tex_spent + (p2-p1).norm();
side_shape->push_tex(side_tex_spent/tex1, (low-tex_v_zero)/tex1 );
side_shape->push_tex(side_tex_spent/tex1, (high-tex_v_zero)/tex1);
side_shape->push_tex(next_side_tex_spent/tex1, (high-tex_v_zero)/tex1);
side_shape->push_tex(next_side_tex_spent/tex1, (low-tex_v_zero)/tex1);
side_tex_spent = next_side_tex_spent;
}
if (top_shape) {
if (cnt==4) top_shape->quads_from = 0;
else top_shape->quads_from = 9;
btVector3 p1(path[0] + sign(center.x()-path[0])*TEST_GAP, path[1] + sign(center.y()-path[1])*TEST_GAP, high);
btVector3 p2(path[2] + sign(center.x()-path[2])*TEST_GAP, path[3] + sign(center.y()-path[3])*TEST_GAP, high);
btVector3 p3(path[4] + sign(center.x()-path[4])*TEST_GAP, path[5] + sign(center.y()-path[5])*TEST_GAP, high);
btVector3 p4(0,0,0);
top_shape->push_vertex(p1.x(), p1.y(), p1.z());
top_shape->push_vertex(p2.x(), p2.y(), p2.z());
top_shape->push_vertex(p3.x(), p3.y(), p3.z());
top_cshape->push_vertex(p1.x(), p1.y(), p1.z());
top_cshape->push_vertex(p2.x(), p2.y(), p2.z());
top_cshape->push_vertex(p3.x(), p3.y(), p3.z());
if (cnt==4) {
p4 = btVector3(path[6] + sign(center.x()-path[6])*TEST_GAP, path[7] + sign(center.y()-path[7])*TEST_GAP, high);
top_shape->push_vertex(p4.x(), p4.y(), p4.z());
top_cshape->push_vertex(p1.x(), p1.y(), p1.z());
top_cshape->push_vertex(p3.x(), p3.y(), p3.z());
top_cshape->push_vertex(p4.x(), p4.y(), p4.z());
}
for (int c=0; c<cnt; c++)
top_shape->push_normal(0,0,1);
for (int c=0; c<(cnt==4 ? 6 : 3); c++)
top_cshape->push_normal(0,0,1);
top_shape->push_tex( (p1.x() + center.x())/tex1, (p1.y() + center.y())/tex1 );
top_shape->push_tex( (p2.x() + center.x())/tex1, (p2.y() + center.y())/tex1 );
top_shape->push_tex( (p3.x() + center.x())/tex1, (p3.y() + center.y())/tex1 );
if (cnt==4)
top_shape->push_tex( (p4.x() + center.x())/tex1, (p4.y() + center.y())/tex1 );
}
shared_ptr<Household::ShapeDetailLevels> shapeset_visual(new Household::ShapeDetailLevels);
shared_ptr<Household::ShapeDetailLevels> shapeset_collision(new Household::ShapeDetailLevels);
if (side_shape) {
shapeset_visual->detail_levels[Household::DETAIL_BEST].push_back(side_shape);
side_cshape->quads_from = side_cshape->v.size();
shapeset_collision->detail_levels[Household::DETAIL_BEST].push_back(side_cshape);
}
if (top_shape) {
shapeset_visual->detail_levels[Household::DETAIL_BEST].push_back(top_shape);
top_cshape->quads_from = top_cshape->v.size();
shapeset_collision->detail_levels[Household::DETAIL_BEST].push_back(top_cshape);
}
if (bot_shape) {
shapeset_visual->detail_levels[Household::DETAIL_BEST].push_back(bot_shape);
bot_cshape->quads_from = bot_cshape->v.size();
shapeset_collision->detail_levels[Household::DETAIL_BEST].push_back(bot_cshape);
}
shapeset_visual->materials = textures_cache;
klass->shapedet_visual = shapeset_visual;
klass->shapedet_collision = shapeset_collision;
klass->make_compound_from_collision_shapes();
shared_ptr<Thingy> th(new Thingy(klass));
th->self_collision_ptr = th.get();
th->bullet_position = btTransform(btTransform(btQuaternion(0,0,0,1), center));
thingy_add(th);
return th;
}