FreeWRL / FreeX3D 4.3.0
Component_Lighting.c
1/*
2
3
4X3D Lighting Component
5
6*/
7
8/****************************************************************************
9 This file is part of the FreeWRL/FreeX3D Distribution.
10
11 Copyright 2009 CRC Canada. (http://www.crc.gc.ca)
12
13 FreeWRL/FreeX3D is free software: you can redistribute it and/or modify
14 it under the terms of the GNU Lesser Public License as published by
15 the Free Software Foundation, either version 3 of the License, or
16 (at your option) any later version.
17
18 FreeWRL/FreeX3D is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 GNU General Public License for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with FreeWRL/FreeX3D. If not, see <http://www.gnu.org/licenses/>.
25****************************************************************************/
26
27
28
29#include <config.h>
30#include <system.h>
31#include <display.h>
32#include <internal.h>
33
34#include <libFreeWRL.h>
35
36#include "../vrml_parser/Structs.h"
37#include "../main/headers.h"
38#include "../opengl/OpenGL_Utils.h"
39#include "RenderFuncs.h"
40//#include "../opengl/OpenGL_Utils.h"
41#include "LinearAlgebra.h"
42
43#define RETURN_IF_LIGHT_STATE_NOT_US \
44 if (renderstate()->render_light== VF_globalLight) { \
45 if (!node->global) return;\
46 /* printf ("and this is a global light\n"); */\
47 } else if (node->global) return; \
48 /* else printf ("and this is a local light\n"); */
49
50#define CHBOUNDS(aaa) \
51 if (aaa.c[0]>1.0) aaa.c[0] = 1.0; \
52 if (aaa.c[0]<0.0) aaa.c[0] = 0.0; \
53 if (aaa.c[1]>1.0) aaa.c[1] = 1.0; \
54 if (aaa.c[1]<0.0) aaa.c[1] = 0.0; \
55 if (aaa.c[2]>1.0) aaa.c[2] = 1.0; \
56 if (aaa.c[2]<0.0) aaa.c[3] = 0.0;
57
58
59void compile_DirectionalLight (struct X3D_DirectionalLight *node) {
60 struct point_XYZ vec;
61
62 vec.x = (double) -((node->direction).c[0]);
63 vec.y = (double) -((node->direction).c[1]);
64 vec.z = (double) -((node->direction).c[2]);
65 normalize_vector(&vec);
66 node->_dir.c[0] = (float) vec.x;
67 node->_dir.c[1] = (float) vec.y;
68 node->_dir.c[2] = (float) vec.z;
69 node->_dir.c[3] = 0.0f;/* 0.0 = this is a vector, not a position */
70
71 node->_col.c[0] = ((node->color).c[0]) * (node->intensity);
72 node->_col.c[1] = ((node->color).c[1]) * (node->intensity);
73 node->_col.c[2] = ((node->color).c[2]) * (node->intensity);
74 node->_col.c[3] = 1;
75 CHBOUNDS(node->_col);
76
77
78 node->_amb.c[0] = ((node->color).c[0]) * (node->ambientIntensity);
79 node->_amb.c[1] = ((node->color).c[1]) * (node->ambientIntensity);
80 node->_amb.c[2] = ((node->color).c[2]) * (node->ambientIntensity);
81 node->_amb.c[3] = 1;
82 CHBOUNDS(node->_amb);
83 MARK_NODE_COMPILED;
84}
85
86
87void render_DirectionalLight (struct X3D_DirectionalLight *node) {
88 /* if we are doing global lighting, is this one for us? */
89 RETURN_IF_LIGHT_STATE_NOT_US
90 /*
91 if (renderstate()->render_light== VF_globalLight) {
92 if (!node->global){
93 printf("x local dir,we want global %u\n",node);
94 return;
95 }
96 printf ("* global dir, we want global %u\n",node);
97 } else {
98 if (node->global){
99 printf("x global dir, we want local %u\n",node);
100 return;
101 }
102 else {
103 printf ("* local dir, we want local %u\n",node);
104 }
105 }
106 */
107 COMPILE_IF_REQUIRED;
108
109 if(node->on) {
110 int light = nextlight();
111 if(light >= 0) {
112 float pos[4] = {0.0f, 0.0f, 0.0f, 1.0f};
113 setLightState(light,TRUE);
114 setLightType(light,2);
115 FW_GL_LIGHTFV(light, GL_SPOT_DIRECTION, (GLfloat* )node->_dir.c);
116 FW_GL_LIGHTFV(light, GL_POSITION, (GLfloat* )pos);
117 FW_GL_LIGHTFV(light, GL_DIFFUSE, node->_col.c);
118 FW_GL_LIGHTFV(light, GL_SPECULAR, node->_col.c);
119 FW_GL_LIGHTFV(light, GL_AMBIENT, node->_amb.c);
120 /* used to test if a PointLight, SpotLight or DirectionalLight in shader */
121 // was used, using lightType now //FW_GL_LIGHTF(light, GL_SPOT_CUTOFF, 0);
122 setLightChangedFlag(light);
123 // not used in directionlight calc //FW_GL_LIGHTF(light,GL_LIGHT_RADIUS,100000.0); /* make it very large */
124 }
125 }
126}
127
128/* global lights are done before the rendering of geometry */
129void prep_DirectionalLight (struct X3D_DirectionalLight *node) {
130 if (!renderstate()->render_light) return;
131 render_DirectionalLight(node);
132}
133
134void compile_PointLight (struct X3D_PointLight *node) {
135 int i;
136
137 for (i=0; i<3; i++) node->_loc.c[i] = node->location.c[i];
138 node->_loc.c[3] = 1.0f;/* 1 == this is a position, not a vector */
139
140 //ConsoleMessage("compile_PointLight, loc %f %f %f %f",node->_loc.c[0],node->_loc.c[1],node->_loc.c[2],node->_loc.c[3]);
141
142 node->_col.c[0] = ((node->color).c[0]) * (node->intensity);
143 node->_col.c[1] = ((node->color).c[1]) * (node->intensity);
144 node->_col.c[2] = ((node->color).c[2]) * (node->intensity);
145 node->_col.c[3] = 1;
146 CHBOUNDS(node->_col);
147
148
149 node->_amb.c[0] = ((node->color).c[0]) * (node->ambientIntensity);
150 node->_amb.c[1] = ((node->color).c[1]) * (node->ambientIntensity);
151 node->_amb.c[2] = ((node->color).c[2]) * (node->ambientIntensity);
152 node->_amb.c[3] = 1;
153 CHBOUNDS(node->_amb);
154 MARK_NODE_COMPILED;
155
156 /* ConsoleMessage ("compile_PointLight, attenuation %f %f %f",
157 node->attenuation.c[0],
158 node->attenuation.c[1],
159 node->attenuation.c[2]);*/
160
161
162 /* ConsoleMessage ("compile_PointLight, col %f %f %f %f amb %f %f %f %f",
163 node->_col.c[0],
164 node->_col.c[1],
165 node->_col.c[2],
166 node->_col.c[3],
167 node->_amb.c[0],
168 node->_amb.c[1],
169 node->_amb.c[2],
170 node->_amb.c[3]);
171 */
172}
173
174
175void render_PointLight (struct X3D_PointLight *node) {
176
177 /* if we are doing global lighting, is this one for us? */
178 RETURN_IF_LIGHT_STATE_NOT_US
179 /*
180 if (renderstate()->render_light== VF_globalLight) {
181 if (!node->global) {
182 printf("x local point, we want global %u\n", node);
183 return;
184 }
185 printf ("* global point, we want global %u\n", node);
186 } else {
187 if (node->global){
188 printf("x global point, we want local %u\n", node);
189 return;
190 }else {
191 printf ("* local point, we want local %u\n", node);
192 }
193 }
194 */
195 COMPILE_IF_REQUIRED;
196
197 if(node->on) {
198 int light = nextlight();
199 if(light >= 0) {
200 float vec[4] = {0.0f, 0.0f, -1.0f, 1.0f};
201
202 setLightState(light,TRUE);
203 setLightType(light,0);
204 FW_GL_LIGHTFV(light, GL_SPOT_DIRECTION, vec);
205 FW_GL_LIGHTFV(light, GL_POSITION, node->_loc.c);
206
207 FW_GL_LIGHTF(light, GL_CONSTANT_ATTENUATION,
208 ((node->attenuation).c[0]));
209 FW_GL_LIGHTF(light, GL_LINEAR_ATTENUATION,
210 ((node->attenuation).c[1]));
211 FW_GL_LIGHTF(light, GL_QUADRATIC_ATTENUATION,
212 ((node->attenuation).c[2]));
213
214
215 FW_GL_LIGHTFV(light, GL_DIFFUSE, node->_col.c);
216 FW_GL_LIGHTFV(light, GL_SPECULAR, node->_col.c);
217 FW_GL_LIGHTFV(light, GL_AMBIENT, node->_amb.c);
218
219 /* used to test if a PointLight, SpotLight or DirectionalLight in shader */
220 // was used, using lightType now //FW_GL_LIGHTF(light, GL_SPOT_CUTOFF, 0);
221
222 FW_GL_LIGHTF(light,GL_LIGHT_RADIUS,node->radius);
223 setLightChangedFlag(light);
224 }
225 }
226}
227
228/* pointLights are done before the rendering of geometry */
229void prep_PointLight (struct X3D_PointLight *node) {
230
231 if (!renderstate()->render_light) return;
232 /* this will be a global light here... */
233 render_PointLight(node);
234}
235
236void compile_SpotLight (struct X3D_SpotLight *node) {
237 struct point_XYZ vec;
238 float dlen;
239 int i;
240
241 for (i=0; i<3; i++) node->_loc.c[i] = node->location.c[i];
242 node->_loc.c[3] = 1.0f;/* 1 == this is a position, not a vector */
243
244 vec.x = (double) node->direction.c[0];
245 vec.y = (double) node->direction.c[1];
246 vec.z = (double) node->direction.c[2];
247 dlen = veclength(vec);
248 if(dlen < .1f) {
249 vec.x = 0.0; vec.y = 0.0, vec.z = -1.0;
250 }
251 normalize_vector(&vec);
252 node->_dir.c[0] = (float) vec.x;
253 node->_dir.c[1] = (float) vec.y;
254 node->_dir.c[2] = (float) vec.z;
255 node->_dir.c[3] = 1.0f;/* 1.0 = SpotLight */
256
257 node->_col.c[0] = ((node->color).c[0]) * (node->intensity);
258 node->_col.c[1] = ((node->color).c[1]) * (node->intensity);
259 node->_col.c[2] = ((node->color).c[2]) * (node->intensity);
260 node->_col.c[3] = 1;
261 CHBOUNDS(node->_col);
262
263
264 node->_amb.c[0] = ((node->color).c[0]) * (node->ambientIntensity);
265 node->_amb.c[1] = ((node->color).c[1]) * (node->ambientIntensity);
266 node->_amb.c[2] = ((node->color).c[2]) * (node->ambientIntensity);
267 node->_amb.c[3] = 1;
268 CHBOUNDS(node->_amb);
269
270 MARK_NODE_COMPILED;
271}
272
273
274void render_SpotLight(struct X3D_SpotLight *node) {
275 float ft;
276
277 /* if we are doing global lighting, is this one for us? */
278 RETURN_IF_LIGHT_STATE_NOT_US
279
280 COMPILE_IF_REQUIRED;
281
282 if(node->on) {
283 int light = nextlight();
284 if(light >= 0) {
285 setLightState(light,TRUE);
286 setLightType(light,1);
287 FW_GL_LIGHTFV(light, GL_SPOT_DIRECTION, node->_dir.c);
288 FW_GL_LIGHTFV(light, GL_POSITION, node->_loc.c);
289
290 FW_GL_LIGHTF(light, GL_CONSTANT_ATTENUATION,
291 ((node->attenuation).c[0]));
292 FW_GL_LIGHTF(light, GL_LINEAR_ATTENUATION,
293 ((node->attenuation).c[1]));
294 FW_GL_LIGHTF(light, GL_QUADRATIC_ATTENUATION,
295 ((node->attenuation).c[2]));
296
297 FW_GL_LIGHTFV(light, GL_DIFFUSE, node->_col.c);
298 FW_GL_LIGHTFV(light, GL_SPECULAR, node->_col.c);
299 FW_GL_LIGHTFV(light, GL_AMBIENT, node->_amb.c);
300
301 //ft =(float)cos((node->beamWidth)/2.0); /* / (PI/4.0); */
302 ft = cosf(node->beamWidth);
303 FW_GL_LIGHTF(light, GL_SPOT_BEAMWIDTH,ft);
304 //ConsoleMessage ("spotLight, bw %f, cuta %f, PI/4 %f", node->beamWidth,node->cutOffAngle, PI/4.0);
305
306 /* create a ratio of light in relation to PI/4.0 */
307 //ft = (float)cos(node->cutOffAngle/2.0); /* / (PI/4.0); */
308 ft = cosf(node->cutOffAngle);
309 FW_GL_LIGHTF(light, GL_SPOT_CUTOFF, ft);
310 setLightChangedFlag(light);
311 //not used in spotlight calculation FW_GL_LIGHTF(light,GL_LIGHT_RADIUS,node->radius);
312 }
313 }
314}
315/* SpotLights are done before the rendering of geometry */
316void prep_SpotLight (struct X3D_SpotLight *node) {
317 if (!renderstate()->render_light) return;
318 render_SpotLight(node);
319}
320
321int getLocalLight();
322void pushLocalLight(int lastlight);
323void popLocalLight();
324
325
326void sib_prep_DirectionalLight(struct X3D_Node *parent, struct X3D_Node *sibAffector){
327 int lastlight;
328 //if ((parent->_renderFlags & VF_localLight)==VF_localLight && renderstate()->render_light != VF_globalLight){
329 if ( renderstate()->render_light != VF_globalLight){
330 saveLightState2(&lastlight);
331 pushLocalLight(lastlight);
332 render_DirectionalLight((struct X3D_DirectionalLight*)sibAffector);
333 }
334}
335void sib_prep_SpotlLight(struct X3D_Node *parent, struct X3D_Node *sibAffector){
336 int lastlight;
337 if ( renderstate()->render_light != VF_globalLight){
338 saveLightState2(&lastlight);
339 pushLocalLight(lastlight);
340 render_SpotLight((struct X3D_SpotLight*)sibAffector);
341 }
342
343}
344void sib_prep_PointLight(struct X3D_Node *parent, struct X3D_Node *sibAffector){
345 int lastlight;
346 if ( renderstate()->render_light != VF_globalLight){
347 saveLightState2(&lastlight);
348 pushLocalLight(lastlight);
349 render_PointLight((struct X3D_PointLight*)sibAffector);
350 }
351}
352
353
354void sib_fin_DirectionalLight(struct X3D_Node *parent, struct X3D_Node *sibAffector){
355 int lastlight;
356 if ( renderstate()->render_light != VF_globalLight) {
357 lastlight = getLocalLight();
358 if(numberOfLights() > lastlight) {
359 setLightChangedFlag(numberOfLights()-1);
360 refreshLightUniforms();
361 }
362 restoreLightState2(lastlight);
363 popLocalLight();
364 }
365}
366void sib_fin_SpotlLight(struct X3D_Node *parent, struct X3D_Node *sibAffector){
367 int lastlight;
368 if (renderstate()->render_light != VF_globalLight) {
369 lastlight = getLocalLight();
370 if(numberOfLights() > lastlight) {
371 setLightChangedFlag(numberOfLights()-1);
372 refreshLightUniforms();
373 }
374 restoreLightState2(lastlight);
375 popLocalLight();
376 }
377}
378void sib_fin_PointLight(struct X3D_Node *parent, struct X3D_Node *sibAffector){
379 int lastlight;
380 if (renderstate()->render_light != VF_globalLight) {
381 lastlight = getLocalLight();
382 if(numberOfLights() > lastlight) {
383 setLightChangedFlag(numberOfLights()-1);
384 refreshLightUniforms();
385 }
386 popLocalLight();
387 restoreLightState2(lastlight);
388 }
389}
390