Project::OSiRiON - Git repositories
Project::OSiRiON
News . About . Screenshots . Downloads . Forum . Wiki . Tracker . Git
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStijn Buys <ingar@osirion.org>2008-05-06 21:07:11 +0000
committerStijn Buys <ingar@osirion.org>2008-05-06 21:07:11 +0000
commit91d3a0352088611d3b78d3344b7a2bf2d4955a0a (patch)
tree74c0a6adf15ae15aa144f66f20272c1fd58a7db3
parent8fefc1d995083f0d4a9873f216ccc6e15688d0a9 (diff)
client-side frame interpolation: frames and timers
-rw-r--r--MODELS59
-rw-r--r--README47
-rw-r--r--src/client/camera.cc4
-rw-r--r--src/client/input.cc8
-rw-r--r--src/client/view.cc23
-rw-r--r--src/core/Makefile.am4
-rw-r--r--src/core/entity.cc14
-rw-r--r--src/core/entity.h30
-rw-r--r--src/core/gameconnection.cc4
-rw-r--r--src/core/gameinterface.cc48
-rw-r--r--src/core/gameinterface.h28
-rw-r--r--src/core/gameserver.cc19
-rw-r--r--src/core/gameserver.h1
-rw-r--r--src/core/netconnection.cc26
-rw-r--r--src/core/stats.h1
-rw-r--r--src/game/game.cc1
-rw-r--r--src/math/functions.h6
-rw-r--r--src/render/draw.cc82
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 <vector>
#include <iomanip>
-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 <iostream>
+#include <string>
+#include <map>
+
#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 <iostream>
-#include <string>
-#include <map>
-
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<unsigned int, core::Entity *>::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<unsigned int, Entity *>::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<unsigned int, Entity *>::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 <name> <text>
* 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<unsigned int, core::Entity *>::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<unsigned int, core::Entity *>::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<model::Light *>::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<core::EntityControlable *>(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<unsigned int, core::Entity *>::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);