X-Git-Url: http://git.tdb.fi/?p=libs%2Fgl.git;a=blobdiff_plain;f=source%2Flight.cpp;h=e910411f276e27ebd305f507513177787caebb25;hp=5b0fa1d768c0601112ebf9dc91313a961ab49949;hb=bec07999d95b76f4b47cffcc564d0cd0afc0435e;hpb=c1405286754104ddc044dddbb0a3505a9a5e3d4a diff --git a/source/light.cpp b/source/light.cpp index 5b0fa1d7..e910411f 100644 --- a/source/light.cpp +++ b/source/light.cpp @@ -1,65 +1,163 @@ -/* $Id$ - -This file is part of libmspgl -Copyright © 2007 Mikko Rasa, Mikkosoft Productions -Distributed under the LGPL -*/ - +#include +#include #include "light.h" +#include "matrix.h" #include "misc.h" +#include "programdata.h" + +using namespace std; namespace Msp { namespace GL { Light::Light(): - ambient(0), diffuse(1), specular(1), - x(0), y(0), z(1), w(0), - sdx(0), sdy(0), sdz(-1), + position(0, 0, 1, 0), + spot_dir(0, 0, -1), spot_exp(0), - spot_cutoff(180) -{ } + spot_cutoff(Geometry::Angle::straight()) +{ + attenuation[0] = 1; + attenuation[1] = 0; + attenuation[2] = 0; +} -void Light::set_ambient(const Color &c) +void Light::update_matrix() { - ambient=c; + 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; + diffuse = c; } void Light::set_specular(const Color &c) { - specular=c; + specular = c; +} + +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_matrix(); +} + +void Light::set_position(const Vector4 &p) +{ + position = p; + if(!position.w) + direction = normalize(-position.slice<3>(0)); + update_matrix(); } -void Light::set_position(float x_, float y_, float z_, float w_) +void Light::set_spot_direction(const Vector3 &d) { - x=x_; - y=y_; - z=z_; - w=w_; + spot_dir = normalize(d); + if(position.w) + direction = spot_dir; + update_matrix(); } -void Light::apply() const +void Light::set_spot_exponent(float e) { - apply_to(current); + if(e<0) + throw invalid_argument("Light::set_spot_exponent"); + + spot_exp = e; +} + +void Light::set_spot_cutoff(const Geometry::Angle &c) +{ + if(c::zero() || (c>Geometry::Angle::right() && c!=Geometry::Angle::straight())) + throw invalid_argument("Light::set_spot_cutoff"); + + spot_cutoff = c; +} + +void Light::disable_spot_cutoff() +{ + set_spot_cutoff(Geometry::Angle::straight()); +} + +void Light::set_attenuation(float c, float l, float q) +{ + attenuation[0] = c; + attenuation[1] = l; + attenuation[2] = q; } -void Light::apply_to(unsigned l) const +void Light::update_shader_data(ProgramData &shdata, const Matrix &view_matrix, unsigned i) const { - l+=GL_LIGHT0; - enable(l); - glLightfv(l, GL_AMBIENT, &ambient.r); - glLightfv(l, GL_DIFFUSE, &diffuse.r); - glLightfv(l, GL_SPECULAR, &specular.r); - glLightfv(l, GL_POSITION, &x); + string base = format("light_sources[%d]", i); + shdata.uniform(base+".position", view_matrix*position); + shdata.uniform(base+".diffuse", diffuse); + shdata.uniform(base+".specular", specular); } -unsigned Light::current=0; + +Light::Loader::Loader(Light &l): + DataFile::ObjectLoader(l) +{ + add("attenuation", &Loader::attenuation); + add("diffuse", &Loader::diffuse); + add("position", &Loader::position); + add("specular", &Loader::specular); + add("spot_direction", &Loader::spot_direction); + add("spot_exponent", &Loader::spot_exponent); + add("spot_cutoff", &Loader::spot_cutoff); +} + +void Light::Loader::attenuation(float c, float l, float q) +{ + obj.set_attenuation(c, l, q); +} + +void Light::Loader::diffuse(float r, float g, float b) +{ + obj.set_diffuse(Color(r, g, b)); +} + +void Light::Loader::position(float x, float y, float z, float w) +{ + obj.set_position(Vector4(x, y, z, w)); +} + +void Light::Loader::specular(float r, float g, float b) +{ + obj.set_specular(Color(r, g, b)); +} + +void Light::Loader::spot_direction(float x, float y, float z) +{ + obj.set_spot_direction(Vector3(x, y, z)); +} + +void Light::Loader::spot_exponent(float e) +{ + obj.set_spot_exponent(e); +} + +void Light::Loader::spot_cutoff(float c) +{ + obj.set_spot_cutoff(Geometry::Angle::from_degrees(c)); +} } // namespace GL } // namespace Msp