From cffe02f49b66a70d40816ffc8dea42f9e52da57f Mon Sep 17 00:00:00 2001 From: Stijn Buys Date: Sat, 28 Feb 2015 20:46:53 +0000 Subject: Reimplemented camera handling enabling 360-degree freelook. --- src/render/camera.cc | 512 +++++++++++++++++------------------------- src/render/camera.h | 305 +++++++++++++++++-------- src/render/draw.cc | 113 +++++++--- src/render/draw.h | 7 +- src/render/dust.cc | 17 +- src/render/dust.h | 5 +- src/render/particleejector.cc | 33 +-- src/render/particleejector.h | 13 +- src/render/particlesystem.cc | 4 +- src/render/particlesystem.h | 3 +- src/render/render.cc | 4 - src/render/renderext.cc | 10 +- src/render/renderext.h | 2 + 13 files changed, 557 insertions(+), 471 deletions(-) (limited to 'src/render') diff --git a/src/render/camera.cc b/src/render/camera.cc index d6cf562..70684d7 100644 --- a/src/render/camera.cc +++ b/src/render/camera.cc @@ -6,17 +6,14 @@ #include -#include "core/application.h" -#include "core/gameinterface.h" -#include "math/mathlib.h" -#include "math/matrix4f.h" #include "render/camera.h" #include "render/gl.h" #include "render/state.h" +#include "core/entity.h" +#include "core/range.h" +#include "math/functions.h" #include "sys/sys.h" -using math::degrees360f; -using math::degrees180f; namespace render { @@ -24,134 +21,72 @@ namespace render const float MIN_DELTA = 10e-10; const float COS_PI_4 = sqrt(2.0f) * 0.5f; -const float pitch_free = -30.0f; -const float pitch_track = -5.0f; -const float pitch_overview = -5.0f; -math::Vector3f Camera::camera_eye; -math::Vector3f Camera::camera_target; -math::Axis Camera::camera_axis; -math::Axis Camera::camera_scene_axis; -Camera::Mode Camera::camera_mode; -Camera::Mode Camera::camera_previous_mode; - -// current and target yaw angle in XZ plane, positive is looking left -float Camera::direction_current; -float Camera::direction_target; -float Camera::target_direction; - -// current and target pitch angle in XY, positive is looking up -float Camera::pitch_current; -float Camera::pitch_target; -float Camera::target_pitch; - -float Camera::distance; -float Camera::camera_zoom; - -void Camera::init() +Camera::Camera(const Mode mode) { - direction_current = 0; - direction_target = 0; - - pitch_current = pitch_track * 2; - pitch_target = pitch_track; - - target_pitch = 0.0f; - target_direction = 0.0f; - - distance = 0.4f; - camera_zoom = 2.0f; - - camera_mode = Overview; - camera_previous_mode = Track; - set_mode(Track); - - camera_axis.clear(); - camera_scene_axis.clear(); - camera_eye.clear(); - camera_target.clear(); - + _mode = mode; + _distance = 1.0f; + _multiplier = 1.0f; + _target_entity = 0; + + _freelook_direction = 0.0f; + _freelook_pitch = 0.0f; + + _movement_direction = 0.0f; + _movement_pitch = 0.0f; } -void Camera::shutdown() +Camera::~Camera() { } -void Camera::set_mode(Mode newmode) +void Camera::set_mode(const Mode mode) { + _mode = mode; + reset(); +} - direction_target = 0; - direction_current = direction_target; - pitch_target = pitch_track; - pitch_current = pitch_target; - - target_direction = 0.0f; - target_pitch = 0.0f; - distance = 0.4f; - - camera_scene_axis.clear(); - - if (camera_mode != Overview) - camera_previous_mode = camera_mode; - - switch (newmode) { - case Track: - // switch camera to Track mode - camera_mode = Track; - if (core::localcontrol()) { - camera_scene_axis.assign(core::localcontrol()->axis()); - } - break; - - case Free: - // switch camera to Free mode - camera_mode = Free; - pitch_target = pitch_free; - pitch_current = pitch_target; - break; - - case Cockpit: - camera_mode = Cockpit; - break; - - case Overview: - // switch camera to Overview mode - camera_mode = Overview; +void Camera::set_multiplier(const float multiplier) +{ + _multiplier = multiplier; +} - default: - break; - } +void Camera::set_freelook_direction(const float angle) +{ + _freelook_direction = angle; +} +void Camera::set_freelook_pitch(const float angle) +{ + _freelook_pitch = angle; } -void Camera::view_next() +void Camera::set_movement_direction(const float speed) +{ + _movement_direction = speed; + math::clamp(_movement_direction, -1.0f, 1.0f); +} + +void Camera::set_movement_pitch(const float speed) { + _movement_pitch = speed; + math::clamp(_movement_pitch, -1.0f, 1.0f); +} - if (!core::localcontrol()) { - set_mode(Overview); - return; - } +void Camera::cycle_mode_next() +{ - switch (camera_mode) { + switch (mode()) { case Free: - // switch camera to Track mode set_mode(Track); - //con_print << "view: track" << std::endl; - //core::application()->notify_message(core::Message::Info, std::string("view: track")); break; case Track: - // switch camera to Cockpit mode set_mode(Cockpit); - //con_print << "view: cockpit" << std::endl; - //core::application()->notify_message(core::Message::Info, std::string("view: cockpit")); break; case Cockpit: - // switch camera to Free mode set_mode(Free); - //con_print << "view: free" << std::endl; - //core::application()->notify_message(core::Message::Info, std::string("view: free")); break; default: @@ -159,34 +94,19 @@ void Camera::view_next() } } -void Camera::view_previous() +void Camera::cycle_mode_previous() { - - if (!core::localcontrol()) { - set_mode(Overview); - return; - } - - switch (camera_mode) { + switch (mode()) { case Cockpit: - // switch camera to Track mode set_mode(Track); - //con_print << "view: track" << std::endl; - //core::application()->notify_message(core::Message::Info, std::string("view: track")); break; case Free: - // switch camera to Cockpit mode set_mode(Cockpit); - //con_print << "view: cockpit" << std::endl; - //core::application()->notify_message(core::Message::Info, std::string("view: cockpit")); break; case Track: - // switch camera to Free mode set_mode(Free); - //con_print << "view: free" << std::endl; - //core::application()->notify_message(core::Message::Info, std::string("view: free")); break; default: @@ -194,180 +114,182 @@ void Camera::view_previous() } } -void Camera::set_zoom(float zoom) +void Camera::reset() { - camera_zoom += zoom; - math::clamp(camera_zoom, 1.0f, 10.0f); -} + if (target()) + { + _target_location.assign(target()->location()); + _target_axis.assign(target()->axis()); + _distance = 0.0f; + } + else + { + _location.clear(); + _target_axis.clear(); + _distance = 0.0f; + } + _axis.assign(_target_axis); + if (mode() == Free) + { + _target_axis.clear(); + } + + _freelook_direction = 0.0f; + _freelook_pitch = 0.0f; -void Camera::frame(float seconds) + _movement_direction = 0.0f; + _movement_pitch = 0.0f; +} +void Camera::set_target(const core::Entity *entity) { - math::Axis target_axis; - float d = 0; - - if (core::localplayer()->view()) { - if (camera_mode != Overview) { - set_mode(Overview); - } - } else if (core::localcontrol()) { - if (camera_mode == Overview) { - set_mode(camera_previous_mode); - } - } else { - if (camera_mode != Overview) { - set_mode(Overview); - } - } + _target_entity = entity; +} - if (mode() == Overview) { - camera_eye.clear(); - - if (core::localplayer()->view()) { - // player view entity - - camera_scene_axis.assign(core::localplayer()->view()->axis()); - if (core::localplayer()->view() == core::localcontrol()) { - camera_scene_axis.change_pitch(pitch_free); - camera_target.assign(core::localplayer()->view()->location()); - distance = math::max(core::localplayer()->view()->radius(), 1.0f) * 2.0f; - } else { - distance = math::max(core::localplayer()->view()->radius(), 1.0f) * 3.0f; - camera_scene_axis.change_direction(180.0f); - camera_target.assign(core::localplayer()->view()->location() - core::localplayer()->view()->axis().left()*(math::max(core::localplayer()->view()->radius(), 1.0f)*0.5f)); +void Camera::frame(const float elapsed) +{ + const float ROTATESPEED = 25.0f * elapsed; + switch(mode()) + { + case Track: + { + math::Axis desired_axis; + + // 3rd person view + if (target()) + { + _target_location.assign(target()->location()); + + if (target()->model()) + { + const float modelscale = target()->radius() / target()->model()->radius(); + _target_location += target()->axis().up() * target()->model()->box().max().z() * modelscale; + } + else + { + _target_location += target()->axis().up() * target()->radius(); + } + desired_axis.assign(target()->axis()); + _distance = target()->radius() * _multiplier * 2.0f; } - - /* - } else if (core::localplayer()->zone()->default_view()) { - // default zone view entity - camera_target.assign(core::localplayer()->zone()->default_view()->location()); - camera_scene_axis.assign(core::localplayer()->zone()->default_view()->axis()); - camera_scene_axis.change_direction(180.0f); - distance = math::max(core::localplayer()->zone()->default_view()->radius(), 1.0f) * 2.0f; - */ - } else { - // default location (0,0,0) - camera_target.clear(); - camera_scene_axis.clear(); - pitch_current = pitch_overview; - camera_scene_axis.change_pitch(pitch_current); - distance = 8.0f; - } - } else { - - camera_target.assign(core::localcontrol()->location()); - target_axis.assign(core::localcontrol()->axis()); - distance = core::localcontrol()->radius(); - - if (mode() == Track) { - - float cosangle; // cosine of an angle - float angle; // angle in radians - math::Vector3f n; // normal of a plane + else + { + _target_location.assign(0.0f, 0.0f, 1.0f); + _distance = _multiplier * 2.0f; + } + // FIXME Bad solution below - // freelook target - target_axis.change_direction(90 * target_direction); - target_axis.change_pitch(90 * target_pitch); - - // rotate scene axis towards target axis - n.assign(math::crossproduct(camera_scene_axis.forward(), target_axis.forward())); - if (!(n.length() < MIN_DELTA)) { + math::Vector3f n (math::crossproduct(_target_axis.forward(), desired_axis.forward())); + float l = n.length(); + float d = math::dotproduct(_target_axis.forward(), desired_axis.forward()); + float a = (d > 0.0f ? 1.0f - d : 1.0f); + if ((a > MIN_DELTA) && (l > MIN_DELTA)) + { n.normalize(); - cosangle = math::dotproduct(camera_scene_axis.forward(), target_axis.forward()); - angle = acos(cosangle) * seconds; // * 180.0f / M_PI; - if (angle > MIN_DELTA) - camera_scene_axis.rotate(n, -angle); + _target_axis.rotate(n, -ROTATESPEED * a); + } - - n.assign(math::crossproduct(camera_scene_axis.left(), target_axis.left())); - if (!(n.length() < MIN_DELTA)) { + + n.assign (math::crossproduct(_target_axis.up(), desired_axis.up())); + l = n.length(); + d = math::dotproduct(_target_axis.up(), desired_axis.up()); + a = (d > 0.0f ? 1.0f - d : 1.0f); + if ((a > MIN_DELTA) && (l > MIN_DELTA)) + { n.normalize(); - cosangle = math::dotproduct(camera_scene_axis.left(), target_axis.left()); - angle = acos(cosangle) * seconds; // * 180.0f / M_PI; - if (angle > MIN_DELTA) - camera_scene_axis.rotate(n, -angle); + _target_axis.rotate(n, -ROTATESPEED * a); + } - n.assign(math::crossproduct(camera_scene_axis.up(), target_axis.up())); - if (!(n.length() < MIN_DELTA)) { - n.normalize(); - cosangle = math::dotproduct(camera_scene_axis.up(), target_axis.up()); - angle = acos(cosangle) * seconds; // * 180.0f / M_PI; - if (angle > MIN_DELTA) - camera_scene_axis.rotate(n, -angle); + _axis.assign(_target_axis); + _axis.change_direction(_freelook_direction); + _axis.change_pitch(_freelook_pitch); + break; + } + + case Cockpit: + { + // 1st person view + if (target()) + { + _target_location.assign(target()->location()); + _target_axis.assign(target()->axis()); + _distance = 0.0f; } - - if (core::localcontrol()->model() && core::localcontrol()->model()->radius()) { - const float modelscale = core::localcontrol()->radius() / core::localcontrol()->model()->radius(); + else + { + _target_location.clear(); + _target_axis.clear(); + _distance = 0.0f; + } + + _axis.assign(_target_axis); + _axis.change_direction(_freelook_direction); + _axis.change_pitch(_freelook_pitch); + break; + } + case Free: + { + // look at self + if (target()) + { + _target_location.assign(target()->location()); + _axis.assign(target()->axis()); - camera_target -= camera_scene_axis.forward() * math::max(FRUSTUMFRONT / WORLDSCALE, core::localcontrol()->model()->box().max().x() * modelscale); - camera_target += camera_scene_axis.up() * math::max(FRUSTUMFRONT / WORLDSCALE, core::localcontrol()->model()->box().max().z() * modelscale); - } else { - camera_target -= camera_scene_axis.forward() * math::max(FRUSTUMFRONT / WORLDSCALE, FRUSTUMFRONT / WORLDSCALE + core::localcontrol()->radius()); - camera_target += camera_scene_axis.up() * math::max(FRUSTUMFRONT / WORLDSCALE, FRUSTUMFRONT / WORLDSCALE + core::localcontrol()->radius()); + _distance = target()->radius() * _multiplier * 2.0f; + } + else + { + _target_location.clear(); + _axis.clear(); + + _distance = _multiplier * 2.0f; } - distance = math::max(FRUSTUMFRONT / WORLDSCALE, FRUSTUMFRONT / WORLDSCALE + camera_zoom * core::localcontrol()->radius()) + 0.001f; - - } else if (mode() == Free) { - - camera_scene_axis.assign(target_axis); - - direction_target = direction_current - 90 * target_direction; - pitch_target = pitch_current - 90 * target_pitch; - - // adjust direction - d = degrees180f(direction_current - direction_target); - direction_current = degrees360f(direction_current - d * seconds); - camera_scene_axis.change_direction(direction_current); - - // adjust pitch - d = degrees180f(pitch_current - pitch_target); - pitch_current = degrees360f(pitch_current - d * seconds); - camera_scene_axis.change_pitch(pitch_current); - - distance = math::max(FRUSTUMFRONT / WORLDSCALE, FRUSTUMFRONT / WORLDSCALE + camera_zoom * core::localcontrol()->radius()) + 0.001f; - - } else if (mode() == Cockpit) { + _target_axis.rotate(math::Vector3f(0.0f, 0.0f, 1.0f), -M_PI * _movement_direction * elapsed); + _target_axis.change_pitch(180.0f * _movement_pitch * elapsed); - camera_scene_axis.assign(target_axis); - - direction_target = + 90 * target_direction; - pitch_target = + 90 * target_pitch; - - // adjust direction - d = degrees180f(direction_current - direction_target); - direction_current = degrees360f(direction_current - d * seconds); - camera_scene_axis.change_direction(direction_current); - - // adjust pitch - d = degrees180f(pitch_current - pitch_target); - pitch_current = degrees360f(pitch_current - d * seconds); - camera_scene_axis.change_pitch(pitch_current); - - if (core::localcontrol()->model()) { - const float modelscale = core::localcontrol()->radius() / core::localcontrol()->model()->radius(); - camera_target += (core::localcontrol()->model()->box().max().x() * modelscale) * - core::localcontrol()->axis().forward(); - } else { - camera_target += (core::localcontrol()->radius()) * - core::localcontrol()->axis().forward(); + _axis.assign(_axis * _target_axis); + _axis.change_direction(_freelook_direction); + _axis.change_pitch(_freelook_pitch); + break; + } + case Overview: + { + if (target()) + { + _target_location.assign(target()->location()); + _target_axis.assign(target()->axis()); + _distance = 2.0f * target()->radius() * _multiplier; + + _target_axis.change_direction(180.0f); + + // default pitch angle + _target_axis.change_pitch(-5.0f); + } + else + { + _target_location.clear(); + _target_axis.clear(); + + _distance = 2.0f * _multiplier; } - distance = (FRUSTUMFRONT / WORLDSCALE) - 0.001f; + + _axis.assign(_target_axis); + break; } } - - // calculate eye position - camera_eye = camera_target - (distance * camera_scene_axis.forward()); - camera_axis.assign(camera_scene_axis); + + _distance += FRUSTUMFRONT / WORLDSCALE; + _location.assign(_target_location - _axis.forward() * _distance); } -void Camera::frustum() +void Camera::draw() { // Change to the projection matrix and set our viewing volume large enough for the skysphere gl::matrixmode(GL_PROJECTION); gl::loadidentity(); - gl::frustum(-FRUSTUMSIZE, FRUSTUMSIZE, -FRUSTUMSIZE / State::aspect(), FRUSTUMSIZE / State::aspect(), FRUSTUMFRONT, core::range::maxdistance * WORLDSCALE); + gl::frustum(-FRUSTUMSIZE, FRUSTUMSIZE, -FRUSTUMSIZE / State::aspect(), FRUSTUMSIZE / State::aspect(), FRUSTUMFRONT, FARPLANE); gl::matrixmode(GL_MODELVIEW); gl::loadidentity(); @@ -376,25 +298,25 @@ void Camera::frustum() gl::rotate(-90.0f, 1.0f , 0.0f, 0.0f); // apply the transpose of the axis transformation (the axis is orhtonormal) - math::Matrix4f matrix; - matrix.assign(camera_scene_axis); + math::Matrix4f matrix(_axis); gl::multmatrix(matrix.transpose()); - gl::scale(4.0f, 4.0f, 4.0f); - - gl::translate(-1.0f * camera_eye); + // apply world scale + gl::scale(WORLDSCALE, WORLDSCALE, WORLDSCALE); + // apply camera eye translation + gl::translate(-1.0f * _location); } -void Camera::frustum_default(float distance, float cx, float cy) +void Camera::draw(const float center_x, const float center_y) { // Change to the projection matrix and set our viewing volume large enough for the skysphere gl::matrixmode(GL_PROJECTION); gl::loadidentity(); - // move eye to (cx, cy) + // move projection center to (cx, cy) // note: the factor 2.0f probably has to be 1.0f/frustum_size - gl::translate(2.0f*(-State::width() * 0.5f + cx) / State::width() , 2.0f*(State::height() * 0.5f - cy) / State::height(), 0.0f); + gl::translate(2.0f*(-State::width() * 0.5f + center_x) / State::width() , 2.0f * (State::height() * 0.5f - center_y) / State::height(), 0.0f); gl::frustum(-FRUSTUMSIZE, FRUSTUMSIZE, -FRUSTUMSIZE / State::aspect(), FRUSTUMSIZE / State::aspect(), FRUSTUMFRONT, 1023.0f); @@ -404,10 +326,13 @@ void Camera::frustum_default(float distance, float cx, float cy) // map world coordinates to opengl coordinates gl::rotate(90.0f, 0.0f, 1.0f, 0.0f); gl::rotate(-90.0f, 1.0f , 0.0f, 0.0f); + + // apply the transpose of the axis transformation (the axis is orhtonormal) + math::Matrix4f matrix(_axis); + gl::multmatrix(matrix.transpose()); - gl::translate(distance + 1.0f, 0.0f, 0.0f); - camera_eye.assign(-distance - 1.0f, 0.0f, 0.0f); - camera_axis.clear(); + // apply camera eye translation + gl::translate(-1.0f * _location); } void Camera::ortho() @@ -420,22 +345,7 @@ void Camera::ortho() gl::matrixmode(GL_MODELVIEW); gl::loadidentity(); } + -void Camera::set_direction(float direction) -{ - target_direction = direction; - math::clamp(target_direction, -1.0f, 1.0f); -} +} // namespace render -void Camera::set_pitch(float pitch) -{ - target_pitch = pitch; - math::clamp(target_pitch, -1.0f, 1.0f); -} - -void Camera::reset() -{ - set_mode(camera_mode); -} - -} diff --git a/src/render/camera.h b/src/render/camera.h index cc6eaa5..4d01fa2 100644 --- a/src/render/camera.h +++ b/src/render/camera.h @@ -7,114 +7,235 @@ #ifndef __INCLUDED_RENDER_CAMERA_H__ #define __INCLUDED_RENDER_CAMERA_H__ -#include "math/mathlib.h" #include "core/range.h" +#include "math/vector3f.h" +#include "math/axis.h" + +namespace core +{ + class Entity; +} namespace render { const float WORLDSCALE = 4.0f; -const float FARPLANE = core::range::maxdistance; + const float FRUSTUMSIZE = 0.5f; const float FRUSTUMFRONT = 1.0f; +const float FARPLANE = core::range::maxdistance * WORLDSCALE; -/// camera functions +/** + * @brief The Camera class draws a camera transformation determined by its current settings + * */ class Camera { public: - - /// enum indicating the camera mode - enum Mode {Free, Track, Cockpit, Overview}; - - /// initialize the camera - static void init(); - - /// shutdown the camera - static void shutdown(); - - /// gameworld coordinates of the camera eye - static inline const math::Vector3f & eye() { - return camera_eye; + /** + * @brief enum indicating the camera mode + * */ + enum Mode {Track, Cockpit, Free, Overview}; + + /** + * @brief default constructor + * */ + Camera(const Mode mode = Track); + + /** + * @brief destructor + * */ + ~Camera(); + + /* --- inspectors ------------------------------------------ */ + + /** + * @brief current camera mode + * */ + inline const Mode mode() const + { + return _mode; } - - /// gameworld coordinates of the camera target - static inline const math::Vector3f & target() { - return camera_target; + + /** + * @brief distance between the camera eye and the target + * */ + inline const float distance() const + { + return _distance; } - - /// gameworld camera axis - static inline const math::Axis & axis() { - return camera_axis; + + /** + * @brief distance multiplier + * The distance multiplier can be used to zoom the camera in or out + * */ + inline const float multiplier() const + { + return _multiplier; } - - /// current camera mode - static inline Mode mode() { - return camera_mode; + + /** + * @brief camera eye location, translation part of the camera transformation + * */ + inline const math::Vector3f & location() const + { + return _location; } - - /// reset the current mode - static void reset(); - - /// progress the camera - static void frame(float elapsed); - - /// enable camera frustum projection - /** The camera frustum projection is used to draw the world - */ - static void frustum(); - - /// enable default frustum projection - /** The default frustum projection is used to draw Gui 3D models - */ - static void frustum_default(float distance, float cx, float cy); - - /// enable orthographic projection - /** The ortographic projetion is used to draw the user interface - */ + + /** + * @brief camera target location,point the camera is looking at + * */ + inline const math::Vector3f & target_location() const + { + return _target_location; + } + + /** + * @brief camera eye axis, rotation part of the camera transformation + * */ + inline const math::Axis & axis() const + { + return _axis; + } + + /** + * @brief the entity the camera is currently looking at + * */ + inline const core::Entity *target() + { + return _target_entity; + } + + /** + * @brief free look direction angle, in degrees + * */ + inline const float freelook_direction() const + { + return _freelook_direction; + } + + /** + * @brief free look pitch angle, in degrees + * */ + inline const float freelook_pitch() const + { + return _freelook_pitch; + } + + /** + * @brief free look direction rotation speed, -1..1 + * */ + inline const float movement_direction() const + { + return _movement_direction; + } + + /** + * @brief free look pitch rotation speed, -1..1 + * */ + inline const float movement_pitch() const + { + return _movement_pitch; + } + + /* --- mutators -------------------------------------------- */ + + /** + * @brief set the current camera mode + * */ + void set_mode(const Mode mode); + + /** + * @brief set next camera mode + * */ + void cycle_mode_next(); + + /** + * @brief set previous camera mode + * */ + void cycle_mode_previous(); + + /** + * @brief set camera target + * */ + void set_target(const core::Entity *entity = 0); + + /** + * @brief set distance multiplier + * */ + void set_multiplier(const float multiplier); + + /** + * @brief set the free look direction angle, in degrees + * */ + void set_freelook_direction(const float angle); + + /** + * @brief set the free look pitch angle, in degrees + * */ + void set_freelook_pitch(const float angle); + + /** + * @brief set the free look direction rotation speed, -1..1 + * */ + void set_movement_direction(const float speed); + + /** + * @brief set the free look pitch rotation speed, -1..1 + * */ + void set_movement_pitch(const float speed); + + /* --- actors ---------------------------------------------- */ + + void reset(); + + /** + * @brief update the camera location and axis. + * */ + void frame(const float elapsed); + + /** + * @brief draw the actual camera transformation + * This method is used to draw the camera projection for the world render + * and applies WORLDSCALE. + * */ + void draw(); + + /** + * @brief draw the actual camera transformation + * This method variant is used by the user interface 3D model widget + * and ignores WORLDSCALE. + * */ + void draw(const float center_x, const float center_y); + + /* --- static ---------------------------------------------- */ + + /** + * @brief set the current transformation matrix to a orthographic projection + * This method is used while drawing the user interface. + * */ static void ortho(); - /// set target zoom - static void set_zoom(float zoom); - - /// set target direction - static void set_direction(float direction); - - /// set target pitch - static void set_pitch(float pitch); - - /// switch to next camera mode - static void view_next(); - - /// wtich to previous camera mode - static void view_previous(); - - /// set specified camera mode - static void set_mode(Mode newmode); - private: - static math::Vector3f camera_eye; - static math::Vector3f camera_target; - static math::Axis camera_axis; - static math::Axis camera_scene_axis; - static Mode camera_mode; - static Mode camera_previous_mode; - - - // current and target yaw angle in XZ plane, positive is looking left - static float direction_current; - static float direction_target; - static float target_direction; - - // current and target pitch angle in XY, positive is looking up - static float pitch_current; - static float pitch_target; - static float target_pitch; - - static float distance; - static float camera_zoom; - -}; - -} // namespace client - -#endif // __INCLUDED_RENDER_CAMERA_H__ + Mode _mode; + + float _distance; + float _multiplier; + math::Vector3f _location; + math::Axis _axis; + + const core::Entity * _target_entity; + math::Vector3f _target_location; + math::Axis _target_axis; + + float _freelook_direction; + float _freelook_pitch; + + float _movement_direction; + float _movement_pitch; + + +}; // class camera + +} // namespace render + +#endif // __INCLUDED_RENDER_CAMERA_H__ diff --git a/src/render/draw.cc b/src/render/draw.cc index c9ccafe..f354780 100644 --- a/src/render/draw.cc +++ b/src/render/draw.cc @@ -19,6 +19,7 @@ #include "model/material.h" #include "model/model.h" +#include "render/camera.h" #include "render/debugdrawer.h" #include "render/draw.h" #include "render/dust.h" @@ -54,6 +55,10 @@ math::Vector3f v7(-1, -1, -1); core::Zone *zone = 0; +Camera _camera_control(Camera::Track); +Camera _camera_overview(Camera::Overview); +Camera *_camera = &_camera_control; + bool draw_particles = true; bool draw_lights = true; @@ -79,11 +84,50 @@ bool compare_entity_distance(const core::Entity * entityfirst, const core::Entit LightEnvironment lightenv_zone; +Camera & camera() +{ + return *_camera; +} + /* ---- Prepare the renderer state --------------------------------- */ void pass_prepare(float seconds) { - using namespace model; + // initialize camera + const core::Entity *previous_target = _camera->target(); + + if (core::localplayer()->view()) + { + _camera = &_camera_overview; + _camera->set_target(core::localplayer()->view()); + _camera->set_multiplier(2.0f); + } + else if (core::localcontrol()) + { + if (core::localcontrol()->state() == core::Entity::Destroyed) + { + _camera = &_camera_overview; + _camera->set_multiplier(1.0f); + } + else + { + _camera = &_camera_control; + } + _camera->set_target(core::localcontrol()); + } + else + { + _camera = &_camera_overview; + _camera->set_target(0); + } + + if (_camera->target() != previous_target) + { + _camera->reset(); + } + + _camera->frame(seconds); + _camera->draw(); // render settings for this pass_prepare draw_lights = true; @@ -121,7 +165,7 @@ void pass_prepare(float seconds) if (!ext_render(entity)) { new RenderExt(entity); } - entity->extension((size_t) core::Extension::Render)->frame(seconds); + ext_render(entity)->frame(seconds, *_camera); if (entity->type() == core::Entity::Globe) { @@ -146,7 +190,7 @@ void pass_prepare(float seconds) else { // add entity to draw lists - if (entity->visible() || !ext_render(entity)->behind()) + if (entity->visible() && !ext_render(entity)->behind()) { drawlist_entities.push_back(entity); } @@ -194,11 +238,11 @@ void draw_pass_sky() gl::enable(GL_TEXTURE_CUBE_MAP); gl::push(); - gl::translate(Camera::eye()); + gl::translate(_camera->location()); gl::color(1.0f, 1.0f, 1.0f, 1.0f); - const float r = 128.0f; + const float r = core::range::maxdistance * 0.5f; gl::begin((r_wireframe && r_wireframe->value()) ? gl::LineLoop : gl::Quads); @@ -239,10 +283,10 @@ void draw_pass_sky() gl::texcoord(-1, 1, -1); gl::vertex(-r, r, -r); gl::end(); - - gl::disable(GL_TEXTURE_CUBE_MAP); gl::pop(); + + gl::disable(GL_TEXTURE_CUBE_MAP); Stats::quads += 6; } @@ -298,18 +342,19 @@ void draw_sphere(const math::Color & color, float radius) } } -void draw_globe_corona(const math::Vector3f location, const math::Color & color, const float radius, const size_t corona_id) +void draw_globe_corona(const Camera & camera, const math::Vector3f & location, const math::Color & color, const float radius, const size_t corona_id) { // draw the globe's corona if (corona_id) { - math::Vector3f v = location - Camera::eye(); + math::Vector3f v(location - camera.location()); v.normalize(); - float a = dotproduct(v, Camera::axis().forward()); + float a = dotproduct(v, camera.axis().forward()); if (a > 0.1f) { - gl::enable(GL_BLEND); + gl::disable(GL_DEPTH_TEST); gl::depthmask(GL_FALSE); // disable depth buffer writes gl::enable(GL_TEXTURE_2D); + gl::enable(GL_BLEND); Textures::bind(corona_id); @@ -320,21 +365,21 @@ void draw_globe_corona(const math::Vector3f location, const math::Color & color, gl::begin(gl::Quads); gl::texcoord(0, 1); - gl::vertex((Camera::axis().up() - Camera::axis().left()) * radius * 4.0f); + gl::vertex((camera.axis().up() - camera.axis().left()) * radius * 4.0f); gl::texcoord(0, 0); - gl::vertex((Camera::axis().up() + Camera::axis().left()) * radius * 4.0f); + gl::vertex((camera.axis().up() + camera.axis().left()) * radius * 4.0f); gl::texcoord(1, 0); - gl::vertex((Camera::axis().up() * -1 + Camera::axis().left()) * radius * 4.0f); + gl::vertex((camera.axis().up() * -1.0f + camera.axis().left()) * radius * 4.0f); gl::texcoord(1, 1); - gl::vertex((Camera::axis().up() * -1 - Camera::axis().left()) * radius * 4.0f); + gl::vertex((camera.axis().up() * -1.0f - camera.axis().left()) * radius * 4.0f); gl::end(); Stats::quads++; + gl::disable(GL_BLEND); gl::disable(GL_TEXTURE_2D); - gl::enable(GL_DEPTH_TEST); gl::depthmask(GL_TRUE); // enable depth buffer writes - gl::disable(GL_BLEND); + gl::enable(GL_DEPTH_TEST); } } } @@ -410,10 +455,10 @@ void draw_pass_globes() math::Vector3f location(globe->location()); float radius = globe->radius(); - if (ext_render(globe)->distance() > (FARPLANE - globe->radius())) { + if (ext_render(globe)->distance() > (core::range::maxdistance - globe->radius())) { // globe is behind the far plane, make a fake size calculation - location = Camera::eye() + (location - Camera::eye()) * ((FARPLANE - globe->radius()) / ext_render(globe)->distance()); - radius *= (FARPLANE - globe->radius()) / (ext_render(globe)->distance()); + location = _camera->location() + (location - _camera->location()) * ((core::range::maxdistance - globe->radius()) / ext_render(globe)->distance()); + radius *= (core::range::maxdistance - globe->radius()) / (ext_render(globe)->distance()); gl::depthmask(GL_FALSE); @@ -428,7 +473,7 @@ void draw_pass_globes() if (globe->corona_id()) { // draw globe corona // corona is rendered in camera space - draw_globe_corona(location, globe->color(), radius, globe->corona_id()); + draw_globe_corona(*_camera, location, globe->color(), radius, globe->corona_id()); } } @@ -446,7 +491,7 @@ void draw_pass_globes() draw_sphere(globe->color(), radius); - if (globe->rings_id()) { + if (globe->rings_id()) { if (!globe->texture_id()) { gl::enable(GL_TEXTURE_2D); } @@ -463,7 +508,7 @@ void draw_pass_globes() gl::enable(GL_LIGHTING); } - if (ext_render(globe)->distance() > (FARPLANE - globe->radius())) { + if (ext_render(globe)->distance() > (core::range::maxdistance - globe->radius())) { gl::depthmask(GL_TRUE); lightenv_zone.draw(); } @@ -1009,13 +1054,13 @@ void draw_model_lights(model::Model *model, const float scale, gl::color(color); gl::texcoord(1, 0); - gl::vertex(location + (Camera::axis().up() - Camera::axis().left()) * light_size); + gl::vertex(location + (_camera->axis().up() - _camera->axis().left()) * light_size); gl::texcoord(0, 0); - gl::vertex(location + (Camera::axis().up() + Camera::axis().left()) * light_size); + gl::vertex(location + (_camera->axis().up() + _camera->axis().left()) * light_size); gl::texcoord(0, 1); - gl::vertex(location + (Camera::axis().up() * -1 + Camera::axis().left()) * light_size); + gl::vertex(location + (_camera->axis().up() * -1 + _camera->axis().left()) * light_size); gl::texcoord(1, 1); - gl::vertex(location + (Camera::axis().up() * -1 - Camera::axis().left()) * light_size); + gl::vertex(location + (_camera->axis().up() * -1 - _camera->axis().left()) * light_size); nbquads++; } @@ -1041,7 +1086,7 @@ void draw_model_lights(model::Model *model, const float scale, // calulcate viewing angle factor flare_axis.assign(entity_axis * flare->axis()); - a = math::absf(dotproduct(flare_axis.forward(), Camera::axis().forward())); + a = math::absf(dotproduct(flare_axis.forward(), _camera->axis().forward())); if (a < 0.001f) { continue; // next flare } @@ -1166,7 +1211,7 @@ void draw_pass_model_fx(float elapsed) if (draw_particles && ext_render(entity)->particles().size()) { for (RenderExt::ParticleSystems::iterator it = ext_render(entity)->particles().begin(); it != ext_render(entity)->particles().end(); ++it) { - (*it)->draw(elapsed); + (*it)->draw(elapsed, *_camera); } } } @@ -1207,11 +1252,11 @@ void draw_pass_spacegrid() float s = 1.0f / gridsize; float z = -4.0f; - float dx = Camera::target().x() - floorf(Camera::target().x()); - float dy = Camera::target().y() - floorf(Camera::target().y()); + float dx = _camera->target_location().x() - floorf(_camera->target_location().x()); + float dy = _camera->target_location().y() - floorf(_camera->target_location().y()); gl::push(); - gl::translate(Camera::target()); + gl::translate(_camera->target_location()); gl::color(0, 0, 1.0f); gl::normal(0, 0, 1.0f); @@ -1316,7 +1361,7 @@ void draw(float seconds) math::Color dust_color(core::localplayer()->zone()->ambient_color()); float s = math::max(math::max(dust_color[0], dust_color[1]), dust_color[2]); dust_color *= 0.8f / s; - Dust::draw(dust_color); // draw spacedust + Dust::draw(*_camera, dust_color); // draw spacedust } // draw entity lights, flares and particles @@ -1406,7 +1451,7 @@ void draw_inidicators(const core::EntityControlable *entity) // these are in model-space coordinates - const float r = entity->model()->radius(); // entity radius + const float r = entity->model()->radius(); // model radius const float l = r * 1.8f * entity->thrust(); // thrust indicator lenght const float b = r * 0.1f; // direction box size diff --git a/src/render/draw.h b/src/render/draw.h index d1c7998..0bac3e2 100644 --- a/src/render/draw.h +++ b/src/render/draw.h @@ -8,7 +8,7 @@ #define __INCLUDED_RENDER_DRAW_H__ #include "core/gameinterface.h" - +#include "render/camera.h" #include "math/axis.h" #include "math/vector3f.h" @@ -34,7 +34,7 @@ void reset(); void draw_sphere(const math::Color & color, float radius); /// draw globe corona -void draw_globe_corona(const math::Vector3f location, const math::Color & color, const float radius, const size_t corona_id); +void draw_globe_corona(const Camera & camera, const math::Vector3f & location, const math::Color & color, const float radius, const size_t corona_id); /// draw globe rings void draw_globe_rings(const math::Color & color, const size_t rings_id); @@ -51,6 +51,9 @@ void draw_model_fragments(model::Model *model, const float enginetime, const bool detail, const bool power, const float thrust ); +/// returns the current camera +Camera & camera(); + class Stats { public: diff --git a/src/render/dust.cc b/src/render/dust.cc index 1ca422c..32d2081 100644 --- a/src/render/dust.cc +++ b/src/render/dust.cc @@ -20,9 +20,8 @@ core::Cvar *r_dustsize; const float LOWSPEEDLIMIT = 5.0f; const float TRAILLENGHT = 0.25f; -const float DUSTDISTANCE = 8.0f; -float *dust = 0; +float *dust = 0; size_t dustsize = 0; void Dust::init() @@ -54,7 +53,7 @@ void Dust::reset() } } -void Dust::draw(math::Color const &dustcolor) +void Dust::draw(const Camera &camera, const math::Color &dustcolor) { float alpha = 0.0f; float traillength = 0.0f; @@ -90,7 +89,7 @@ void Dust::draw(math::Color const &dustcolor) return; } - + const float dust_distance = camera.distance() * camera.multiplier(); if (!dust) { con_debug << " generating dust..." << std::endl; @@ -98,9 +97,9 @@ void Dust::draw(math::Color const &dustcolor) dust = (float *) malloc(sizeof(float) * dustsize * 3); for (size_t i = 0; i < dustsize; i++) { - dust[i*3] = core::localcontrol()->location().x() + (math::randomf(2) - 1) * (DUSTDISTANCE + core::localcontrol()->radius() * 2.0f); - dust[i*3+1] = core::localcontrol()->location().y() + (math::randomf(2) - 1) * (DUSTDISTANCE + core::localcontrol()->radius() * 2.0f); - dust[i*3+2] = core::localcontrol()->location().z() + (math::randomf(2) - 1) * (DUSTDISTANCE + core::localcontrol()->radius() * 2.0f); + dust[i*3] = core::localcontrol()->location().x() + (math::randomf(2) - 1) * (dust_distance + core::localcontrol()->radius() * 2.0f); + dust[i*3+1] = core::localcontrol()->location().y() + (math::randomf(2) - 1) * (dust_distance + core::localcontrol()->radius() * 2.0f); + dust[i*3+2] = core::localcontrol()->location().z() + (math::randomf(2) - 1) * (dust_distance + core::localcontrol()->radius() * 2.0f); } } @@ -123,9 +122,9 @@ void Dust::draw(math::Color const &dustcolor) v[j] = dust[i*3+j] - core::localcontrol()->axis().forward()[j] * traillength; } - if (dsquare > (2.0f * core::localcontrol()->radius() + DUSTDISTANCE)*(2.0f * core::localcontrol()->radius() + DUSTDISTANCE)) { + if (dsquare > (2.0f * core::localcontrol()->radius() + dust_distance)*(2.0f * core::localcontrol()->radius() + dust_distance)) { for (size_t j = 0; j < 3; j++) { - dust[i*3+j] = core::localcontrol()->location()[j] + (math::randomf(2) - 1) * (DUSTDISTANCE + core::localcontrol()->radius() * 2.0f); + dust[i*3+j] = core::localcontrol()->location()[j] + (math::randomf(2) - 1) * (dust_distance + core::localcontrol()->radius() * 2.0f); v[j] = dust[i*3+j] - core::localcontrol()->axis().forward()[j] * traillength; } } diff --git a/src/render/dust.h b/src/render/dust.h index 4653550..a42cb25 100644 --- a/src/render/dust.h +++ b/src/render/dust.h @@ -7,6 +7,9 @@ #ifndef __INCLUDED_RENDER_DUST_H__ #define __INCLUDED_RENDER_DUST_H__ +#include "math/color.h" +#include "render/camera.h" + namespace render { @@ -19,7 +22,7 @@ public: static void shutdown(); - static void draw(math::Color const &dustcolor); + static void draw(const Camera &camera, const math::Color &dustcolor); static void reset(); }; diff --git a/src/render/particleejector.cc b/src/render/particleejector.cc index 22ddf2d..51be345 100644 --- a/src/render/particleejector.cc +++ b/src/render/particleejector.cc @@ -38,7 +38,7 @@ void ParticleEjector::clear() ejector_last_eject = 0; } -void ParticleEjector::frame(const float seconds, const math::Vector3f & ps_location, const math::Axis & ps_axis, const float thrust_factor) +void ParticleEjector::frame(const float seconds, const Camera &camera, const math::Vector3f & ps_location, const math::Axis & ps_axis, const float thrust_factor) { unsigned long now = core::application()->timestamp(); @@ -166,12 +166,13 @@ void ParticleEjector::frame(const float seconds, const math::Vector3f & ps_locat break; } - if (particles().size()) { - draw(ps_location, ps_axis); + if (particles().size()) + { + draw(camera, ps_location, ps_axis); } } -void ParticleEjector::draw(const math::Vector3f & ps_location, const math::Axis & ps_axis) +void ParticleEjector::draw(const Camera &camera, const math::Vector3f & ps_location, const math::Axis & ps_axis) { } @@ -188,22 +189,22 @@ ParticleEjectorSprite::~ParticleEjectorSprite() } -void ParticleEjectorSprite::draw(const math::Vector3f & ps_location, const math::Axis & ps_axis) +void ParticleEjectorSprite::draw(const Camera &camera, const math::Vector3f & ps_location, const math::Axis & ps_axis) { math::Vector3f quad[4]; Textures::bind(texture()); gl::begin(gl::Quads); - quad[0].assign((Camera::axis().up() - Camera::axis().left())); - quad[1].assign((Camera::axis().up() + Camera::axis().left())); - quad[2].assign((Camera::axis().up() * -1 + Camera::axis().left())); - quad[3].assign((Camera::axis().up() * -1 - Camera::axis().left())); + quad[0].assign((camera.axis().up() - camera.axis().left())); + quad[1].assign((camera.axis().up() + camera.axis().left())); + quad[2].assign((camera.axis().up() * -1 + camera.axis().left())); + quad[3].assign((camera.axis().up() * -1 - camera.axis().left())); for (Particles::iterator it = particles().begin(); it != particles().end(); it++) { Particle *particle = (*it); math::Axis rotation; - rotation.rotate(Camera::axis().forward(), particle->rotation()); + rotation.rotate(camera.axis().forward(), particle->rotation()); math::Vector3f l(attached() ? ps_location + ps_axis * particle->location() : particle->location()); const float r = particle->radius(); @@ -235,7 +236,7 @@ ParticleEjectorFlare::~ParticleEjectorFlare() } -void ParticleEjectorFlare::draw(const math::Vector3f & ps_location, const math::Axis & ps_axis) +void ParticleEjectorFlare::draw(const Camera &camera, const math::Vector3f & ps_location, const math::Axis & ps_axis) { Textures::bind(texture()); gl::begin(gl::Quads); @@ -274,7 +275,7 @@ ParticleEjectorTrail::~ParticleEjectorTrail() } -void ParticleEjectorTrail::draw(const math::Vector3f & ps_location, const math::Axis & ps_axis) +void ParticleEjectorTrail::draw(const Camera &camera, const math::Vector3f & ps_location, const math::Axis & ps_axis) { if (!particles().size()) { return; @@ -292,7 +293,7 @@ void ParticleEjectorTrail::draw(const math::Vector3f & ps_location, const math:: gl::color((*first)->color()); //math::Vector3f first_location(attached() ? ps_location + ps_axis * (*first)->location() : (*first)->location()); - math::Vector3f first_normal(math::crossproduct(((*first)->location() - ps_location), ((*first)->location() - Camera::eye()))); + math::Vector3f first_normal(math::crossproduct(((*first)->location() - ps_location), ((*first)->location() - camera.location()))); first_normal.normalize(); math::Vector3f next_normal(first_normal); @@ -312,7 +313,7 @@ void ParticleEjectorTrail::draw(const math::Vector3f & ps_location, const math:: Stats::quads++; while (next != particles().end()) { - next_normal.assign(math::crossproduct(((*next)->location() - (*first)->location()), ((*next)->location() - Camera::eye()))); + next_normal.assign(math::crossproduct(((*next)->location() - (*first)->location()), ((*next)->location() - camera.location()))); next_normal.normalize(); gl::color((*first)->color()); @@ -353,7 +354,7 @@ ParticleEjectorStreak::~ParticleEjectorStreak() } -void ParticleEjectorStreak::draw(const math::Vector3f & ps_location, const math::Axis & ps_axis) +void ParticleEjectorStreak::draw(const Camera &camera, const math::Vector3f & ps_location, const math::Axis & ps_axis) { if (!particles().size()) { return; @@ -377,7 +378,7 @@ void ParticleEjectorStreak::draw(const math::Vector3f & ps_location, const math: math::Vector3f first_location(attached() ? ps_location + ps_axis * (*first)->location() : (*first)->location()); math::Vector3f next_location(attached() ? ps_location + ps_axis * (*next)->location() : (*next)->location()); - normal.assign(math::crossproduct((first_location - Camera::eye()), (next_location - Camera::eye()))); + normal.assign(math::crossproduct((first_location - camera.location()), (next_location - camera.location()))); normal.normalize(); gl::color((*first)->color()); diff --git a/src/render/particleejector.h b/src/render/particleejector.h index d68b32f..57a46d7 100644 --- a/src/render/particleejector.h +++ b/src/render/particleejector.h @@ -9,6 +9,7 @@ #include +#include "render/camera.h" #include "render/particleejectorscript.h" #include "render/particle.h" @@ -53,7 +54,7 @@ public: /** * @brief updated the particles attached to the ejector, and drawn them * */ - void frame(const float seconds, const math::Vector3f & ps_location, const math::Axis & ps_axis, const float thrust_factor); + void frame(const float seconds, const Camera &camera, const math::Vector3f & ps_location, const math::Axis & ps_axis, const float thrust_factor); /** * @brief remove all particles @@ -66,7 +67,7 @@ protected: return ejector_particles; } - virtual void draw(const math::Vector3f & ps_location, const math::Axis & ps_axis); + virtual void draw(const Camera &camera, const math::Vector3f & ps_location, const math::Axis & ps_axis); private: unsigned long ejector_timestamp; @@ -85,7 +86,7 @@ public: virtual ~ParticleEjectorSprite(); protected: - virtual void draw(const math::Vector3f & ps_location, const math::Axis & ps_axis); + virtual void draw(const Camera &camera, const math::Vector3f & ps_location, const math::Axis & ps_axis); }; /** @@ -98,7 +99,7 @@ public: virtual ~ParticleEjectorFlare(); protected: - virtual void draw(const math::Vector3f & ps_location, const math::Axis & ps_axis); + virtual void draw(const Camera &camera, const math::Vector3f & ps_location, const math::Axis & ps_axis); }; /** @@ -110,7 +111,7 @@ public: virtual ~ParticleEjectorTrail(); protected: - virtual void draw(const math::Vector3f & ps_location, const math::Axis & ps_axis); + virtual void draw(const Camera &camera, const math::Vector3f & ps_location, const math::Axis & ps_axis); }; /** @@ -122,7 +123,7 @@ public: virtual ~ParticleEjectorStreak(); protected: - virtual void draw(const math::Vector3f & ps_location, const math::Axis & ps_axis); + virtual void draw(const Camera &camera, const math::Vector3f & ps_location, const math::Axis & ps_axis); }; } // namespace render diff --git a/src/render/particlesystem.cc b/src/render/particlesystem.cc index abc4f0c..74ee498 100644 --- a/src/render/particlesystem.cc +++ b/src/render/particlesystem.cc @@ -137,7 +137,7 @@ void ParticleSystem::clear() (*it)->clear(); } } -void ParticleSystem::draw(const float seconds) +void ParticleSystem::draw(const float seconds, const Camera &camera) { // clear particles for docked entities if ( entity() && (entity()->type() == core::Entity::Controlable)) { @@ -231,7 +231,7 @@ void ParticleSystem::draw(const float seconds) } ejector->enable(ejector_active); - (*it)->frame(seconds, current_location, current_axis * ejector->axis(), thrust_factor); + (*it)->frame(seconds, camera, current_location, current_axis * ejector->axis(), thrust_factor); } } diff --git a/src/render/particlesystem.h b/src/render/particlesystem.h index 974806f..7675021 100644 --- a/src/render/particlesystem.h +++ b/src/render/particlesystem.h @@ -11,6 +11,7 @@ #include "core/entity.h" +#include "render/camera.h" #include "render/particlesystemscript.h" #include "render/particleejector.h" @@ -30,7 +31,7 @@ public: ParticleSystem(const ParticleSystemScript *script, const core::Entity *entity, const model::Particles *modelclass); ~ParticleSystem(); - void draw(const float seconds); + void draw(const float seconds, const Camera &camera); /** * @brief clear all particles from all ejectors diff --git a/src/render/render.cc b/src/render/render.cc index 88b2577..b2c2984 100644 --- a/src/render/render.cc +++ b/src/render/render.cc @@ -125,8 +125,6 @@ void init(int width, int height) } r_mipmap->set_info("[bool] use hardware generated mipmaps (recommended on)"); - Camera::init(); - Textures::init(); Text::init(); @@ -279,8 +277,6 @@ void shutdown() Textures::shutdown(); - Camera::shutdown(); - Dust::shutdown(); State::shutdown(); diff --git a/src/render/renderext.cc b/src/render/renderext.cc index c66f036..c311be9 100644 --- a/src/render/renderext.cc +++ b/src/render/renderext.cc @@ -103,7 +103,11 @@ RenderExt::~RenderExt() void RenderExt::frame(float elapsed) { - state_distance = math::distance(Camera::eye(), entity()->location()); +} + +void RenderExt::frame(float elapsed, const Camera & camera) +{ + state_distance = math::distance(camera.location(), entity()->location()); state_visible = entity()->visible(); state_detailvisible = false; @@ -139,7 +143,7 @@ void RenderExt::frame(float elapsed) return; } - if ((controlable == core::localcontrol()) && (Camera::mode() == Camera::Cockpit)) { + if ((controlable == core::localcontrol()) && (camera.mode() == camera.Cockpit)) { state_visible = false; return; } @@ -233,7 +237,7 @@ void RenderExt::frame(float elapsed) } } - if (math::dotproduct(Camera::axis().forward(), entity()->location() + Camera::axis().forward() * entity()->radius() - Camera::eye()) < 0.0f) { + if (math::dotproduct(camera.axis().forward(), entity()->location() + camera.axis().forward() * entity()->radius() - camera.location()) < 0.0f) { state_behind = true; } } diff --git a/src/render/renderext.h b/src/render/renderext.h index 65fc5ed..3186a9c 100644 --- a/src/render/renderext.h +++ b/src/render/renderext.h @@ -75,6 +75,8 @@ public: } virtual void frame(float elapsed); + + virtual void frame(float elapsed, const Camera & camera); private: -- cgit v1.2.3