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/draw.cc | 113 +++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 79 insertions(+), 34 deletions(-) (limited to 'src/render/draw.cc') 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 -- cgit v1.2.3