diff --git a/src/animations/three_d_animation.cpp b/src/animations/three_d_animation.cpp index 608bdfb40..b0caabfde 100644 --- a/src/animations/three_d_animation.cpp +++ b/src/animations/three_d_animation.cpp @@ -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 + 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; igetMeshBufferCount(); 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; jgetIndexCount(); 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; jgetIndexCount(); 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 icreatePhysicalBody(); + 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); diff --git a/src/animations/three_d_animation.hpp b/src/animations/three_d_animation.hpp index c6e930906..2c8800a38 100644 --- a/src/animations/three_d_animation.hpp +++ b/src/animations/three_d_animation.hpp @@ -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. */ diff --git a/src/physics/triangle_mesh.hpp b/src/physics/triangle_mesh.hpp index b55d0cec5..daf949344 100644 --- a/src/physics/triangle_mesh.hpp +++ b/src/physics/triangle_mesh.hpp @@ -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,