From 28ba97bdd8fb6ca352dc49dba01a66bd155ad523 Mon Sep 17 00:00:00 2001 From: Stijn Buys Date: Sat, 15 Nov 2008 19:24:55 +0000 Subject: entity extensions --- src/audio/audio.cc | 2 +- src/client/Makefile.am | 10 +- src/client/client.cc | 15 +-- src/client/client.h | 17 +++- src/client/clientext.cc | 23 +++++ src/client/clientext.h | 30 ++++++ src/client/soundext.cc | 147 +++++++++++++++++++++++++++++ src/client/soundext.h | 49 ++++++++++ src/client/targets.cc | 108 +++++----------------- src/client/view.cc | 31 +++++-- src/core/Makefile.am | 12 +-- src/core/application.cc | 6 -- src/core/application.h | 3 - src/core/clientstate.cc | 96 ------------------- src/core/clientstate.h | 95 ------------------- src/core/entity.cc | 22 +++-- src/core/entity.h | 14 +-- src/core/extension.cc | 29 ++++++ src/core/extension.h | 42 +++++++++ src/core/gameconnection.cc | 2 +- src/core/gameinterface.cc | 94 ------------------- src/core/gameinterface.h | 7 -- src/core/gameserver.cc | 12 +-- src/core/netconnection.cc | 2 +- src/model/model.h | 6 ++ src/render/Makefile.am | 7 +- src/render/camera.cc | 23 ++--- src/render/draw.cc | 225 ++++++++++++++++----------------------------- src/render/dust.cc | 4 +- src/render/render.cc | 8 ++ src/render/render.h | 7 ++ src/render/renderext.cc | 114 +++++++++++++++++++++++ src/render/renderext.h | 45 +++++++++ 33 files changed, 696 insertions(+), 611 deletions(-) create mode 100644 src/client/clientext.cc create mode 100644 src/client/clientext.h create mode 100644 src/client/soundext.cc create mode 100644 src/client/soundext.h delete mode 100644 src/core/clientstate.cc delete mode 100644 src/core/clientstate.h create mode 100644 src/core/extension.cc create mode 100644 src/core/extension.h create mode 100644 src/render/renderext.cc create mode 100644 src/render/renderext.h 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(entity->extension(core::Extension::Client)); } + +inline SoundExt *ext_sound(core::Entity *entity) + { return static_cast(entity->extension(core::Extension::Sound)); } + +inline render::RenderExt *ext_render(core::Entity *entity) + { return static_cast(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 +#include + +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(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(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(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 #include +#include #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(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(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(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(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(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 +#include + +#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(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(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__ + -- cgit v1.2.3