]> git.tdb.fi Git - libs/gl.git/blob - source/materials/light.cpp
Remove the misc.h header
[libs/gl.git] / source / materials / light.cpp
1 #include <stdexcept>
2 #include <msp/strings/format.h>
3 #include "light.h"
4 #include "matrix.h"
5 #include "programdata.h"
6
7 using namespace std;
8
9 namespace Msp {
10 namespace GL {
11
12 Light::Light():
13         color(1),
14         transmittance(1),
15         position(0, 0, 1, 0),
16         spot_dir(0, 0, -1),
17         spot_exp(0),
18         spot_cutoff(Geometry::Angle<float>::straight()),
19         generation(0)
20 {
21         attenuation[0] = 1;
22         attenuation[1] = 0;
23         attenuation[2] = 0;
24 }
25
26 void Light::update_matrix()
27 {
28         Vector3 up_dir;
29         if(20*abs(direction.z)>abs(direction.x)+abs(direction.y))
30                 up_dir.y = 1;
31         else
32                 up_dir.z = 1;
33         Vector3 right_dir = normalize(cross(direction, up_dir));
34
35         Vector4 columns[4];
36         columns[0] = compose(right_dir, 0.0f);
37         columns[1] = compose(cross(right_dir, direction), 0.0f);
38         columns[2] = compose(-direction, 0.0f);
39         columns[3] = position;
40         matrix = Matrix::from_columns(columns);
41 }
42
43 void Light::set_color(const Color &c)
44 {
45         color = c;
46         ++generation;
47 }
48
49 void Light::set_transmittance(const Color &t)
50 {
51         transmittance = t;
52         ++generation;
53 }
54
55 void Light::set_matrix(const Matrix &m)
56 {
57         Placeable::set_matrix(m);
58         position = matrix.column(3);
59         spot_dir = normalize(-matrix.column(2).slice<3>(0));
60         direction = (position.w ? spot_dir : normalize(-position.slice<3>(0)));
61         update_matrix();
62         ++generation;
63 }
64
65 void Light::set_position(const Vector4 &p)
66 {
67         position = p;
68         if(!position.w)
69                 direction = normalize(-position.slice<3>(0));
70         update_matrix();
71         ++generation;
72 }
73
74 void Light::set_spot_direction(const Vector3 &d)
75 {
76         spot_dir = normalize(d);
77         if(position.w)
78                 direction = spot_dir;
79         update_matrix();
80         ++generation;
81 }
82
83 void Light::set_spot_exponent(float e)
84 {
85         if(e<0)
86                 throw invalid_argument("Light::set_spot_exponent");
87
88         spot_exp = e;
89         ++generation;
90 }
91
92 void Light::set_spot_cutoff(const Geometry::Angle<float> &c)
93 {
94         if(c<Geometry::Angle<float>::zero() || (c>Geometry::Angle<float>::right() && c!=Geometry::Angle<float>::straight()))
95                 throw invalid_argument("Light::set_spot_cutoff");
96
97         spot_cutoff = c;
98         ++generation;
99 }
100
101 void Light::disable_spot_cutoff()
102 {
103         set_spot_cutoff(Geometry::Angle<float>::straight());
104         ++generation;
105 }
106
107 void Light::set_attenuation(float c, float l, float q)
108 {
109         attenuation[0] = c;
110         attenuation[1] = l;
111         attenuation[2] = q;
112         ++generation;
113 }
114
115 void Light::update_shader_data(ProgramData &shdata, unsigned i) const
116 {
117         string base = format("light_sources[%d]", i);
118         shdata.uniform(base+".position", position);
119         shdata.uniform(base+".color", color.r*transmittance.r, color.g*transmittance.g, color.b*transmittance.b);
120         shdata.uniform(base+".enabled", 1);
121 }
122
123
124 Light::Loader::Loader(Light &l):
125         DataFile::ObjectLoader<Light>(l)
126 {
127         add("attenuation", &Loader::attenuation);
128         add("color", &Loader::color);
129         add("position", &Loader::position);
130         add("spot_direction", &Loader::spot_direction);
131         add("spot_exponent", &Loader::spot_exponent);
132         add("spot_cutoff", &Loader::spot_cutoff);
133
134         // Deprecated
135         add("diffuse", &Loader::color);
136         add("specular");
137 }
138
139 void Light::Loader::attenuation(float c, float l, float q)
140 {
141         obj.set_attenuation(c, l, q);
142 }
143
144 void Light::Loader::color(float r, float g, float b)
145 {
146         obj.set_color(Color(r, g, b));
147 }
148
149 void Light::Loader::position(float x, float y, float z, float w)
150 {
151         obj.set_position(Vector4(x, y, z, w));
152 }
153
154 void Light::Loader::spot_direction(float x, float y, float z)
155 {
156         obj.set_spot_direction(Vector3(x, y, z));
157 }
158
159 void Light::Loader::spot_exponent(float e)
160 {
161         obj.set_spot_exponent(e);
162 }
163
164 void Light::Loader::spot_cutoff(float c)
165 {
166         obj.set_spot_cutoff(Geometry::Angle<float>::from_degrees(c));
167 }
168
169 } // namespace GL
170 } // namespace Msp