X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=source%2Flight.cpp;h=aeb17c5be4a604b79235ade3cd2423d34e83dfb0;hb=0e130c02d5e89397ac4963676534e0005359c61e;hp=a3b3d014c0a51a16762c7a82285f4a6a8960247c;hpb=9dc2c20e8c7ac91d932b12492591b65786e24b0f;p=libs%2Fgl.git diff --git a/source/light.cpp b/source/light.cpp index a3b3d014..aeb17c5b 100644 --- a/source/light.cpp +++ b/source/light.cpp @@ -18,7 +18,7 @@ Light::Light(): 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; @@ -54,7 +54,7 @@ void Light::update_parameter(int mask, int index) const if(mask&SPOT_EXP) glLightf(l, GL_SPOT_EXPONENT, spot_exp); if(mask&SPOT_CUTOFF) - glLightf(l, GL_SPOT_CUTOFF, spot_cutoff); + glLightf(l, GL_SPOT_CUTOFF, spot_cutoff.degrees()); if(mask&ATTENUATION) { glLightf(l, GL_CONSTANT_ATTENUATION, attenuation[0]); @@ -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,30 +92,62 @@ 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 = d; + spot_dir = normalize(d); + if(position.w) + direction = spot_dir; update_parameter(SPOT_DIR); + update_matrix(); } void Light::set_spot_exponent(float e) { + if(e<0) + throw invalid_argument("Light::set_spot_exponent"); + spot_exp = e; update_parameter(SPOT_EXP); } void Light::set_spot_cutoff(float c) { + set_spot_cutoff(Geometry::Angle::from_degrees(c)); +} + +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; update_parameter(SPOT_CUTOFF); } +void Light::disable_spot_cutoff() +{ + set_spot_cutoff(Geometry::Angle::straight()); +} + void Light::set_attenuation(float c, float l, float q) { attenuation[0] = c;