From ebe064bf159a5c6e90f2bbe902efa16c6e654ff8 Mon Sep 17 00:00:00 2001 From: Stijn Buys Date: Fri, 6 May 2011 16:32:55 +0000 Subject: Always use a btCompoundShape for complex collision, added infrastructure for collision mesh animation, minor API documentation updates --- src/core/entity.cc | 304 ++++++++++++++++++++++++++--------------------------- 1 file changed, 150 insertions(+), 154 deletions(-) (limited to 'src/core/entity.cc') diff --git a/src/core/entity.cc b/src/core/entity.cc index 64812cc..bba3c5c 100644 --- a/src/core/entity.cc +++ b/src/core/entity.cc @@ -150,7 +150,7 @@ Entity::Entity() : entity_body = 0; entity_body_info = 0; - + entity_collision_shape = 0; entity_speed = 0.0f; entity_radius = 0.5f; @@ -188,7 +188,7 @@ Entity::Entity(std::istream & is) entity_body = 0; entity_body_info = 0; - + entity_collision_shape = 0; entity_speed = 0.0f; entity_created = true; @@ -230,11 +230,16 @@ Entity::~Entity() } } - for (CollisionShapes::iterator sit = entity_collision_shapes.begin(); sit != entity_collision_shapes.end(); sit++) { + if (entity_collision_shape) { + delete entity_collision_shape; + entity_collision_shape = 0; + } + + for (CollisionShapes::iterator sit = entity_collision_child_shapes.begin(); sit != entity_collision_child_shapes.end(); sit++) { delete (*sit); (*sit) = 0; } - entity_collision_shapes.clear(); + entity_collision_child_shapes.clear(); if (entity_body) delete entity_body; @@ -455,10 +460,6 @@ void Entity::receive_server_update(std::istream &is) { } -void Entity::frame(float seconds) -{ -} - void Entity::upkeep(const unsigned long timestamp) { } @@ -486,6 +487,17 @@ void Entity::remove_menu(std::string const &label) } } + +void Entity::frame(float seconds) +{ + if (entity_collision_child_shapes.size()) { + //btCompoundShape *compoundshape = static_cast (entity_collision_shape); + + // TODO apply collision mesh animation + + } +} + void Entity::reset() { if (!radius() || flag_is_set(NonSolid)) { @@ -498,84 +510,80 @@ void Entity::reset() t.setOrigin(to_btVector3(location())); t.setBasis(to_btMatrix3x3(axis())); - // construct physics body if necessary + // construct physics body if required if (!entity_body) { - btCollisionShape * myshape = 0; + + // if there is no body, this entity should not have shapes either + assert (entity_collision_shape == 0); + assert (entity_collision_child_shapes.size() == 0); // create collision shape if (model() && model()->radius()) { const float modelscale = radius() / model()->radius(); if (flag_is_set(Complex) && model()->collisionmodel() && model()->collisionmodel()->size()) { - if (model()->collisionmodel()->size() == 1 ) { - // the collision model only has a single mesh, - // we can use a triangle mesh shape - - model::CollisionMesh *mesh = (*model()->collisionmodel()->meshes().begin()); + + // complex collision is enabled and a valid collision model has been found + btCompoundShape *compoundshape = new btCompoundShape(); + for (model::CollisionModel::CollisionMeshes::iterator it = model()->collisionmodel()->meshes().begin(); + it != model()->collisionmodel()->meshes().end(); it++) { + + model::CollisionMesh *mesh = (*it); - // static entities use a btBvhTriangleMeshShape + // generate a btCollisionShape for each model::CollisionMesh in the model::CollisionModel + // static entities use a btBvhTriangleMeshShape btBvhTriangleMeshShape *meshshape = new btBvhTriangleMeshShape(mesh->triangles(), true, true); + meshshape->setMargin(Cvar::sv_collisionmargin->value()); + btVector3 meshscalevec(mesh->scale(), mesh->scale(), mesh->scale()); + meshshape->setLocalScaling(meshscalevec); meshshape->buildOptimizedBvh(); - meshshape->recalcLocalAabb(); - - btVector3 modelscalevec(modelscale, modelscale, modelscale); - meshshape->setLocalScaling(modelscalevec); - - shapes().push_back(meshshape); - myshape = meshshape; - - } else { - // the collision model has multiple meshes that need to be - // combined into a compound shape - btCompoundShape *compoundshape = new btCompoundShape(); - - for (model::CollisionModel::CollisionMeshes::iterator it = model()->collisionmodel()->meshes().begin(); - it != model()->collisionmodel()->meshes().end(); it++) { - - model::CollisionMesh *mesh = (*it); - btTransform childtransform; - childtransform.setIdentity(); + meshshape->recalcLocalAabb(); + + // apply collision mesh properties to the btCollisionShape + btTransform child_transform; + child_transform.setIdentity(); + child_transform.setOrigin(to_btVector3(mesh->location())); + child_transform.setBasis(to_btMatrix3x3(mesh->axis())); - // static entities use a btBvhTriangleMeshShape - btBvhTriangleMeshShape *meshshape = new btBvhTriangleMeshShape(mesh->triangles(), true, true); - meshshape->buildOptimizedBvh(); - meshshape->recalcLocalAabb(); - - // FIXME apply vertexgroup transformations - compoundshape->addChildShape(childtransform, meshshape); - shapes().push_back(meshshape); + switch (mesh->type()) { + case model::FragmentGroup::Rotate: + case model::FragmentGroup::Move: + meshshape->setUserPointer((void *) mesh); + break; + + default: + meshshape->setUserPointer(0); } - - btVector3 modelscalevec(modelscale, modelscale, modelscale); - compoundshape->setLocalScaling(modelscalevec); - - shapes().push_back(compoundshape); - myshape = compoundshape; + // add the mesh to the compoundhape and store a pointer to the child shape + compoundshape->addChildShape(child_transform, meshshape); + entity_collision_child_shapes.push_back(meshshape); } + btVector3 modelscalevec(modelscale, modelscale, modelscale); + compoundshape->setLocalScaling(modelscalevec); + + entity_collision_shape = compoundshape; + } else { + // model without collision model // use bounding box btBoxShape *boxshape = new btBoxShape(to_btVector3(model()->box().max() * modelscale)); - shapes().push_back(boxshape); - myshape = boxshape; + entity_collision_shape = boxshape; } } else { + // no model // use a sphere with a radius matching the entity btSphereShape *sphereshape = new btSphereShape(radius()); - shapes().push_back(sphereshape); - myshape = sphereshape; - + entity_collision_shape = sphereshape; + // TODO the actual shape should depend on Entity::Shape } - // set margin on each mesh - for (CollisionShapes::iterator it = shapes().begin(); it != shapes().end(); it++) { - (*it)->setMargin(Cvar::sv_collisionmargin->value()); - } - + entity_collision_shape->setMargin(Cvar::sv_collisionmargin->value()); + // create physics body btVector3 inertia(0, 0, 0); - entity_body_info = new btRigidBody::btRigidBodyConstructionInfo(0, 0, myshape, inertia); + entity_body_info = new btRigidBody::btRigidBodyConstructionInfo(0, 0, entity_collision_shape, inertia); entity_body = new btRigidBody(*entity_body_info); entity_body->setActivationState(ISLAND_SLEEPING); @@ -638,81 +646,77 @@ void EntityDynamic::reset() // construct physics body if necessary if (!entity_body) { - btCollisionShape * myshape = 0; // create collision shape if (model() && model()->radius()) { const float modelscale = radius() / model()->radius(); if (flag_is_set(Complex) && model()->collisionmodel() && model()->collisionmodel()->size()) { - if (model()->collisionmodel()->size() == 1 ) { - // the collision model only has a single mesh, - // we can use a triangle mesh shape - - model::CollisionMesh *mesh = (*model()->collisionmodel()->meshes().begin()); + // complex collision is enabled and a valid collision model has been found + btCompoundShape *compoundshape = new btCompoundShape(); + for (model::CollisionModel::CollisionMeshes::iterator it = model()->collisionmodel()->meshes().begin(); + it != model()->collisionmodel()->meshes().end(); it++) { - // static entities use a btBvhTriangleMeshShape - btGImpactMeshShape *meshshape = new btGImpactMeshShape(mesh->triangles()); - btVector3 modelscalevec(modelscale, modelscale, modelscale); - meshshape->setLocalScaling(modelscalevec); - - shapes().push_back(meshshape); - myshape = meshshape; - - } else { - // the collision model has multiple meshes that need to be - // combined into a compound shape - btCompoundShape *compoundshape = new btCompoundShape(); + model::CollisionMesh *mesh = (*it); - for (model::CollisionModel::CollisionMeshes::iterator it = model()->collisionmodel()->meshes().begin(); - it != model()->collisionmodel()->meshes().end(); it++) { - - model::CollisionMesh *mesh = (*it); - btTransform childtransform; + // generate a btCollisionShape for each model::CollisionMesh in the model::CollisionModel + // dynamic entities use btGImpactMeshShape + btGImpactMeshShape *meshshape = new btGImpactMeshShape(mesh->triangles()); + meshshape->setMargin(Cvar::sv_collisionmargin->value()); + btVector3 meshscalevec(mesh->scale(), mesh->scale(), mesh->scale()); + meshshape->setLocalScaling(meshscalevec); + + // apply collision mesh properties to the btCollisionShape + btTransform child_transform; + child_transform.setIdentity(); + child_transform.setOrigin(to_btVector3(mesh->location())); + child_transform.setBasis(to_btMatrix3x3(mesh->axis())); - // dynamic entities use a btGImpactMeshShape - btGImpactMeshShape *meshshape = new btGImpactMeshShape(mesh->triangles()); - // FIXME apply vertexgroup transformations - compoundshape->addChildShape(childtransform, meshshape); - shapes().push_back(meshshape); + switch (mesh->type()) { + case model::FragmentGroup::Rotate: + case model::FragmentGroup::Move: + meshshape->setUserPointer((void *) mesh); + break; + + default: + meshshape->setUserPointer(0); } - btVector3 modelscalevec(modelscale, modelscale, modelscale); - compoundshape->setLocalScaling(modelscalevec); - - shapes().push_back(compoundshape); - myshape = compoundshape; + // add the mesh to the compoundhape and store a pointer to the child shape + compoundshape->addChildShape(child_transform, meshshape); + entity_collision_child_shapes.push_back(meshshape); } + btVector3 modelscalevec(modelscale, modelscale, modelscale); + compoundshape->setLocalScaling(modelscalevec); + + entity_collision_shape = compoundshape; + } else { // use bounding box btBoxShape *boxshape = new btBoxShape(to_btVector3(model()->box().max() * modelscale)); - shapes().push_back(boxshape); - myshape = boxshape; + entity_collision_shape = boxshape; } } else { // use a sphere with a radius matching the entity btSphereShape *sphereshape = new btSphereShape(radius()); - shapes().push_back(sphereshape); - myshape = sphereshape; - + entity_collision_shape = sphereshape; } - // set margin on each mesh - for (CollisionShapes::iterator it = shapes().begin(); it != shapes().end(); it++) { - (*it)->setMargin(Cvar::sv_collisionmargin->value()); - } + // set margin + entity_collision_shape->setMargin(Cvar::sv_collisionmargin->value()); + // calculate inertia btVector3 inertia(0, 0, 0); if (entity_mass) - myshape->calculateLocalInertia(entity_mass, inertia); + entity_collision_shape->calculateLocalInertia(entity_mass, inertia); // create motion state entity_motionstate = new btDefaultMotionState(t); // create physics body - entity_body_info = new btRigidBody::btRigidBodyConstructionInfo(entity_mass, entity_motionstate, myshape, inertia); + entity_body_info = new btRigidBody::btRigidBodyConstructionInfo(entity_mass, entity_motionstate, entity_collision_shape, inertia); entity_body = new btRigidBody(*entity_body_info); if (entity_mass) { @@ -747,6 +751,8 @@ void EntityDynamic::reset() void EntityDynamic::frame(float seconds) { + Entity::frame(seconds); + if (entity_state == Docked) { return; } @@ -1103,87 +1109,77 @@ void EntityControlable::reset() // construct physics body if necessary if (!entity_body) { - btCollisionShape * myshape = 0; - + // create collision shape if (model() && model()->radius()) { const float modelscale = radius() / model()->radius(); - if (flag_is_set(Complex) && model()->collisionmodel() && (model()->collisionmodel()->size() > 0) ) { - if (model()->collisionmodel()->size() == 1 ) { - // the collision model only has a single mesh, - // we can use a triangle mesh shape - - model::CollisionMesh *mesh = (*model()->collisionmodel()->meshes().begin()); + if (flag_is_set(Complex) && model()->collisionmodel() && model()->collisionmodel()->size()) { + // complex collision is enabled and a valid collision model has been found + btCompoundShape *compoundshape = new btCompoundShape(); + for (model::CollisionModel::CollisionMeshes::iterator it = model()->collisionmodel()->meshes().begin(); + it != model()->collisionmodel()->meshes().end(); it++) { - // dynamic entities use a btGImpactMeshShape - btGImpactMeshShape *meshshape = new btGImpactMeshShape(mesh->triangles()); - btVector3 modelscalevec(modelscale, modelscale, modelscale); - meshshape->setLocalScaling(modelscalevec); + model::CollisionMesh *mesh = (*it); - shapes().push_back(meshshape); - myshape = meshshape; + // generate a btCollisionShape for each model::CollisionMesh in the model::CollisionModel + // dynamic entities use btGImpactMeshShape + btGImpactMeshShape *meshshape = new btGImpactMeshShape(mesh->triangles()); + meshshape->setMargin(Cvar::sv_collisionmargin->value()); + btVector3 meshscalevec(mesh->scale(), mesh->scale(), mesh->scale()); + meshshape->setLocalScaling(meshscalevec); meshshape->updateBound(); - - } else { - // the collision model has multiple meshes that need to be - // combined into a compound shape - btCompoundShape *compoundshape = new btCompoundShape(); - btVector3 modelscalevec(modelscale, modelscale, modelscale); - - for (model::CollisionModel::CollisionMeshes::iterator it = model()->collisionmodel()->meshes().begin(); - it != model()->collisionmodel()->meshes().end(); it++) { - - model::CollisionMesh *mesh = (*it); - btTransform childtransform; - childtransform.setIdentity(); - - // dynamic entities use a btGImpactMeshShape - btGImpactMeshShape *meshshape = new btGImpactMeshShape(mesh->triangles()); - meshshape->setLocalScaling(modelscalevec); - meshshape->updateBound(); + + // apply collision mesh properties to the btCollisionShape + btTransform child_transform; + child_transform.setIdentity(); + child_transform.setOrigin(to_btVector3(mesh->location())); + child_transform.setBasis(to_btMatrix3x3(mesh->axis())); - // FIXME apply vertexgroup transformations - compoundshape->addChildShape(childtransform, meshshape); - shapes().push_back(meshshape); + switch (mesh->type()) { + case model::FragmentGroup::Rotate: + case model::FragmentGroup::Move: + meshshape->setUserPointer((void *) mesh); + break; + + default: + meshshape->setUserPointer(0); } - - - - shapes().push_back(compoundshape); - myshape = compoundshape; + // add the mesh to the compoundhape and store a pointer to the child shape + compoundshape->addChildShape(child_transform, meshshape); + entity_collision_child_shapes.push_back(meshshape); } + btVector3 modelscalevec(modelscale, modelscale, modelscale); + compoundshape->setLocalScaling(modelscalevec); + + entity_collision_shape = compoundshape; + } else { // use bounding box btBoxShape *boxshape = new btBoxShape(to_btVector3(model()->box().max() * modelscale)); - shapes().push_back(boxshape); - myshape = boxshape; + entity_collision_shape = boxshape; } } else { // use a sphere with a radius matching the entity btSphereShape *sphereshape = new btSphereShape(radius()); - shapes().push_back(sphereshape); - myshape = sphereshape; - + entity_collision_shape = sphereshape; } // set margin on each mesh - for (CollisionShapes::iterator it = shapes().begin(); it != shapes().end(); it++) { - (*it)->setMargin(Cvar::sv_collisionmargin->value()); - } + entity_collision_shape->setMargin(Cvar::sv_collisionmargin->value()); btVector3 inertia(0, 0, 0); if (entity_mass) - myshape->calculateLocalInertia(entity_mass, inertia); + entity_collision_shape->calculateLocalInertia(entity_mass, inertia); // create motion state entity_motionstate = new btDefaultMotionState(t); // create physics body - entity_body_info = new btRigidBody::btRigidBodyConstructionInfo(entity_mass, entity_motionstate, myshape, inertia); + entity_body_info = new btRigidBody::btRigidBodyConstructionInfo(entity_mass, entity_motionstate, entity_collision_shape, inertia); entity_body = new btRigidBody(*entity_body_info); entity_body->setActivationState(DISABLE_DEACTIVATION); -- cgit v1.2.3