added 3dengfx into the repo, probably not the correct version for this
[summerhack] / src / 3dengfx / src / 3dengfx / light.cpp
1 /*
2 Copyright 2004 John Tsiombikas <nuclear@siggraph.org>
3
4 This file is part of 3dengfx, realtime visualization system.
5
6 3dengfx is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 3dengfx is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with 3dengfx; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19 */
20
21 #include "3dengfx_config.h"
22
23 #include "3denginefx.hpp"
24 #include "opengl.h"
25 #include "light.hpp"
26
27 Light::Light() {
28         ambient_color = Color(0, 0, 0);
29         diffuse_color = Color(1.0f, 1.0f, 1.0f);
30         specular_color = Color(1.0f, 1.0f, 1.0f);
31         intensity = 1.0f;
32         attenuation[0] = 1.0f;
33         attenuation[1] = 0.0f;
34         attenuation[2] = 0.0f;
35         cast_shadows = false;
36 }
37
38 Light::~Light() {}
39
40 void Light::set_color(const Color &c, unsigned short color_flags) {
41         if(color_flags & LIGHTCOL_AMBIENT) {
42                 ambient_color = c;
43         }
44         
45         if(color_flags & LIGHTCOL_DIFFUSE) {
46                 diffuse_color = c;
47         }
48         
49         if(color_flags & LIGHTCOL_SPECULAR) {
50                 specular_color = c;
51         }
52 }
53
54
55 void Light::set_color(const Color &amb, const Color &diff, const Color &spec) {
56         ambient_color = amb;
57         diffuse_color = diff;
58         specular_color = spec;
59 }
60
61 Color Light::get_color(unsigned short which) const {
62         switch(which) {
63         case LIGHTCOL_AMBIENT:
64                 return ambient_color;
65                 
66         case LIGHTCOL_SPECULAR:
67                 return specular_color;
68                 
69         case LIGHTCOL_DIFFUSE:
70         default:
71                 return diffuse_color;
72         }
73 }
74
75 void Light::set_intensity(scalar_t intensity) {
76         this->intensity = intensity;
77 }
78
79 scalar_t Light::get_intensity() const {
80         return intensity;
81 }
82
83 void Light::set_attenuation(scalar_t att0, scalar_t att1, scalar_t att2) {
84         attenuation[0] = att0;
85         attenuation[1] = att1;
86         attenuation[2] = att2;
87 }
88
89 scalar_t Light::get_attenuation(int which) const {
90         return attenuation[which];
91 }
92
93 Vector3 Light::get_attenuation_vector() const {
94         return Vector3(attenuation[0], attenuation[1], attenuation[2]);
95 }
96
97 void Light::set_shadow_casting(bool shd) {
98         cast_shadows = shd;
99 }
100
101 bool Light::casts_shadows() const {
102         return cast_shadows;
103 }
104
105 // ------- point lights -------
106
107 PointLight::PointLight(const Vector3 &pos, const Color &col) {
108         set_position(pos);
109         diffuse_color = specular_color = col;
110 }
111
112 PointLight::~PointLight() {}
113
114 void PointLight::set_gl_light(int n, unsigned long time) const {
115         int light_num = GL_LIGHT0 + n;
116         
117         Vector4 pos;
118         if(time == XFORM_LOCAL_PRS) {
119                 pos = (Vector4)local_prs.position;
120         } else {
121                 pos = (Vector4)get_prs(time).position;
122         }
123         
124         glMatrixMode(GL_MODELVIEW);
125         glPushMatrix();
126         Matrix4x4 test = engfx_state::view_matrix;
127         test.translate(pos);
128         load_matrix_gl(test);
129
130         Color amb = ambient_color * intensity;
131         Color dif = diffuse_color * intensity;
132         Color spec = specular_color * intensity;
133
134         float position[] = {0.0f, 0.0f, 0.0f, 1.0f};
135         float gl_amb[] = {amb.r, amb.g, amb.b, ambient_color.a};
136         float gl_dif[] = {dif.r, dif.g, dif.b, diffuse_color.a};
137         float gl_spec[] = {spec.r, spec.g, spec.b, specular_color.a};
138         
139         glLightfv(light_num, GL_POSITION, position);
140         glLightfv(light_num, GL_AMBIENT, gl_amb);
141         glLightfv(light_num, GL_DIFFUSE, gl_dif);
142         glLightfv(light_num, GL_SPECULAR, gl_spec);
143         glLightf(light_num, GL_CONSTANT_ATTENUATION, (float)attenuation[0]);
144         glLightf(light_num, GL_LINEAR_ATTENUATION, (float)attenuation[1]);
145         glLightf(light_num, GL_QUADRATIC_ATTENUATION, (float)attenuation[2]);
146         
147         glEnable(light_num);
148         
149         glPopMatrix();
150
151         if(!engfx_state::bump_light) set_bump_light(this);
152 }
153
154
155
156 // ------- directional lights -------
157
158 DirLight::DirLight(const Vector3 &dir, const Color &col) {
159         this->dir = dir;
160         diffuse_color = specular_color = col;
161 }
162
163 DirLight::~DirLight() {}
164
165 Vector3 DirLight::get_direction()
166 {
167         return dir;
168 }
169
170 void DirLight::set_gl_light(int n, unsigned long time) const {
171         int light_num = GL_LIGHT0 + n;
172         
173         Vector3 ldir = dir.transformed(get_prs(time).rotation);
174         
175         glMatrixMode(GL_MODELVIEW);
176         glPushMatrix();
177         Matrix4x4 test = engfx_state::view_matrix;
178         load_matrix_gl(test);
179
180         Color amb = ambient_color * intensity;
181         Color dif = diffuse_color * intensity;
182         Color spec = specular_color * intensity;
183
184         float position[] = {-ldir.x, -ldir.y, -ldir.z, 0.0f};
185         float gl_amb[] = {amb.r, amb.g, amb.b, ambient_color.a};
186         float gl_dif[] = {dif.r, dif.g, dif.b, diffuse_color.a};
187         float gl_spec[] = {spec.r, spec.g, spec.b, specular_color.a};
188         
189         glLightfv(light_num, GL_POSITION, position);
190         glLightfv(light_num, GL_AMBIENT, gl_amb);
191         glLightfv(light_num, GL_DIFFUSE, gl_dif);
192         glLightfv(light_num, GL_SPECULAR, gl_spec);
193         
194         glEnable(light_num);
195         
196         glPopMatrix();
197
198         if(!engfx_state::bump_light) set_bump_light(this);
199 }