From 50947891a97f19fa11f9f073c8988156f9655d97 Mon Sep 17 00:00:00 2001 From: Stijn Buys Date: Fri, 6 May 2011 18:27:55 +0000 Subject: Support for func_rotate and func_move collision meshes. --- src/core/entity.cc | 47 ++++++++++++++++++++++++++++++++++++++++------ src/core/gameserver.cc | 6 ++---- src/model/collisionmesh.cc | 20 +++++++++++++------- src/model/collisionmesh.h | 14 ++++++++++++-- src/model/mapfile.cc | 32 +++++++++++++++++++++++++++++-- src/render/draw.cc | 13 +++++++++++-- 6 files changed, 109 insertions(+), 23 deletions(-) (limited to 'src') diff --git a/src/core/entity.cc b/src/core/entity.cc index bba3c5c..1535de8 100644 --- a/src/core/entity.cc +++ b/src/core/entity.cc @@ -490,11 +490,44 @@ 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 - + if (entity_collision_child_shapes.size() > 0) { + btCompoundShape *compoundshape = static_cast (entity_collision_shape); + bool recalculate = false; + + for (int n = 0; n < compoundshape->getNumChildShapes(); n++) { + model::CollisionMesh *mesh = static_cast(compoundshape->getChildShape(n)->getUserPointer()); + + if (mesh) { + if (mesh->type() == model::FragmentGroup::Rotate) { + const float rotation_radians = math::degrees360f(game()->time() * mesh->speed()) * M_PI / 180.0f; + math::Axis rotation_axis; + rotation_axis.rotate(mesh->movement(), rotation_radians); + + btTransform child_transform; + child_transform.setIdentity(); + child_transform.setOrigin(math::to_btVector3(mesh->location())); + child_transform.setBasis(math::to_btMatrix3x3(mesh->axis() * rotation_axis)); + + compoundshape->updateChildTransform(n, child_transform); + + } else if (mesh->type() == model::FragmentGroup::Move ) { + + const float freq = mesh->speed() / mesh->distance(); + math::Vector3f translation(mesh->movement() * mesh->distance()); + translation *= sinf(core::game()->time() * M_PI * freq) * 0.5f + 0.5f; + + btTransform child_transform; + child_transform.setIdentity(); + child_transform.setOrigin(to_btVector3(mesh->location() + mesh->axis() * translation)); + child_transform.setBasis(math::to_btMatrix3x3(mesh->axis())); + + compoundshape->updateChildTransform(n, child_transform); + } + } + + if (recalculate) + compoundshape->recalculateLocalAabb(); + } } } @@ -548,11 +581,13 @@ void Entity::reset() switch (mesh->type()) { case model::FragmentGroup::Rotate: case model::FragmentGroup::Move: + con_debug << " ^Rcollision mesh attached to btCollisionShape " << std::endl; meshshape->setUserPointer((void *) mesh); break; default: - meshshape->setUserPointer(0); + meshshape->setUserPointer(0); + break; } // add the mesh to the compoundhape and store a pointer to the child shape compoundshape->addChildShape(child_transform, meshshape); diff --git a/src/core/gameserver.cc b/src/core/gameserver.cc index 564622f..6a20317 100644 --- a/src/core/gameserver.cc +++ b/src/core/gameserver.cc @@ -549,10 +549,8 @@ void GameServer::frame(unsigned long timestamp) for (Entity::Registry::iterator it = Entity::registry().begin(); it != Entity::registry().end(); it++) { Entity *entity = (*it).second; - if ((entity->type() == Entity::Dynamic) || (entity->type() == Entity::Controlable)) { - entity->frame(elapsed); - - } + entity->frame(elapsed); + } // expand zone keepalive bounding box diff --git a/src/model/collisionmesh.cc b/src/model/collisionmesh.cc index 808da63..0bb6580 100644 --- a/src/model/collisionmesh.cc +++ b/src/model/collisionmesh.cc @@ -32,7 +32,12 @@ CollisionMesh::CollisionMesh(const CollisionMesh &other) collisionmesh_scale = other.scale(); collisionmesh_speed = other.speed(); collisionmesh_distance = other.distance(); + + collisionmesh_location.assign(other.location()); + collisionmesh_axis.assign(other.axis()); + collisionmesh_movement.assign(other.movement()); } + CollisionMesh::~CollisionMesh() { if (collisionmesh_owns_triangles) @@ -41,14 +46,15 @@ CollisionMesh::~CollisionMesh() collisionmesh_triangles = 0; } -void CollisionMesh::set_params(const FragmentGroup *group) +void CollisionMesh::set_params(const FragmentGroup & group) { - collisionmesh_type = group->type(); - collisionmesh_location.assign(group->location()); - collisionmesh_axis.assign(group->axis()); - collisionmesh_scale = group->scale(); - collisionmesh_speed = group->speed(); - collisionmesh_distance = group->distance(); + collisionmesh_type = group.type(); + collisionmesh_location.assign(group.location()); + collisionmesh_axis.assign(group.axis()); + collisionmesh_movement.assign(group.movement()); + collisionmesh_scale = group.scale(); + collisionmesh_speed = group.speed(); + collisionmesh_distance = group.distance(); } diff --git a/src/model/collisionmesh.h b/src/model/collisionmesh.h index e80774d..c1f9846 100644 --- a/src/model/collisionmesh.h +++ b/src/model/collisionmesh.h @@ -72,6 +72,10 @@ public: return collisionmesh_axis; } + inline const math::Vector3f &movement() const { + return collisionmesh_movement; + } + inline const float speed() const { return collisionmesh_speed; } @@ -105,12 +109,16 @@ public: collisionmesh_axis.assign(axis); } + inline void set_movement(const math::Vector3f &movement) { + collisionmesh_movement.assign(movement); + } + /** * @brief apply FragmentGroup parameters to the mesh - * This method applies the fragmentgroups type, location, axis, distance, speed and scale + * This method applies the fragmentgroups type, location, axis, movement, distance, speed and scale * to the collision mesh */ - void set_params(const FragmentGroup *group); + void set_params(const FragmentGroup &group); /** * @brief movement speed @@ -147,6 +155,8 @@ private: math::Vector3f collisionmesh_location; math::Axis collisionmesh_axis; + math::Vector3f collisionmesh_movement; + float collisionmesh_speed; float collisionmesh_scale; float collisionmesh_distance; diff --git a/src/model/mapfile.cc b/src/model/mapfile.cc index 0abbdbd..270d63f 100644 --- a/src/model/mapfile.cc +++ b/src/model/mapfile.cc @@ -1317,8 +1317,36 @@ void MapFile::load_fragmentgroup(Model *model, const FragmentGroup::Type class_t } // apply vertexgroup params to the collision mesh - collisionmesh->set_params(group); - + collisionmesh->set_location(translation); + collisionmesh->set_type(class_type); + + // these fragmentgroups are on the same level as worldspawn (no submodels) + // their rotation axis is always identity + + switch (class_type) { + case FragmentGroup::None: + break; + + case FragmentGroup::Rotate: + if (class_speed == 0) { + // default rotation speed 45 degrees per second + class_speed = 45.0f; + } + collisionmesh->set_speed(class_speed); + collisionmesh->set_movement(class_axis.forward()); + break; + + case FragmentGroup::Move: + group->set_speed(class_speed); + group->set_distance(class_distance); + group->set_movement(class_axis.forward()); + break; + + case FragmentGroup::Door: + group->set_speed(class_speed); + break; + } + // add the collision mesh to the collision model model->collisionmodel()->add_mesh(collisionmesh); } diff --git a/src/render/draw.cc b/src/render/draw.cc index c19dc39..46f62ca 100644 --- a/src/render/draw.cc +++ b/src/render/draw.cc @@ -671,14 +671,14 @@ void draw_model_fragments(model::Model *model, gl::scale(s, s, s); if (group->type() == model::FragmentGroup::Rotate) { - const float rotation_angle = math::degrees360f((group->engine() ? enginetime : core::application()->time()) * group->speed()); + const float rotation_angle = math::degrees360f((group->engine() ? enginetime : core::game()->time()) * group->speed()); gl::rotate(-rotation_angle, group->movement()); } else if (group->type() == model::FragmentGroup::Move ) { const float freq = group->speed() / group->distance(); math::Vector3f translation(group->movement() * group->distance()); - translation *= sinf((group->engine() ? enginetime : core::application()->time()) * M_PI * freq) * 0.5f + 0.5f; + translation *= sinf((group->engine() ? enginetime : core::game()->time()) * M_PI * freq) * 0.5f + 0.5f; gl::translate(translation); } @@ -950,6 +950,15 @@ void draw_model_axis(const core::Entity *entity) void draw_pass_model_fragments() { + /* + * FIXME + * For moving and rotating fragmentgroups, the enginetime must match + * the time used by core:: to calculate the rotation or movement + * of the asssociated collision models. + * Currently, enginetime is client-side only, and there is no way + * to sync core and render movement of fragmentgroups without sacrificing + * the functionality of the FragmentGroup::engine() flag. + */ for (core::Zone::Content::iterator it = zone->content().begin(); it != zone->content().end(); it++) { core::Entity *entity = (*it); -- cgit v1.2.3