From 930db4020b9af2ccd999cb3a8c980cc9d527f8cf Mon Sep 17 00:00:00 2001 From: Stijn Buys Date: Sat, 10 May 2008 10:19:16 +0000 Subject: client-side axis interpolation --- src/client/camera.cc | 26 +++++++------- src/core/clientstate.cc | 38 ++++++++++++++++++++ src/core/clientstate.h | 65 +++++++++++++++++++++++++++++++++ src/core/entity.cc | 15 +++++--- src/core/gameconnection.cc | 6 ++-- src/core/gameinterface.cc | 89 ++++++++++++++++++++++++++++++++++++++++++++++ src/math/plane3f.cc | 32 ----------------- src/math/plane3f.h | 52 --------------------------- src/model/plane.cc | 4 +++ src/model/vertexdata.cc | 0 src/model/vertexdata.h | 0 src/render/draw.cc | 39 ++++++++++---------- 12 files changed, 241 insertions(+), 125 deletions(-) create mode 100644 src/core/clientstate.cc create mode 100644 src/core/clientstate.h delete mode 100644 src/math/plane3f.cc delete mode 100644 src/math/plane3f.h create mode 100644 src/model/vertexdata.cc create mode 100644 src/model/vertexdata.h (limited to 'src') diff --git a/src/client/camera.cc b/src/client/camera.cc index 573194a..28f60c5 100644 --- a/src/client/camera.cc +++ b/src/client/camera.cc @@ -170,16 +170,16 @@ void draw(float seconds) set_mode(Track); if (core::localcontrol()->state()) { - // client prediction has not been run yet - target = core::localcontrol()->state()->previouslocation() - + (core::localcontrol()->location() - core::localcontrol()->state()->previouslocation()) * core::game()->timeoffset(); + target.assign(core::localcontrol()->state()->location()); + axis.assign(core::localcontrol()->state()->axis()); + } else { + target.assign(core::localcontrol()->location()); + axis.assign(core::localcontrol()->axis()); } - else - target = core::localcontrol()->location(); - + if (mode == Track) { - if (core::localcontrol()->model()) - target += core::localcontrol()->model()->maxbbox().x * core::localcontrol()->axis().forward(); + if (core::localcontrol()->state() && core::localcontrol()->model()) + target += core::localcontrol()->model()->maxbbox().x * core::localcontrol()->state()->axis().forward(); // make the camera swing while turning target_direction = core::localcontrol()->target_direction; @@ -194,21 +194,21 @@ void draw(float seconds) pitch_target = pitch_current - 90 * target_pitch; } else if (mode == Cockpit) { - if (core::localcontrol()->model()) - target += core::localcontrol()->model()->maxbbox().x * core::localcontrol()->axis().forward(); + if (core::localcontrol()->state() && core::localcontrol()->model()) + target += core::localcontrol()->model()->maxbbox().x * core::localcontrol()->state()->axis().forward(); } - axis.assign(core::localcontrol()->axis()); + if (mode != Cockpit) { // adjust direction d = degrees180f(yaw_current - yaw_target); - yaw_current = degrees360f( yaw_current - 2* d * seconds); + yaw_current = degrees360f( yaw_current - d * seconds); axis.change_direction(yaw_current); // adjust pitch target d = degrees180f(pitch_current - pitch_target); - pitch_current = degrees360f(pitch_current - 2* d *seconds); + pitch_current = degrees360f(pitch_current - d *seconds); axis.change_pitch(pitch_current); if (core::localcontrol()->model()) diff --git a/src/core/clientstate.cc b/src/core/clientstate.cc new file mode 100644 index 0000000..b34b16a --- /dev/null +++ b/src/core/clientstate.cc @@ -0,0 +1,38 @@ +/* + core/clientstate.cc + This file is part of the Osirion project and is distributed under + the terms of the GNU General Public License version 2 +*/ + +#include "core/clientstate.h" + +namespace core { + +ClientState::ClientState() +{ + state_visible = false; + state_detailvisible = false; + state_fuzz = math::randomf(); +} + +ClientState::ClientState(Entity *entity) +{ + state_visible = false; + state_detailvisible = false; + state_fuzz = math::randomf(); + assign(entity); +} + +ClientState::~ClientState() +{} + +void ClientState::assign(Entity * entity) +{ + state_location.assign(entity->location()); + state_axis.assign(entity->axis()); + + state_previouslocation.assign(entity->location()); + state_previousaxis.assign(entity->axis()); +} + +} diff --git a/src/core/clientstate.h b/src/core/clientstate.h new file mode 100644 index 0000000..915f96f --- /dev/null +++ b/src/core/clientstate.h @@ -0,0 +1,65 @@ +/* + core/clientstate.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_CLIENTSTATE_H__ +#define __INCLUDED_CORE_CLIENTSTATE_H__ + +#include "math/axis.h" +#include "math/mathlib.h" +#include "math/vector3f.h" + +namespace core +{ + class ClientState; +} + +#include "core/entity.h" + +namespace core +{ + +/// Entity client render state +class ClientState { +public: + ClientState(); + ClientState(Entity *entity); + + ~ClientState(); + + inline math::Vector3f const & location() { return state_location; } + + inline math::Vector3f const & previouslocation() { return state_previouslocation; } + + inline math::Axis const & previousaxis() { return state_previousaxis; } + + inline math::Axis const & axis() { return state_axis; } + + inline bool visible() const { return state_visible; } + + inline bool detailvisible() const { return state_detailvisible; } + + /// client render fuzz factor + inline float fuzz() const { return state_fuzz; }; + + /// assign the content of an entity + void assign(Entity *entity); + + math::Vector3f state_location; + math::Axis state_axis; + + math::Vector3f state_previouslocation; + math::Axis state_previousaxis; + + bool state_visible; + bool state_detailvisible; + + float state_fuzz; +}; + +} + +#endif // __INCLUDED_CORE_CLIENTSTATE_H__ + diff --git a/src/core/entity.cc b/src/core/entity.cc index cc956b0..46231d8 100644 --- a/src/core/entity.cc +++ b/src/core/entity.cc @@ -115,7 +115,11 @@ Entity::Entity(std::istream & is) is >> entity_color; is >> s; // shape is >> entity_radius; - is >> entity_axis; + + is >> entity_axis[0]; + is >> entity_axis[1]; + entity_axis[2] = math::crossproduct(entity_axis.forward(), entity_axis.left()); + entity_shape = (Shape) s ; char c; @@ -135,7 +139,9 @@ Entity::Entity(std::istream & is) entity_destroyed = false; entity_dirty = false; + // this entity is created clientside entity_clientstate = 0; + add(this, entity_id); } @@ -156,7 +162,8 @@ void Entity::serialize(std::ostream & os) const << entity_color << " " << entity_shape << " " << entity_radius << " " - << entity_axis << " " + << entity_axis.forward() << " " + << entity_axis.left() << " " << "\"" << entity_name << "\" " << "\"" << entity_modelname << "\""; } @@ -232,16 +239,16 @@ void EntityDynamic::serialize_server_update(std::ostream & os) const os << entity_location << " "; os << entity_axis.forward() << " "; os << entity_axis.left() << " "; - os << entity_axis.up() << " "; os << entity_speed; } void EntityDynamic::recieve_server_update(std::istream &is) { is >> entity_location; + // axis up vector is the crossproduct of forward and left is >> entity_axis[0]; is >> entity_axis[1]; - is >> entity_axis[2]; + entity_axis[2] = math::crossproduct(entity_axis.forward(), entity_axis.left()); is >> entity_speed; } diff --git a/src/core/gameconnection.cc b/src/core/gameconnection.cc index b5ac27d..c86a0ae 100644 --- a/src/core/gameconnection.cc +++ b/src/core/gameconnection.cc @@ -102,9 +102,7 @@ void GameConnection::frame(float seconds) if (connection_frametime < f) { return; } - } - - connection_frametime = 0; + } if (localcontrol() && localcontrol()->dirty()) { std::ostringstream netmsg; @@ -129,6 +127,8 @@ void GameConnection::frame(float seconds) } connection_network->transmit(); + + connection_frametime = 0; } } diff --git a/src/core/gameinterface.cc b/src/core/gameinterface.cc index d1bc1c3..99f884d 100644 --- a/src/core/gameinterface.cc +++ b/src/core/gameinterface.cc @@ -120,6 +120,95 @@ void GameInterface::update_clientstate(float seconds) if (game_clientframetime > game_serverframetime) game_clientframetime = game_serverframetime; + + std::map::iterator it; + for (it=Entity::registry.begin(); it != Entity::registry.end(); it++) { + + Entity *entity = (*it).second; + + // update client state + if (!entity->state()) { + entity->entity_clientstate = new core::ClientState(entity); + } + + if (!(entity->flags() & core::Entity::Static)) { + + // clientstate location + entity->state()->state_location = entity->state()->previouslocation() + + (entity->location() - entity->state()->previouslocation()) * core::game()->timeoffset(); + + if (core::game()->clientframetime() < core::game()->serverframetime()) { + + // http://local.wasp.uwa.edu.au/~pbourke/geometry/planeline/ + float side; + float u; + + // clientstate axis: direction + + side = entity->state()->axis().left().x * entity->axis().forward().x + + entity->state()->axis().left().y * entity->axis().forward().y + + entity->state()->axis().left().z * entity->axis().forward().z; + + if (fabs(side) < 0.9999) { + // project entity->axis().forward() into the plane with entity->state()->axis().up() normal + math::Vector3f const & n = entity->state()->axis().up(); + math::Vector3f p(entity->axis().forward()); + u = p[0]*n[0] + p[1]*n[1] + p[2]*n[2] / (-n[0]*n[0] - n[1]*n[1] - n[2] * n[2]); + p = entity->axis().forward() + u * n; + + float cosangle = math::dotproduct(p, entity->state()->axis().forward()); + float angle = acos(cosangle) * 180.0f / M_PI; + angle = math::sgnf(side) * angle * seconds / + (core::game()->serverframetime() - core::game()->clientframetime()); + + if (angle > 0.001) + entity->state()->state_axis.change_direction(angle); + } + + // clientstate axis: pitch + side = entity->state()->axis().forward().x * entity->axis().up().x + + entity->state()->axis().forward().y * entity->axis().up().y + + entity->state()->axis().forward().z * entity->axis().up().z; + + if (fabs(side) < 0.9999) { + // project entity->axis().up() into the plane with entity->state()->axis()->left() normal + math::Vector3f const & n = entity->state()->axis().left(); + math::Vector3f p(entity->axis().up()); + u = p[0]*n[0] + p[1]*n[1] + p[2]*n[2] / (-n[0]*n[0] - n[1]*n[1] - n[2] * n[2]); + p = entity->axis().up() + u * n; + + float cosangle = math::dotproduct(p, entity->state()->axis().up()); + float angle = acos(cosangle) * 180.0f / M_PI; + angle = math::sgnf(side) * angle * seconds / + (core::game()->serverframetime() - core::game()->clientframetime()); + + if (angle > 0.001) + entity->state()->state_axis.change_pitch(-angle); + } + + + /* + // clientstate axis: roll + side = entity->state()->axis().left().x * entity->axis().up().x + + entity->state()->axis().left().y * entity->axis().up().y + + entity->state()->axis().left().z * entity->axis().up().z; + + if (fabs(side) < 0.9999) { + float cosangle = math::dotproduct(entity->axis().up(), entity->state()->axis().up()); + float angle = acos(cosangle) * 180.0f / M_PI; + angle = math::sgnf(side) * angle * seconds / + (core::game()->serverframetime() - core::game()->clientframetime()); + + if (angle > 0.001) + entity->state()->state_axis.change_roll(-angle); + } + */ + + } + + } + + } } float GameInterface::timeoffset() { diff --git a/src/math/plane3f.cc b/src/math/plane3f.cc deleted file mode 100644 index 232bc98..0000000 --- a/src/math/plane3f.cc +++ /dev/null @@ -1,32 +0,0 @@ -/* - math/plane3f.cc - This file is part of the Osirion project and is distributed under - the terms of the GNU General Public License version 2 -*/ - -#include "math/plane3f.h" -#include - -namespace math -{ - -Plane3f::Plane3f(Vector3f const & point0, Vector3f const &point1, Vector3f const &point2) -{ - plane_point[0] = point0; - plane_point[1] = point1; - plane_point[2] = point2; - - plane_normal = crossproduct((plane_point[1] - plane_point[0]) , (plane_point[2] - plane_point[0]) ); - pd = -1 * (plane_normal.x * plane_point[0].x + plane_normal.y * plane_point[0].y + plane_normal.z * plane_point[0].z); -} - -Plane3f::Plane3f(Plane3f const & other) -{ - for (size_t i=0; i < 3; i++) - this->plane_point[i] = other.plane_point[i]; - - plane_normal = crossproduct((plane_point[1] - plane_point[0]) , (plane_point[2] - plane_point[0]) ); - pd = -1 * (plane_normal.x * plane_point[0].x + plane_normal.y * plane_point[0].y + plane_normal.z * plane_point[0].z); -} - -} diff --git a/src/math/plane3f.h b/src/math/plane3f.h deleted file mode 100644 index 02037d2..0000000 --- a/src/math/plane3f.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - math/plane3f.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_MATH_PLANE3F_H__ -#define __INCLUDED_MATH_PLANE3F_H__ - -#include "math/vector3f.h" - -namespace math -{ - -/** @brief A class representing a plane in 3d space - * all points p(x, y, z) on the plane satisfy the general equation - * x*a() + y*b() + z*c() + d() = 0 - */ -class Plane3f -{ -public: - /// a plane defined by 3 points in space - Plane3f(Vector3f const & point0, Vector3f const &point1, Vector3f const &point2); - /// copy constructor - Plane3f(Plane3f const & other); - - /// normal of the plane, not normalized to lenght 1 - inline Vector3f const & normal() const { return plane_normal; } - /// the points defining the plane. - /// @param i 0 <= i < 3 - inline Vector3f const & point(size_t i) const { return plane_point[i]; } - /// plane texture - inline std::string & texture() { return plane_texture; } - /// first parameter of the general equation - inline float a() const { return plane_normal[0]; } - /// second parameter of the general equation - inline float b() const { return plane_normal[1]; } - /// third param of the general equation - inline float c() const { return plane_normal[2]; } - /// fourth parameter of the general equation - inline float d() const { return pd; } - -private: - Vector3f plane_point[3]; - Vector3f plane_normal; - std::string plane_texture; - float pd; -}; - -} - -#endif // __INCLUDED_MATH_PLANE3F_H__ diff --git a/src/model/plane.cc b/src/model/plane.cc index 2d548ce..761918f 100644 --- a/src/model/plane.cc +++ b/src/model/plane.cc @@ -12,6 +12,10 @@ namespace model { using math::Vector3f; +/* + * all points p(x, y, z) on the plane satisfy the general equation + * x*a() + y*b() + z*c() + d() = 0 + */ Plane::Plane(Vector3f const & point0, Vector3f const &point1, Vector3f const &point2) { diff --git a/src/model/vertexdata.cc b/src/model/vertexdata.cc new file mode 100644 index 0000000..e69de29 diff --git a/src/model/vertexdata.h b/src/model/vertexdata.h new file mode 100644 index 0000000..e69de29 diff --git a/src/render/draw.cc b/src/render/draw.cc index 26655e0..7a780bf 100644 --- a/src/render/draw.cc +++ b/src/render/draw.cc @@ -174,7 +174,7 @@ void draw_model_evertex(core::Entity *entity) Stats::tris += count/3; } } - +/* void draw_model_engines(core::EntityControlable *entity) { model::Model *model = entity->model(); @@ -228,11 +228,12 @@ void draw_model_shield(core::EntityControlable *entity) //gl::pop(); } +*/ /* ----- Render passes --------------------------------------------- */ /* calculate entity visibility */ -void pass_prepare() +void pass_prepare(float seconds) { std::map::iterator it; for (it=core::Entity::registry.begin(); it != core::Entity::registry.end(); it++) { @@ -257,21 +258,17 @@ void pass_prepare() } } - // update client state if (!entity->state()) { - entity->entity_clientstate = new core::ClientState(); - entity->state()->assign(entity); + entity->entity_clientstate = new core::ClientState(entity); } - entity->state()->state_visible = false; - entity->state()->state_detailvisible = false; - if (!flag_is_set(entity->flags(), core::Entity::Static)) { - entity->state()->state_location = entity->state()->previouslocation() + - (entity->location() - entity->state()->previouslocation()) * core::game()->timeoffset(); - } + entity->state()->state_visible = true; + entity->state()->state_detailvisible = false; // calculate visibility for entities with models if (entity->model()) { + + entity->state()->state_visible = false; float dq = math::distancesquared(camera_eye, entity->location()); if (dq <= drawfxdistance*drawfxdistance*entity->model()->radius()) { @@ -285,9 +282,6 @@ void pass_prepare() } } else { - - entity->state()->state_visible = true; - if ((entity->type() == core::Entity::Globe) && flag_is_set(entity->flags(), core::Entity::Bright)) { // bright globes set level light @@ -298,7 +292,8 @@ void pass_prepare() glLightfv(GL_LIGHT0, GL_POSITION, light_position); } - } + } + } } @@ -313,7 +308,7 @@ void draw_pass_default() if (!entity->model()) { gl::push(); gl::translate(entity->state()->location()); - gl::multmatrix(entity->axis()); + gl::multmatrix(entity->state()->axis()); if (flag_is_set(entity->flags(), core::Entity::Bright)) { gl::disable(GL_LIGHTING); @@ -356,7 +351,7 @@ void draw_pass_model_vertex() if (entity->model() && entity->state()->visible()) { gl::push(); gl::translate(entity->state()->location()); - gl::multmatrix(entity->axis()); + gl::multmatrix(entity->state()->axis()); draw_model_vertex(entity); @@ -376,7 +371,7 @@ void draw_pass_model_evertex() if (entity->model() && entity->state()->visible()) { gl::push(); gl::translate(entity->state()->location()); - gl::multmatrix(entity->axis()); + gl::multmatrix(entity->state()->axis()); draw_model_evertex(entity); @@ -386,6 +381,7 @@ void draw_pass_model_evertex() } /* Draw model shields */ +/* void draw_pass_model_shields() { for (std::map::iterator it=core::Entity::registry.begin(); it != core::Entity::registry.end(); it++) { @@ -398,7 +394,7 @@ void draw_pass_model_shields() { if (entity->type() == core::Entity::Controlable) { gl::push(); gl::translate(entity->state()->location()); - gl::multmatrix(entity->axis()); + gl::multmatrix(entity->state()->axis()); draw_model_shield((core::EntityControlable *)entity); gl::pop(); @@ -407,6 +403,7 @@ void draw_pass_model_shields() { } } } +*/ /* draw model lights and engines */ void draw_pass_model_fx() @@ -518,7 +515,7 @@ void draw_pass_model_corona() for (std::map::iterator it=core::Entity::registry.begin(); it != core::Entity::registry.end(); it++) { core::Entity *entity = (*it).second; - if (entity->state()->visible() && (entity->shape() != core::Entity::Sphere)) { + if ((entity->shape() != core::Entity::Sphere) && entity->state() && entity->state()->visible()) { gl::push(); gl::translate(entity->state()->location()); math::Color color = entity->color(); @@ -582,7 +579,7 @@ void draw(math::Axis const &axis, math::Vector3f const &eye, math::Vector3f cons camera_eye.assign(eye); camera_axis.assign(axis); - pass_prepare(); + pass_prepare(seconds); gl::enable(GL_DEPTH_TEST); // enable depth buffer writing gl::enable(GL_CULL_FACE); // enable culling -- cgit v1.2.3