From 05d70b38a546f35a7687cae6ae3fcd6ab78898b2 Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Fri, 10 Nov 2017 09:26:38 +0200 Subject: [PATCH] Derive Camera and Light from Placeable --- source/camera.cpp | 14 +++++++++++--- source/camera.h | 13 ++++++++----- source/light.cpp | 33 +++++++++++++++++++++++++++++++++ source/light.h | 10 ++++++++-- 4 files changed, 60 insertions(+), 10 deletions(-) diff --git a/source/camera.cpp b/source/camera.cpp index ae35f632..e7c925c9 100644 --- a/source/camera.cpp +++ b/source/camera.cpp @@ -85,6 +85,14 @@ void Camera::look_at(const Vector3 &p) set_look_direction(p-position); } +void Camera::set_object_matrix(const Matrix &m) +{ + position = m.column(3).slice<3>(0); + look_dir = normalize(-m.column(2).slice<3>(0)); + up_dir = normalize(m.column(1).slice<3>(0)); + update_object_matrix(); +} + Vector3 Camera::project(const Vector4 &p) const { Vector4 r = proj_matrix*(view_matrix*p); @@ -99,7 +107,7 @@ Vector3 Camera::project(const Vector3 &p) const Vector4 Camera::unproject(const Vector4 &p) const { Vector4 r = invert(proj_matrix)*Vector4(p.x, p.y, p.z, 1.0f); - r = object_matrix*Vector4(r.x/r.w, r.y/r.w, r.z/r.w, p.w); + r = matrix*Vector4(r.x/r.w, r.y/r.w, r.z/r.w, p.w); return r; } @@ -137,8 +145,8 @@ void Camera::update_object_matrix() columns[1] = compose(cross(right_dir, look_dir), 0.0f); columns[2] = compose(-look_dir, 0.0f); columns[3] = compose(position, 1.0f); - object_matrix = Matrix::from_columns(columns); - view_matrix = invert(object_matrix); + matrix = Matrix::from_columns(columns); + view_matrix = invert(matrix); } } // namespace GL diff --git a/source/camera.h b/source/camera.h index 412d69ff..d96ada81 100644 --- a/source/camera.h +++ b/source/camera.h @@ -1,13 +1,12 @@ #ifndef MSP_GL_CAMERA_H_ #define MSP_GL_CAMERA_H_ -#include "matrix.h" -#include "vector.h" +#include "placeable.h" namespace Msp { namespace GL { -class Camera +class Camera: public Placeable { private: Geometry::Angle fov; @@ -23,7 +22,6 @@ private: Vector3 look_dir; Vector3 up_dir; Matrix view_matrix; - Matrix object_matrix; Matrix proj_matrix; public: @@ -52,13 +50,18 @@ public: const Vector3 &get_look_direction() const { return look_dir; } const Vector3 &get_up_direction() const { return up_dir; } + virtual void set_matrix(const Matrix &m) { set_object_matrix(m); } + + /** Sets the position and orientation of the camera from an object matrix. */ + void set_object_matrix(const Matrix &); + /** Returns the view matrix, used to transform coordinates from world space to eye space. */ const Matrix &get_view_matrix() const { return view_matrix; } /** Returns the object matrix, used to transform coordinates from eye space to world space. */ - const Matrix &get_object_matrix() const { return object_matrix; } + const Matrix &get_object_matrix() const { return matrix; } /** Returns the projection matrix. */ const Matrix &get_projection_matrix() const { return proj_matrix; } diff --git a/source/light.cpp b/source/light.cpp index f74b3acb..aeb17c5b 100644 --- a/source/light.cpp +++ b/source/light.cpp @@ -63,6 +63,23 @@ void Light::update_parameter(int mask, int index) const } } +void Light::update_matrix() +{ + Vector3 up_dir; + if(20*abs(direction.z)>abs(direction.x)+abs(direction.y)) + up_dir.y = 1; + else + up_dir.z = 1; + Vector3 right_dir = normalize(cross(direction, up_dir)); + + Vector4 columns[4]; + columns[0] = compose(right_dir, 0.0f); + columns[1] = compose(cross(right_dir, direction), 0.0f); + columns[2] = compose(-direction, 0.0f); + columns[3] = position; + matrix = Matrix::from_columns(columns); +} + void Light::set_diffuse(const Color &c) { diffuse = c; @@ -75,16 +92,32 @@ void Light::set_specular(const Color &c) update_parameter(SPECULAR); } +void Light::set_matrix(const Matrix &m) +{ + Placeable::set_matrix(m); + position = matrix.column(3); + spot_dir = normalize(-matrix.column(2).slice<3>(0)); + direction = (position.w ? spot_dir : normalize(-position.slice<3>(0))); + update_parameter(POSITION|SPOT_DIR); + update_matrix(); +} + void Light::set_position(const Vector4 &p) { position = p; update_parameter(POSITION); + if(!position.w) + direction = normalize(-position.slice<3>(0)); + update_matrix(); } void Light::set_spot_direction(const Vector3 &d) { spot_dir = normalize(d); + if(position.w) + direction = spot_dir; update_parameter(SPOT_DIR); + update_matrix(); } void Light::set_spot_exponent(float e) diff --git a/source/light.h b/source/light.h index b775a711..396e276d 100644 --- a/source/light.h +++ b/source/light.h @@ -3,7 +3,7 @@ #include #include "color.h" -#include "vector.h" +#include "placeable.h" namespace Msp { namespace GL { @@ -24,7 +24,7 @@ Pipeline::Pass. Lights do not cast shadows by themselves. See ShadowMap for that. */ -class Light +class Light: public Placeable { private: enum ParameterMask @@ -42,6 +42,7 @@ private: Color specular; Vector4 position; Vector3 spot_dir; + Vector3 direction; float spot_exp; Geometry::Angle spot_cutoff; float attenuation[3]; @@ -52,6 +53,7 @@ public: private: void update_parameter(int, int = -1) const; + void update_matrix(); public: /** Sets the diffuse (direction-independent) color of the Light. Provided @@ -65,6 +67,10 @@ public: const Color &get_diffuse() const { return diffuse; } const Color &get_specular() const { return specular; } + /** Sets the postion and orientation of the Light from a matrix. Negative Z + axis is used as the spot direction, other axes are ignored. */ + virtual void set_matrix(const Matrix &); + /** Sets the position of the Light. For a directional light, set the xyz components to a vector pointing towards the light and the w component to 0. */ void set_position(const Vector4 &); -- 2.43.0