Project::OSiRiON - Git repositories
Project::OSiRiON
News . About . Screenshots . Downloads . Forum . Wiki . Tracker . Git
summaryrefslogtreecommitdiff
path: root/src/core
diff options
context:
space:
mode:
Diffstat (limited to 'src/core')
-rw-r--r--src/core/Makefile.am73
-rw-r--r--src/core/entity.cc127
-rw-r--r--src/core/entity.h78
-rw-r--r--src/core/gameserver.cc9
-rw-r--r--src/core/physics.cc54
-rw-r--r--src/core/physics.h53
-rw-r--r--src/core/zone.cc36
-rw-r--r--src/core/zone.h9
8 files changed, 402 insertions, 37 deletions
diff --git a/src/core/Makefile.am b/src/core/Makefile.am
index 6085085..7155f86 100644
--- a/src/core/Makefile.am
+++ b/src/core/Makefile.am
@@ -1,17 +1,72 @@
METASOURCES = AUTO
INCLUDES = -I$(top_srcdir)/src
-libcore_la_SOURCES = application.cc commandbuffer.cc core.cc cvar.cc \
- descriptions.cc entity.cc extension.cc func.cc gameconnection.cc gameinterface.cc \
- gameserver.cc info.cc item.cc inventory.cc label.cc loader.cc module.cc netclient.cc \
- netconnection.cc netplayer.cc netserver.cc parser.cc player.cc stats.cc timer.cc zone.cc
+noinst_LTLIBRARIES = libcore.la
+
libcore_la_LDFLAGS = -avoid-version -no-undefined
+
libcore_la_LIBADD = $(top_builddir)/src/model/libmodel.la \
$(top_builddir)/src/filesystem/libfilesystem.la $(top_builddir)/src/math/libmath.la $(top_builddir)/src/sys/libsys.la \
$(top_builddir)/src/auxiliary/libauxiliary.la
-noinst_LTLIBRARIES = libcore.la
-noinst_HEADERS = application.h commandbuffer.h core.h cvar.h entity.h func.h \
- gameconnection.h gameinterface.h gameserver.h label.h message.h module.h net.h netclient.h \
- netconnection.h netserver.h player.h range.h stats.h timer.h parser.h descriptions.h \
- extension.h loader.h info.h item.h inventory.h zone.h
+
+libcore_la_SOURCES = \
+ application.cc \
+ commandbuffer.cc \
+ core.cc \
+ cvar.cc \
+ descriptions.cc \
+ entity.cc \
+ extension.cc \
+ func.cc \
+ gameconnection.cc \
+ gameinterface.cc \
+ gameserver.cc \
+ info.cc \
+ inventory.cc \
+ item.cc \
+ label.cc \
+ loader.cc \
+ module.cc \
+ netclient.cc \
+ netconnection.cc \
+ netplayer.cc \
+ netserver.cc \
+ parser.cc \
+ physics.cc \
+ player.cc \
+ stats.cc \
+ timer.cc \
+ zone.cc
+
+noinst_HEADERS = \
+ application.h \
+ commandbuffer.h \
+ core.h \
+ cvar.h \
+ descriptions.h \
+ entity.h \
+ extension.h \
+ func.h \
+ gameconnection.h \
+ gameinterface.h \
+ gameserver.h \
+ info.h \
+ inventory.h \
+ item.h \
+ label.h \
+ loader.h \
+ message.h \
+ module.h \
+ netclient.h \
+ netconnection.h \
+ net.h \
+ netplayer.h \
+ netserver.h \
+ parser.h \
+ physics.h \
+ player.h \
+ range.h \
+ stats.h \
+ timer.h \
+ zone.h
diff --git a/src/core/entity.cc b/src/core/entity.cc
index ba79424..8a7976f 100644
--- a/src/core/entity.cc
+++ b/src/core/entity.cc
@@ -15,6 +15,8 @@
#include "core/application.h"
#include "core/gameinterface.h"
+#include "BulletCollision/CollisionShapes/btBoxShape.h"
+
namespace core
{
@@ -141,7 +143,12 @@ Entity::Entity() :
entity_flags = 0;
entity_moduletypeid = 0;
+ entity_model = 0;
+ entity_body = 0;
+ entity_collision_shape = 0;
+
entity_speed = 0.0f;
+ entity_mass = 0.0f;
entity_radius = 0.5f;
entity_shape = Diamond;
@@ -150,8 +157,6 @@ Entity::Entity() :
entity_destroyed = false;
entity_dirty = false;
- entity_model = 0;
-
entity_zone = 0;
entity_oldzone = 0;
entity_visible = true;
@@ -175,7 +180,11 @@ Entity::Entity(std::istream & is)
entity_visible = true;
entity_model = 0;
+ entity_body = 0;
+ entity_collision_shape = 0;
+
entity_speed = 0.0f;
+ entity_mass = 0.0f;
entity_created = true;
entity_destroyed = false;
@@ -209,6 +218,12 @@ Entity::~Entity()
if (entity_zone)
entity_zone->remove(this);
+
+ if (entity_collision_shape)
+ delete entity_collision_shape;
+
+ if (entity_body)
+ delete entity_body;
}
void Entity::die()
@@ -229,6 +244,34 @@ void Entity::clear_updates()
}
}
+// reset physics state
+void Entity::reset()
+{
+ if (!entity_body) {
+ if (entity_collision_shape ) {
+ delete entity_collision_shape ;
+ entity_collision_shape = 0;
+ }
+
+ if (model()) {
+ entity_collision_shape = new btBoxShape(to_btVector3(model()->maxbbox()));
+ } else {
+ entity_collision_shape = new btSphereShape(radius());
+ }
+
+ btVector3 inertia(0, 0, 0);
+ entity_body = new btRigidBody(0.0f, 0, entity_collision_shape, inertia);
+ }
+
+ btTransform t;
+ t.setIdentity();
+ t.setOrigin(to_btVector3(location()));
+ t.setBasis(to_btMatrix3x3(axis()));
+
+ entity_body->setWorldTransform(t);
+ set_dirty();
+}
+
void Entity::set_info(Info *info)
{
entity_info = info;
@@ -260,8 +303,9 @@ void Entity::set_zone(Zone *zone)
entity_zone = zone;
entity_dirty = true;
- if (entity_zone)
+ if (entity_zone) {
entity_zone->add(this);
+ }
}
void Entity::set_model(model::Model *model)
@@ -460,16 +504,21 @@ EntityDynamic::EntityDynamic() : Entity()
{
entity_state = Normal;
entity_timer = 0;
+
+ entity_motionstate = new btDefaultMotionState();
}
EntityDynamic::EntityDynamic(std::istream & is) : Entity(is)
{
entity_state = Normal;
entity_timer = 0;
+ entity_motionstate = 0;
}
EntityDynamic::~EntityDynamic()
{
+ if (entity_motionstate)
+ delete entity_motionstate;
}
void EntityDynamic::set_state(int state)
@@ -480,17 +529,66 @@ void EntityDynamic::set_state(int state)
}
}
+// reset physics state
+void EntityDynamic::reset()
+{
+ assert(entity_motionstate);
+
+ // construct physics body if necessary
+ if (!entity_body) {
+ if (entity_collision_shape ) {
+ delete entity_collision_shape ;
+ entity_collision_shape = 0;
+ }
+
+ if (model()) {
+ entity_collision_shape = new btBoxShape(to_btVector3(model()->maxbbox()));
+ } else {
+ entity_collision_shape = new btSphereShape(radius());
+ }
+
+ btVector3 inertia(0, 0, 0);
+ entity_collision_shape->calculateLocalInertia(entity_mass, inertia);
+ entity_body = new btRigidBody(entity_mass, entity_motionstate, entity_collision_shape, inertia);
+ }
+
+ // transfer entity location to motion state
+ btTransform t;
+ t.setIdentity();
+ t.setOrigin(to_btVector3(location()));
+ t.setBasis(to_btMatrix3x3(axis()));
+ entity_body->setWorldTransform(t);
+ if (zone())
+ zone()->physics()->synchronizeSingleMotionState(entity_body);
+
+ set_dirty();
+}
+
void EntityDynamic::frame(float seconds)
{
if ((flags() & Static) == Static)
return;
- if (entity_speed == 0)
- return;
-
- get_location() += axis().forward() * entity_speed * seconds;
-
- set_dirty();
+ // transfer bullet state to entity state
+ // FIXME disable physics when docked
+ if (entity_body && entity_motionstate) {
+
+ // this makes sure an update is sent if speed goes to 0 in the next step
+ if (entity_speed > 0) {
+ set_dirty();
+ }
+
+ btTransform t;
+ entity_motionstate->getWorldTransform(t);
+ get_location().assign(t.getOrigin());
+ get_axis().assign(t.getBasis());
+
+ entity_speed = (float) entity_body->getLinearVelocity().length();
+
+ if (entity_speed > 0) {
+ set_dirty();
+ }
+ }
}
void EntityDynamic::serialize_server_create(std::ostream & os) const
@@ -755,6 +853,17 @@ void EntityControlable::set_strafe(float strafe)
}
}
+void EntityControlable::set_vstrafe(float vstrafe)
+{
+ if ((flags() & Static) == Static)
+ return;
+
+ if (target_vstrafe != vstrafe) {
+ target_vstrafe = vstrafe;
+ set_dirty();
+ }
+}
+
void EntityControlable::set_afterburner(float afterburner)
{
if ((flags() & Static) == Static)
diff --git a/src/core/entity.h b/src/core/entity.h
index 3ba2b0c..2719040 100644
--- a/src/core/entity.h
+++ b/src/core/entity.h
@@ -28,6 +28,7 @@ class EntityControlable;
#include "core/descriptions.h"
#include "core/inventory.h"
#include "core/label.h"
+#include "core/physics.h"
#include "core/player.h"
#include "core/zone.h"
@@ -146,11 +147,30 @@ public:
return entity_radius;
}
- /// current speed of the entity in game units per second
+ /**
+ * @brief current speed of the entity in game units per second
+ * For a normal entity, speed is always 0. Use the EntityDynamic
+ * and EntityControlable classes to create moving entities
+ */
inline const float speed() const {
return entity_speed;
}
+ /// mass of the entity
+ inline const float mass() const {
+ return entity_mass;
+ }
+
+ /// physics body
+ inline btRigidBody *body() {
+ return entity_body;
+ }
+
+ /// collision shape
+ inline btCollisionShape *collision_shape() {
+ return entity_collision_shape;
+ }
+
/// indicates a server-side entity
inline const bool serverside() const {
return entity_serverside;
@@ -234,11 +254,6 @@ public:
*/
virtual void set_zone(Zone *zone);
- /// current speed of the entity in game units per second
- inline void set_speed(const float speed) {
- entity_speed = speed;
- }
-
/// set visibility
inline void set_visible(const bool visible = true) {
entity_visible = visible;
@@ -259,10 +274,11 @@ public:
inline void set_radius(const float radius) {
entity_radius = radius;
}
-
-/* ---- actors ---------------------------------------------------- */
+
+ /* ---- actors ---------------------------------------------------- */
/// called when the entity received a docking request
+ // FIXME move docking functions to game
virtual void dock(Entity *entity);
/// set flags
@@ -275,6 +291,11 @@ public:
entity_flags &= ~flag;
}
+ /**
+ * @brief reset the physics state
+ */
+ virtual void reset();
+
/// add an entity menu
void add_menu(MenuDescription *menu);
@@ -318,7 +339,6 @@ public:
/**
* @brief mutable reference to the secondary color
*/
-
inline math::Color& get_color_second() {
return entity_color_second;
}
@@ -387,7 +407,7 @@ public:
/* entity_ variables can be set by the module */
- /// speed of the entity
+ float entity_mass;
float entity_speed;
Shape entity_shape;
unsigned int entity_moduletypeid;
@@ -398,8 +418,11 @@ public:
/// timestamp when entity data was received from the server
float entity_servertimestamp;
-private:
+protected:
+ btRigidBody *entity_body;
+ btCollisionShape *entity_collision_shape;
+private:
unsigned int entity_id;
unsigned int entity_flags;
@@ -430,7 +453,7 @@ private:
Info* entity_info;
Extension* entity_extension[4];
-
+
static Registry entity_registry;
static size_t entity_nextid;
@@ -466,6 +489,27 @@ public:
return entity_timer;
}
+ inline btMotionState *motionstate() {
+ return entity_motionstate;
+ }
+
+ /*----- mutators -------------------------------------------------- */
+
+ /// mass of the entity
+ inline void set_mass(const float mass) {
+ entity_mass = mass;
+ }
+
+ /// current speed of the entity in game units per second
+ inline void set_speed(const float speed) {
+ entity_speed = speed;
+ }
+
+ /**
+ * @brief reset the physics state
+ */
+ virtual void reset();
+
/*----- serializers ----------------------------------------------- */
/// serialize the entity to a stream
@@ -501,6 +545,9 @@ public:
protected:
float entity_timer;
int entity_state;
+
+ btMotionState *entity_motionstate;
+
};
@@ -577,7 +624,10 @@ public:
void set_roll(float roll);
/// set target strafe
- void set_strafe(float strage);
+ void set_strafe(float strafe);
+
+ /// set target vertical strafe
+ void set_vstrafe(float vstrafe);
/// set afterburner/reverse
void set_afterburner(float afterburner);
@@ -621,6 +671,8 @@ protected:
float target_afterburner;
float target_strafe;
+
+ float target_vstrafe;
float entity_movement;
diff --git a/src/core/gameserver.cc b/src/core/gameserver.cc
index 31c6d42..597de33 100644
--- a/src/core/gameserver.cc
+++ b/src/core/gameserver.cc
@@ -14,6 +14,7 @@
#include "core/gameserver.h"
#include "core/loader.h"
#include "core/parser.h"
+#include "core/physics.h"
#include "core/netserver.h"
#include "filesystem/filesystem.h"
#include "sys/sys.h"
@@ -130,6 +131,8 @@ GameServer::GameServer() : GameInterface()
Parser::init();
+ Physics::init();
+
server_module = Loader::init();
if (!server_module) {
@@ -228,8 +231,10 @@ GameServer::~GameServer()
Func::remove("time");
Func::remove("who");
+ Physics::done();
+
Parser::done();
-
+
server_instance = 0;
}
@@ -490,6 +495,8 @@ void GameServer::frame(unsigned long timestamp)
update_clientstate();
}*/
+ Physics::frame(timestamp);
+
if ((Cvar::sv_dedicated->value() || Cvar::sv_private->value())) {
if (core::Cvar::sv_framerate->value()) {
float f = 1000.0f / core::Cvar::sv_framerate->value();
diff --git a/src/core/physics.cc b/src/core/physics.cc
new file mode 100644
index 0000000..a8577b3
--- /dev/null
+++ b/src/core/physics.cc
@@ -0,0 +1,54 @@
+/*
+ core/physics.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/physics.h"
+#include "core/zone.h"
+
+namespace core {
+
+btDefaultCollisionConfiguration *Physics::physics_configuration;
+btCollisionDispatcher *Physics::physics_dispatcher;
+btSequentialImpulseConstraintSolver *Physics::physics_solver;
+unsigned long Physics::physics_timestamp;
+
+void Physics::init()
+{
+ con_print << "^BInitializing physics engine..." << std::endl;
+
+ physics_configuration = new btDefaultCollisionConfiguration();
+ physics_dispatcher = new btCollisionDispatcher(physics_configuration);
+ physics_solver = new btSequentialImpulseConstraintSolver;
+
+ physics_timestamp = 0;
+}
+
+void Physics::done()
+{
+ con_print << "^Bshutting down physics engine..." << std::endl;
+ delete physics_solver;
+ delete physics_dispatcher;
+ delete physics_configuration;
+
+ physics_configuration = 0;
+ physics_dispatcher = 0;
+ physics_solver = 0;
+}
+
+void Physics::frame(const unsigned long timestamp)
+{
+ if (!timestamp)
+ return;
+
+ const float seconds = (float) (timestamp - physics_timestamp) / 1000.0f;
+
+ for (core::Zone::Registry::iterator it = core::Zone::registry().begin(); it != core::Zone::registry().end(); it++) {
+ (*it).second->physics()->stepSimulation(seconds);
+ }
+
+ physics_timestamp = timestamp;
+}
+
+} // namespace core \ No newline at end of file
diff --git a/src/core/physics.h b/src/core/physics.h
new file mode 100644
index 0000000..e565403
--- /dev/null
+++ b/src/core/physics.h
@@ -0,0 +1,53 @@
+/*
+ core/physics.h
+ This file is part of the Osirion project and is distributed under
+ the terms and conditions of the GNU General Public License version 2
+*/
+
+#ifndef __INCLUDED_CORE_PHYSICS_H__
+#define __INCLUDED_CORE_PHYSICS_H__
+
+#include "sys/sys.h"
+#include "math/vector3f.h"
+#include "math/axis.h"
+
+#include "btBulletDynamicsCommon.h"
+#include "BulletCollision/CollisionShapes/btTriangleMesh.h"
+#include "BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h"
+#include "BulletCollision/Gimpact/btGImpactShape.h"
+
+namespace core
+{
+
+class Physics {
+public:
+ static void init();
+
+ static void done();
+
+ static void frame(const unsigned long timestamp);
+
+ inline static btDefaultCollisionConfiguration *configuration() {
+ return physics_configuration;
+ }
+
+ inline static btCollisionDispatcher *dispatcher() {
+ return physics_dispatcher;
+ }
+
+ inline static btSequentialImpulseConstraintSolver *solver() {
+ return physics_solver;
+ }
+
+private:
+ static btDefaultCollisionConfiguration *physics_configuration;
+ static btCollisionDispatcher *physics_dispatcher;
+ static btSequentialImpulseConstraintSolver *physics_solver;
+
+ static unsigned long physics_timestamp;
+};
+
+} // namespace core
+
+#endif // __INCLUDED_CORE_PHYSICS_H__
+
diff --git a/src/core/zone.cc b/src/core/zone.cc
index 3791b93..8a8c056 100644
--- a/src/core/zone.cc
+++ b/src/core/zone.cc
@@ -116,27 +116,46 @@ void Zone ::clear()
}
/* ---- class Zone ------------------------------------------------- */
-Zone::Zone(std::string const & label)
+Zone::Zone(std::string const & label) : Label(label)
{
- zone_id = 0;
- zone_sky.clear();
+ zone_id = 0;
zone_defaultview = 0;
- set_label(label);
+ btVector3 worldAabbMin(-10000, -10000, -10000);
+ btVector3 worldAabbMax(10000, 10000, 10000);
+ const int maxProxies = 1024;
+
+ zone_bullet_cache = new btAxisSweep3(worldAabbMin, worldAabbMax, maxProxies);
+ zone_bullet_world = new btDiscreteDynamicsWorld(Physics::dispatcher(), zone_bullet_cache, Physics::solver(), Physics::configuration());
+
+ // disable gravity
+ zone_bullet_world->setGravity(btVector3(0.0f, 0.0f, 0.0f));
+
}
-Zone::Zone(std::istream & is)
+Zone::Zone(std::istream & is) : Label()
{
zone_id = 0;
+ zone_defaultview = 0;
+ // client side does not setup a bullet physics environment
+ zone_bullet_cache = 0;
+ zone_bullet_world = 0;
receive_server_update(is);
}
Zone::~Zone()
{
for (Content::iterator it = zone_content.begin(); it != zone_content.end(); it++) {
+ (*it) = 0;
}
zone_content.clear();
+
+ if (zone_bullet_world)
+ delete zone_bullet_world;
+
+ if (zone_bullet_cache)
+ delete zone_bullet_cache;
}
void Zone::print()
@@ -153,12 +172,19 @@ void Zone::print()
void Zone::add(Entity *entity)
{
zone_content.push_back(entity);
+ if (physics() && entity->body()) {
+ physics()->addRigidBody(entity->body());
+ entity->reset();
+ }
}
void Zone::remove(Entity *entity)
{
for (Content::iterator it = zone_content.begin(); it != zone_content.end(); it++) {
if ((*it) == entity) {
+ if (physics() && entity->body()) {
+ physics()->removeRigidBody(entity->body());
+ }
zone_content.erase(it);
return;
}
diff --git a/src/core/zone.h b/src/core/zone.h
index 38a9298..f040939 100644
--- a/src/core/zone.h
+++ b/src/core/zone.h
@@ -19,6 +19,7 @@ class Zone;
}
#include "core/entity.h"
+#include "core/physics.h"
namespace core
{
@@ -140,6 +141,11 @@ public:
/// remove an entity from this zone
void remove(Entity *entity);
+ /// physics world for this zone
+ inline btDiscreteDynamicsWorld *physics() {
+ return zone_bullet_world;
+ }
+
private:
unsigned int zone_id;
@@ -149,6 +155,9 @@ private:
static Registry zone_registry;
Entity *zone_defaultview;
+
+ btAxisSweep3 *zone_bullet_cache;
+ btDiscreteDynamicsWorld *zone_bullet_world;
};
}