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-11-15 19:24:55 +0000
committerStijn Buys <ingar@osirion.org>2008-11-15 19:24:55 +0000
commit28ba97bdd8fb6ca352dc49dba01a66bd155ad523 (patch)
treeeb4abd0505eb842e15201783529814bda1ae6e76
parent1f0dbeeabdffff096908473168898c5fa63bcff0 (diff)
entity extensions
-rw-r--r--src/audio/audio.cc2
-rw-r--r--src/client/Makefile.am10
-rw-r--r--src/client/client.cc15
-rw-r--r--src/client/client.h17
-rw-r--r--src/client/clientext.cc23
-rw-r--r--src/client/clientext.h30
-rw-r--r--src/client/soundext.cc147
-rw-r--r--src/client/soundext.h49
-rw-r--r--src/client/targets.cc108
-rw-r--r--src/client/view.cc31
-rw-r--r--src/core/Makefile.am12
-rw-r--r--src/core/application.cc6
-rw-r--r--src/core/application.h3
-rw-r--r--src/core/clientstate.cc96
-rw-r--r--src/core/clientstate.h95
-rw-r--r--src/core/entity.cc22
-rw-r--r--src/core/entity.h14
-rw-r--r--src/core/extension.cc29
-rw-r--r--src/core/extension.h42
-rw-r--r--src/core/gameconnection.cc2
-rw-r--r--src/core/gameinterface.cc94
-rw-r--r--src/core/gameinterface.h7
-rw-r--r--src/core/gameserver.cc12
-rw-r--r--src/core/netconnection.cc2
-rw-r--r--src/model/model.h6
-rw-r--r--src/render/Makefile.am7
-rw-r--r--src/render/camera.cc23
-rw-r--r--src/render/draw.cc225
-rw-r--r--src/render/dust.cc4
-rw-r--r--src/render/render.cc8
-rw-r--r--src/render/render.h7
-rw-r--r--src/render/renderext.cc114
-rw-r--r--src/render/renderext.h45
33 files changed, 696 insertions, 611 deletions
diff --git a/src/audio/audio.cc b/src/audio/audio.cc
index ca30590..84c7e0e 100644
--- a/src/audio/audio.cc
+++ b/src/audio/audio.cc
@@ -58,7 +58,7 @@ void init()
void reset()
{
- con_print << "^BReloading audio..." << std::endl;
+ con_print << "^BInitializing audio..." << std::endl;
Sources::reset();
Buffers::reset();
diff --git a/src/client/Makefile.am b/src/client/Makefile.am
index c855ad8..1d015a3 100644
--- a/src/client/Makefile.am
+++ b/src/client/Makefile.am
@@ -7,12 +7,12 @@ else
noinst_LTLIBRARIES = libclient.la
endif
-libclient_la_SOURCES = action.cc chat.cc client.cc input.cc joystick.cc key.cc \
- keyboard.cc notifications.cc targets.cc video.cc view.cc
+libclient_la_SOURCES = action.cc chat.cc client.cc clientext.cc input.cc joystick.cc key.cc \
+ keyboard.cc notifications.cc soundext.cc targets.cc video.cc view.cc
libclient_la_CFLAGS = $(LIBSDL_CFLAGS) $(GL_CFLAGS)
libclient_la_LDFLAGS = -avoid-version -no-undefined $(GL_LIBS) $(LIBSDL_LIBS)
-noinst_HEADERS = action.h chat.h client.h input.h joystick.h key.h keyboard.h \
- notifications.h targets.h video.h view.h
-libclient_la_LIBADD = $(top_builddir)/src/core/libcore.la \
+noinst_HEADERS = action.h chat.h client.h clientext.h input.h joystick.h key.h keyboard.h \
+ notifications.h soundext.h targets.h video.h view.h
+libclient_la_LIBADD = $(top_builddir)/src/core/libcore.la $(top_builddir)/src/audio/libaudio.la \
$(top_builddir)/src/render/librender.la $(top_builddir)/src/ui/libui.la
diff --git a/src/client/client.cc b/src/client/client.cc
index 42ee5a0..061f29b 100644
--- a/src/client/client.cc
+++ b/src/client/client.cc
@@ -309,16 +309,6 @@ void Client::notify_message(const core::Message::Channel channel, const std::str
con_print << message << std::endl;
}
-/* FIXME
-
- these notifications are hacks and need to be fixed
-*/
-
-void Client::notify_remove_sound(size_t source)
-{
- audio::Sources::remove(source);
-}
-
//--- engine functions --------------------------------------------
void Client::func_snd_restart(std::string const &args)
@@ -326,8 +316,9 @@ void Client::func_snd_restart(std::string const &args)
// unload entity sounds
for (core::Entity::Registry::iterator it = core::Entity::registry().begin(); it != core::Entity::registry().end(); it++) {
core::Entity *entity = (*it).second;
- if (entity->state())
- entity->state()->clearsound();
+
+ if (ext_sound(entity))
+ delete ext_sound(entity);
}
audio::reset();
diff --git a/src/client/client.h b/src/client/client.h
index 33f64e5..8dd00cb 100644
--- a/src/client/client.h
+++ b/src/client/client.h
@@ -8,7 +8,12 @@
#define __INCLUDED_CLIENT_H__
#include "core/application.h"
+#include "core/extension.h"
+#include "core/entity.h"
+#include "client/clientext.h"
+#include "client/soundext.h"
#include "client/view.h"
+#include "render/renderext.h"
/// client part of the engine
namespace client {
@@ -44,9 +49,6 @@ public:
/// text notifications from the client
void notify_message(const char *message);
- /// remove sound source notification
- virtual void notify_remove_sound(size_t source);
-
/// clear zone notification
virtual void notify_zonechange();
@@ -77,6 +79,15 @@ private:
Client *client();
+inline ClientExt *ext_client(core::Entity *entity)
+ { return static_cast<ClientExt *>(entity->extension(core::Extension::Client)); }
+
+inline SoundExt *ext_sound(core::Entity *entity)
+ { return static_cast<SoundExt *>(entity->extension(core::Extension::Sound)); }
+
+inline render::RenderExt *ext_render(core::Entity *entity)
+ { return static_cast<render::RenderExt *>(entity->extension(core::Extension::Render)); }
+
}
#endif // __INCLUDED_CLIENT_H__
diff --git a/src/client/clientext.cc b/src/client/clientext.cc
new file mode 100644
index 0000000..980ecc0
--- /dev/null
+++ b/src/client/clientext.cc
@@ -0,0 +1,23 @@
+/*
+ client/clientext.cc
+ This file is part of the Osirion project and is distributed under
+ the terms of the GNU General Public License version 2
+*/
+
+
+#include "client/clientext.h"
+
+namespace client
+{
+
+ClientExt::ClientExt(core::Entity *entity) : core::Extension(core::Extension::Client, entity)
+{
+}
+
+ClientExt::~ClientExt()
+{
+}
+
+} // namespace client
+
+
diff --git a/src/client/clientext.h b/src/client/clientext.h
new file mode 100644
index 0000000..d76546d
--- /dev/null
+++ b/src/client/clientext.h
@@ -0,0 +1,30 @@
+/*
+ client/clientext.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_CLIENT_CLIENTEXT_H__
+#define __INCLUDED_CLIENT_CLIENTEXT_H__
+
+#include "core/extension.h"
+
+namespace client
+{
+
+/// the client extension of an entity
+class ClientExt :public core::Extension {
+public:
+ ClientExt(core::Entity *entity);
+ ~ClientExt();
+
+ virtual void frame(float elapsed);
+
+private:
+
+};
+
+} // namespace client
+
+#endif // __INCLUDED_CLIENT_CLIENTEXT_H__
+
diff --git a/src/client/soundext.cc b/src/client/soundext.cc
new file mode 100644
index 0000000..421575d
--- /dev/null
+++ b/src/client/soundext.cc
@@ -0,0 +1,147 @@
+/*
+ client/soundext.cc
+ This file is part of the Osirion project and is distributed under
+ the terms of the GNU General Public License version 2
+*/
+
+
+#include "audio/audio.h"
+#include "audio/buffers.h"
+#include "audio/sources.h"
+#include "auxiliary/functions.h"
+#include "core/gameinterface.h"
+#include "core/entity.h"
+#include "client/soundext.h"
+#include "client/client.h"
+
+#include <sstream>
+#include <iomanip>
+
+namespace client
+{
+
+SoundExt::SoundExt(core::Entity *entity) : core::Extension(core::Extension::Sound, entity)
+{
+ state_thusterloopbuffer = 0;
+
+ state_impulseloopbuffer = 0;
+ state_impulsestartbuffer = 0;
+ state_impulsestopbuffer = 0;
+
+ state_engineloopbuffer = 0;
+ state_engineloopsource = 0;
+
+ state_engineeventbuffer = 0;
+ state_engineeventsource = 0;
+
+ // load engine sound
+ if (entity->type() == core::Entity::Controlable)
+ {
+ core::EntityControlable *entityco = static_cast<core::EntityControlable *>(entity);
+ unsigned int enginesoundset = 0;
+ unsigned int impulsesoundset = 0;
+
+ if (entityco->model()) {
+ enginesoundset = entityco->model()->enginesound();
+ impulsesoundset = entityco->model()->impulsesound();
+ }
+
+
+ std::stringstream soundname;
+ soundname << "engines/loop" << std::setfill('0') << std::setw(2) << enginesoundset;
+ state_thusterloopbuffer = audio::Buffers::load(soundname.str());
+
+ // load impulse sound
+ // FIXME load impulse sound set
+ state_impulseloopbuffer = audio::Buffers::load("engines/impulse_loop00");
+ state_impulsestartbuffer = audio::Buffers::load("engines/impulse_start00");
+ state_impulsestopbuffer = audio::Buffers::load("engines/impulse_stop00");
+ }
+
+ state_engineloopsource = audio::Sources::get();
+ state_engineeventsource = audio::Sources::get();
+}
+
+SoundExt::~SoundExt()
+{
+ clear();
+}
+
+void SoundExt::clear()
+{
+ if (state_engineloopsource) {
+ audio::Sources::remove(state_engineloopsource);
+ }
+
+ if (state_engineeventsource) {
+ audio::Sources::remove(state_engineeventsource);
+ }
+
+ state_thusterloopbuffer = 0;
+ state_impulseloopbuffer = 0;
+ state_impulsestartbuffer = 0;
+ state_impulsestopbuffer = 0;
+
+ state_engineloopbuffer = 0;
+ state_engineloopsource = 0;
+
+ state_engineeventbuffer = 0;
+ state_engineeventsource = 0;
+}
+
+void SoundExt::frame(float elapsed)
+{
+ core::EntityControlable *entity = static_cast<core::EntityControlable *>(this->entity());
+
+ float speed = entity->speed();
+ float pitch = 1.0f;
+ float gain = 0.0;
+ if (entity->eventstate() == core::Entity::Impulse) {
+ pitch = 1.0f;
+ gain = 1.0f;
+ } else if (entity->thrust() > 0 ) {
+ pitch = 0.2f + entity->thrust() * 0.8f;
+ gain = 0.8f;
+ }
+
+ if (entity->eventstate() == core::Entity::ImpulseInitiate ) {
+
+ if (state_engineeventbuffer != state_impulsestartbuffer) {
+ audio::update_source(state_engineeventsource,
+ entity->location() - entity->axis().forward() * entity->model()->maxbbox().y , entity->axis().forward() * speed);
+ state_engineeventbuffer = audio::play(state_engineeventsource, state_impulsestartbuffer);
+ }
+ } else if (entity->eventstate() == core::Entity::Impulse) {
+
+ state_engineeventbuffer = state_impulseloopbuffer;
+
+ if (state_engineloopbuffer != state_impulseloopbuffer) {
+ state_engineloopbuffer = audio::loop(state_engineloopsource, state_impulseloopbuffer, pitch, 0);
+ }
+ pitch = 1.0f;
+ } else {
+
+ if (state_engineeventbuffer == state_impulseloopbuffer) {
+ audio::update_source(state_engineeventsource,
+ entity->location() - entity->axis().forward() * entity->model()->maxbbox().y , entity->axis().forward() * speed);
+ state_engineeventbuffer = audio::play(state_engineeventsource, state_impulsestopbuffer);
+ }
+ state_engineeventbuffer = 0;
+
+ if (state_engineloopbuffer != state_thusterloopbuffer) {
+ state_engineloopbuffer = audio::loop(state_engineloopsource, state_thusterloopbuffer, pitch, 0);
+ }
+ }
+
+
+ audio::update_source(state_engineloopsource,
+ entity->location() - entity->axis().forward() * entity->model()->maxbbox().x , entity->axis().forward() * speed, pitch, gain);
+
+ audio::update_source(state_engineeventsource,
+ entity->location() - entity->axis().forward() * entity->model()->maxbbox().x , entity->axis().forward() * speed);
+
+}
+
+} // namespace client
+
+
diff --git a/src/client/soundext.h b/src/client/soundext.h
new file mode 100644
index 0000000..d2028dd
--- /dev/null
+++ b/src/client/soundext.h
@@ -0,0 +1,49 @@
+/*
+ client/soundext.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_CLIENT_SOUNDEXT_H__
+#define __INCLUDED_CLIENT_SOUNDEXT_H__
+
+#include "core/extension.h"
+
+namespace client
+{
+
+/// the sound extension of an entity
+class SoundExt :public core::Extension {
+public:
+ SoundExt(core::Entity *Entity);
+ ~SoundExt();
+
+ virtual void frame(float elapsed);
+
+private:
+ void clear();
+
+ /// index of the audio buffer containing the thruster sound loop
+ size_t state_thusterloopbuffer;
+ /// index of the audio buffer containing the impulse sound loop
+ size_t state_impulseloopbuffer;
+ /// index of the audio buffer containing the impulse drive start sound
+ size_t state_impulsestartbuffer;
+ /// index of the audio buffer containing the impulse drive stop sound
+ size_t state_impulsestopbuffer;
+
+ /// index of the audio buffer currently looping in enginesource
+ size_t state_engineloopbuffer;
+ /// index of the audio source used to play the engine sound loop
+ size_t state_engineloopsource;
+ /// index of the audio last played on the event source
+ size_t state_engineeventbuffer;
+ /// index of the audio source used to play engine sound events
+ size_t state_engineeventsource;
+};
+
+}
+ //namespace client
+ //
+#endif // __INCLUDED_CLIENT_CLIENTEXT_H__
+
diff --git a/src/client/targets.cc b/src/client/targets.cc
index 8b77644..3ccea8a 100644
--- a/src/client/targets.cc
+++ b/src/client/targets.cc
@@ -14,7 +14,9 @@
#include "audio/sources.h"
#include "auxiliary/functions.h"
#include "audio/sources.h"
+#include "client/client.h"
#include "client/input.h"
+#include "client/soundext.h"
#include "client/view.h"
#include "client/video.h"
#include "core/application.h"
@@ -47,13 +49,13 @@ bool is_legal_target(core::Entity *entity)
return true;
} else if (entity == core::localcontrol()) {
return false;
- } else if (entity->state()->distance() < 0.001f) {
+ } else if (ext_render(entity)->distance() < 0.001f) {
return false;
} else {
if (entity->type() != core::Entity::Controlable) {
- return entity->state()->visible();
+ return ext_render(entity)->visible();
- } else if (entity->state()->distance() < core::range::visible) {
+ } else if (ext_render(entity)->distance() < core::range::visible) {
return true;
}
}
@@ -224,7 +226,7 @@ void func_target_center(std::string const &args)
for (core::Zone::Content::iterator it=core::localcontrol()->zone()->content().begin(); it != core::localcontrol()->zone()->content().end(); it++) {
core::Entity *entity = (*it);
- math::Vector3f v(entity->state()->location() - render::Camera::eye());
+ math::Vector3f v(entity->location() - render::Camera::eye());
v.normalize();
if (is_legal_target(entity) && math::dotproduct(render::Camera::axis().forward(), v) > 0.85 ) {
@@ -291,98 +293,31 @@ void render_listener_sound()
math::Vector3f velocity(0, 0 ,0);
if (core::localcontrol()) {
- velocity.assign(core::localcontrol()->state()->axis().forward() * core::localcontrol()->speed());
+ velocity.assign(core::localcontrol()->axis().forward() * core::localcontrol()->speed());
}
audio::update_listener(render::Camera::eye(), render::Camera::axis(), velocity);
}
-void render_entity_sound(core::EntityControlable *entity)
+void render_entity_sound(core::Entity *entity)
{
- if (!(entity->type() == core::Entity::Controlable))
- return;
-
if (!(snd_engines && snd_engines->value())) {
- entity->state()->clearsound();
+ if (ext_sound(entity))
+ delete ext_sound(entity);
return;
}
- core::ClientState *state = entity->state();
- if (!(entity->model() && state->detailvisible())) {
- entity->state()->clearsound();
+ if (!ext_render(entity) || !ext_render(entity)->visible()) {
+ if (ext_sound(entity))
+ delete ext_sound(entity);
return;
}
- if (!state->state_thusterloopbuffer || ! state->state_impulseloopbuffer) {
- // load engine sound
- size_t enginesound = 0;
- if (entity->model())
- enginesound = entity->model()->enginesound();
-
- std::stringstream soundname;
- soundname << "engines/loop" << std::setfill('0') << std::setw(2) << enginesound;
- state->state_thusterloopbuffer = audio::Buffers::load(soundname.str());
-
- // load impulse sound
- // FIXME read impulse sound set from model
- state->state_impulseloopbuffer = audio::Buffers::load("engines/impulse_loop00");
- state->state_impulsestartbuffer = audio::Buffers::load("engines/impulse_start00");
- state->state_impulsestopbuffer = audio::Buffers::load("engines/impulse_stop00");
- }
-
-
- if (!state->state_engineloopsource) {
- state->state_engineloopsource = audio::Sources::get();
- state->state_engineeventsource = audio::Sources::get();
- }
-
- float speed = entity->speed();
- float pitch = 1.0f;
- float gain = 0.0;
- if (entity->eventstate() == core::Entity::Impulse) {
- pitch = 1.0f;
- gain = 1.0f;
- } else if (entity->thrust() > 0 ) {
- pitch = 0.2f + entity->thrust() * 0.8f;
- gain = 0.8f;
+ if (!ext_sound(entity)) {
+ new SoundExt(entity);
}
-
-
- if (entity->eventstate() == core::Entity::ImpulseInitiate ) {
-
- if (state->state_engineeventbuffer != state->state_impulsestartbuffer) {
- audio::update_source(state->state_engineeventsource,
- state->location() - state->axis().forward() * entity->model()->maxbbox().y , state->axis().forward() * speed);
- state->state_engineeventbuffer = audio::play(state->state_engineeventsource, state->state_impulsestartbuffer);
- }
- } else if (entity->eventstate() == core::Entity::Impulse) {
-
- state->state_engineeventbuffer = state->state_impulseloopbuffer;
- if (state->state_engineloopbuffer != state->state_impulseloopbuffer) {
- state->state_engineloopbuffer = audio::loop(state->state_engineloopsource, state->state_impulseloopbuffer, pitch, 0);
- }
- pitch = 1.0f;
- } else {
-
- if (state->state_engineeventbuffer == state->state_impulseloopbuffer) {
- audio::update_source(state->state_engineeventsource,
- state->location() - state->axis().forward() * entity->model()->maxbbox().y , state->axis().forward() * speed);
- state->state_engineeventbuffer = audio::play(state->state_engineeventsource, state->state_impulsestopbuffer);
- }
- state->state_engineeventbuffer = 0;
-
- if (state->state_engineloopbuffer != state->state_thusterloopbuffer) {
- state->state_engineloopbuffer = audio::loop(state->state_engineloopsource, state->state_thusterloopbuffer, pitch, 0);
- }
- }
-
-
- audio::update_source(state->state_engineloopsource,
- state->location() - state->axis().forward() * entity->model()->maxbbox().y , state->axis().forward() * speed, pitch, gain);
-
- audio::update_source(state->state_engineeventsource,
- state->location() - state->axis().forward() * entity->model()->maxbbox().y , state->axis().forward() * speed);
+ entity->extension((size_t) core::Extension::Sound)->frame(0.0f);
}
@@ -428,8 +363,9 @@ void draw()
// render entity sound
if (entity->type() == core::Entity::Controlable) {
- render_entity_sound(static_cast<core::EntityControlable *>(entity));
+ render_entity_sound(entity);
}
+
// find the current target
if (!core::localplayer()->view() && core::localcontrol() && is_legal_target(entity)) {
@@ -438,7 +374,7 @@ void draw()
}
// check if the mouse is hovering the entity
- Vector3f v(entity->state()->location() - render::Camera::eye());
+ Vector3f v(entity->location() - render::Camera::eye());
v.normalize();
if (math::dotproduct(render::Camera::axis().forward(), v) > 0.75 ) {
@@ -448,11 +384,11 @@ void draw()
float r = entity->radius() * 0.5f;
- if (entity->state()->distance() > 512)
+ if (ext_render(entity)->distance() > 512.0f)
math::clamp(r, 8.0f,r);
- else if (entity->state()->distance() > 256)
+ else if (ext_render(entity)->distance() > 256.0f)
math::clamp(r, 4.0f,r);
- else if (entity->state()->distance() > 128.0f)
+ else if (ext_render(entity)->distance() > 128.0f)
math::clamp(r, 2.0f,r);
// if the cursor-beam hits the entity sphere
diff --git a/src/client/view.cc b/src/client/view.cc
index 90a30ef..0f981ca 100644
--- a/src/client/view.cc
+++ b/src/client/view.cc
@@ -77,7 +77,7 @@ void DevInfo::draw()
<< "^Nspeed ^B" << core::localcontrol()->speed() << '\n';
if (target) {
- d = math::distance(core::localcontrol()->location(), target->state()->location()) - target->radius() - core::localcontrol()->radius();
+ d = math::distance(core::localcontrol()->location(), target->location()) - target->radius() - core::localcontrol()->radius();
textstream << "^Ndist ^B" << d << '\n';
}
}
@@ -298,14 +298,14 @@ void draw_entity_world_target(core::Entity *entity)
if (!model->docks().size())
return;
- float d = math::distance(core::localcontrol()->location(), entity->state()->location()) - entity->radius() - core::localcontrol()->radius();
+ float d = math::distance(core::localcontrol()->location(), entity->location()) - entity->radius() - core::localcontrol()->radius();
if (d > 100.0f)
return;
gl::enable(GL_DEPTH_TEST);
gl::push();
- gl::translate(entity->state()->location());
- gl::multmatrix(entity->state()->axis());
+ gl::translate(entity->location());
+ gl::multmatrix(entity->axis());
gl::color(0, 1.0f, 1.0f, 1.0f);
@@ -355,7 +355,7 @@ void draw_entity_world_target(core::Entity *entity)
void draw_entity_offscreen_target(core::Entity *entity, bool is_active_target)
{
- math::Vector3f target(entity->state()->location() - render::Camera::eye());
+ math::Vector3f target(entity->location() - render::Camera::eye());
target = render::Camera::axis().transpose() * target;
float cx = 0;
@@ -414,11 +414,11 @@ void draw_entity_target(core::Entity *entity, bool is_active_target)
using math::Vector3f;
// don't draw target if we're very close to it
- if (entity->state()->distance() < 0.001f)
+ if (ext_render(entity)->distance() < 0.001f)
return;
// don't draw target if it is outside the visible cone
- Vector3f target(entity->state()->location() - render::Camera::eye());
+ Vector3f target(entity->location() - render::Camera::eye());
if (math::dotproduct(render::Camera::axis().forward(), Vector3f::normalized(target)) < 0.75 ) {
draw_entity_offscreen_target(entity, is_active_target);
return;
@@ -492,7 +492,7 @@ void draw_entity_target(core::Entity *entity, bool is_active_target)
if (is_active_target) {
// entity name and distance
std::stringstream strdistance;
- float d = math::distance(core::localcontrol()->location(), entity->state()->location()) - entity->radius() - core::localcontrol()->radius();
+ float d = math::distance(core::localcontrol()->location(), entity->location()) - entity->radius() - core::localcontrol()->radius();
if (d > 0 ) {
if (d > 100.0f) {
strdistance << roundf(d * 0.1f) << "km";
@@ -572,7 +572,7 @@ void draw_hud()
std::stringstream strtarget;
strtarget << "^B" << target->name() << "\n^B";
- d = math::distance(core::localcontrol()->location(), target->state()->location())
+ d = math::distance(core::localcontrol()->location(), target->location())
- target->radius() - core::localcontrol()->radius();
if (d > 0 ) {
@@ -582,12 +582,23 @@ void draw_hud()
} else {
strtarget << roundf(d * 100.0f) << "m";
}
+
+ if (core::localcontrol()->speed() > 0.1f) {
+ strtarget << "^N eta:^B ";
+ float eta = floorf(d / core::localcontrol()->speed() );
+ if (eta > 60.0f) {
+ float etamin = floorf(eta / 60.0f);
+ strtarget << etamin << "min ";
+ eta -= etamin * 60;
+ }
+ strtarget << eta << "sec";
+ }
} else {
strtarget << " --";
}
strtarget << '\n';
Text::draw(render::State::width() - 4-Text::fontwidth()*32, render::State::height() - Text::fontheight()*2 -4, strtarget);
- y = 3.0f;
+ y += 2.0f;
}
Text::setcolor('N'); //set normal color
diff --git a/src/core/Makefile.am b/src/core/Makefile.am
index 2c90dec..fbdf311 100644
--- a/src/core/Makefile.am
+++ b/src/core/Makefile.am
@@ -1,8 +1,8 @@
METASOURCES = AUTO
INCLUDES = -I$(top_srcdir)/src
-libcore_la_SOURCES = application.cc clientstate.cc commandbuffer.cc core.cc \
- cvar.cc descriptions.cc entity.cc func.cc gameconnection.cc gameinterface.cc \
+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 module.cc netclient.cc netconnection.cc netplayer.cc netserver.cc \
parser.cc player.cc stats.cc timer.cc zone.cc
libcore_la_LDFLAGS = -avoid-version -no-undefined
@@ -11,7 +11,7 @@ libcore_la_LIBADD = $(top_builddir)/src/model/libmodel.la \
$(top_builddir)/src/auxiliary/libauxiliary.la
noinst_LTLIBRARIES = libcore.la
-noinst_HEADERS = application.h clientstate.h commandbuffer.h core.h cvar.h \
- entity.h func.h gameconnection.h gameinterface.h gameserver.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
+noinst_HEADERS = application.h commandbuffer.h core.h cvar.h entity.h func.h \
+ gameconnection.h gameinterface.h gameserver.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
diff --git a/src/core/application.cc b/src/core/application.cc
index 7326383..f24f0f7 100644
--- a/src/core/application.cc
+++ b/src/core/application.cc
@@ -489,12 +489,6 @@ void Application::notify_connect()
{
}
-void Application::notify_remove_sound(size_t source)
-{
- // the default implementation does nothing.
- // Dedicated servers don't need sounds
-}
-
/* -- static engine functions -------------------------------------- */
void Application::func_help(std::string const &args)
diff --git a/src/core/application.h b/src/core/application.h
index bcd4042..e992131 100644
--- a/src/core/application.h
+++ b/src/core/application.h
@@ -81,9 +81,6 @@ public:
/// zone change notification
virtual void notify_zonechange();
- /// remove sound source notification
- virtual void notify_remove_sound(size_t source);
-
/// a pointer to the current application instance
static inline Application *instance() { return application_instance; }
diff --git a/src/core/clientstate.cc b/src/core/clientstate.cc
deleted file mode 100644
index 298e653..0000000
--- a/src/core/clientstate.cc
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- 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"
-#include "core/application.h"
-#include "sys/sys.h"
-
-namespace core {
-
-ClientState::ClientState()
-{
- state_visible = false;
- state_detailvisible = false;
- state_targetable = false;
-
- state_thusterloopbuffer = 0;
- state_impulseloopbuffer = 0;
- state_impulsestartbuffer = 0;
- state_impulsestopbuffer = 0;
-
- state_engineloopbuffer = 0;
- state_engineloopsource = 0;
- state_engineeventbuffer = 0;
- state_engineeventsource = 0;
-
- state_engine_trail_offset = 0;
-
- state_fuzz = math::randomf();
- state_distance = -1;
-}
-
-ClientState::ClientState(Entity *entity)
-{
- state_visible = false;
- state_detailvisible = false;
- state_targetable = false;
-
- state_thusterloopbuffer = 0;
- state_impulseloopbuffer = 0;
- state_impulsestartbuffer = 0;
- state_impulsestopbuffer = 0;
-
- state_engineloopbuffer = 0;
- state_engineloopsource = 0;
- state_engineeventbuffer = 0;
- state_engineeventsource = 0;
-
- state_engine_trail_offset = 0;
-
- state_fuzz = math::randomf();
- state_distance = -1;
-
- assign(entity);
-}
-
-ClientState::~ClientState()
-{
- clearsound();
-}
-
-void ClientState::clearsound()
-{
- if (state_engineloopsource) {
- application()->notify_remove_sound(state_engineloopsource);
- }
-
- if (state_engineeventsource) {
- application()->notify_remove_sound(state_engineeventsource);
- }
-
- state_thusterloopbuffer = 0;
- state_impulseloopbuffer = 0;
- state_impulsestartbuffer = 0;
- state_impulsestopbuffer = 0;
-
- state_engineloopbuffer = 0;
- state_engineloopsource = 0;
-
- state_engineeventbuffer = 0;
- state_engineeventsource = 0;
-}
-
-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());
- state_distance = -1;
-}
-
-}
diff --git a/src/core/clientstate.h b/src/core/clientstate.h
deleted file mode 100644
index ffd6331..0000000
--- a/src/core/clientstate.h
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- 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() const { return state_location; }
-
- inline math::Vector3f const & previouslocation() const { return state_previouslocation; }
-
- inline math::Axis const & previousaxis() const { return state_previousaxis; }
-
- inline math::Axis const & axis() const { return state_axis; }
-
- inline bool visible() const { return state_visible; }
-
- inline bool detailvisible() const { return state_detailvisible; }
-
- inline bool targetable() const { return state_targetable; }
-
- inline float distance() const { return state_distance; }
-
- /// client render fuzz factor
- inline float fuzz() const { return state_fuzz; };
-
- /// assign the content of an entity
- void assign(Entity *entity);
-
- /// clear attached sounds
- void clearsound();
-
- math::Vector3f state_location;
- math::Axis state_axis;
-
- math::Vector3f state_previouslocation;
- math::Axis state_previousaxis;
-
- bool state_visible;
- bool state_detailvisible;
- bool state_targetable;
-
- float state_fuzz;
- float state_engine_trail_offset;
-
- /// distance from the camera eye to the entity
- float state_distance;
-
- /// index of the audio buffer containing the thruster sound loop
- size_t state_thusterloopbuffer;
- /// index of the audio buffer containing the impulse sound loop
- size_t state_impulseloopbuffer;
- /// index of the audio buffer containing the impulse drive start sound
- size_t state_impulsestartbuffer;
- /// index of the audio buffer containing the impulse drive stop sound
- size_t state_impulsestopbuffer;
-
- /// index of the audio buffer currently looping in enginesource
- size_t state_engineloopbuffer;
- /// index of the audio source used to play the engine sound loop
- size_t state_engineloopsource;
- /// index of the audio last played on the event source
- size_t state_engineeventbuffer;
- /// index of the audio source used to play engine sound events
- size_t state_engineeventsource;
-};
-
-}
-
-#endif // __INCLUDED_CORE_CLIENTSTATE_H__
-
diff --git a/src/core/entity.cc b/src/core/entity.cc
index e2aac1c..47086ee 100644
--- a/src/core/entity.cc
+++ b/src/core/entity.cc
@@ -6,6 +6,7 @@
#include <vector>
#include <iomanip>
+#include <cstring>
#include "auxiliary/functions.h"
#include "sys/sys.h"
@@ -105,14 +106,14 @@ Entity::Entity(unsigned int flags) :
entity_label.clear();
entity_name.clear();
- entity_clientstate = 0;
-
entity_zone = 0;
entity_oldzone = 0;
entity_visible = true;
entity_serverside = false;
+ memset(entity_extension, 0, sizeof(entity_extension));
+
add(this);
}
@@ -125,25 +126,28 @@ Entity::Entity(std::istream & is)
entity_visible = true;
entity_model = 0;
- entity_clientstate = 0;
entity_created = true;
- entity_destroyed = false;
+ entity_destroyed = false;
+
+ memset(entity_extension, 0, sizeof(entity_extension));
}
Entity::~Entity()
{
+ // delete extensions
+ for (size_t i =0; i < 4; i++) {
+ if (entity_extension[i])
+ delete entity_extension[i];
+ entity_extension[i] = 0;
+ }
+
// delete entity menus
for (Menus::iterator it = menus().begin(); it != menus().end(); it++) {
delete (*it);
}
menus().clear();
- if (entity_clientstate) {
- delete entity_clientstate;
- entity_clientstate = 0;
- }
-
if (entity_zone)
entity_zone->remove(this);
}
diff --git a/src/core/entity.h b/src/core/entity.h
index 4e757c1..01fedc2 100644
--- a/src/core/entity.h
+++ b/src/core/entity.h
@@ -24,7 +24,7 @@ class EntityControlable;
}
-#include "core/clientstate.h"
+#include "core/extension.h"
#include "core/descriptions.h"
#include "core/player.h"
#include "core/zone.h"
@@ -35,6 +35,8 @@ namespace core
/// The base world entity. All gameworld entities must derive from this class.
class Entity
{
+ friend class Extension;
+
public:
/// Entity flags
enum Flags {Static=1, Solid=2, Bright=4, Dockable=8};
@@ -80,9 +82,6 @@ public:
/// entity name (can not contain double qoutes ")
inline std::string const & name() { return entity_name; }
- /// 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; }
@@ -125,6 +124,9 @@ public:
/// entity menus
inline Menus &menus() { return entity_menus; }
+ /// extensions
+ inline Extension *extension(size_t type) { return entity_extension[type]; }
+
/// find a menu
MenuDescription *find_menu(std::string const &label);
@@ -248,8 +250,6 @@ public:
/// timestamp when entity data was received from the server
float entity_servertimestamp;
- ClientState *entity_clientstate;
-
protected:
// the zone the entity belongs to
Zone *entity_zone;
@@ -271,6 +271,8 @@ private:
Menus entity_menus;
+ Extension* entity_extension[4];
+
static Registry entity_registry;
static size_t entity_nextid;
diff --git a/src/core/extension.cc b/src/core/extension.cc
new file mode 100644
index 0000000..7106fa5
--- /dev/null
+++ b/src/core/extension.cc
@@ -0,0 +1,29 @@
+/*
+ core/extension.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/extension.h"
+
+namespace core
+{
+
+Extension::Extension(Type type, Entity *entity)
+{
+ extension_entity = entity;
+ extension_type = type;
+
+ if (entity)
+ entity->entity_extension[(size_t) type] = this;
+}
+
+Extension::~Extension()
+{
+ if (extension_entity)
+ extension_entity->entity_extension[(size_t) extension_type] = 0;
+}
+
+
+} // namespace core
+
diff --git a/src/core/extension.h b/src/core/extension.h
new file mode 100644
index 0000000..0b9ecad
--- /dev/null
+++ b/src/core/extension.h
@@ -0,0 +1,42 @@
+/*
+ core/extension.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_EXTENSION_H__
+#define __INCLUDED_CORE_EXTENSION_H__
+
+namespace core {
+ class Extension;
+}
+
+#include "core/entity.h"
+
+namespace core {
+
+/// a abstract base class for entity extensions
+class Extension {
+public:
+ /// extension types
+ enum Type { Client=0, Render=1, Sound=2, Game=3 };
+
+ inline Type type() const { return extension_type; }
+
+ inline Entity *entity() { return extension_entity; }
+
+ Extension(Type type, Entity *entity);
+ virtual ~Extension();
+
+ virtual void frame(float elapsed) = 0;
+
+private:
+ Type extension_type;
+ Entity *extension_entity;
+
+};
+
+} // namespace core
+
+#endif // __INCLUDED_CORE_EXTENSION_H__
+
diff --git a/src/core/gameconnection.cc b/src/core/gameconnection.cc
index 7942f9e..c2763ee 100644
--- a/src/core/gameconnection.cc
+++ b/src/core/gameconnection.cc
@@ -121,7 +121,7 @@ void GameConnection::frame(unsigned long timestamp)
return;
}
- update_clientstate();
+ //update_clientstate();
// get incoming messages
connection_network->frame();
diff --git a/src/core/gameinterface.cc b/src/core/gameinterface.cc
index d99ec15..9551176 100644
--- a/src/core/gameinterface.cc
+++ b/src/core/gameinterface.cc
@@ -120,100 +120,6 @@ void GameInterface::clear()
game_players.clear();
}
-void GameInterface::reset_clientstate()
-{
-// game_previousframetime = prevtimestamp;
-// game_serverframetime = timestamp;
-// game_time = timestamp;
-
- for (Entity::Registry::iterator it = Entity::registry().begin(); it != Entity::registry().end(); it++) {
-
- Entity *entity = (*it).second;
-
- if (entity->state() && !(entity->flags() & Entity::Static))
- entity->state()->assign(entity);
- }
-
-// if ( game_clientframetime < game_previousframetime)
-// game_clientframetime = game_previousframetime;
-// else if ( game_clientframetime > game_serverframetime)
-// game_clientframetime = game_serverframetime;
-
-}
-
-
-void GameInterface::update_entity_clientstate(Entity *entity)
-{
- if (!entity->state()) {
- entity->entity_clientstate = new ClientState(entity);
- entity->entity_clientstate->assign(entity);
- } else
- entity->state()->assign(entity);
- }
-
-/*
- if (!(entity->flags() & Entity::Static)) {
-
- // clientstate location
- entity->state()->state_location = entity->state()->previouslocation() +
- (entity->location() - entity->state()->previouslocation()) * timeoffset();
-
- if (game_clientframetime <= game_serverframetime) {
-
- if(Cvar::cl_prediction->value() > 1) {
- entity->state()->state_axis.assign(entity->state()->previousaxis());
-
- float cosangle; // cosine of an angle
- float angle; // angle in radians
- math::Vector3f n; // normal of a plane
-
- n.assign(math::crossproduct( entity->state()->axis().forward(), entity->axis().forward()));
- if (!(n.length() < MIN_DELTA)) {
- n.normalize();
- cosangle = math::dotproduct( entity->state()->axis().forward(), entity->axis().forward());
- angle = acos(cosangle) * timeoffset(); // * 180.0f / M_PI;
- if (angle > MIN_DELTA)
- entity->state()->state_axis.rotate(n, -angle);
- }
-
- n.assign(math::crossproduct( entity->state()->axis().left(), entity->axis().left()));
- if (!(n.length() < MIN_DELTA)) {
- n.normalize();
- cosangle = math::dotproduct( entity->state()->axis().left(), entity->axis().left());
- angle = acos(cosangle) * timeoffset(); // * 180.0f / M_PI;
- if (angle > MIN_DELTA)
- entity->state()->state_axis.rotate(n, -angle);
- }
-
- n.assign(math::crossproduct( entity->state()->axis().up(), entity->axis().up()));
- if (!(n.length() < MIN_DELTA)) {
- n.normalize();
- cosangle = math::dotproduct( entity->state()->axis().up(), entity->axis().up());
- angle = acos(cosangle) * timeoffset(); // * 180.0f / M_PI;
- if (angle > MIN_DELTA)
- entity->state()->state_axis.rotate(n, -angle);
- }
-
- } else {
- entity->state()->state_axis.assign(entity->axis());
- }
- } else {
- entity->state()->state_axis.assign(entity->axis());
- }
-
- } else {
- entity->state()->assign(entity);
- }
-}
-*/
-
-void GameInterface::update_clientstate()
-{
- for (Entity::Registry::iterator it = Entity::registry().begin(); it != Entity::registry().end(); it++) {
- update_entity_clientstate((*it).second);
- }
-}
-
void GameInterface::list_players()
{
using namespace std;
diff --git a/src/core/gameinterface.h b/src/core/gameinterface.h
index c916d15..f188475 100644
--- a/src/core/gameinterface.h
+++ b/src/core/gameinterface.h
@@ -54,13 +54,6 @@ public:
/// clear all game variables, game functions and entities
void clear();
- /// reset the client state
- void reset_clientstate();
-
- /// update the client state timers
- void update_clientstate();
-
- void update_entity_clientstate(Entity *entity);
/*----- virtual mutators ------------------------------------------ */
diff --git a/src/core/gameserver.cc b/src/core/gameserver.cc
index 47f5715..b8f8730 100644
--- a/src/core/gameserver.cc
+++ b/src/core/gameserver.cc
@@ -472,9 +472,9 @@ void GameServer::frame(unsigned long timestamp)
if (localplayer()->dirty())
localplayer()->update_info();
- if (!Cvar::sv_dedicated->value()) {
+ /*if (!Cvar::sv_dedicated->value()) {
update_clientstate();
- }
+ }*/
if ((Cvar::sv_dedicated->value() || Cvar::sv_private->value())) {
if (core::Cvar::sv_framerate->value()) {
@@ -490,9 +490,9 @@ void GameServer::frame(unsigned long timestamp)
float elapsed = (float) (server_timestamp - server_previoustime) / 1000.0f;
// copy the previous entity state to the client state
- if (!Cvar::sv_dedicated->value()) {
+ /*if (!Cvar::sv_dedicated->value()) {
reset_clientstate();
- }
+ }*/
// run a time frame on each entity
for (Entity::Registry::iterator it=Entity::registry().begin(); it != Entity::registry().end(); it++) {
@@ -536,9 +536,9 @@ void GameServer::frame(unsigned long timestamp)
localplayer()->player_zonechange = false;
}
- if (!Cvar::sv_dedicated->value()) {
+ /*if (!Cvar::sv_dedicated->value()) {
update_clientstate();
- }
+ }*/
}
void GameServer::save_config()
diff --git a/src/core/netconnection.cc b/src/core/netconnection.cc
index 0bb33db..7e12ce7 100644
--- a/src/core/netconnection.cc
+++ b/src/core/netconnection.cc
@@ -524,7 +524,7 @@ void NetConnection::parse_incoming_message(const std::string & message)
}
entity->receive_server_create(msgstream);
- game()->update_entity_clientstate(entity);
+ //game()->update_entity_clientstate(entity);
}
} else if (command == "menu") {
diff --git a/src/model/model.h b/src/model/model.h
index 51f8964..cb10386 100644
--- a/src/model/model.h
+++ b/src/model/model.h
@@ -110,6 +110,12 @@ public:
return model_enginesound;
}
+ /// impulse sound set for this model
+ inline unsigned int impulsesound() const
+ {
+ return model_impulsesound;
+ }
+
/// engine color for this model
inline math::Color const & enginecolor() const { return model_enginecolor; }
diff --git a/src/render/Makefile.am b/src/render/Makefile.am
index 7919ee2..4054490 100644
--- a/src/render/Makefile.am
+++ b/src/render/Makefile.am
@@ -10,6 +10,7 @@ endif
librender_la_LDFLAGS = -avoid-version -no-undefined @GL_LIBS@
librender_la_LIBADD = $(top_builddir)/src/math/libmath.la
librender_la_SOURCES = camera.cc draw.cc dust.cc gl.cc image.cc jpgfile.cc \
- pngfile.cc render.cc screenshot.cc state.cc text.cc textures.cc tgafile.cc
-noinst_HEADERS = camera.h draw.h dust.h gl.h image.h render.h text.h textures.h \
- tgafile.h pngfile.h jpgfile.h screenshot.h state.h
+ pngfile.cc render.cc renderext.cc screenshot.cc state.cc text.cc textures.cc \
+ tgafile.cc
+noinst_HEADERS = camera.h draw.h dust.h gl.h image.h jpgfile.h pngfile.h \
+ render.h renderext.h screenshot.h state.h text.h textures.h tgafile.h
diff --git a/src/render/camera.cc b/src/render/camera.cc
index 875b147..c136375 100644
--- a/src/render/camera.cc
+++ b/src/render/camera.cc
@@ -98,10 +98,7 @@ void Camera::set_mode(Mode newmode) {
// switch camera to Track mode
camera_mode = Track;
if (core::localcontrol()) {
- if (core::localcontrol()->state())
- camera_axis.assign(core::localcontrol()->state()->axis());
- else
- camera_axis.assign(core::localcontrol()->axis());
+ camera_axis.assign(core::localcontrol()->axis());
}
break;
@@ -242,8 +239,8 @@ void Camera::frame(float seconds)
}
} else {
- camera_target.assign(core::localcontrol()->state()->location());
- target_axis.assign(core::localcontrol()->state()->axis());
+ camera_target.assign(core::localcontrol()->location());
+ target_axis.assign(core::localcontrol()->axis());
distance = core::localcontrol()->radius();
if (mode() == Track) {
@@ -306,14 +303,12 @@ void Camera::frame(float seconds)
camera_axis.assign(target_axis);
- if (core::localcontrol()->state()) {
- if (core::localcontrol()->model()) {
- camera_target += (core::localcontrol()->model()->maxbbox().x+0.05) *
- core::localcontrol()->state()->axis().forward();
- } else {
- camera_target += (core::localcontrol()->radius() + 0.05) *
- core::localcontrol()->state()->axis().forward();
- }
+ if (core::localcontrol()->model()) {
+ camera_target += (core::localcontrol()->model()->maxbbox().x+0.05) *
+ core::localcontrol()->axis().forward();
+ } else {
+ camera_target += (core::localcontrol()->radius() + 0.05) *
+ core::localcontrol()->axis().forward();
}
distance = 0.0f;
}
diff --git a/src/render/draw.cc b/src/render/draw.cc
index 2975ecb..4f58f3d 100644
--- a/src/render/draw.cc
+++ b/src/render/draw.cc
@@ -41,10 +41,6 @@ math::Vector3f v5(1, 1, -1);
math::Vector3f v6(-1, 1, -1);
math::Vector3f v7(-1, -1, -1);
-const float drawdistance = 256.0f;
-const float drawfxdistance = 64.0f;
-const float farplane = 1016.0f;
-
core::Zone *zone = 0;
float zone_light[4]; // locaton of the zone light
math::Color zone_color; // color of the zone light
@@ -75,115 +71,45 @@ void pass_prepare(float seconds)
for (core::Zone::Content::iterator it = zone->content().begin(); it != zone->content().end(); it++) {
core::Entity *entity = (*it);
- // load entity models and light flare textures
- if (!entity->model() && entity->modelname().c_str()[0]) {
- entity->set_modelname(entity->modelname());
+ if (!ext_render(entity)) {
+ new RenderExt(entity);
}
-
- if (entity->model()) {
- model::Model *model = entity->model();
+ entity->extension((size_t) core::Extension::Render)->frame(seconds);
- for (Model::Lights::iterator lit = model->lights().begin(); lit != model->lights().end(); lit++) {
- Light *light = (*lit);
+ // globes
+ if (entity->type() == core::Entity::Globe) {
+ core::EntityGlobe *globe = static_cast<core::EntityGlobe *>(entity);
- // load light texture
- std::stringstream flarename;
- flarename << "bitmaps/fx/flare" << std::setfill('0') << std::setw(2) << light->flare();
- light->render_texture = Textures::load(flarename.str());
+ // add the globe to the globes list
+ if (globe->visible()) {
+ globes_list[ext_render(globe)->distance()] = globe;
}
- for(Model::Engines::iterator eit = model->engines().begin(); eit != model->engines().end(); eit++) {
- Engine *engine = (*eit);
-
- if (!engine->flare()) engine->engine_flare = 1;
-
- // load engine texture
- std::stringstream flarename;
- flarename << "bitmaps/fx/flare" << std::setfill('0') << std::setw(2) << engine->flare();
- engine->render_texture = Textures::load(flarename.str());
- }
-
- for (Model::Flares::iterator flit = model->flares().begin(); flit != model->flares().end(); flit++) {
- Flare *flare = (*flit);
-
- // load flare texture
- std::stringstream flarename;
- flarename << "bitmaps/fx/flare" << std::setfill('0') << std::setw(2) << flare->flare();
- flare->render_texture = Textures::load(flarename.str());
- }
- }
-
- entity->state()->state_visible = entity->visible();
+ // add level lights
+ if (flag_is_set(globe->flags(), core::Entity::Bright)) {
- if ((entity->type() == core::Entity::Controlable)) {
- if (static_cast<core::EntityDynamic *>(entity)->eventstate() == core::Entity::Docked) {
- entity->state()->state_visible = false;
- }
- }
+ // bright globes set level light
+ GLfloat diffuse_light[4];
+ GLfloat ambient_light[] = { 0.0f, 0.0f, 0.0f, 1.0f };
+ GLfloat specular_light[] = { 0.2f, 0.2f, 0.2f, 1.0f };
- entity->state()->state_detailvisible = false;
- entity->state()->state_targetable = false;
- entity->state()->state_distance = math::distance(Camera::eye(), entity->state()->location());
-
- if (entity->state()->visible()) {
- // globes
- if (entity->type() == core::Entity::Globe) {
- core::EntityGlobe *globe = static_cast<core::EntityGlobe *>(entity);
-
- // add the globe to the globes list
- globes_list[globe->state()->distance()] = globe;
-
- // load globe textures
- if (!globe->render_texture && globe->texture().size()) {
- std::stringstream texname;
- texname << "textures/" << globe->texture();
- globe->render_texture = Textures::load(texname.str());
- if (!globe->render_texture)
- globe->entity_texture.clear();
- }
-
- if (flag_is_set(globe->flags(), core::Entity::Bright)) {
-
- // bright globes set level light
- GLfloat diffuse_light[4];
- GLfloat ambient_light[] = { 0.0f, 0.0f, 0.0f, 1.0f };
- GLfloat specular_light[] = { 0.2f, 0.2f, 0.2f, 1.0f };
-
- for (size_t i=0; i <3; i++) {
- zone_light[i] = globe->location()[i];
- zone_color[i] = globe->color()[i];
- diffuse_light[i] = globe->color()[i] * 0.4;
- }
- zone_light[3] = 1.0f;
- diffuse_light[3] = 1.0f;
-
- glLightfv(GL_LIGHT1, GL_POSITION, zone_light);
- glLightfv(GL_LIGHT1, GL_AMBIENT, ambient_light);
- glLightfv(GL_LIGHT1, GL_DIFFUSE, diffuse_light);
- glLightfv(GL_LIGHT1, GL_SPECULAR, specular_light);
- gl::enable(GL_LIGHT1);
- has_zone_light = true;
- }
-
- } else if (entity->model()) {
-
- float r = entity->model()->radius();
- math::clamp(r, 1.0f, farplane / drawfxdistance);
- if (entity->state()->distance() < drawfxdistance * r) {
- // entites within detail range
- entity->state()->state_visible = true;
- entity->state()->state_detailvisible = true;
- } else if (entity->state()->distance() < drawdistance * r && entity->state()->distance() < core::range::max) {
- // entities within drawing distance, outside detail range
- entity->state()->state_visible = true;
- entity->state()->state_detailvisible = false;
- } else {
- // out of range
- entity->state()->state_visible = false;
- entity->state()->state_detailvisible = false;
+ for (size_t i=0; i <3; i++) {
+ zone_light[i] = globe->location()[i];
+ zone_color[i] = globe->color()[i];
+ diffuse_light[i] = globe->color()[i] * 0.4;
}
+ zone_light[3] = 1.0f;
+ diffuse_light[3] = 1.0f;
+
+ glLightfv(GL_LIGHT1, GL_POSITION, zone_light);
+ glLightfv(GL_LIGHT1, GL_AMBIENT, ambient_light);
+ glLightfv(GL_LIGHT1, GL_DIFFUSE, diffuse_light);
+ glLightfv(GL_LIGHT1, GL_SPECULAR, specular_light);
+ gl::enable(GL_LIGHT1);
+ has_zone_light = true;
}
- }
+
+ }
}
}
@@ -265,7 +191,7 @@ void draw_globe(core::EntityGlobe *globe)
Globes have to be rendered distance sorted, closest last.
Globes behind farplane should be rendered with z-buffer writes disabled.
*/
- math::Vector3f location(globe->state()->location());
+ math::Vector3f location(globe->location());
float radius = globe->radius();
if(flag_is_set(globe->flags(), core::Entity::Bright)) {
@@ -282,10 +208,10 @@ void draw_globe(core::EntityGlobe *globe)
gl::enable(GL_TEXTURE_2D);
}
- if (globe->state()->distance() > farplane) {
+ if (ext_render(globe)->distance() > farplane) {
// globe is behind the far plane, make a fake size calculation
- location = Camera::eye() + (location - Camera::eye()) * (farplane / globe->state()->distance());
- radius *= farplane / globe->state()->distance();
+ location = Camera::eye() + (location - Camera::eye()) * (farplane / ext_render(globe)->distance());
+ radius *= farplane / ext_render(globe)->distance();
gl::depthmask(GL_FALSE);
@@ -293,7 +219,7 @@ void draw_globe(core::EntityGlobe *globe)
// move zone light
float fake_light[4];
for (size_t i=0; i < 3; i++) {
- fake_light[i] = zone_light[i] + location[i] - globe->state()->location()[i];
+ fake_light[i] = zone_light[i] + location[i] - globe->location()[i];
}
fake_light[3] = 1.0f;
glLightfv(GL_LIGHT1, GL_POSITION, fake_light);
@@ -314,9 +240,14 @@ void draw_globe(core::EntityGlobe *globe)
}
Textures::bind("bitmaps/fx/corona");
- if (globe->state()->distance() <= farplane) {
+ if (ext_render(globe)->distance() <= farplane) {
gl::depthmask(GL_FALSE);
}
+
+ //glDisableClientState(GL_VERTEX_ARRAY);
+ //glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+ //glDisableClientState(GL_NORMAL_ARRAY);
+
math::Color color(globe->color());
color.a = a - 0.1f;
@@ -325,30 +256,33 @@ void draw_globe(core::EntityGlobe *globe)
gl::begin(gl::Quads);
glTexCoord2f(0,1);
- gl::vertex((Camera::axis().up() - Camera::axis().left()) * radius * 2.0f);
+ gl::vertex((Camera::axis().up() - Camera::axis().left()) * radius * 4.0f);
glTexCoord2f(0,0);
- gl::vertex((Camera::axis().up() + Camera::axis().left()) * radius * 2.0f);
+ gl::vertex((Camera::axis().up() + Camera::axis().left()) * radius * 4.0f);
glTexCoord2f(1,0);
- gl::vertex((Camera::axis().up() * -1 + Camera::axis().left()) * radius * 2.0f);
+ gl::vertex((Camera::axis().up() * -1 + Camera::axis().left()) * radius * 4.0f);
glTexCoord2f(1,1);
- gl::vertex((Camera::axis().up() * -1 - Camera::axis().left()) * radius * 2.0f);
+ gl::vertex((Camera::axis().up() * -1 - Camera::axis().left()) * radius * 4.0f);
gl::end();
Stats::quads++;
+
+ //glEnableClientState(GL_VERTEX_ARRAY);
+ //glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+ //glEnableClientState(GL_NORMAL_ARRAY);
gl::disable(GL_BLEND);
- if (globe->state()->distance() <= farplane) {
+ if (ext_render(globe)->distance() <= farplane) {
gl::depthmask(GL_TRUE);
}
if (!globe->render_texture) {
gl::disable(GL_TEXTURE_2D);
}
}
- radius *= 0.5f;
}
- gl::multmatrix(globe->state()->axis());
+ gl::multmatrix(globe->axis());
if (globe->rotationspeed()) {
float angle = math::degrees360f(core::application()->time() * globe->rotationspeed());
@@ -359,7 +293,7 @@ void draw_globe(core::EntityGlobe *globe)
gl::pop();
- if (globe->state()->distance() > farplane) {
+ if (ext_render(globe)->distance() > farplane) {
gl::depthmask(GL_TRUE);
@@ -475,7 +409,7 @@ void draw_entity_diamond(core::Entity *entity)
gl::end();
/* ---- draw rotating body lines ---- */
- float angle = (core::application()->time() + entity->state()->fuzz() ) * 45.0f;
+ float angle = (core::application()->time() + ext_render(entity)->fuzz() ) * 45.0f;
angle = angle - 360.0f * floorf(angle / 360.0f);
gl::rotate(angle, math::Vector3f::Zaxis());
@@ -552,8 +486,8 @@ void draw_pass_default()
if (!entity->serverside() && !entity->model() && (entity->type() != core::Entity::Globe)) {
gl::push();
- gl::translate(entity->state()->location());
- gl::multmatrix(entity->state()->axis());
+ gl::translate(entity->location());
+ gl::multmatrix(entity->axis());
if (flag_is_set(entity->flags(), core::Entity::Bright)) {
gl::disable(GL_LIGHTING);
@@ -710,7 +644,7 @@ void draw_model_fragments(core::Entity *entity)
}
}
- draw_fragment(fragment, entity->state()->detailvisible());
+ draw_fragment(fragment, ext_render(entity)->detailvisible());
}
if (!use_light) {
@@ -758,10 +692,10 @@ void draw_pass_model_fragments()
for (core::Zone::Content::iterator it = zone->content().begin(); it != zone->content().end(); it++) {
core::Entity *entity = (*it);
- if (entity->model() && entity->state()->visible()) {
+ if (entity->model() && ext_render(entity)->visible()) {
gl::push();
- gl::translate(entity->state()->location());
- gl::multmatrix(entity->state()->axis());
+ gl::translate(entity->location());
+ gl::multmatrix(entity->axis());
draw_model_fragments(entity);
@@ -818,7 +752,7 @@ void draw_pass_model_fx(float elapsed)
power = false;
}
- if (entity->model() && entity->state()->detailvisible() && power) {
+ if (entity->model() && ext_render(entity)->detailvisible() && power) {
// draw model lights
for (model::Model::Lights::iterator lit = entity->model()->lights().begin(); lit != entity->model()->lights().end(); lit++) {
light = (*lit);
@@ -826,9 +760,9 @@ void draw_pass_model_fx(float elapsed)
// strobe frequency
t = 1.0f;
if (light->strobe())
- t = (core::application()->time() + entity->state()->fuzz() - light->offset()) * light->frequency();
+ t = (core::application()->time() + ext_render(entity)->fuzz() - light->offset()) * light->frequency();
if ((!light->strobe()) || (( t - floorf(t)) <= light->time())) {
- location.assign(entity->state()->location() + (entity->state()->axis() * light->location()));
+ location.assign(entity->location() + (entity->axis() * light->location()));
light_size = 0.0625 * light->radius();
if (current_texture != light->texture()) {
@@ -864,14 +798,14 @@ void draw_pass_model_fx(float elapsed)
// strobe frequency
t = 1.0f;
if (flare->strobe())
- t = (core::application()->time() + entity->state()->fuzz() - flare->offset()) * flare->frequency();
+ t = (core::application()->time() + ext_render(entity)->fuzz() - flare->offset()) * flare->frequency();
if ((!flare->strobe()) || (( t - floorf(t)) <= flare->time())) {
- flare_axis.assign(entity->state()->axis());
+ flare_axis.assign(entity->axis());
if (flare->angle())
flare_axis.change_direction(flare->angle());
- location.assign(entity->state()->location() + (entity->state()->axis() * flare->location()));
+ location.assign(entity->location() + (entity->axis() * flare->location()));
light_size = 0.0625 * flare->radius();
if (current_texture != flare->texture()) {
@@ -915,18 +849,18 @@ void draw_pass_model_fx(float elapsed)
}
if (u > 0) {
- t = entity->state()->state_engine_trail_offset;
+ t = ext_render(entity)->state_engine_trail_offset;
t += elapsed * 4.0f * u;
if (t > 1.0f)
t -= 1.0f;
math::clamp(t, 0.0f, 1.0f);
- entity->state()->state_engine_trail_offset = t;
+ ext_render(entity)->state_engine_trail_offset = t;
for(model::Model::Engines::iterator eit = entity->model()->engines().begin(); eit != entity->model()->engines().end(); eit++) {
engine = (*eit);
- location.assign(entity->state()->location() + (entity->state()->axis() * engine->location()));
+ location.assign(entity->location() + (entity->axis() * engine->location()));
engine_size = 0.0625 * engine->radius();
if (current_texture != engine->texture() ) {
@@ -935,10 +869,10 @@ void draw_pass_model_fx(float elapsed)
gl::begin(gl::Quads);
}
- quad[0].assign(entity->state()->axis().up() - entity->state()->axis().left());
- quad[1].assign(entity->state()->axis().up() + entity->state()->axis().left());
- quad[2].assign(entity->state()->axis().up() * -1 + entity->state()->axis().left());
- quad[3].assign(entity->state()->axis().up() * -1 - entity->state()->axis().left());
+ quad[0].assign(entity->axis().up() - entity->axis().left());
+ quad[1].assign(entity->axis().up() + entity->axis().left());
+ quad[2].assign(entity->axis().up() * -1 + entity->axis().left());
+ quad[3].assign(entity->axis().up() * -1 - entity->axis().left());
// assign engine color to the flare
if (!engine->noflare()){
@@ -965,7 +899,7 @@ void draw_pass_model_fx(float elapsed)
gl::begin(gl::Quads);
}
color.assign(1.0f, 1.0f);
- offset.assign(entity->state()->axis().forward() * engine_size);
+ offset.assign(entity->axis().forward() * engine_size);
if (t > 0)
location -= offset * t;
@@ -1010,7 +944,7 @@ void draw_pass_model_fx(float elapsed)
}
-void draw_pass_model_corona()
+void draw_pass_model_radius()
{
if (!(r_radius && r_radius->value()))
return;
@@ -1018,9 +952,9 @@ void draw_pass_model_corona()
for (core::Zone::Content::iterator it = zone->content().begin(); it != zone->content().end(); it++) {
core::Entity *entity = (*it);
- if (entity->model() && entity->state()->visible()) {
+ if (entity->model() && ext_render(entity)->visible()) {
gl::push();
- gl::translate(entity->state()->location());
+ gl::translate(entity->location());
math::Color color = entity->color();
color.a = 0.25f;
draw_sphere(color, entity->model()->radius());
@@ -1094,17 +1028,17 @@ void draw(float seconds)
// enable vertex arrays
glEnableClientState(GL_VERTEX_ARRAY);
- glEnableClientState(GL_COLOR_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);
- gl::enable(GL_DEPTH_TEST);
+ gl::disable(GL_DEPTH_TEST);
gl::depthmask(GL_FALSE); // disable depth buffer writing
draw_pass_sky(); // draw the skysphere
gl::depthmask(GL_TRUE); // enable writing to the depth buffer
+ gl::enable(GL_DEPTH_TEST);
gl::enable(GL_CULL_FACE); // enable culling
gl::enable(GL_COLOR_MATERIAL); // enable color tracking
@@ -1112,6 +1046,7 @@ void draw(float seconds)
//gl::enable(GL_RESCALE_NORMAL); // rescale normals by the transformation matrix scale factor
gl::enable(GL_NORMALIZE);
+
draw_pass_globes(); // draw globes
draw_pass_default(); // draw entities without model
@@ -1140,7 +1075,7 @@ void draw(float seconds)
gl::enable(GL_LIGHTING);
gl::enable(GL_RESCALE_NORMAL);
- draw_pass_model_corona(); // draw entity radius
+ draw_pass_model_radius(); // draw entity radius
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
diff --git a/src/render/dust.cc b/src/render/dust.cc
index 81d40fb..4b74ef9 100644
--- a/src/render/dust.cc
+++ b/src/render/dust.cc
@@ -120,13 +120,13 @@ void Dust::draw(math::Color const &dustcolor)
float dsquare = 0;
for (size_t j = 0; j < 3; j++) {
dsquare += (core::localcontrol()->location()[j] - dust[i*3+j]) * (core::localcontrol()->location()[j] - dust[i*3+j]);
- v[j] = dust[i*3+j] - core::localcontrol()->state()->axis().forward()[j] * traillength;
+ v[j] = dust[i*3+j] - core::localcontrol()->axis().forward()[j] * traillength;
}
if (dsquare > (core::localcontrol()->radius() + DUSTDISTANCE)*(core::localcontrol()->radius() + DUSTDISTANCE)) {
for (size_t j = 0; j < 3; j++) {
dust[i*3+j] = core::localcontrol()->location()[j] + (math::randomf(2) - 1) * (DUSTDISTANCE + core::localcontrol()->radius());
- v[j] = dust[i*3+j] - core::localcontrol()->state()->axis().forward()[j] * traillength;
+ v[j] = dust[i*3+j] - core::localcontrol()->axis().forward()[j] * traillength;
}
}
diff --git a/src/render/render.cc b/src/render/render.cc
index 81237dc..ab3b751 100644
--- a/src/render/render.cc
+++ b/src/render/render.cc
@@ -118,6 +118,10 @@ void unload()
globe->render_texture = 0;
}
}
+
+ if (ext_render(entity)) {
+ delete ext_render(entity);
+ }
}
}
@@ -143,6 +147,10 @@ void clear()
core::EntityGlobe *globe = static_cast<core::EntityGlobe *>(entity);
globe->render_texture = 0;
}
+
+ if (ext_render(entity)) {
+ delete ext_render(entity);
+ }
}
// clear model refistry
diff --git a/src/render/render.h b/src/render/render.h
index 4317540..422e521 100644
--- a/src/render/render.h
+++ b/src/render/render.h
@@ -17,6 +17,7 @@
#include "render/gl.h"
#include "render/text.h"
#include "render/textures.h"
+#include "render/renderext.h"
namespace render {
@@ -44,6 +45,12 @@ namespace render {
extern model::VertexArray *vertexarray;
+
+ inline RenderExt *ext_render(core::Entity *entity) { return static_cast<RenderExt *>(entity->extension((size_t)core::Extension::Render)); }
+
+ const float drawdistance = 256.0f;
+ const float drawfxdistance = 64.0f;
+ const float farplane = 1016.0f;
}
diff --git a/src/render/renderext.cc b/src/render/renderext.cc
new file mode 100644
index 0000000..ffe462f
--- /dev/null
+++ b/src/render/renderext.cc
@@ -0,0 +1,114 @@
+/*
+ render/renderext.cc
+ This file is part of the Osirion project and is distributed under
+ the terms of the GNU General Public License version 2
+*/
+
+#include <sstream>
+#include <iomanip>
+
+#include "math/functions.h"
+#include "core/range.h"
+#include "model/model.h"
+#include "render/renderext.h"
+#include "render/render.h"
+#include "render/textures.h"
+
+namespace render
+{
+
+RenderExt::RenderExt(core::Entity *entity) : core::Extension(core::Extension::Render, entity)
+{
+ state_visible = false;
+ state_detailvisible = false;
+ state_fuzz = math::randomf();
+
+ state_engine_trail_offset = 0;
+
+ using namespace model;
+
+ if (entity->model()) {
+ model::Model *model = entity->model();
+
+ for (Model::Lights::iterator lit = model->lights().begin(); lit != model->lights().end(); lit++) {
+ Light *light = (*lit);
+
+ // load light texture
+ std::stringstream flarename;
+ flarename << "bitmaps/fx/flare" << std::setfill('0') << std::setw(2) << light->flare();
+ light->render_texture = Textures::load(flarename.str());
+ }
+
+ for(Model::Engines::iterator eit = model->engines().begin(); eit != model->engines().end(); eit++) {
+ Engine *engine = (*eit);
+
+ if (!engine->flare()) engine->engine_flare = 1;
+
+ // load engine texture
+ std::stringstream flarename;
+ flarename << "bitmaps/fx/flare" << std::setfill('0') << std::setw(2) << engine->flare();
+ engine->render_texture = Textures::load(flarename.str());
+ }
+
+ for (Model::Flares::iterator flit = model->flares().begin(); flit != model->flares().end(); flit++) {
+ Flare *flare = (*flit);
+
+ // load flare texture
+ std::stringstream flarename;
+ flarename << "bitmaps/fx/flare" << std::setfill('0') << std::setw(2) << flare->flare();
+ flare->render_texture = Textures::load(flarename.str());
+ }
+ } else if (entity->type() == core::Entity::Globe) {
+ core::EntityGlobe *globe = static_cast<core::EntityGlobe *>(entity);
+
+ // load globe textures
+ if (!globe->render_texture && globe->texture().size()) {
+ std::stringstream texname;
+ texname << "textures/" << globe->texture();
+ globe->render_texture = Textures::load(texname.str());
+ if (!globe->render_texture)
+ globe->entity_texture.clear();
+ }
+ }
+}
+
+RenderExt::~RenderExt()
+{
+}
+
+void RenderExt::frame(float elapsed)
+{
+ state_distance = math::distance(Camera::eye(), entity()->location());
+
+ state_visible = entity()->visible();
+ state_detailvisible = false;
+
+ if ((entity()->type() == core::Entity::Controlable)) {
+ if (static_cast<core::EntityDynamic *>(entity())->eventstate() == core::Entity::Docked) {
+ state_visible = false;
+ }
+ }
+
+ if (state_visible && entity()->model()) {
+ float r = entity()->model()->radius();
+ math::clamp(r, 1.0f, farplane / drawfxdistance);
+ if (distance() < drawfxdistance * r) {
+ // entity within detail range
+ state_visible = true;
+ state_detailvisible = true;
+ } else if ((distance() < drawdistance * r) && (distance() < core::range::max)) {
+ // entity within drawing distance, outside detail range
+ state_visible = true;
+ state_detailvisible = false;
+ } else {
+ // entity out of range
+ state_visible = false;
+ state_detailvisible = false;
+ }
+ }
+
+}
+
+} // namespace render
+
+
diff --git a/src/render/renderext.h b/src/render/renderext.h
new file mode 100644
index 0000000..eafa707
--- /dev/null
+++ b/src/render/renderext.h
@@ -0,0 +1,45 @@
+/*
+ render/renderext.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_RENDER_RENDEREXT_H__
+#define __INCLUDED_RENDER_RENDEREXT_H__
+
+#include "core/extension.h"
+
+namespace render
+{
+
+/// the render extension of an entity
+class RenderExt :public core::Extension {
+public:
+ RenderExt(core::Entity *entity);
+ ~RenderExt();
+
+ virtual void frame(float elapsed);
+
+ inline bool visible() const { return state_visible; }
+ inline bool detailvisible() const { return state_detailvisible; }
+
+ inline float fuzz() const { return state_fuzz; }
+
+ /// distance to the camera
+ inline float distance() const { return state_distance; }
+
+ // FIXME
+ float state_engine_trail_offset;
+
+private:
+ bool state_visible;
+ bool state_detailvisible;
+
+ float state_fuzz;
+ float state_distance;
+};
+
+} // namespace render
+
+#endif // __INCLUDED_RENDER_RENDEREXT_H__
+