Project::OSiRiON - Git repositories
Project::OSiRiON
News . About . Screenshots . Downloads . Forum . Wiki . Tracker . Git
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/core/entity.cc47
-rw-r--r--src/core/gameserver.cc6
-rw-r--r--src/model/collisionmesh.cc20
-rw-r--r--src/model/collisionmesh.h14
-rw-r--r--src/model/mapfile.cc32
-rw-r--r--src/render/draw.cc13
6 files changed, 109 insertions, 23 deletions
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<btCompoundShape *> (entity_collision_shape);
-
- // TODO apply collision mesh animation
-
+ if (entity_collision_child_shapes.size() > 0) {
+ btCompoundShape *compoundshape = static_cast<btCompoundShape *> (entity_collision_shape);
+ bool recalculate = false;
+
+ for (int n = 0; n < compoundshape->getNumChildShapes(); n++) {
+ model::CollisionMesh *mesh = static_cast<model::CollisionMesh *>(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);