From 91d3a0352088611d3b78d3344b7a2bf2d4955a0a Mon Sep 17 00:00:00 2001 From: Stijn Buys Date: Tue, 6 May 2008 21:07:11 +0000 Subject: client-side frame interpolation: frames and timers --- MODELS | 59 ++++++++++++++++++++++++++------- README | 47 ++++++++++++++++++++++++-- src/client/camera.cc | 4 +-- src/client/input.cc | 8 +++-- src/client/view.cc | 23 +++++++------ src/core/Makefile.am | 4 +-- src/core/entity.cc | 14 +++----- src/core/entity.h | 30 ++++++++--------- src/core/gameconnection.cc | 4 +++ src/core/gameinterface.cc | 48 ++++++++++++++++++++++++++- src/core/gameinterface.h | 28 ++++++++++++++++ src/core/gameserver.cc | 19 ++++++++++- src/core/gameserver.h | 1 + src/core/netconnection.cc | 26 ++++++++++----- src/core/stats.h | 1 - src/game/game.cc | 1 + src/math/functions.h | 6 ++++ src/render/draw.cc | 82 +++++++++++++++++++++++++--------------------- 18 files changed, 300 insertions(+), 105 deletions(-) diff --git a/MODELS b/MODELS index 6f84ff1..43130df 100644 --- a/MODELS +++ b/MODELS @@ -86,7 +86,7 @@ Detail brushes is close enough to the camera. When it is further away, only structural brushes will be rendered. - This means that any objects that could only been seen from close by + This means that any object that could only been seen from close by should be made from detail brushes. This has one improtant implication: if you show the structural brushes @@ -107,21 +107,58 @@ Textures will be ignored on load. The use of common/clip is reserved for future use. At the moment they will be ignored as well. - At the time of writing, texture names are hardcoded in src/core/model.cc + At the time of writing, texture names are hardcoded + in src/model/mapfile.cc -Entities +Lights + + Unlike quake, light entities are not used to add lighting information + to the level but to add point lights to a model. Adding a light will + render a light flare texture in the corresponding location. + + The flare value indicates what texture will be used to draw the light. + The flare value maps to bitmaps/fx/flare??.tga. The default flare is 0. + + The light value is used to determine the size of the flare. The engine + default is 100, resulting in rather large flares. + + The default color is white, but the color can be set through radiant's + color menu (K key). If the entity option (spawnflag 2) is set, the + color value will be ignored and the light will be rendered with the + color of the entity it is attached to. + + The strobe option (spawnflag 1) will create a blinking light. A number + of options can be set to manipulate the flashing behaviour. By default + a strobe light will be half a second on, half a second off. + + The frequency value changes the number of flashes per second. + + The offset value changes the moment the light will be on. Offset is + measured in seconds. - Add an info_engine entity to add an engine exhaust to a ship model. + The time value sets the fraction of the time the light will be on. + The default is 0.5. + + Lights will only be rendered if the model is close enough. + + I also came across this usefull information: + http://en.wikipedia.org/wiki/Starboard + + In short, the green light should be on the right side, the red light + on the left side. + +Engines + + Add a target_engine entity to add an engine exhaust to a ship model. An engine exhaust always points to the rear (negative X-axis). + + An engine is rendered as a pulsating light flare. The size of the flare + can be set through the radius value. The default engine radius is 100. + Engines will only be rendered if the model is close enough. - target_turret and target_cannon are not yet implemented. +Other entities -Lights + target_cockpit, target_turret and target_cannon are not yet implemented. - Support for light entities is very basic, the end result is far - from pleasing for the eye. They do have their use, since lights - are only rendered if the model is close enough. The engine does support - coloured lights (with the 'K' menu in GtkRadiant). - The strobe option (spawnflag 1) will create a flashing light. diff --git a/README b/README index 2a345c5..b08720f 100644 --- a/README +++ b/README @@ -86,6 +86,23 @@ Console functions cl_color 1.0 1.0 0.0 connect +Statistics + + To activate statistics, set the draw_stats variable to 1: + + draw_stats 1 + + This will draw the following statistics on the right side + of the screen: + + fps frames per second + tris number of triangles drawn + quads number of quads drawn + tx network upstream traffic, in kb + rx network downstream traffic, in kb + + The fps counter will not show values above 9999. + Configuration Variables marked with the 'A' flag will be archived, their value @@ -93,16 +110,42 @@ Configuration server reads its configuration from server.ini, the client will use client.ini. + If you delete these files, the default configuration will be restored. + Dedicated server By default, the dedicated server will accept incoming connections - on UDP port 8042. There is no server console. + on UDP port 8042. There is no server console. If you have trouble connecting, try editing the server configuration file ~/.osirion/base/server.ini and change the net_server setting to the server's actual IP address. The default listening port can be altered by changing the net_port setting. +Command line + + Both the client and the dedicated server can parse command line + options. Any console command can be added to the command line with + sign. + + To start a client and connect to a remote server: + + src/osirion +connect remote.server.org + + To start a client and create a new network game: + + src/osirion +set sv_private 1 +connect +join + + To start a dedicated server and set the server framerate to 30 frames per + second: + + src/osiriond +set sv_framerate 30 + + Note: + + Setting variable values from the command line can result in weird values being + written to client.cfg and server.cfg. If you run into problems, check those + files or delete them. + Note for windows32 users On windows32, the game uses the 'home' subdirectory as your personal @@ -201,7 +244,7 @@ Acknowledgements License - The Osirion Project is distributed under + The Osirion Project is distributed under the terms and conditions of the GNU General Public License version 2. diff --git a/src/client/camera.cc b/src/client/camera.cc index 8144781..808ff7e 100644 --- a/src/client/camera.cc +++ b/src/client/camera.cc @@ -179,8 +179,8 @@ void draw(float seconds) target_direction = core::localcontrol()->target_direction; pitch_target = core::localcontrol()->target_pitch; - yaw_target = - 45 * target_direction; - pitch_target = pitch_track -45 * target_pitch; + yaw_target = - 25 * target_direction; + pitch_target = pitch_track - 25 * target_pitch; } else if (mode == Free) { diff --git a/src/client/input.cc b/src/client/input.cc index 17ca724..fa23c1a 100644 --- a/src/client/input.cc +++ b/src/client/input.cc @@ -12,6 +12,7 @@ #include "client/camera.h" #include "client/keyboard.h" #include "client/video.h" +#include "math/functions.h" #include "render/text.h" #include "SDL/SDL.h" @@ -231,7 +232,7 @@ void frame(float seconds) break; case SDL_KEYDOWN: if (event.key.keysym.sym == '`' || event.key.keysym.sym == '~') { - last_control = 0; + //last_control = 0; console::toggle(); if (console::visible() && chat::visible()) @@ -298,8 +299,9 @@ void frame(float seconds) local_direction = mouse_direction; local_pitch = mouse_pitch; } else if (camera::mode == camera::Free) { - camera::set_direction(-mouse_direction); - camera::set_pitch(-mouse_pitch); + // squared values to smoothen camera movement + camera::set_direction( -mouse_direction * math::absf(mouse_direction)); + camera::set_pitch(-mouse_pitch * math::absf(mouse_pitch)); } } else { diff --git a/src/client/view.cc b/src/client/view.cc index 660930b..488a1cb 100644 --- a/src/client/view.cc +++ b/src/client/view.cc @@ -132,19 +132,18 @@ void draw_status() gl::color(1.0f, 1.0f, 1.0f, 1.0f); std::stringstream status; - int hours = (int) sys::time() / 3600; - int minutes = (int)(sys::time() - 3600*hours) / 60; - int seconds = (int)(sys::time() - 3600*hours - 60 *minutes); - status << "clock " << std::setfill('0') << std::setw(2) << hours << ":" - << std::setfill('0') << std::setw(2) << minutes << ":" - << std::setfill('0') << std::setw(2) << seconds; - - minutes = (int) floorf(core::application()->time() / 60.0f); - seconds = (int) floorf(core::application()->time() - (float) minutes* 60.0f); - - status << " time " << std::setfill('0') << std::setw(2) << minutes << ":" << std::setfill('0') << std::setw(2) << seconds; + /* + int minutes = (int) floorf(core::application()->time() / 60.0f); + int seconds = (int) floorf(core::application()->time() - (float) minutes* 60.0f); + */ + + if (core::game()) { + int minutes = (int) floorf(core::game()->clientframetime() / 60.0f); + int seconds = (int) floorf( core::game()->clientframetime() - (float) minutes* 60.0f); - draw_text(CHARWIDTH, 4, status); + status << " time " << std::setfill('0') << std::setw(2) << minutes << ":" << std::setfill('0') << std::setw(2) << seconds; + draw_text(CHARWIDTH, 4, status); + } // print stats if desired if (draw_stats && draw_stats->value()) { diff --git a/src/core/Makefile.am b/src/core/Makefile.am index 7c18362..efa4e7b 100644 --- a/src/core/Makefile.am +++ b/src/core/Makefile.am @@ -1,7 +1,7 @@ METASOURCES = AUTO INCLUDES = -I$(top_srcdir)/src -libcore_la_SOURCES = application.cc commandbuffer.cc core.cc cvar.cc entity.cc \ +libcore_la_SOURCES = application.cc commandbuffer.cc clientstate.cc core.cc cvar.cc entity.cc \ func.cc gameconnection.cc gameinterface.cc gameserver.cc module.cc netclient.cc \ netconnection.cc netserver.cc player.cc stats.cc libcore_la_LDFLAGS = -avoid-version -no-undefined @@ -9,7 +9,7 @@ libcore_la_LIBADD = $(top_builddir)/src/filesystem/libfilesystem.la \ $(top_builddir)/src/math/libmath.la $(top_builddir)/src/sys/libsys.la $(top_builddir)/src/model/libmodel.la noinst_LTLIBRARIES = libcore.la -noinst_HEADERS = application.h commandbuffer.h core.h cvar.h entity.h func.h \ +noinst_HEADERS = application.h commandbuffer.h clientstate.h core.h cvar.h entity.h func.h \ gameconnection.h gameinterface.h gameserver.h module.h net.h \ netclient.h netconnection.h netserver.cc player.h stats.h diff --git a/src/core/entity.cc b/src/core/entity.cc index d2fef43..cc956b0 100644 --- a/src/core/entity.cc +++ b/src/core/entity.cc @@ -7,13 +7,9 @@ #include #include -namespace core -{ - class Entity; -} - #include "sys/sys.h" #include "core/entity.h" +#include "core/cvar.h" namespace core { @@ -101,8 +97,7 @@ Entity::Entity(unsigned int flags) : entity_modelname.clear(); entity_name.clear(); - entity_renderstate = 0; - entity_renderfuzz = math::randomf(); + entity_clientstate = 0; add(this); } @@ -140,14 +135,15 @@ Entity::Entity(std::istream & is) entity_destroyed = false; entity_dirty = false; - entity_renderstate = 0; - entity_renderfuzz = math::randomf(); + entity_clientstate = 0; add(this, entity_id); } Entity::~Entity() { + if (entity_clientstate) + delete entity_clientstate; } void Entity::serialize(std::ostream & os) const diff --git a/src/core/entity.h b/src/core/entity.h index 1e80435..287157b 100644 --- a/src/core/entity.h +++ b/src/core/entity.h @@ -7,6 +7,10 @@ #ifndef __INCLUDED_CORE_ENTITY_H__ #define __INCLUDED_CORE_ENTITY_H__ +#include +#include +#include + #include "model/model.h" #include "math/axis.h" #include "math/mathlib.h" @@ -19,12 +23,9 @@ class EntityControlable; } +#include "core/clientstate.h" #include "core/player.h" -#include -#include -#include - namespace core { @@ -33,11 +34,11 @@ class Entity { public: /// Entity flags + /** + * entities with the Static flag set will not get client-side interpolation + */ enum Flags {Static=1, Solid=2, Bright=4}; - /// Entity render state flags - enum State {InRange=1, InCloseRange=2}; - /// Entity type constants enum Type {Default=0, Dynamic=1, Controlable=2, Globe=3}; @@ -64,12 +65,6 @@ public: /// core type id virtual inline unsigned int type() const { return Default; } - /// client state - inline unsigned int state() const { return entity_renderstate; } - - /// client render fuzz factor - inline float fuzz() const { return entity_renderfuzz; }; - /// entity flags inline unsigned int flags() const { return entity_flags; } @@ -79,6 +74,9 @@ public: /// entity model name inline std::string const & modelname() { return entity_modelname; } + /// entity client render state + inline ClientState * state() { return entity_clientstate; } + /// pointer to the model, is used client-side inline model::Model * model() { return entity_model; } @@ -158,8 +156,10 @@ public: bool entity_created; bool entity_destroyed; - unsigned int entity_renderstate; - float entity_renderfuzz; + /// timestamp when entity data was received from the server + float entity_servertimestamp; + + ClientState *entity_clientstate; private: /// add an entity to the registry diff --git a/src/core/gameconnection.cc b/src/core/gameconnection.cc index 4f410d5..baf0967 100644 --- a/src/core/gameconnection.cc +++ b/src/core/gameconnection.cc @@ -88,6 +88,10 @@ void GameConnection::frame(float seconds) return; } + if (!Cvar::sv_dedicated->value()) { + update_clientstate(); + } + connection_frametime += seconds; float f = 0; diff --git a/src/core/gameinterface.cc b/src/core/gameinterface.cc index 5789592..8d351a0 100644 --- a/src/core/gameinterface.cc +++ b/src/core/gameinterface.cc @@ -91,7 +91,53 @@ void GameInterface::clear() // remove all models model::Model::clear(); + + game_previousframetime = 0; + game_serverframetime = 0; + game_clientframetime = 0; + game_timestep = 0; + game_frames = 0; } +void GameInterface::reset_clientstate(float servertime) +{ + game_timestep = (servertime - game_serverframetime); + + if (game_timestep < 0) + game_timestep = 0; + + game_previousframetime = game_serverframetime; + game_serverframetime = servertime; + game_clientframetime = game_previousframetime; + + std::map::iterator it; + for (it=core::Entity::registry.begin(); it != core::Entity::registry.end(); it++) { + + core::Entity *entity = (*it).second; + + if (entity->state() && !(entity->flags() & Entity::Static)) + entity->state()->assign(entity); + } + + game_frames = 0; +} -} // namespace core +void GameInterface::update_clientstate() +{ + game_frames++; + game_clientframetime += game_timestep; + + if (game_clientframetime > game_serverframetime) + game_clientframetime = game_serverframetime; +} + +float GameInterface::timeoffset() { + float d = game_serverframetime - game_previousframetime; + if (d < 0) + d = 1; + float t = game_serverframetime - game_clientframetime; + + return t/d; +} + +} diff --git a/src/core/gameinterface.h b/src/core/gameinterface.h index e38c061..2324bb5 100644 --- a/src/core/gameinterface.h +++ b/src/core/gameinterface.h @@ -27,6 +27,20 @@ public: /// return the local player inline Player *localplayer() { return &game_localplayer; } + /// return the server time of the last received server frame + inline float serverframetime() const { return game_serverframetime; } + + /// return the server time of the previous received server frame + inline float previousframetime() const { return game_serverframetime; } + + /// return the server time of the previous received server frame + inline float clientframetime() const { return game_clientframetime; } + + /// client frame time between previousframetime and serverframetime, from 0 - 1 + float timeoffset(); + + inline float timestep() const { return game_timestep; } + /*----- virtual inspectors --------------------------------------- */ /// returns true if the game server can run a time frime @@ -37,6 +51,12 @@ public: /// clear all game variables, game functions and entities void clear(); + /// reset the client state + void reset_clientstate(float servertime); + + /// update the client state timers + void update_clientstate(); + /*----- virtual mutators ------------------------------------------ */ /// run one game time frame @@ -46,6 +66,14 @@ public: protected: /// the local player static Player game_localplayer; + + float game_serverframetime; + float game_previousframetime; + + float game_timestep; + float game_clientframetime; + + unsigned int game_frames; }; /// global local player instance diff --git a/src/core/gameserver.cc b/src/core/gameserver.cc index ae2b3a9..3c126fc 100644 --- a/src/core/gameserver.cc +++ b/src/core/gameserver.cc @@ -32,6 +32,7 @@ GameServer::GameServer() : GameInterface() con_print << "Initializing game server...\n"; server_instance = this; server_network = 0; + server_time = 0; server_frametime = 0.0f; server_maxplayerid = 1; @@ -243,6 +244,8 @@ void GameServer::frame(float seconds) if (error()) return; + server_time += seconds; + // process incoming network messages if (server_network) { server_network->receive(); @@ -256,6 +259,10 @@ void GameServer::frame(float seconds) if (localplayer()->dirty()) localplayer()->update_info(); + if (!Cvar::sv_dedicated->value()) { + update_clientstate(); + } + server_frametime += seconds; if ((Cvar::sv_dedicated->value() || Cvar::sv_private->value())) { @@ -266,7 +273,12 @@ void GameServer::frame(float seconds) } } } - + + // copy the previous entity state to the client state + if (!Cvar::sv_dedicated->value()) { + reset_clientstate(server_time); + } + // run a time frame on each entity std::map::iterator it; for (it=Entity::registry.begin(); it != Entity::registry.end(); it++) { @@ -292,6 +304,11 @@ void GameServer::frame(float seconds) server_network->transmit(); // TODO - start server frame + std::ostringstream framehdr; + framehdr.str(""); + framehdr << "frame " << server_time << "\n"; + server_network->broadcast(framehdr.str()); + std::map::iterator it; for (it=Entity::registry.begin(); it != Entity::registry.end(); it++) { Entity *entity = (*it).second; diff --git a/src/core/gameserver.h b/src/core/gameserver.h index 907d69e..4fb9c47 100644 --- a/src/core/gameserver.h +++ b/src/core/gameserver.h @@ -75,6 +75,7 @@ private: unsigned int server_maxplayerid; float server_frametime; + float server_time; }; inline GameServer *server() { return GameServer::instance(); } diff --git a/src/core/netconnection.cc b/src/core/netconnection.cc index dda339c..55480d2 100644 --- a/src/core/netconnection.cc +++ b/src/core/netconnection.cc @@ -267,6 +267,7 @@ void NetConnection::transmit() * msg public * die * ent + * frame * sup * pif */ @@ -305,6 +306,12 @@ void NetConnection::parse_incoming_message(const std::string & message) } else if (command == "ping") { + } else if (command == "frame") { + float timestamp; + if (msgstream >> timestamp) { + game()->reset_clientstate(timestamp); + } + } else if (command == "die") { unsigned int id; if (msgstream >> id) { @@ -339,14 +346,17 @@ void NetConnection::parse_incoming_message(const std::string & message) } } } else if (command == "sup") { - unsigned int id; - if (msgstream >> id) { - //con_debug << "Received update entity id " << id << std::endl; - Entity *entity = Entity::find(id); - if (!entity) { - con_warn << "Update for unknown entity " << id << std::endl; - } else - entity->recieve_server_update(msgstream); + if (connection_state == Connected) + { + unsigned int id; + if (msgstream >> id) { + //con_debug << "Received update entity id " << id << std::endl; + Entity *entity = Entity::find(id); + if (!entity) { + con_warn << "Update for unknown entity " << id << std::endl; + } else + entity->recieve_server_update(msgstream); + } } } else if (command == "pif") { diff --git a/src/core/stats.h b/src/core/stats.h index 44153ec..9d90fdc 100644 --- a/src/core/stats.h +++ b/src/core/stats.h @@ -7,7 +7,6 @@ #ifndef __INCLUDED_CORE_STATS_H__ #define __INCLUDED_CORE_STATS_H__ -/// this namespace contains the network subsystem namespace core { diff --git a/src/game/game.cc b/src/game/game.cc index 31b99c2..3bdcb8e 100644 --- a/src/game/game.cc +++ b/src/game/game.cc @@ -190,6 +190,7 @@ void Game::init() } else if (worldini.got_section("entity")) { entity = new core::Entity(); + entity->entity_flags += core::Entity::Static; } else if (worldini.got_section()) { con_warn << worldini.name() << " unknown section '" << worldini.section() << "' at line " << worldini.line() << std::endl; diff --git a/src/math/functions.h b/src/math/functions.h index b44a4e5..16de778 100644 --- a/src/math/functions.h +++ b/src/math/functions.h @@ -55,6 +55,12 @@ inline void clamp(float &value, float min=0.0f, float max=1.0f) if (value < min) value = min; else if (value > max) value = max; } +/// return the absolute value of a float +inline float absf(float f) +{ + if (f >0) return f; else return -f; +} + } // namespace math #endif // __INCLUDED_MATH_FUNCTIONS_H__ diff --git a/src/render/draw.cc b/src/render/draw.cc index 1017746..b0671de 100644 --- a/src/render/draw.cc +++ b/src/render/draw.cc @@ -44,19 +44,6 @@ math::Axis camera_axis; float angle = 0; - -/* ----- Distance test functions ----------------------------------- */ - -inline bool test_draw_distance(core::Entity *entity) -{ - return (entity->entity_renderstate > 0); -} - -inline bool test_drawfx_distance(core::Entity *entity) -{ - return ((entity->entity_renderstate & core::Entity::InCloseRange) == core::Entity::InCloseRange); -} - // function to test flags inline bool flag_is_set(unsigned int spawnflags, unsigned int flag) { return ((spawnflags & flag) == flag); @@ -162,7 +149,7 @@ void draw_entity_axis(core::Entity *entity) void draw_model_vertex(core::Entity *entity) { size_t count = entity->model()->vertex_structural(); - if (test_drawfx_distance(entity)) + if (entity->state()->detailvisible()) count += entity->model()->vertex_detail(); // draw model vertices @@ -176,7 +163,7 @@ void draw_model_vertex(core::Entity *entity) void draw_model_evertex(core::Entity *entity) { size_t count = entity->model()->evertex_structural(); - if (test_drawfx_distance(entity)) + if (entity->state()->detailvisible()) count += entity->model()->evertex_detail(); // draw model evertices @@ -245,15 +232,19 @@ void draw_model_shield(core::EntityControlable *entity) /* ----- Render passes --------------------------------------------- */ /* calculate entity visibility */ -void pass_visibility() +void pass_prepare() { std::map::iterator it; for (it=core::Entity::registry.begin(); it != core::Entity::registry.end(); it++) { core::Entity *entity = (*it).second; - entity->entity_renderstate = 0; + if (!entity->state()) { + entity->entity_clientstate = new core::ClientState(); + } + entity->state()->state_visible = false; + entity->state()->state_detailvisible = false; - // load entity models if necessary + // load entity models and light flare textures if (!entity->model() && entity->modelname().size()) { entity->entity_model = model::Model::load(entity->modelname()); @@ -271,25 +262,40 @@ void pass_visibility() } } - if (entity->model()) { + // update client state + if (entity->state() && flag_is_set(entity->flags(), core::Entity::Static)) { + entity->state()->state_location = entity->state()->previouslocation() + + (entity->location() - entity->state()->previouslocation()) * core::game()->timeoffset(); + } + + // calculate visibility for entities with models + if (entity->model()) { float dq = math::distancesquared(camera_eye, entity->location()); if (dq <= drawfxdistance*drawfxdistance*entity->model()->radius()) { - // entites withint drawfxdistance - entity->entity_renderstate = core::Entity::InCloseRange; + // entites within drawing distance + entity->state()->state_visible = true; + entity->state()->state_detailvisible = true; } else if (dq <= drawdistance*drawdistance*entity->model()->radius()) { // entities within drawdistance - entity->entity_renderstate = core::Entity::InRange; + entity->state()->state_visible = true; + entity->state()->state_detailvisible = false; } - } else if ((entity->type() == core::Entity::Globe) && flag_is_set(entity->flags(), core::Entity::Bright)) { - // bright globes set level light - GLfloat light_position[4]; - for (size_t i=0; i <3; i++) - light_position[i] = entity->location()[i]; - light_position[3] = 1.0f; + } else { - glLightfv(GL_LIGHT0, GL_POSITION, light_position); + entity->state()->state_visible = true; + + if ((entity->type() == core::Entity::Globe) && flag_is_set(entity->flags(), core::Entity::Bright)) { + + // bright globes set level light + GLfloat light_position[4]; + for (size_t i=0; i <3; i++) + light_position[i] = entity->location()[i]; + light_position[3] = 1.0f; + + glLightfv(GL_LIGHT0, GL_POSITION, light_position); + } } } } @@ -345,7 +351,7 @@ void draw_pass_model_vertex() for (it=core::Entity::registry.begin(); it != core::Entity::registry.end(); it++) { core::Entity *entity = (*it).second; - if (test_draw_distance(entity)) { + if (entity->model() && entity->state()->visible()) { gl::push(); gl::translate(entity->location()); gl::multmatrix(entity->axis()); @@ -365,7 +371,7 @@ void draw_pass_model_evertex() core::Entity *entity = (*it).second; - if (test_draw_distance(entity)) { + if (entity->model() && entity->state()->visible()) { gl::push(); gl::translate(entity->location()); gl::multmatrix(entity->axis()); @@ -384,7 +390,7 @@ void draw_pass_model_shields() { core::Entity *entity = (*it).second; - if (test_drawfx_distance(entity)) { + if (entity->model() && entity->state()->detailvisible()) { if (entity->type() == core::Entity::Controlable) { @@ -415,7 +421,7 @@ void draw_pass_model_fx() for (std::map::iterator it=core::Entity::registry.begin(); it != core::Entity::registry.end(); it++) { core::Entity *entity = (*it).second; - if (test_drawfx_distance(entity)) { + if (entity->model() && entity->state()->detailvisible()) { // draw model lights for (std::list::iterator lit = entity->model()->model_light.begin(); lit != entity->model()->model_light.end(); lit++) { @@ -423,7 +429,7 @@ void draw_pass_model_fx() // strobe frequency t = 1.0f; if ((*lit)->strobe()) - t = (core::application()->time() + entity->fuzz() + (*lit)->offset()) * (*lit)->frequency(); + t = (core::application()->time() + entity->state()->fuzz() + (*lit)->offset()) * (*lit)->frequency(); if (!(*lit)->strobe() || (( t - floorf(t)) <= (*lit)->time())) { math::Vector3f location = entity->location() + (entity->axis() * (*lit)->location()); @@ -469,7 +475,7 @@ void draw_pass_model_fx() float u = static_cast(entity)->thrust(); - t = entity->fuzz() + core::application()->time() * 4; + t = entity->state()->fuzz() + core::application()->time() * 4; t = t - floorf(t); if (t > 0.5) @@ -510,7 +516,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 (test_draw_distance(entity)) { + if (entity->state()->visible() && (entity->shape() != core::Entity::Sphere)) { gl::push(); gl::translate(entity->location()); math::Color color = entity->color(); @@ -574,7 +580,7 @@ void draw(math::Axis const &axis, math::Vector3f const &eye, math::Vector3f cons camera_eye.assign(eye); camera_axis.assign(axis); - pass_visibility(); + pass_prepare(); gl::enable(GL_DEPTH_TEST); // enable depth buffer writing gl::enable(GL_CULL_FACE); // enable culling @@ -618,7 +624,7 @@ void draw(math::Axis const &axis, math::Vector3f const &eye, math::Vector3f cons gl::enable(GL_LIGHTING); gl::enable(GL_RESCALE_NORMAL); - draw_pass_model_corona(); // draw entity radius and star corona + draw_pass_model_corona(); // draw entity radius glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_NORMAL_ARRAY); -- cgit v1.2.3