+#include "directionallight.h"
+#include "programdata.h"
+
+using namespace std;
+
+namespace Msp {
+namespace GL {
+
+DirectionalLight::DirectionalLight():
+ transmittance(1.0f),
+ direction(0.0f, 0.0f, -1.0f)
+{ }
+
+void DirectionalLight::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] = Vector4(0.0f, 0.0f, 0.0f, 1.0f);
+ matrix = Matrix::from_columns(columns);
+}
+
+void DirectionalLight::set_matrix(const Matrix &m)
+{
+ Placeable::set_matrix(m);
+ direction = normalize(-matrix.column(2).slice<3>(0));
+ update_matrix();
+ ++generation;
+}
+
+void DirectionalLight::set_direction(const Vector3 &d)
+{
+ direction = normalize(d);
+ update_matrix();
+ ++generation;
+}
+
+void DirectionalLight::set_transmittance(const Color &t)
+{
+ transmittance = t;
+ ++generation;
+}
+
+void DirectionalLight::update_shader_data(ProgramData &shdata, const string &base) const
+{
+ shdata.uniform(base+".type", 1);
+ shdata.uniform(base+".position", -direction.x, -direction.y, -direction.z, 0.0f);
+ shdata.uniform(base+".color", color.r*transmittance.r, color.g*transmittance.g, color.b*transmittance.b);
+ shdata.uniform(base+".attenuation", 1.0f, 0.0f, 0.0f);
+}
+
+
+DataFile::Loader::ActionMap DirectionalLight::Loader::shared_actions;
+
+DirectionalLight::Loader::Loader(DirectionalLight &l):
+ DerivedObjectLoader<DirectionalLight, Light::Loader>(l)
+{
+ set_actions(shared_actions);
+}
+
+void DirectionalLight::Loader::init_actions()
+{
+ Light::Loader::init_actions();
+ add("direction", &Loader::direction);
+}
+
+void DirectionalLight::Loader::direction(float x, float y, float z)
+{
+ obj.set_direction(Vector3(x, y, z));
+}
+
+} // namespace GL
+} // namespace Msp