Project::OSiRiON - Git repositories
Project::OSiRiON
News . About . Screenshots . Downloads . Forum . Wiki . Tracker . Git
summaryrefslogtreecommitdiff
path: root/src
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
parent1687737ca713cd0baeca3cf79950ef4877640c99 (diff)
Always use a btCompoundShape for complex collision,
added infrastructure for collision mesh animation, minor API documentation updates
Diffstat (limited to 'src')
-rw-r--r--src/core/entity.cc304
-rw-r--r--src/core/entity.h25
-rw-r--r--src/model/collisionmesh.cc14
-rw-r--r--src/model/collisionmesh.h84
-rw-r--r--src/model/fragment.cc2
-rw-r--r--src/model/fragment.h15
-rw-r--r--src/model/mapfile.cc10
7 files changed, 279 insertions, 175 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);
diff --git a/src/core/entity.h b/src/core/entity.h
index a356525..230ce1b 100644
--- a/src/core/entity.h
+++ b/src/core/entity.h
@@ -167,8 +167,17 @@ public:
}
/// physics collision shape
- inline CollisionShapes collision_shapes() {
- return entity_collision_shapes;
+ inline btCollisionShape *collision_shape() {
+ return entity_collision_shape;
+ }
+
+ /**
+ * @brief physics collision child shapes
+ * if the collision_shape is not a btcompoundShape,
+ * this set will be empty
+ **/
+ inline CollisionShapes & collision_child_shapes() {
+ return entity_collision_child_shapes;
}
/// indicates a server-side entity
@@ -196,11 +205,6 @@ public:
return entity_menus;
}
- /// entity collision shapes
- inline CollisionShapes & shapes() {
- return entity_collision_shapes;
- }
-
/// extensions
inline Extension *extension(size_t type) const {
return entity_extension[type];
@@ -453,7 +457,12 @@ public:
protected:
btRigidBody *entity_body;
btRigidBody::btRigidBodyConstructionInfo *entity_body_info;
- CollisionShapes entity_collision_shapes;
+
+ // the main bullet collision shape for this entity
+ btCollisionShape *entity_collision_shape;
+
+ // bullet collision child shapes for this entity,
+ CollisionShapes entity_collision_child_shapes;
// the zone the entity belongs to
Zone* entity_zone;
diff --git a/src/model/collisionmesh.cc b/src/model/collisionmesh.cc
index 5d2328a..e341e9f 100644
--- a/src/model/collisionmesh.cc
+++ b/src/model/collisionmesh.cc
@@ -47,6 +47,10 @@ CollisionMesh::CollisionMesh()
collisionmesh_size = 0;
// btTriangleMesh (bool use32bitIndices=true, bool use4componentVertices=true)
collisionmesh_triangles = new btTriangleMesh(true, false);
+
+ collisionmesh_scale = 1.0f;
+ collisionmesh_speed = 0.0f;
+ collisionmesh_distance = 0.0f;
}
CollisionMesh::~CollisionMesh()
@@ -54,9 +58,15 @@ CollisionMesh::~CollisionMesh()
delete collisionmesh_triangles;
}
-void CollisionMesh::set_type(const FragmentGroup::Type type)
+void CollisionMesh::set_params(const FragmentGroup *group)
{
- collisionmesh_type = type;
+ 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();
+
}
void CollisionMesh::add_triangle(const math::Vector3f & v0, const math::Vector3f & v1, const math::Vector3f & v2)
diff --git a/src/model/collisionmesh.h b/src/model/collisionmesh.h
index cbd063a..4ab1c19 100644
--- a/src/model/collisionmesh.h
+++ b/src/model/collisionmesh.h
@@ -48,13 +48,83 @@ public:
inline btTriangleMesh *triangles() {
return collisionmesh_triangles;
}
+
+ /**
+ * @brief location of the mesh within the parent model
+ * location() is a point in collision model coordinate space
+ * that indicates the (0,0,0) location of this mesh.
+ * The worldspawn mesh should have location (0,0,0)
+ * */
+ inline const math::Vector3f &location() const {
+ return collisionmesh_location;
+ }
+
+ /**
+ * @brief transformation axis
+ * For normal groups, this is the rotation matrix of the mesh
+ * For rotating groups axis->forward() is the axis of the rotation.
+ * For movers, axis->forward() is the axis of movement.
+ * */
+ inline const math::Axis & axis() const {
+ return collisionmesh_axis;
+ }
+
+ inline const float speed() const {
+ return collisionmesh_speed;
+ }
+ inline const float distance() const {
+ return collisionmesh_distance;
+ }
+
+ inline const float scale() const {
+ return collisionmesh_scale;
+ }
+
+ inline const FragmentGroup::Type type() const {
+ return collisionmesh_type;
+ }
+
/* ---- mutators ------------------------------------------- */
/**
* @brief change the group type
* */
- void set_type(const FragmentGroup::Type type);
+ inline void set_type(const FragmentGroup::Type type) {
+ collisionmesh_type = type;
+ }
+
+ inline void set_location(const math::Vector3f &location) {
+ collisionmesh_location.assign(location);
+ }
+
+ inline void set_axis(const math::Axis &axis) {
+ collisionmesh_axis.assign(axis);
+ }
+
+ /**
+ * @brief apply FragmentGroup parameters to the mesh
+ * This method applies the fragmentgroups type, location, axis, distance, speed and scale
+ * to the collision mesh
+ */
+ void set_params(const FragmentGroup *group);
+
+ /**
+ * @brief movement speed
+ * For rotating meshes this is the number of degrees per second
+ * For movers, this is the speed in units per second
+ */
+ inline void set_speed(const float speed) {
+ collisionmesh_speed = speed;
+ }
+
+ inline void set_distance(const float distance) {
+ collisionmesh_distance = distance;
+ }
+
+ inline void set_scale(const float scale) {
+ collisionmesh_scale = scale;
+ }
/**
* @brief add a triangle to the collision mesh
@@ -89,8 +159,8 @@ public:
static void add(CollisionMesh *collisionmesh);
- static bool initialized() {
- return collisionmesh_initialized;
+ inline static bool initialized() {
+ return collisionmesh_initialized;
}
private:
@@ -102,6 +172,14 @@ private:
size_t collisionmesh_size;
btTriangleMesh *collisionmesh_triangles;
FragmentGroup::Type collisionmesh_type;
+
+ math::Vector3f collisionmesh_location;
+ math::Axis collisionmesh_axis;
+
+ float collisionmesh_speed;
+ float collisionmesh_scale;
+ float collisionmesh_distance;
+
};
} // namespace model
diff --git a/src/model/fragment.cc b/src/model/fragment.cc
index 54ffad9..b4666f4 100644
--- a/src/model/fragment.cc
+++ b/src/model/fragment.cc
@@ -63,7 +63,7 @@ FragmentGroup::FragmentGroup()
{
group_type = None;
group_scale = 1.0f;
-
+ group_distance = 0.0f;
group_speed = 0.0f;
group_engine = false;
}
diff --git a/src/model/fragment.h b/src/model/fragment.h
index db5f569..fcacecc 100644
--- a/src/model/fragment.h
+++ b/src/model/fragment.h
@@ -98,10 +98,17 @@ public:
return group_location;
}
+ /**
+ * @brief movement vector for moving groups
+ * For rotating groups, this is the rotation axis
+ */
inline const math::Vector3f &movement() const {
return group_movement;
}
+ /**
+ * @brief local rotation matrix of the group
+ */
inline const math::Axis & axis() const {
return group_axis;
}
@@ -150,17 +157,15 @@ public:
/**
- * @brief rotation axis
- * For normal groups, this is the transformation matrix
- * For rotating groups axis->forward() is the axis of the rotation.
- * For movers, axis->forward() is the axis of movement.
+ * @brief set the rotation axis
+ * set the local rotation matrix of the group
*/
inline void set_axis(const math::Axis &axis) {
group_axis.assign(axis);
}
/**
- * @brief movement speed
+ * @brief set movement speed
* For rotating groups this is the number of degrees per second
* For movers, this is the speed in units per second
*/
diff --git a/src/model/mapfile.cc b/src/model/mapfile.cc
index 92349c0..b05880f 100644
--- a/src/model/mapfile.cc
+++ b/src/model/mapfile.cc
@@ -1305,7 +1305,7 @@ void MapFile::load_fragmentgroup(Model *model, const FragmentGroup::Type class_t
// add the vertexgroup to the model
model->add_group(group);
- // add collision triangles
+ // load collision triangles into a mesh
if (map_load_clip) {
if (map_collisiontriangles.size()) {
CollisionMesh *collisionmesh = new CollisionMesh();
@@ -1315,7 +1315,10 @@ void MapFile::load_fragmentgroup(Model *model, const FragmentGroup::Type class_t
Triangle *triangle = (*it);
collisionmesh->add_triangle(triangle->v0() - translation, triangle->v1() - translation, triangle->v2() - translation);
}
-
+
+ // apply vertexgroup params to the collision mesh
+ collisionmesh->set_params(group);
+
// add the collision mesh to the collision model
model->collisionmodel()->add_mesh(collisionmesh);
}
@@ -1958,6 +1961,9 @@ Model * MapFile::load(std::string const &name)
cmit != model->collisionmodel()->meshes().end(); cmit++) {
collision_tris_count += (*cmit)->size();
collision_mesh_count++;
+
+ // translate collision meshes
+ (*cmit)->set_location((*cmit)->location() - map_center);
}
con_debug << " " << mapfile.name() << " collision " << collision_tris_count << " triangles " << collision_mesh_count << " meshes" << std::endl;