On forum, with minigolf course, it was suggested that it would be cool to be able to use more accurate collision shapes, for instance enabling the windmill to hit the kart. I agree, and bullet can do that, so it's not possible :) but not used anywhere atm

git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/trunk@9867 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
auria 2011-09-18 19:53:02 +00:00
parent 31d7ff78f0
commit b7b1c02bb0
3 changed files with 145 additions and 3 deletions

View File

@ -23,17 +23,24 @@
#include "animations/ipo.hpp"
#include "graphics/irr_driver.hpp"
#include "graphics/material.hpp"
#include "graphics/material_manager.hpp"
#include "graphics/mesh_tools.hpp"
#include "io/xml_node.hpp"
#include "modes/world.hpp"
#include "physics/physics.hpp"
#include "physics/kart_motion_state.hpp"
#include "physics/physics.hpp"
#include "physics/triangle_mesh.hpp"
#include "tracks/bezier_curve.hpp"
#include "utils/constants.hpp"
#include <IMeshSceneNode.h>
ThreeDAnimation::ThreeDAnimation(const XMLNode &node)
: AnimationBase(node)
{
m_triangle_mesh = NULL;
/** Save the initial position and rotation in the base animation object. */
setInitialTransform(AnimationBase::m_node->getPosition(),
AnimationBase::m_node->getRotation() );
@ -81,6 +88,131 @@ void ThreeDAnimation::createPhysicsBody(const std::string &shape)
float radius = 0.5f*std::max(extend.getX(), extend.getY());
m_collision_shape = new btConeShapeZ(radius, extend.getZ());
}
else if(shape=="exact")
{
TriangleMesh* triangle_mesh = new TriangleMesh();
// In case of readonly materials we have to get the material from
// the mesh, otherwise from the node. This is esp. important for
// water nodes, which only have the material defined in the node,
// but not in the mesh at all!
bool is_readonly_material = false;
scene::IMesh* mesh = NULL;
switch (m_node->getType())
{
case scene::ESNT_MESH :
case scene::ESNT_WATER_SURFACE :
case scene::ESNT_OCTREE :
mesh = ((scene::IMeshSceneNode*)m_node)->getMesh();
is_readonly_material =
((scene::IMeshSceneNode*)m_node)->isReadOnlyMaterials();
break;
case scene::ESNT_ANIMATED_MESH :
// for now just use frame 0
mesh = ((scene::IAnimatedMeshSceneNode*)m_node)->getMesh()->getMesh(0);
is_readonly_material =
((scene::IAnimatedMeshSceneNode*)m_node)->isReadOnlyMaterials();
break;
default:
fprintf(stderr, "[3DAnimation] Unknown object type, cannot create exact collision body!\n");
return;
} // switch node->getType()
//core::matrix4 mat;
//mat.setRotationDegrees(hpr);
//mat.setTranslation(pos);
//core::matrix4 mat_scale;
// Note that we can't simply call mat.setScale, since this would
// overwrite the elements on the diagonal, making any rotation incorrect.
//mat_scale.setScale(scale);
//mat *= mat_scale;
for(unsigned int i=0; i<mesh->getMeshBufferCount(); i++)
{
scene::IMeshBuffer *mb = mesh->getMeshBuffer(i);
// FIXME: take translation/rotation into account
if (mb->getVertexType() != video::EVT_STANDARD &&
mb->getVertexType() != video::EVT_2TCOORDS)
{
fprintf(stderr, "WARNING: Physics::convertTrack: Ignoring type '%d'!",
mb->getVertexType());
continue;
}
// Handle readonly materials correctly: mb->getMaterial can return
// NULL if the node is not using readonly materials. E.g. in case
// of a water scene node, the mesh (which is the animated copy of
// the original mesh) does not contain any material information,
// the material is only available in the node.
const video::SMaterial &irrMaterial =
is_readonly_material ? mb->getMaterial()
: m_node->getMaterial(i);
video::ITexture* t=irrMaterial.getTexture(0);
const Material* material=0;
TriangleMesh *tmesh = triangle_mesh;
if(t)
{
std::string image = std::string(core::stringc(t->getName()).c_str());
material=material_manager->getMaterial(StringUtils::getBasename(image));
if(material->isIgnore())
continue;
}
u16 *mbIndices = mb->getIndices();
Vec3 vertices[3];
Vec3 normals[3];
if (mb->getVertexType() == video::EVT_STANDARD)
{
irr::video::S3DVertex* mbVertices=(video::S3DVertex*)mb->getVertices();
for(unsigned int j=0; j<mb->getIndexCount(); j+=3)
{
for(unsigned int k=0; k<3; k++)
{
int indx=mbIndices[j+k];
core::vector3df v = mbVertices[indx].Pos;
//mat.transformVect(v);
vertices[k]=v;
normals[k]=mbVertices[indx].Normal;
} // for k
if(tmesh) tmesh->addTriangle(vertices[0], vertices[1],
vertices[2], normals[0],
normals[1], normals[2],
material );
} // for j
}
else
{
if (mb->getVertexType() == video::EVT_2TCOORDS)
{
irr::video::S3DVertex2TCoords* mbVertices = (video::S3DVertex2TCoords*)mb->getVertices();
for(unsigned int j=0; j<mb->getIndexCount(); j+=3)
{
for(unsigned int k=0; k<3; k++)
{
int indx=mbIndices[j+k];
core::vector3df v = mbVertices[indx].Pos;
//mat.transformVect(v);
vertices[k]=v;
normals[k]=mbVertices[indx].Normal;
} // for k
if(tmesh) tmesh->addTriangle(vertices[0], vertices[1],
vertices[2], normals[0],
normals[1], normals[2],
material );
} // for j
}
}
} // for i<getMeshBufferCount
triangle_mesh->createPhysicalBody();
m_collision_shape = &triangle_mesh->getCollisionShape();
m_triangle_mesh = triangle_mesh;
}
else
{
fprintf(stderr, "Shape '%s' is not supported, ignored.\n", shape.c_str());
@ -114,6 +246,11 @@ ThreeDAnimation::~ThreeDAnimation()
delete m_motion_state;
delete m_collision_shape;
}
if (m_triangle_mesh)
{
delete m_triangle_mesh;
}
} // ~ThreeDAnimation
// ----------------------------------------------------------------------------
@ -149,7 +286,7 @@ void ThreeDAnimation::update(float dt)
if(m_body)
{
hpr = DEGREE_TO_RAD*hpr;
btQuaternion q(-hpr.Z, -hpr.X, -hpr.Y);
btQuaternion q(hpr.X, hpr.Y, hpr.Z);
Vec3 p(xyz);
btTransform trans(q,p);
m_motion_state->setWorldTransform(trans);

View File

@ -51,6 +51,9 @@ private:
/** A user pointer to connect a bullet body with this object. */
UserPointer m_user_pointer;
/** Non-null only if the shape is exact */
TriangleMesh *m_triangle_mesh;
/** We have to store the rotation value as computed in blender, since
* irrlicht uses a different order, so for rotation animations we
* can not use the value returned by getRotation from a scene node. */

View File

@ -63,7 +63,9 @@ public:
{return m_triangleIndex2Material[n];}
// ------------------------------------------------------------------------
const btCollisionShape &getCollisionShape() const
{return *m_collision_shape;}
{ return *m_collision_shape; }
// ------------------------------------------------------------------------
btCollisionShape &getCollisionShape() { return *m_collision_shape; }
// ------------------------------------------------------------------------
bool castRay(const btVector3 &from, const btVector3 &to,
btVector3 *xyz, const Material **material,