]> git.tdb.fi Git - libs/gl.git/commitdiff
Derive Camera and Light from Placeable
authorMikko Rasa <tdb@tdb.fi>
Fri, 10 Nov 2017 07:26:38 +0000 (09:26 +0200)
committerMikko Rasa <tdb@tdb.fi>
Fri, 10 Nov 2017 07:26:38 +0000 (09:26 +0200)
source/camera.cpp
source/camera.h
source/light.cpp
source/light.h

index ae35f632438df2d9a7a8a416f838deabde6b8320..e7c925c99064a8f911a694fb733281f9fcca1e5f 100644 (file)
@@ -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
index 412d69ff56bb83cd222e26805ffe784dca66563e..d96ada81e45c4c26840e79c4b813f6034c1a8d82 100644 (file)
@@ -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<float> 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; }
index f74b3acb149071238d9053d41a400141854085d5..aeb17c5be4a604b79235ade3cd2423d34e83dfb0 100644 (file)
@@ -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)
index b775a71188c690ce17d9c78aac0d9d6ac7dce933..396e276da94f519bfd59c2c1c4c80b8c37ae1efc 100644 (file)
@@ -3,7 +3,7 @@
 
 #include <vector>
 #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<float> 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 &);