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-05 18:08:45 +0000
committerStijn Buys <ingar@osirion.org>2011-05-05 18:08:45 +0000
commit1687737ca713cd0baeca3cf79950ef4877640c99 (patch)
treef6cfd31c850cec95da491036f1dd772397128549 /src
parent09d68d3d1d77d45343e3562c0b5e0cd6816d47d3 (diff)
Initial support for btCompoundShape and the infrastructure required to accomodate multiple meshes per collision model,
added prototype files for signals
Diffstat (limited to 'src')
-rw-r--r--src/core/Makefile.am2
-rw-r--r--src/core/entity.cc236
-rw-r--r--src/core/entity.h16
-rw-r--r--src/core/physics.cc4
-rw-r--r--src/core/signals.cc16
-rw-r--r--src/core/signals.h51
-rw-r--r--src/model/Makefile.am2
-rw-r--r--src/model/collisionmesh.cc27
-rw-r--r--src/model/collisionmesh.h31
-rw-r--r--src/model/collisionmodel.cc76
-rw-r--r--src/model/collisionmodel.h111
-rw-r--r--src/model/mapfile.cc83
-rw-r--r--src/model/mapfile.h1
-rw-r--r--src/model/model.cc6
-rw-r--r--src/model/model.h12
15 files changed, 552 insertions, 122 deletions
diff --git a/src/core/Makefile.am b/src/core/Makefile.am
index ce76303..e6b98e5 100644
--- a/src/core/Makefile.am
+++ b/src/core/Makefile.am
@@ -31,6 +31,7 @@ noinst_HEADERS = \
physics.h \
player.h \
range.h \
+ signals.h \
stats.h \
timer.h \
zone.h
@@ -60,6 +61,7 @@ libcore_la_SOURCES = \
parser.cc \
physics.cc \
player.cc \
+ signals.cc \
stats.cc \
timer.cc \
zone.cc
diff --git a/src/core/entity.cc b/src/core/entity.cc
index ec25017..64812cc 100644
--- a/src/core/entity.cc
+++ b/src/core/entity.cc
@@ -150,7 +150,6 @@ Entity::Entity() :
entity_body = 0;
entity_body_info = 0;
- entity_collision_shape = 0;
entity_speed = 0.0f;
@@ -189,7 +188,6 @@ Entity::Entity(std::istream & is)
entity_body = 0;
entity_body_info = 0;
- entity_collision_shape = 0;
entity_speed = 0.0f;
@@ -214,8 +212,9 @@ Entity::~Entity()
}
// delete entity menus
- for (Menus::iterator it = menus().begin(); it != menus().end(); it++) {
- delete(*it);
+ for (Menus::iterator mit = menus().begin(); mit != menus().end(); mit++) {
+ delete (*mit);
+ (*mit) = 0;
}
menus().clear();
@@ -231,8 +230,11 @@ Entity::~Entity()
}
}
- if (entity_collision_shape)
- delete entity_collision_shape;
+ for (CollisionShapes::iterator sit = entity_collision_shapes.begin(); sit != entity_collision_shapes.end(); sit++) {
+ delete (*sit);
+ (*sit) = 0;
+ }
+ entity_collision_shapes.clear();
if (entity_body)
delete entity_body;
@@ -498,33 +500,82 @@ void Entity::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()->collisionmesh()) {
- // use collision mesh
- // static entities use a btBvhTriangleMeshShape
- btBvhTriangleMeshShape *meshshape = new btBvhTriangleMeshShape(model()->collisionmesh()->triangles(), true, true);
- meshshape->buildOptimizedBvh();
- meshshape->recalcLocalAabb();
+ 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());
+
+ // static entities use a btBvhTriangleMeshShape
+ btBvhTriangleMeshShape *meshshape = new btBvhTriangleMeshShape(mesh->triangles(), true, true);
+ meshshape->buildOptimizedBvh();
+ meshshape->recalcLocalAabb();
+
+ btVector3 modelscalevec(modelscale, modelscale, modelscale);
+ meshshape->setLocalScaling(modelscalevec);
+
+ shapes().push_back(meshshape);
+ myshape = meshshape;
- btVector3 modelscalevec(modelscale, modelscale, modelscale);
- meshshape->setLocalScaling(modelscalevec);
+ } 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();
+
+ // 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);
+ }
+
+ btVector3 modelscalevec(modelscale, modelscale, modelscale);
+ compoundshape->setLocalScaling(modelscalevec);
+
+ shapes().push_back(compoundshape);
+ myshape = compoundshape;
+ }
- entity_collision_shape = meshshape;
} else {
// use bounding box
- entity_collision_shape = new btBoxShape(to_btVector3(model()->box().max() * modelscale));
+ btBoxShape *boxshape = new btBoxShape(to_btVector3(model()->box().max() * modelscale));
+ shapes().push_back(boxshape);
+ myshape = boxshape;
}
+
} else {
- entity_collision_shape = new btSphereShape(radius());
+ // use a sphere with a radius matching the entity
+ btSphereShape *sphereshape = new btSphereShape(radius());
+ shapes().push_back(sphereshape);
+ myshape = 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);
// create physics body
- entity_body_info = new btRigidBody::btRigidBodyConstructionInfo(0, 0, entity_collision_shape, inertia);
+ btVector3 inertia(0, 0, 0);
+ entity_body_info = new btRigidBody::btRigidBodyConstructionInfo(0, 0, myshape, inertia);
entity_body = new btRigidBody(*entity_body_info);
entity_body->setActivationState(ISLAND_SLEEPING);
@@ -587,38 +638,81 @@ 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()->collisionmesh()) {
- // use collision mesh
- // dynamic entities use a btGImpactMeshShape
- btGImpactMeshShape *meshshape = new btGImpactMeshShape(model()->collisionmesh()->triangles());
+ 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());
+
+ // 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;
- btVector3 modelscalevec(modelscale, modelscale, modelscale);
- meshshape->setLocalScaling(modelscalevec);
- meshshape->updateBound();
+ } 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;
+
+ // dynamic entities use a btGImpactMeshShape
+ btGImpactMeshShape *meshshape = new btGImpactMeshShape(mesh->triangles());
+ // FIXME apply vertexgroup transformations
+ compoundshape->addChildShape(childtransform, meshshape);
+ shapes().push_back(meshshape);
+ }
+
+ btVector3 modelscalevec(modelscale, modelscale, modelscale);
+ compoundshape->setLocalScaling(modelscalevec);
+
+ shapes().push_back(compoundshape);
+ myshape = compoundshape;
+ }
- entity_collision_shape = meshshape;
} else {
// use bounding box
- entity_collision_shape = new btBoxShape(to_btVector3(model()->box().max() * modelscale));
+ btBoxShape *boxshape = new btBoxShape(to_btVector3(model()->box().max() * modelscale));
+ shapes().push_back(boxshape);
+ myshape = boxshape;
}
+
} else {
- entity_collision_shape = new btSphereShape(radius());
+ // use a sphere with a radius matching the entity
+ btSphereShape *sphereshape = new btSphereShape(radius());
+ shapes().push_back(sphereshape);
+ myshape = sphereshape;
+
}
- entity_collision_shape->setMargin(Cvar::sv_collisionmargin->value());
+ // set margin on each mesh
+ for (CollisionShapes::iterator it = shapes().begin(); it != shapes().end(); it++) {
+ (*it)->setMargin(Cvar::sv_collisionmargin->value());
+ }
+
btVector3 inertia(0, 0, 0);
if (entity_mass)
- entity_collision_shape->calculateLocalInertia(entity_mass, inertia);
+ myshape->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, entity_collision_shape, inertia);
+ entity_body_info = new btRigidBody::btRigidBodyConstructionInfo(entity_mass, entity_motionstate, myshape, inertia);
entity_body = new btRigidBody(*entity_body_info);
if (entity_mass) {
@@ -1009,37 +1103,87 @@ 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()->collisionmesh()) {
- // use collision mesh
- // dynamic entities use a btGImpactMeshShape
- btGImpactMeshShape *meshshape = new btGImpactMeshShape(model()->collisionmesh()->triangles());
+ 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());
+
+ // dynamic entities use a btGImpactMeshShape
+ btGImpactMeshShape *meshshape = new btGImpactMeshShape(mesh->triangles());
+ btVector3 modelscalevec(modelscale, modelscale, modelscale);
+ meshshape->setLocalScaling(modelscalevec);
+
+ shapes().push_back(meshshape);
+ myshape = meshshape;
+ meshshape->updateBound();
- btVector3 modelscalevec(modelscale, modelscale, modelscale);
- meshshape->setLocalScaling(modelscalevec);
- meshshape->setMargin(Cvar::sv_collisionmargin->value());
- 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();
+
+ // FIXME apply vertexgroup transformations
+ compoundshape->addChildShape(childtransform, meshshape);
+ shapes().push_back(meshshape);
+ }
+
+
+
+
+ shapes().push_back(compoundshape);
+ myshape = compoundshape;
+ }
- entity_collision_shape = meshshape;
} else {
// use bounding box
- entity_collision_shape = new btBoxShape(to_btVector3(model()->box().max() * modelscale));
+ btBoxShape *boxshape = new btBoxShape(to_btVector3(model()->box().max() * modelscale));
+ shapes().push_back(boxshape);
+ myshape = boxshape;
}
+
} else {
- entity_collision_shape = new btSphereShape(radius());
+ // use a sphere with a radius matching the entity
+ btSphereShape *sphereshape = new btSphereShape(radius());
+ shapes().push_back(sphereshape);
+ myshape = sphereshape;
+
}
+
+ // set margin on each mesh
+ for (CollisionShapes::iterator it = shapes().begin(); it != shapes().end(); it++) {
+ (*it)->setMargin(Cvar::sv_collisionmargin->value());
+ }
+
btVector3 inertia(0, 0, 0);
if (entity_mass)
- entity_collision_shape->calculateLocalInertia(entity_mass, inertia);
+ myshape->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, entity_collision_shape, inertia);
+ entity_body_info = new btRigidBody::btRigidBodyConstructionInfo(entity_mass, entity_motionstate, myshape, 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 54849b7..a356525 100644
--- a/src/core/entity.h
+++ b/src/core/entity.h
@@ -57,6 +57,9 @@ public:
/// entity menus collection typedef
typedef std::list<MenuDescription *> Menus;
+
+ /// type definition for entity bullet shapes collection
+ typedef std::list<btCollisionShape *> CollisionShapes;
/// create a new entity and add it to the registry
Entity();
@@ -164,8 +167,8 @@ public:
}
/// physics collision shape
- inline btCollisionShape *collision_shape() {
- return entity_collision_shape;
+ inline CollisionShapes collision_shapes() {
+ return entity_collision_shapes;
}
/// indicates a server-side entity
@@ -192,6 +195,11 @@ public:
inline Menus &menus() {
return entity_menus;
}
+
+ /// entity collision shapes
+ inline CollisionShapes & shapes() {
+ return entity_collision_shapes;
+ }
/// extensions
inline Extension *extension(size_t type) const {
@@ -445,9 +453,9 @@ public:
protected:
btRigidBody *entity_body;
btRigidBody::btRigidBodyConstructionInfo *entity_body_info;
- btCollisionShape *entity_collision_shape;
+ CollisionShapes entity_collision_shapes;
- // the zone the entity belongs to
+ // the zone the entity belongs to
Zone* entity_zone;
// the previous zone the entity belonged too
Zone* entity_oldzone;
diff --git a/src/core/physics.cc b/src/core/physics.cc
index 5504c50..90fb184 100644
--- a/src/core/physics.cc
+++ b/src/core/physics.cc
@@ -21,7 +21,7 @@ void Physics::init()
{
con_print << "^BInitializing physics engine..." << std::endl;
- model::CollisionMesh::init();
+ model::CollisionModel::init();
physics_configuration = new btDefaultCollisionConfiguration();
physics_dispatcher = new btCollisionDispatcher(physics_configuration);
@@ -35,7 +35,7 @@ void Physics::done()
{
con_print << "^BShutting down physics engine..." << std::endl;
- model::CollisionMesh::shutdown();
+ model::CollisionModel::shutdown();
delete physics_solver;
delete physics_dispatcher;
diff --git a/src/core/signals.cc b/src/core/signals.cc
new file mode 100644
index 0000000..f05b328
--- /dev/null
+++ b/src/core/signals.cc
@@ -0,0 +1,16 @@
+/*
+ core/signals.cc
+ This file is part of the Osirion project and is distributed under
+ the terms and conditions of the GNU General Public License version 2
+*/
+
+#include "core/signals.h"
+
+namespace core {
+
+void Signal::send(Player *sender, Player *reciever, Signals signal)
+{
+
+}
+
+} // namespace core \ No newline at end of file
diff --git a/src/core/signals.h b/src/core/signals.h
new file mode 100644
index 0000000..88841ea
--- /dev/null
+++ b/src/core/signals.h
@@ -0,0 +1,51 @@
+/*
+ core/signals.h
+ This file is part of the Osirion project and is distributed under
+ the terms of the GNU General Public License version 2
+*/
+
+#ifndef __INCLUDED_CORE_SIGNALS_H__
+#define __INCLUDED_CORE_SIGNALS_H__
+
+#include <list>
+
+#include "core/player.h"
+
+namespace core
+{
+
+/**
+ * @brief a signal is a confirmation request from one player to another.
+ */
+class Signal {
+public:
+ /// signal types
+ enum Signals {Trade = 1, Dock = 2, Chat = 3};
+
+ /// current state of a signal
+ enum State {Rejected = 0, Accepted = 1, Pending = 2};
+
+
+ /// type definition for the signal registry
+ typedef std::list<Signal*> Registry;
+
+ static void send(Player *sender, Player *receiver, Signals signal);
+
+ static void init();
+
+ static void done();
+
+ static void clear();
+
+private:
+ Signals signal_type;
+ State signal_state;
+ unsigned long signal_timestamp;
+
+ static Registry signal_registry;
+};
+
+}
+
+#endif // __INCLUDED_CORE_SIGNALS_H__
+
diff --git a/src/model/Makefile.am b/src/model/Makefile.am
index de6d902..3552392 100644
--- a/src/model/Makefile.am
+++ b/src/model/Makefile.am
@@ -6,6 +6,7 @@ noinst_LTLIBRARIES = libmodel.la
noinst_HEADERS = \
asefile.h \
collisionmesh.h \
+ collisionmodel.h \
face.h \
fragment.h \
mapfile.h \
@@ -21,6 +22,7 @@ noinst_HEADERS = \
libmodel_la_SOURCES = \
asefile.cc \
collisionmesh.cc \
+ collisionmodel.cc \
face.cc \
fragment.cc \
mapfile.cc \
diff --git a/src/model/collisionmesh.cc b/src/model/collisionmesh.cc
index 5d4505a..5d2328a 100644
--- a/src/model/collisionmesh.cc
+++ b/src/model/collisionmesh.cc
@@ -26,7 +26,7 @@ void CollisionMesh::shutdown()
void CollisionMesh::add(CollisionMesh *collisionmesh)
{
- collisionmesh_registry[collisionmesh->name()] = collisionmesh;
+ collisionmesh_registry.push_back(collisionmesh);
}
void CollisionMesh::clear()
@@ -34,26 +34,16 @@ void CollisionMesh::clear()
con_debug << " clearing collision meshes" << std::endl;
for (Registry::iterator i = collisionmesh_registry.begin(); i != collisionmesh_registry.end(); ++i) {
- delete (*i).second;
- (*i).second = 0;
+ delete (*i);
+ (*i) = 0;
}
collisionmesh_registry.clear();
}
-CollisionMesh *CollisionMesh::find(const std::string &name)
-{
- for (Registry::iterator i = collisionmesh_registry.begin(); i != collisionmesh_registry.end(); ++i) {
- if ((*i).first.compare(name) == 0)
- return (*i).second;
- }
-
- return 0;
-}
-
-CollisionMesh::CollisionMesh(const std::string &name) :
- collisionmesh_name(name)
+CollisionMesh::CollisionMesh()
{
+ collisionmesh_type = FragmentGroup::None;
collisionmesh_size = 0;
// btTriangleMesh (bool use32bitIndices=true, bool use4componentVertices=true)
collisionmesh_triangles = new btTriangleMesh(true, false);
@@ -64,6 +54,11 @@ CollisionMesh::~CollisionMesh()
delete collisionmesh_triangles;
}
+void CollisionMesh::set_type(const FragmentGroup::Type type)
+{
+ collisionmesh_type = type;
+}
+
void CollisionMesh::add_triangle(const math::Vector3f & v0, const math::Vector3f & v1, const math::Vector3f & v2)
{
collisionmesh_triangles->addTriangle(
@@ -72,7 +67,7 @@ void CollisionMesh::add_triangle(const math::Vector3f & v0, const math::Vector3f
to_btVector3(v2),
true
);
- collisionmesh_size += 1;
+ collisionmesh_size++;
}
} // namespace model
diff --git a/src/model/collisionmesh.h b/src/model/collisionmesh.h
index 9efd21a..cbd063a 100644
--- a/src/model/collisionmesh.h
+++ b/src/model/collisionmesh.h
@@ -8,6 +8,7 @@
#define __INCLUDED_MODEL_COLLISIONMESH_H__
#include "math/mathlib.h"
+#include "model/fragment.h"
#include "BulletCollision/CollisionShapes/btTriangleMesh.h"
@@ -17,23 +18,23 @@
namespace model
{
+/**
+ * @brief a collection of triangles, representing the collision geometry of a model
+ * A CollisionModel consists of a number of collisionmeshes.
+ * */
class CollisionMesh
{
public:
- /// type definition for the material registry
- typedef std::map<std::string, CollisionMesh *> Registry;
+ /// type definition for the collisionmesh registry
+ typedef std::list<CollisionMesh *> Registry;
- CollisionMesh(const std::string &name);
+ CollisionMesh();
~CollisionMesh();
/* ---- inspectors ----------------------------------------- */
- inline const std::string &name() const {
- return collisionmesh_name;
- }
-
/**
* @brief the number of triangles in the collision mesh
*/
@@ -41,10 +42,6 @@ public:
return collisionmesh_size;
}
- static bool initialized() {
- return collisionmesh_initialized;
- }
-
/**
* @brief the bullet triangle mesh object
*/
@@ -53,6 +50,11 @@ public:
}
/* ---- mutators ------------------------------------------- */
+
+ /**
+ * @brief change the group type
+ * */
+ void set_type(const FragmentGroup::Type type);
/**
* @brief add a triangle to the collision mesh
@@ -86,15 +88,20 @@ public:
*/
static void add(CollisionMesh *collisionmesh);
+
+ static bool initialized() {
+ return collisionmesh_initialized;
+ }
+
private:
/// the materials registry
static Registry collisionmesh_registry;
static bool collisionmesh_initialized;
- std::string collisionmesh_name;
size_t collisionmesh_size;
btTriangleMesh *collisionmesh_triangles;
+ FragmentGroup::Type collisionmesh_type;
};
} // namespace model
diff --git a/src/model/collisionmodel.cc b/src/model/collisionmodel.cc
new file mode 100644
index 0000000..d52c9bc
--- /dev/null
+++ b/src/model/collisionmodel.cc
@@ -0,0 +1,76 @@
+/*
+ model/collisionmodel.cc
+ This file is part of the Osirion project and is distributed under
+ the terms of the GNU General Public License version 2
+*/
+
+#include "sys/sys.h"
+#include "model/collisionmodel.h"
+
+namespace model {
+
+CollisionModel::CollisionModel(const std::string & label) :
+ collisionmodel_label(label)
+{
+
+}
+
+CollisionModel::~CollisionModel()
+{
+ // clear the list of meshes, do not delete the meshes
+ for (CollisionMeshes::iterator it = collisionmodel_meshes.begin(); it != collisionmodel_meshes.end(); it++) {
+ (*it) = 0;
+ }
+ collisionmodel_meshes.clear();
+}
+
+void CollisionModel::add_mesh(CollisionMesh *mesh)
+{
+ collisionmodel_meshes.push_back(mesh);
+}
+
+/* ---- static methods --------------------------------------------- */
+
+CollisionModel::Registry CollisionModel::collisionmodel_registry;
+
+void CollisionModel::init()
+{
+ CollisionMesh::init();
+ clear();
+}
+
+void CollisionModel::shutdown()
+{
+ clear();
+ CollisionMesh::shutdown();
+}
+
+CollisionModel *CollisionModel::find(const std::string & label)
+{
+ for (Registry::iterator it = collisionmodel_registry.begin(); it != collisionmodel_registry.end(); it++) {
+ CollisionModel *cmodel = (*it);
+ if (cmodel->label().compare(label) == 0)
+ return cmodel;
+
+ }
+ return 0;
+}
+
+void CollisionModel::clear()
+{
+ for (Registry::iterator it = collisionmodel_registry.begin(); it != collisionmodel_registry.end(); it++) {
+ CollisionModel *collisionmodel = (*it);
+ delete collisionmodel;
+ (*it) = 0;
+ }
+ collisionmodel_registry.clear();
+ con_debug << " clearing collision models" << std::endl;
+
+}
+
+void CollisionModel::add(CollisionModel *collisionmodel)
+{
+ collisionmodel_registry.push_back(collisionmodel);
+}
+
+} //namespace model \ No newline at end of file
diff --git a/src/model/collisionmodel.h b/src/model/collisionmodel.h
new file mode 100644
index 0000000..04268d2
--- /dev/null
+++ b/src/model/collisionmodel.h
@@ -0,0 +1,111 @@
+/*
+ model/collisionmodel.h
+ This file is part of the Osirion project and is distributed under
+ the terms of the GNU General Public License version 2
+*/
+
+#ifndef __INCLUDED_MODEL_COLLISIONMODEL_H__
+#define __INCLUDED_MODEL_COLLISIONMODEL_H__
+
+#include <list>
+#include <string>
+
+#include "math/mathlib.h"
+#include "model/collisionmesh.h"
+
+namespace model
+{
+
+/**
+ * @brief a container class for collision geometry
+ * The CollisionModel class holds a list of references to one or more CollisionMeshes.
+ * It is referenced by a single Model, and the static registry takes ownership of the
+ * CollisionModel instances. This is because a Model can be reloaded while the game is running,
+ * but the CollisionMeshes are tied to bullet physics and can not be reloaded on the fly.
+ * Note that the CollisionModel doesn't own its meshes either, it merely reference them.
+ * CollisionMeshes are stored in the static CollisionMesh::registry() and can be referenced
+ * by multiple CollisionModels.
+ */
+class CollisionModel
+{
+public:
+ /**
+ * @brief type definition for the CollisionModel registry
+ * */
+ typedef std::list<CollisionModel *> Registry;
+
+ /**
+ * @brief type definition for a lost of collision meshes
+ * */
+ typedef std::list<CollisionMesh *> CollisionMeshes;
+
+ /**
+ * @brief create a new collisionmodel with a give label
+ * */
+ CollisionModel(const std::string & label);
+ ~CollisionModel();
+
+ inline const std::string &label() const {
+ return collisionmodel_label;
+ }
+
+ /**
+ * @brief returns the number of meshes this collision model consists of
+ * */
+ inline const size_t size() const {
+ return collisionmodel_meshes.size();
+ }
+
+ /**
+ * @brief the collection of meshes this model consists of
+ * */
+ inline CollisionMeshes & meshes() {
+ return collisionmodel_meshes;
+ }
+
+ /**
+ * @brief add a mesh to the CollisionModel
+ * CollisionModel does not take ownership of the COllisionMesh,
+ * the mesh should be registered with the CollisionMesh::registry
+ * */
+ void add_mesh(CollisionMesh *mesh);
+
+ /**
+ * @brief initialize the CollisionModel registry
+ * init() calls clear()
+ * */
+ static void init();
+
+ /**
+ * @brief shutdown the CollisionModel registry
+ * shutdown() calls clear()
+ * */
+ static void shutdown();
+
+ /**
+ * @brief clear the CollisionModel registry and delete all CollisionModel instances it holds
+ * */
+ static void clear();
+
+ /**
+ * @brief add a CollisionModel to the registry
+ * the models label should be unique and not yet exist in the registry.
+ * */
+ static void add(CollisionModel *collisionmodel);
+
+ /**
+ * @brief search the registry for a model with a particular label, returns 0 if not found.
+ * */
+ static CollisionModel *find(const std::string & label);
+
+private:
+ std::string collisionmodel_label;
+ CollisionMeshes collisionmodel_meshes;
+
+ static Registry collisionmodel_registry;
+
+}; // class CollisionModel
+
+} // namespace model
+
+#endif // __INCLUDED_MODEL_COLLISIONMODEL_H__
diff --git a/src/model/mapfile.cc b/src/model/mapfile.cc
index 20d4c5c..92349c0 100644
--- a/src/model/mapfile.cc
+++ b/src/model/mapfile.cc
@@ -174,6 +174,8 @@ void MapFile::clear_materials()
delete(*mit).second;
}
map_materials.clear();
+
+ map_collisiontriangles.clear();
}
bool MapFile::open(std::string const & mapname)
@@ -357,12 +359,12 @@ bool MapFile::read_patchdef()
std::string word;
if (!(linestream >> word)) {
- //con_debug << "Error reading trialing line ')'" << std::endl;
+ //con_debug << "Error reading trailing line ')'" << std::endl;
return false;
}
if (word.compare(")") != 0) {
- //con_debug << "No trialing line ')'" << std::endl;
+ //con_debug << "No trailing line ')'" << std::endl;
return false;
}
}
@@ -1300,8 +1302,25 @@ void MapFile::load_fragmentgroup(Model *model, const FragmentGroup::Type class_t
}
- // add the group to the model
+ // add the vertexgroup to the model
model->add_group(group);
+
+ // add collision triangles
+ if (map_load_clip) {
+ if (map_collisiontriangles.size()) {
+ CollisionMesh *collisionmesh = new CollisionMesh();
+
+ // add clip triangles to collision mesh
+ for (TriangleList::iterator it = map_collisiontriangles.begin(); it != map_collisiontriangles.end(); it++) {
+ Triangle *triangle = (*it);
+ collisionmesh->add_triangle(triangle->v0() - translation, triangle->v1() - translation, triangle->v2() - translation);
+ }
+
+ // add the collision mesh to the collision model
+ model->collisionmodel()->add_mesh(collisionmesh);
+ }
+ }
+
}
void MapFile::unknown_value() const
@@ -1365,17 +1384,18 @@ Model * MapFile::load(std::string const &name)
float r, s;
std::string str;
- // load clip into collision mesh
- // if the model has been loaded before (e.g. on r_restart), the collision mesh won't be reloaded
- // submodel clip will not be imported
- model->set_collisionmesh(CollisionMesh::find(name));
-
- if (CollisionMesh::initialized() && !model->collisionmesh()) {
- mapfile.map_load_clip = true;
+ // load clip into collision meshes
+ // if the model has been loaded before (e.g. on r_restart), the collision model won't be reloaded
+ mapfile.map_collisionmodel = CollisionModel::find(name);
+ if (!mapfile.map_collisionmodel) {
+ mapfile.map_load_clip = true;
+ mapfile.map_collisionmodel = new CollisionModel(name);
+ CollisionModel::add(mapfile.map_collisionmodel);
} else {
mapfile.map_load_clip = false;
}
-
+ model->set_collisionmodel(mapfile.map_collisionmodel);
+
while (mapfile.getline()) {
if (mapfile.got_classname("worldspawn")) {
mapfile.clear_bbox();
@@ -1840,6 +1860,12 @@ Model * MapFile::load(std::string const &name)
delete groupdst;
}
}
+
+ /* TODO
+ *
+ * import submodel collision meshes
+ */
+
// copy light tags
for (Model::Lights::const_iterator lit = submodel_model->lights().begin(); lit != submodel_model->lights().end(); lit++) {
@@ -1921,31 +1947,22 @@ Model * MapFile::load(std::string const &name)
con_warn << mapfile.name() << " quake2 style brushes detected" << std::endl;
con_debug << " " << mapfile.name() << " " << mapfile.map_brushes << " brushes " <<
- model->model_tris_detail_count << "/" << model->model_tris_count << " detail/tris " <<
- model->model_quad_detail_count << "/" << model->model_quad_count << " detail/quads" << std::endl;
+ model->model_tris_count << " triangles " <<
+ model->model_quad_count << " quads" << std::endl;
- if (mapfile.map_load_clip) {
- if (mapfile.map_collisiontriangles.size()) {
-
- CollisionMesh *collisionmesh = new CollisionMesh(name);
-
- // add clip triangles to collision mesh
- for (TriangleList::iterator it = mapfile.map_collisiontriangles.begin(); it != mapfile.map_collisiontriangles.end(); it++) {
- Triangle *triangle = (*it);
- collisionmesh->add_triangle(triangle->v0() - map_center, triangle->v1() - map_center, triangle->v2() - map_center);
- }
-
- // TODO merge submodel collision meshes
- // seperate collision meshes for movers
-
- // register the mesh
- CollisionMesh::add(collisionmesh);
- model->set_collisionmesh(collisionmesh);
-
- con_debug << " " << mapfile.name() << " " << model->collisionmesh()->size() << " collision triangles" << std::endl;
+ if (mapfile.map_load_clip && model->collisionmodel() && model->collisionmodel()->meshes().size()) {
+ size_t collision_tris_count = 0; // total number of triangles in the collision model
+ size_t collision_mesh_count = 0; // number of meshes in the collision model
+
+ for (CollisionModel::CollisionMeshes::const_iterator cmit = model->collisionmodel()->meshes().begin();
+ cmit != model->collisionmodel()->meshes().end(); cmit++) {
+ collision_tris_count += (*cmit)->size();
+ collision_mesh_count++;
}
+
+ con_debug << " " << mapfile.name() << " collision " << collision_tris_count << " triangles " << collision_mesh_count << " meshes" << std::endl;
}
-
+
return model;
}
diff --git a/src/model/mapfile.h b/src/model/mapfile.h
index b576384..011c01d 100644
--- a/src/model/mapfile.h
+++ b/src/model/mapfile.h
@@ -184,6 +184,7 @@ private:
bool last_read_was_classend;
bool map_load_clip;
+ CollisionModel *map_collisionmodel;
unsigned int map_brushes;
unsigned int map_faces;
diff --git a/src/model/model.cc b/src/model/model.cc
index d1805df..ab89dae 100644
--- a/src/model/model.cc
+++ b/src/model/model.cc
@@ -30,7 +30,7 @@ Model::Model(const std::string & name) :
model_quad_detail_count = 0;
model_quad_count = 0;
- model_collisionmesh = 0;
+ model_collisionmodel = 0;
}
Model::~Model()
@@ -72,8 +72,8 @@ Model::~Model()
model_sounds.clear();
}
-void Model::set_collisionmesh(CollisionMesh *collisionmesh)
-{ model_collisionmesh = collisionmesh;
+void Model::set_collisionmodel(CollisionModel *collisionmodel)
+{ model_collisionmodel = collisionmodel;
}
diff --git a/src/model/model.h b/src/model/model.h
index 8e3d82d..c15213c 100644
--- a/src/model/model.h
+++ b/src/model/model.h
@@ -13,7 +13,7 @@
#include "math/mathlib.h"
-#include "model/collisionmesh.h"
+#include "model/collisionmodel.h"
#include "model/tags.h"
#include "model/fragment.h"
@@ -76,8 +76,8 @@ public:
return model_groups;
}
- inline CollisionMesh *collisionmesh() {
- return model_collisionmesh;
+ inline CollisionModel *collisionmodel() {
+ return model_collisionmodel;
}
/// list of model light tags
@@ -150,8 +150,8 @@ public:
/// set model radius
void set_radius(const float radius);
- /// set model collision mesh
- void set_collisionmesh(CollisionMesh *collisionmesh);
+ /// set collision model
+ void set_collisionmodel(CollisionModel *collisionmodel);
/// set model origin
void set_origin(const math::Vector3f &origin);
@@ -206,7 +206,7 @@ private:
Groups model_groups;
float model_radius;
static Registry model_registry;
- CollisionMesh *model_collisionmesh;
+ CollisionModel *model_collisionmodel;
};
}