diff options
Diffstat (limited to 'src/core')
-rw-r--r-- | src/core/Makefile.am | 73 | ||||
-rw-r--r-- | src/core/entity.cc | 127 | ||||
-rw-r--r-- | src/core/entity.h | 78 | ||||
-rw-r--r-- | src/core/gameserver.cc | 9 | ||||
-rw-r--r-- | src/core/physics.cc | 54 | ||||
-rw-r--r-- | src/core/physics.h | 53 | ||||
-rw-r--r-- | src/core/zone.cc | 36 | ||||
-rw-r--r-- | src/core/zone.h | 9 |
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; }; } |