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:
parent
31d7ff78f0
commit
b7b1c02bb0
@ -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);
|
||||
|
@ -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. */
|
||||
|
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user