shared_ptr World::tool_quad_prism()

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;
}