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/client/hud.cc | 22 +- src/client/hudenginestatus.cc | 3 +- src/client/input.cc | 185 +++++++++------ src/client/savegamemenu.cc | 4 +- src/client/soundext.cc | 4 +- src/client/targets.cc | 30 +-- src/client/video.cc | 2 - 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 + src/ui/modelview.cc | 20 +- src/ui/modelview.h | 3 + 22 files changed, 725 insertions(+), 576 deletions(-) (limited to 'src') diff --git a/src/client/hud.cc b/src/client/hud.cc index 1ae008c..49f9c9d 100644 --- a/src/client/hud.cc +++ b/src/client/hud.cc @@ -73,8 +73,8 @@ void HUD::draw_offscreen_target(core::Entity *entity, bool is_active_target) const core::EntityControlable *controlable = ( (entity->type() == core::Entity::Controlable) ? static_cast(entity) : 0 ); - math::Vector3f target(entity->location() - render::Camera::eye()); - target = render::Camera::axis().transpose() * target; + math::Vector3f target(entity->location() - render::camera().location()); + target = render::camera().axis().transpose() * target; math::Vector2f screen_edge; @@ -205,8 +205,8 @@ void HUD::draw_target(core::Entity *entity, bool is_active_target) } // don't draw target if it is outside the visible cone - Vector3f target(entity->location() - render::Camera::eye()); - if (math::dotproduct(render::Camera::axis().forward(), Vector3f::normalized(target)) < 0.75) { + Vector3f target(entity->location() - render::camera().location()); + if (math::dotproduct(render::camera().axis().forward(), Vector3f::normalized(target)) < 0.75) { draw_offscreen_target(entity, is_active_target); return; } @@ -216,7 +216,7 @@ void HUD::draw_target(core::Entity *entity, bool is_active_target) // calculate target screen position // transform the target into the camera coordinate system - target = render::Camera::axis().transpose() * target; + target = render::camera().axis().transpose() * target; // calculate the intersection between the line (0,0,0)-target and the frustum front float t = (render::FRUSTUMFRONT + 0.001f) / target.x(); @@ -416,10 +416,12 @@ void HUD::draw() { using namespace render; - if (core::localcontrol() && (input::mouse_control || input::joystick_control) && - (render::Camera::mode() == render::Camera::Cockpit || render::Camera::mode() == render::Camera::Track)) { + if (core::localcontrol() && (input::mouse_control || input::joystick_control) && (render::camera().mode() != render::camera().Overview)) + { hud_center->set_visible(true); - } else { + } + else + { hud_center->set_visible(false); } @@ -468,7 +470,7 @@ void HUD::draw() if (has_mouse_focus()) { - if (render::Camera::mode() == render::Camera::Overview) { + if (render::camera().mode() == render::camera().Overview) { ui::root()->set_pointer("pointer", ui::Palette::Highlight); @@ -484,7 +486,7 @@ void HUD::draw() ui::root()->set_pointer("control", ui::Palette::Pointer); - } else if ((input::joystick_lastmoved_time() > input::mouse_lastmoved_time()) && (render::Camera::mode() == render::Camera::Cockpit || render::Camera::mode() == render::Camera::Track)) { + } else if ((input::joystick_lastmoved_time() > input::mouse_lastmoved_time()) && (render::camera().mode() == render::camera().Cockpit || render::camera().mode() == render::camera().Track)) { ui::root()->set_pointer(); diff --git a/src/client/hudenginestatus.cc b/src/client/hudenginestatus.cc index 1283970..0eeafba 100644 --- a/src/client/hudenginestatus.cc +++ b/src/client/hudenginestatus.cc @@ -11,8 +11,9 @@ #include "ui/ui.h" #include "ui/iconbutton.h" #include "ui/paint.h" -#include "render/render.h" +#include "render/camera.h" #include "render/gl.h" +#include "render/render.h" namespace client { diff --git a/src/client/input.cc b/src/client/input.cc index 72fa5af..dadc027 100644 --- a/src/client/input.cc +++ b/src/client/input.cc @@ -139,9 +139,6 @@ void func_ui_control(std::string const &args) local_direction = 0.0f; local_pitch = 0.0f; local_roll = 0.0f; - - render::Camera::set_direction(0.0f); - render::Camera::set_pitch(0.0f); } con_print << "mouse control is " << ((input_mousecontrol->value()) ? "on" : "off") << std::endl; @@ -152,7 +149,7 @@ void func_ui_control(std::string const &args) void func_view_next(std::string const &args) { if (!core::localplayer()->view() && core::application()->connected() && core::localcontrol()) { - render::Camera::view_next(); + render::camera().cycle_mode_next(); local_roll = 0; local_pitch = 0; local_direction = 0; @@ -163,7 +160,7 @@ void func_view_next(std::string const &args) void func_view_prev(std::string const &args) { if (!core::localplayer()->view() && core::application()->connected() && core::localcontrol()) { - render::Camera::view_previous(); + render::camera().cycle_mode_previous(); local_roll = 0; local_pitch = 0; local_direction = 0; @@ -348,7 +345,8 @@ void shutdown() void action_press(Key *key) { - switch(key->action()->id()) { + switch(key->action()->id()) + { case Action::None: case Action::Console: return; @@ -411,60 +409,95 @@ void action_press(Key *key) /* -- camera control ------------------------------ */ + case Action::FreeLook: + if (!freelook_control_override) + { + freelook_control_override = true; + freelook_control_override_time = key->pressed(); + + freelook_control_x = mouse_x; + freelook_control_y = mouse_y; + } + break; case Action::LookLeft: - if (render::Camera::mode() == render::Camera::Free) + if (render::camera().mode() == render::Camera::Free) { - render::Camera::set_direction(math::min(key->pressed() - core::application()->time(), 1.0f)); - } else { - render::Camera::set_direction(-math::min(key->pressed() - core::application()->time(), 1.0f)); + render::camera().set_movement_direction(-1.0f); + } + else if ((render::camera().mode() == render::Camera::Track) || (render::camera().mode() == render::Camera::Cockpit)) + { + render::camera().set_freelook_direction(90.0f); } break; case Action::LookRight: - if (render::Camera::mode() == render::Camera::Free) + if (render::camera().mode() == render::Camera::Free) { - render::Camera::set_direction(-math::min(key->pressed() - core::application()->time(), 1.0f)); - } else { - render::Camera::set_direction(math::min(key->pressed() - core::application()->time(), 1.0f)); + render::camera().set_movement_direction(1.0f); + } + else if ((render::camera().mode() == render::Camera::Track) || (render::camera().mode() == render::Camera::Cockpit)) + { + render::camera().set_freelook_direction(-90.0f); } break; case Action::LookUp: - if (render::Camera::mode() == render::Camera::Free) + if (render::camera().mode() == render::Camera::Free) { - render::Camera::set_pitch(math::min(key->pressed() - core::application()->time(), 1.0f)); - } else { - render::Camera::set_pitch(-math::min(key->pressed() - core::application()->time(), 1.0f)); + render::camera().set_movement_pitch(1.0f); + } + else if ((render::camera().mode() == render::Camera::Track) || (render::camera().mode() == render::Camera::Cockpit)) + { + render::camera().set_freelook_pitch(90.0f); } break; case Action::LookDown: - if (render::Camera::mode() == render::Camera::Free) + if (render::camera().mode() == render::Camera::Free) { - render::Camera::set_pitch(-math::min(key->pressed() - core::application()->time(), 1.0f)); - } else { - render::Camera::set_pitch(math::min(key->pressed() - core::application()->time(), 1.0f)); + render::camera().set_movement_pitch(-1.0f); + } + else if ((render::camera().mode() == render::Camera::Track) || (render::camera().mode() == render::Camera::Cockpit)) + { + render::camera().set_freelook_pitch(-90.0f); } break; case Action::ZoomIn: - render::Camera::set_zoom(-0.1f); + if (!core::localplayer()->view()) + { + float m = render::camera().multiplier(); + if (m > 1.0f) + { + m -= 0.1f; + } + else + { + m = 1.0f; + } + render::camera().set_multiplier(m); + } break; case Action::ZoomOut: - render::Camera::set_zoom(+0.1f); - break; - case Action::FreeLook: - if (!freelook_control_override) + if (!core::localplayer()->view()) { - freelook_control_override = true; - freelook_control_override_time = key->pressed(); - - freelook_control_x = mouse_x; - freelook_control_y = mouse_y; + float m = render::camera().multiplier(); + if (m < 5.0f) + { + m += 0.1f; + } + else + { + m = 5.0f; + } + render::camera().set_multiplier(m); } break; - + /* -- fire control -------------------------------- */ case Action::Fire: local_controlflags = local_controlflags | core::EntityControlable::ControlFlagFire; break; + + default: + break; } } @@ -531,15 +564,15 @@ void action_release(Key *key) mouse_control_override_time = 0.0f; if (!input_mousecontrol->value() || (joystick_control && mouse_control && - (render::Camera::mode() == render::Camera::Track || render::Camera::mode() == render::Camera::Cockpit))) { + (render::camera().mode() == render::Camera::Track || render::camera().mode() == render::Camera::Cockpit))) { local_direction = 0.0f; local_pitch = 0.0f; local_roll = 0.0f; local_vstrafe = 0.0f; local_strafe = 0.0f; - render::Camera::set_direction(0.0f); - render::Camera::set_pitch(0.0f); + render::camera().set_movement_direction(0.0f); + render::camera().set_movement_pitch(0.0f); } } break; @@ -547,16 +580,26 @@ void action_release(Key *key) /* -- camera control ------------------------------ */ case Action::LookLeft: - render::Camera::set_direction(0.0f); - break; case Action::LookRight: - render::Camera::set_direction(0.0f); + if (render::camera().mode() == render::Camera::Free) + { + render::camera().set_movement_direction(0.0f); + } + else if ((render::camera().mode() == render::Camera::Track) || (render::camera().mode() == render::Camera::Cockpit)) + { + render::camera().set_freelook_direction(0.0f); + } break; case Action::LookUp: - render::Camera::set_pitch(0.0f); - break; case Action::LookDown: - render::Camera::set_pitch(0.0f); + if (render::camera().mode() == render::Camera::Free) + { + render::camera().set_movement_pitch(0.0f); + } + else if ((render::camera().mode() == render::Camera::Track) || (render::camera().mode() == render::Camera::Cockpit)) + { + render::camera().set_freelook_pitch(0.0f); + } break; case Action::ZoomIn: break; @@ -568,8 +611,8 @@ void action_release(Key *key) freelook_control_override = false; freelook_control_override_time = 0.0f; - render::Camera::set_direction(0.0f); - render::Camera::set_pitch(0.0f); + render::camera().set_freelook_direction(0.0f); + render::camera().set_freelook_pitch(0.0f); } break; @@ -601,8 +644,8 @@ bool console_key_pressed(const Key *key) local_pitch = 0.0f; local_roll = 0.0f; - render::Camera::set_direction(0.0f); - render::Camera::set_pitch(0.0f); + //render::Camera::set_direction(0.0f); + //render::Camera::set_pitch(0.0f); ui::console()->toggle(); return true; @@ -737,7 +780,7 @@ void reset() mouse_direction = 0.0f; mouse_x = render::State::width() / 2; mouse_y = render::State::height() / 2; - render::Camera::reset(); + render::camera().reset(); render::Dust::reset(); mouse_control_override = false; mouse_control_override_time = 0.0f; @@ -951,18 +994,23 @@ void frame() // if freelook_control is true, the mouse controls freelook freelook_control = ui::console()->hidden() && freelook_control_override && (freelook_control_override_time + (input_mousedelay->value() / 1000.0f) < core::application()->time()); - // if mouse control is true, the mouse controls the spacecraft - mouse_control = ui::console()->hidden() && ((input_mousecontrol->value() > 0) || (mouse_control_override && (mouse_control_override_time + (input_mousedelay->value() / 1000.0f) < core::application()->time()) )); + if (!freelook_control) + { + // if mouse control is true, the mouse controls the spacecraft + mouse_control = ui::console()->hidden() && ((input_mousecontrol->value() > 0) || (mouse_control_override && (mouse_control_override_time + (input_mousedelay->value() / 1000.0f) < core::application()->time()) )); - // joystick control takes presedence over mouse control, but not over mouse_control_override - if (mouse_control && joystick_control && ((render::Camera::mode() == render::Camera::Track) || (render::Camera::mode() == render::Camera::Cockpit))) { - if (!(mouse_control_override && (mouse_control_override_time + (input_mousedelay->value() / 1000.0f) < core::application()->time()))) { - mouse_control = false; + // joystick control takes presedence over mouse control, but not over mouse_control_override + if (mouse_control && joystick_control && ((render::camera().mode() == render::Camera::Track) || (render::camera().mode() == render::Camera::Cockpit))) + { + if (!(mouse_control_override && (mouse_control_override_time + (input_mousedelay->value() / 1000.0f) < core::application()->time()))) + { + mouse_control = false; + } } } if (mouse_control || freelook_control ) { - const float aim_square_size = 256.0f; + const float aim_square_size = math::min(render::State::width(), render::State::height()) * 0.5f; int l = mouse_x; int h = mouse_y; @@ -991,7 +1039,7 @@ void frame() if (freelook_control) { // mouse is controling freelook - switch (render::Camera::mode()) + switch (render::camera().mode()) { case render::Camera::Track: case render::Camera::Cockpit: @@ -1007,14 +1055,18 @@ void frame() // disable autopilot override local_controlflags = local_controlflags & ~core::EntityControlable::ControlFlagOverride; } - render::Camera::set_direction(mouse_direction); - render::Camera::set_pitch(mouse_pitch); + + render::camera().set_freelook_direction(180.0f * mouse_direction); + render::camera().set_freelook_pitch(90.0f * mouse_pitch); break; case render::Camera::Free: - render::Camera::set_direction(-mouse_direction * math::absf(mouse_direction)); - render::Camera::set_pitch(-mouse_pitch * math::absf(mouse_pitch)); + render::camera().set_movement_direction(0.0f); + render::camera().set_movement_pitch(0.0f); + + render::camera().set_freelook_direction(180.0f * mouse_direction); + render::camera().set_freelook_pitch(90.0f * mouse_pitch); // disable autopilot override local_controlflags = local_controlflags & ~core::EntityControlable::ControlFlagOverride; @@ -1027,7 +1079,7 @@ void frame() } else if (mouse_control) { // mouse is controling direction - switch (render::Camera::mode()) + switch (render::camera().mode()) { case render::Camera::Track: case render::Camera::Cockpit: @@ -1039,8 +1091,8 @@ void frame() break; case render::Camera::Free: - render::Camera::set_direction(-mouse_direction * math::absf(mouse_direction)); - render::Camera::set_pitch(-mouse_pitch * math::absf(mouse_pitch)); + render::camera().set_movement_direction(mouse_direction); + render::camera().set_movement_pitch(mouse_pitch); // disable autopilot override local_controlflags = local_controlflags & ~core::EntityControlable::ControlFlagOverride; @@ -1053,11 +1105,10 @@ void frame() } } else { - //render::Camera::set_direction(0.0f); - //render::Camera::set_pitch(0.0f); - // disable autopilot override local_controlflags = local_controlflags & ~core::EntityControlable::ControlFlagOverride; + render::camera().set_movement_direction(0.0f); + render::camera().set_movement_pitch(0.0f); } math::clamp(local_direction, -1.0f, 1.0f); @@ -1089,8 +1140,8 @@ void frame() local_afterburner = 0.0f; local_controlflags = core::EntityControlable::ControlFlagNone; - render::Camera::set_direction(0.0f); - render::Camera::set_pitch(0.0f); + //render::Camera::set_direction(0.0f); + //render::Camera::set_pitch(0.0f); } } diff --git a/src/client/savegamemenu.cc b/src/client/savegamemenu.cc index d002b54..2ba038f 100644 --- a/src/client/savegamemenu.cc +++ b/src/client/savegamemenu.cc @@ -567,9 +567,9 @@ void SaveGameMenu::savescreenshot(std::string savename) gl::clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // set camera transformation - render::Camera::frame(0.0f); + render::camera().frame(0.0f); - render::Camera::frustum(); + render::camera().draw(); // draw the world render::draw(0.0f); diff --git a/src/client/soundext.cc b/src/client/soundext.cc index dd86a70..9de548b 100644 --- a/src/client/soundext.cc +++ b/src/client/soundext.cc @@ -14,7 +14,7 @@ #include "core/entityprojectile.h" #include "client/soundext.h" #include "client/client.h" -#include "render/camera.h" +#include "render/draw.h" #include #include @@ -45,7 +45,7 @@ void render_listener_sound() (*snd_volume) = master_volume; } - audio::update_listener(render::Camera::eye(), render::Camera::axis(), velocity, master_volume); + audio::update_listener(render::camera().location(), render::camera().axis(), velocity, master_volume); } void render_entity_sound(core::Entity *entity) diff --git a/src/client/targets.cc b/src/client/targets.cc index b320b08..ae2afb0 100644 --- a/src/client/targets.cc +++ b/src/client/targets.cc @@ -25,7 +25,7 @@ #include "core/range.h" #include "math/axis.h" #include "math/vector3f.h" -#include "render/camera.h" +#include "render/draw.h" #include "render/state.h" namespace client @@ -395,19 +395,19 @@ void func_target_center(std::string const &args) // this is essentialy the hover algorithm with the cursor in the center const core::Entity *new_target = 0; - math::Vector3f center = render::Camera::eye() + render::Camera::axis().forward() * (render::FRUSTUMFRONT + 0.001); + math::Vector3f center = render::camera().location() + render::camera().axis().forward() * (render::FRUSTUMFRONT + 0.001); float smallest_d = -1; for (core::Zone::Content::const_iterator it = core::localcontrol()->zone()->content().begin(); it != core::localcontrol()->zone()->content().end(); it++) { const core::Entity *entity = (*it); - math::Vector3f v(entity->location() - render::Camera::eye()); + math::Vector3f v(entity->location() - render::camera().location()); v.normalize(); - if (is_valid_hud_target(entity) && math::dotproduct(render::Camera::axis().forward(), v) > 0.85) { + if (is_valid_hud_target(entity) && math::dotproduct(render::camera().axis().forward(), v) > 0.85) { // calculate the distance from entity location to the line [eye - cursor] - float d = math::Vector3f::length(math::crossproduct((center - render::Camera::eye()) , (render::Camera::eye() - entity->location()))) / math::Vector3f::length(center - render::Camera::eye()); + float d = math::Vector3f::length(math::crossproduct((center - render::camera().location()) , (render::camera().location() - entity->location()))) / math::Vector3f::length(center - render::camera().location()); // the entity closer to the center beam if (smallest_d < 0 || d < smallest_d) { @@ -495,7 +495,7 @@ void frame() float x = 0; float y = 0; - if ((input::joystick_lastmoved_time() > input::mouse_lastmoved_time()) && (render::Camera::mode() == render::Camera::Cockpit || render::Camera::mode() == render::Camera::Track)) { + if ((input::joystick_lastmoved_time() > input::mouse_lastmoved_time()) && (render::camera().mode() == render::Camera::Cockpit || render::camera().mode() == render::Camera::Track)) { x = 0; y = 0; } else { @@ -503,13 +503,13 @@ void frame() y = (float)(input::mouse_position_y() - render::State::height() / 2) / (float)render::State::height() / render::State::aspect(); } - cursor_aim.assign(render::Camera::eye() + render::Camera::axis().forward() * (render::FRUSTUMFRONT + 0.001)); - cursor_aim -= render::Camera::axis().left() * x; - cursor_aim -= render::Camera::axis().up() * y; + cursor_aim.assign(render::camera().location() + render::camera().axis().forward() * (render::FRUSTUMFRONT + 0.001)); + cursor_aim -= render::camera().axis().left() * x; + cursor_aim -= render::camera().axis().up() * y; float aim_distance = core::range::fxdistance; - //math::Vector3f center = render::Camera::eye() + (render::Camera::axis().forward() * (render::FRUSTUMFRONT + 0.001f)); + //math::Vector3f center = render::camera().location() + (render::camera().axis().forward() * (render::FRUSTUMFRONT + 0.001f)); for (core::Zone::Content::iterator it = zone->content().begin(); it != zone->content().end(); it++) { core::Entity *entity = (*it); @@ -526,13 +526,13 @@ void frame() } // check if the mouse is hovering the entity - Vector3f v(entity->location() - render::Camera::eye()); + Vector3f v(entity->location() - render::camera().location()); v.normalize(); - if (math::dotproduct(render::Camera::axis().forward(), v) > 0.75) { + if (math::dotproduct(render::camera().axis().forward(), v) > 0.75) { // calculate the distance from entity location to the line [eye - cursor] - float d = math::Vector3f::length(math::crossproduct((cursor_aim - render::Camera::eye()) , (render::Camera::eye() - entity->location()))) / math::Vector3f::length(cursor_aim - render::Camera::eye()); + float d = math::Vector3f::length(math::crossproduct((cursor_aim - render::camera().location()) , (render::camera().location() - entity->location()))) / math::Vector3f::length(cursor_aim - render::camera().location()); float r = entity->radius(); @@ -549,7 +549,7 @@ void frame() if (z < 0 || myz < z) { current_hover = entity->id(); // aim slightly behind target to prevent colliding projectiles - aim_distance = entity->radius() + math::distance(render::Camera::eye(), entity->location()); + aim_distance = entity->radius() + math::distance(render::camera().location(), entity->location()); z = myz; } } @@ -559,7 +559,7 @@ void frame() } } - cursor_aim = render::Camera::eye() + (cursor_aim - render::Camera::eye()) * aim_distance / math::distance(render::Camera::eye(), cursor_aim); + cursor_aim = render::camera().location() + (cursor_aim - render::camera().location()) * aim_distance / math::distance(render::camera().location(), cursor_aim); if (!current_target) { current_target_id = 0; diff --git a/src/client/video.cc b/src/client/video.cc index b7eb325..5f8c14d 100644 --- a/src/client/video.cc +++ b/src/client/video.cc @@ -328,8 +328,6 @@ void frame(float elapsed) if (core::application()->connected()) { if (core::game()->time() && core::localplayer()->zone()) { - render::Camera::frame(elapsed); - render::Camera::frustum(); render::draw(elapsed); // draw the world targets::frame(); // validate current target, render sound 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: diff --git a/src/ui/modelview.cc b/src/ui/modelview.cc index f1676b1..25a3865 100755 --- a/src/ui/modelview.cc +++ b/src/ui/modelview.cc @@ -38,6 +38,8 @@ ModelView::ModelView(Widget *parent) : Widget(parent) modelview_axis.change_direction(180); modelview_axis.change_pitch(-15); + modelview_camera.set_mode(render::Camera::Free); + modelview_mode = Model; } @@ -54,6 +56,8 @@ void ModelView::reset() { set_background(false); + modelview_camera.set_mode(render::Camera::Free); + modelview_axis.clear(); modelview_axis.change_direction(180); modelview_axis.change_pitch(-15); @@ -104,13 +108,13 @@ bool ModelView::on_mousewheel(const math::Vector2f & direction) { if (direction.y() > 0 ) { - modelview_zoom -= 0.25f; + modelview_zoom -= 0.1f; if (modelview_zoom < 1.0f) modelview_zoom = 1.0f; return true; } else if (direction.y() < 0 ) { - modelview_zoom += 0.25f; + modelview_zoom += 0.1f; if (modelview_zoom > 5.0f) modelview_zoom = 5.0f; return true; @@ -203,7 +207,9 @@ void ModelView::draw_globe() const float reference_radius = radius() * minwidget / minscreen; // gl 3d mode - render::Camera::frustum_default(modelview_zoom, center.x(), center.y()); + modelview_camera.set_multiplier(modelview_zoom); + modelview_camera.frame(0); + modelview_camera.draw(center.x(), center.y()); // set up light environment render::Light *light = new render::Light( @@ -246,7 +252,7 @@ void ModelView::draw_globe() if (modelview_globecoronaname.size()) { size_t corona_id = render::Textures::load("textures/" + modelview_globecoronaname); - render::draw_globe_corona(math::Vector3f(0.0f, 0.0f, 0.0f), modelview_color_primary, reference_radius, corona_id); + render::draw_globe_corona(modelview_camera, math::Vector3f(0.0f, 0.0f, 0.0f), modelview_color_primary, reference_radius, corona_id); } } @@ -311,8 +317,10 @@ void ModelView::draw_model() const float modelscale = reference_radius / model->radius(); // gl 3d mode - render::Camera::frustum_default(modelview_zoom, center.x(), center.y()); - + modelview_camera.set_multiplier(modelview_zoom); + modelview_camera.frame(0); + modelview_camera.draw(center.x(), center.y()); + // set up light environment render::Light *light = new render::Light( math::Vector3f(LIGHT_DISTANCE * reference_radius, 0, 0), diff --git a/src/ui/modelview.h b/src/ui/modelview.h index f9566cd..7fd11a9 100755 --- a/src/ui/modelview.h +++ b/src/ui/modelview.h @@ -9,6 +9,7 @@ #include "math/axis.h" #include "ui/widget.h" +#include "render/camera.h" namespace ui { @@ -137,6 +138,8 @@ private: math::Axis modelview_axis; math::Vector2f modelview_cursor; bool modelview_dragging; + + render::Camera modelview_camera; }; } -- cgit v1.2.3