Project::OSiRiON - Git repositories
Project::OSiRiON
News . About . Screenshots . Downloads . Forum . Wiki . Tracker . Git
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStijn Buys <ingar@osirion.org>2011-05-06 16:32:55 +0000
committerStijn Buys <ingar@osirion.org>2011-05-06 16:32:55 +0000
commitebe064bf159a5c6e90f2bbe902efa16c6e654ff8 (patch)
treec15ac8d3a9c5a21ce09da1b6834ab7e9f98d9e10 /src/core/entity.cc
parent1687737ca713cd0baeca3cf79950ef4877640c99 (diff)
Always use a btCompoundShape for complex collision,
added infrastructure for collision mesh animation, minor API documentation updates
Diffstat (limited to 'src/core/entity.cc')
-rw-r--r--src/core/entity.cc304
1 files changed, 150 insertions, 154 deletions
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<btCompoundShape *> (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);