OCC22199 OpenGL memory leaks in TKOpenGl
[occt.git] / src / OpenGl / OpenGl_LightBox.cxx
CommitLineData
7fd59977 1/***********************************************************************
2
3FONCTION :
4----------
5Gestion des light sous OpenGL
6
7
8REMARQUES:
9----------
10
11- We can't take in account GL_QUADRATIC_ATTENUATION.
12
13- Position des lumieres. Il faut faire le glLight(GL_POSITION) apres la
14gestion des matrices de transformation (GL_MODELVIEW).
15
16- Se mefier de GL_POSITION pour les lumieres directionelle. GL_POSITION
17indique bien la position ou se trouve la lumiere. Comme on a une direction
18comme valeur il faut l'inverser.
19
20
21FONCTIONNEMENT:
22---------------
23- La variable lightOn permet d'optimiser le changement d'etat des lumieres.
24Ceci permet d'eviter d'appeler glIsEnable(GL_LIGHTING). Il faut bien sur
25que l'on utilise les 2 points d'entree LightOn() et LightOff().
26L'init de la variable est faite par call_func_redraw_all_structs (OpenGl_funcs.c)
27
28
29HISTORIQUE DES MODIFICATIONS :
30--------------------------------
3120-06-97 : PCT ; creation
3230-06-96 : FMN ; Integration
3318-07-96 : FMN, PCT ; Correction indice, ajout IsLightOn()
3425-07-97 : CAL ; Portage NT (include OpenGl_tgl_all.h)
3507-10-97 : FMN ; Simplification WNT
36
37************************************************************************/
38
39/*----------------------------------------------------------------------*/
40/*
41* Includes
42*/
43
44#include <OpenGl_tgl_all.hxx>
45
46#include <stdio.h>
47#include <stdlib.h>
48
49#include <math.h>
50#include <memory.h>
51
52#include <OpenGl_LightBox.hxx>
53#include <OpenGl_Memory.hxx>
54
55/*----------------------------------------------------------------------*/
56/*
57* Constantes
58*/
59#ifndef DEBUG
60#define DEBUG 0
61#endif
62
63#define NO_PRINT_DEBUG
64
65#define GROW_SIZE_WKS 10
66#define GROW_SIZE_LIGHT 8
67
68#ifndef M_PI
69# define M_PI 3.14159265358979323846
70#endif
71
72/*----------------------------------------------------------------------*/
73/*
74* Types definis
75*/
76struct TEL_LIGHT_DATA
77{
78 Tint LightID;
79 TEL_LIGHT light;
80 IMPLEMENT_MEMORY_OPERATORS
81};
82
83struct TEL_LIGHT_WKS
84{
85 Tint wks;
86 int lights_count;
87 int lights_size;
88 TEL_LIGHT_DATA *lights;
89 IMPLEMENT_MEMORY_OPERATORS
90};
91
92
93/*----------------------------------------------------------------------*/
94/*
95* Variables statiques
96*/
97
98static TEL_LIGHT_WKS *wks = NULL;
99static int wks_count = 0;
100static int wks_size = 0;
101
102static GLfloat default_amb[4] = { 0.0, 0.0, 0.0, 1.0 };
103static GLfloat default_sptdir[3] = { 0.0, 0.0, -1.0 };
104static GLfloat default_sptexpo = 0.0;
105static GLfloat default_sptcutoff = 180.0;
106
107static GLboolean lightOn = GL_FALSE;
108
109/*----------------------------------------------------------------------*/
110/*
111* Fonctions privees
112*/
113
114/*-----------------------------------------------------------------*/
115/*
116* Set des lumieres
117*/
118static void bind_light(TEL_LIGHT *lptr, int *gl_lid)
119{
120 GLfloat data_amb[4];
121 GLfloat data_diffu[4];
122 GLfloat data_pos[4];
123 GLfloat data_sptdir[3];
124 GLfloat data_sptexpo;
125 GLfloat data_sptcutoff;
126 GLfloat data_constantattenuation;
127 GLfloat data_linearattenuation;
128 GLint cur_matrix;
129
130
131 /* on n'a droit qu'a 8 lights avec OpenGL... */
132 if (*gl_lid > GL_LIGHT7) return;
133
134
135 /* la light est une headlight ? */
136 if (lptr->HeadLight)
137 {
138 glGetIntegerv(GL_MATRIX_MODE, &cur_matrix);
139 glMatrixMode(GL_MODELVIEW);
140 glPushMatrix();
141 glLoadIdentity();
142 }
143
144
145 /* set la light en fonction de son type */
146 switch (lptr->type)
147 {
148 case TLightAmbient:
149 data_amb[0] = lptr->col.rgb[0];
150 data_amb[1] = lptr->col.rgb[1];
151 data_amb[2] = lptr->col.rgb[2];
152 data_amb[3] = 1.0;
153
154 /*------------------------- Ambient ---------------------------*/
155 /*
156 * The GL_AMBIENT parameter refers to RGBA intensity of the ambient
157 * light.
158 */
159 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, data_amb);
160
161#if DEBUG
162 printf("OpenGL_LightBox::bind_light:LightAmbient \n");
163 printf("\tGL_LIGHT_MODEL_AMBIENT %f %f %f \n", data_amb[0], data_amb[1], data_amb[2]);
164#endif
165 break;
166
167
168 case TLightDirectional:
169 data_diffu[0] = lptr->col.rgb[0];
170 data_diffu[1] = lptr->col.rgb[1];
171 data_diffu[2] = lptr->col.rgb[2];
172 data_diffu[3] = 1.0;
173
174 /*------------------------- Direction ---------------------------*/
175 /* From Open GL Programming Rev 1 Guide Chapt 6 :
176 Lighting The Mathematics of Lighting ( p 168 )
177
178 Directional Light Source ( Infinite ) :
179 if the last parameter of GL_POSITION , w , is zero, the
180 corresponding light source is a Directional one.
181
182 GL_SPOT_CUTOFF a 180 signifie que ce n'est pas un spot.
183 To create a realistic effect, set the GL_SPECULAR parameter
184 to the same value as the GL_DIFFUSE.
185 */
186
187 data_pos[0] = -lptr->dir[0];
188 data_pos[1] = -lptr->dir[1];
189 data_pos[2] = -lptr->dir[2];
190 data_pos[3] = 0.0;
191
192 glLightfv(*gl_lid, GL_AMBIENT, default_amb);
193 glLightfv(*gl_lid, GL_DIFFUSE, data_diffu);
194 glLightfv(*gl_lid, GL_SPECULAR, data_diffu);
195
196 glLightfv(*gl_lid, GL_POSITION, data_pos);
197 glLightfv(*gl_lid, GL_SPOT_DIRECTION, default_sptdir);
198 glLightf(*gl_lid, GL_SPOT_EXPONENT, default_sptexpo);
199 glLightf(*gl_lid, GL_SPOT_CUTOFF, default_sptcutoff);
200
201#if DEBUG
202 printf("OpenGL_LightBox::bind_light:LightDirection \n");
203 printf("\tGL_AMBIENT %f %f %f \n", default_amb[0], default_amb[1], default_amb[2]);
204 printf("\tGL_DIFFUSE %f %f %f \n", data_diffu[0], data_diffu[1], data_diffu[2]);
205 printf("\tGL_SPECULAR %f %f %f \n", data_diffu[0], data_diffu[1], data_diffu[2]);
206 printf("\tGL_POSITION %f %f %f \n", data_pos[0], data_pos[1], data_pos[2]);
207#endif
208 break;
209
210
211 case TLightPositional:
212 data_diffu[0] = lptr->col.rgb[0];
213 data_diffu[1] = lptr->col.rgb[1];
214 data_diffu[2] = lptr->col.rgb[2];
215 data_diffu[3] = 1.0;
216
217 /*------------------------- Position -----------------------------*/
218 /* From Open GL Programming Rev 1 Guide Chapt 6 :
219 Lighting The Mathematics of Lighting ( p 168 )
220 Positional Light Source :
221 if the last parameter of GL_POSITION , w , is nonzero,
222 the corresponding light source is a Positional one.
223
224 GL_SPOT_CUTOFF a 180 signifie que ce n'est pas un spot.
225
226 To create a realistic effect, set the GL_SPECULAR parameter
227 to the same value as the GL_DIFFUSE.
228 */
229
230 data_pos[0] = lptr->pos[0];
231 data_pos[1] = lptr->pos[1];
232 data_pos[2] = lptr->pos[2];
233 data_pos[3] = 1.0;
234
235 data_constantattenuation = lptr->atten[0];
236 data_linearattenuation = lptr->atten[1];
237
238 glLightfv(*gl_lid, GL_AMBIENT, default_amb);
239 glLightfv(*gl_lid, GL_DIFFUSE, data_diffu);
240 glLightfv(*gl_lid, GL_SPECULAR, data_diffu);
241
242 glLightfv(*gl_lid, GL_POSITION, data_pos);
243 glLightfv(*gl_lid, GL_SPOT_DIRECTION, default_sptdir);
244 glLightf(*gl_lid, GL_SPOT_EXPONENT, default_sptexpo);
245 glLightf(*gl_lid, GL_SPOT_CUTOFF, default_sptcutoff);
246 glLightf(*gl_lid, GL_CONSTANT_ATTENUATION, data_constantattenuation);
247 glLightf(*gl_lid, GL_LINEAR_ATTENUATION, data_linearattenuation);
248 glLightf(*gl_lid, GL_QUADRATIC_ATTENUATION, 0.0);
249
250#if DEBUG
251 printf("OpenGL_LightBox::bind_light:LightPosition \n");
252 printf("\tGL_AMBIENT %f %f %f \n", default_amb[0], default_amb[1], default_amb[2]);
253 printf("\tGL_DIFFUSE %f %f %f \n", data_diffu[0], data_diffu[1], data_diffu[2]);
254 printf("\tGL_SPECULAR %f %f %f \n", data_diffu[0], data_diffu[1], data_diffu[2]);
255 printf("\tGL_POSITION %f %f %f \n", data_pos[0], data_pos[1], data_pos[2]);
256#endif
257 break;
258
259
260 case TLightSpot:
261 data_diffu[0] = lptr->col.rgb[0];
262 data_diffu[1] = lptr->col.rgb[1];
263 data_diffu[2] = lptr->col.rgb[2];
264 data_diffu[3] = 1.0;
265
266 data_pos[0] = lptr->pos[0];
267 data_pos[1] = lptr->pos[1];
268 data_pos[2] = lptr->pos[2];
269 data_pos[3] = 1.0;
270
271 data_sptdir[0] = lptr->dir[0];
272 data_sptdir[1] = lptr->dir[1];
273 data_sptdir[2] = lptr->dir[2];
274
275 data_sptexpo = ( float )lptr->shine * 128.0F;
276 data_sptcutoff = ( float )(lptr->angle * 180.0F)/( float )M_PI;
277
278 data_constantattenuation = lptr->atten[0];
279 data_linearattenuation = lptr->atten[1];
280
281 glLightfv(*gl_lid, GL_AMBIENT, default_amb);
282 glLightfv(*gl_lid, GL_DIFFUSE, data_diffu);
283 glLightfv(*gl_lid, GL_SPECULAR, data_diffu);
284
285 glLightfv(*gl_lid, GL_POSITION, data_pos);
286 glLightfv(*gl_lid, GL_SPOT_DIRECTION, data_sptdir);
287 glLightf(*gl_lid, GL_SPOT_EXPONENT, data_sptexpo);
288 glLightf(*gl_lid, GL_SPOT_CUTOFF, data_sptcutoff);
289 glLightf(*gl_lid, GL_CONSTANT_ATTENUATION, data_constantattenuation);
290 glLightf(*gl_lid, GL_LINEAR_ATTENUATION, data_linearattenuation);
291 glLightf(*gl_lid, GL_QUADRATIC_ATTENUATION, 0.0);
292
293#if DEBUG
294 printf("OpenGL_LightBox::bind_light:LightSpot \n");
295 printf("\tGL_AMBIENT %f %f %f \n", default_amb[0], default_amb[1], default_amb[2]);
296 printf("\tGL_DIFFUSE %f %f %f \n", data_diffu[0], data_diffu[1], data_diffu[2]);
297 printf("\tGL_SPECULAR %f %f %f \n", data_diffu[0], data_diffu[1], data_diffu[2]);
298 printf("\tGL_POSITION %f %f %f \n", data_pos[0], data_pos[1], data_pos[2]);
299 printf("\tGL_SPOT_DIRECTION %f %f %f \n", data_sptdir[0], data_sptdir[1], data_sptdir[2]);
300 printf("\tGL_SPOT_EXPONENT %f \n", data_sptexpo);
301 printf("\tGL_SPOT_CUTOFF %f \n", data_sptcutoff);
302 printf("\tGL_CONSTANT_ATTENUATION %f \n", data_constantattenuation);
303 printf("\tGL_LINEAR_ATTENUATION %f \n", data_linearattenuation);
304#endif
305 break;
306 }
307
308
309 if (lptr->type != TLightAmbient)
310 {
311#if DEBUG
312 printf("OpenGL_LightBox::bind_light:glEnable %d \n", *gl_lid);
313#endif
314 glEnable(*gl_lid);
315 (*gl_lid)++;
316 }
317
318
319 /* si la light etait une headlight alors restaure la matrice precedente */
320 if (lptr->HeadLight)
321 {
322 glPopMatrix();
323 glMatrixMode(cur_matrix);
324 }
325}
326
327
328/*-----------------------------------------------------------------*/
329/*
330* recherche de la liste de lampe d'une wks, creation d'une liste si non existante
331*/
332static int find_wks(Tint WksID, int alloc)
333{
334 int i;
335
336 /* recherche la wks dans la liste si elle existe */
337 for (i=0; i<wks_count; i++)
338 if (wks[i].wks == WksID)
339 return i;
340
341 if (!alloc) return -1;
342
343 /* la wks n'existe pas => on fait de la place si yen a plus */
344 if (wks_count == wks_size )
345 {
346 wks_size += GROW_SIZE_WKS;
347 if (!wks)
348 wks = new TEL_LIGHT_WKS[wks_size];
349 else
350#if defined(__SUNPRO_CC) && (__SUNPRO_CC <= 0x530)
351 wks = (TEL_LIGHT_WKS*)realloc(wks, wks_size*sizeof(TEL_LIGHT_WKS));
352#else
353 wks = cmn_resizemem<TEL_LIGHT_WKS>(wks, wks_size);
354#endif
355
356 if (!wks)
357 return -1;
358 }
359
360 wks[wks_count].wks = WksID;
361 wks[wks_count].lights = NULL;
362 wks[wks_count].lights_size = 0;
363 wks[wks_count].lights_count = 0;
364
365 return wks_count++;
366}
367
368/*-----------------------------------------------------------------*/
369/*
370* recherche une lampe d'une wks, creation d'une lampe si elle n'existe pas
371*/
372static int find_light(int WksIdx, Tint LightID, int alloc)
373{
374 int i;
375 TEL_LIGHT_DATA *lights;
376
377
378 /* recherche la light dans la liste de la wks */
379 lights = wks[WksIdx].lights;
380 for (i=0; i<wks[WksIdx].lights_count; i++)
381 if (lights[i].LightID == LightID)
382 return i;
383
384 if (!alloc) return -1;
385
386 /* la lampe n'existe pas => on cree une lampe */
387 if (wks[WksIdx].lights_count == wks[WksIdx].lights_size)
388 {
389 wks[WksIdx].lights_size += GROW_SIZE_LIGHT;
390 if (!wks[WksIdx].lights)
391 wks[WksIdx].lights = new TEL_LIGHT_DATA[wks[WksIdx].lights_size];
392 else
393 wks[WksIdx].lights =
394#if defined(__SUNPRO_CC) && (__SUNPRO_CC <= 0x530)
395 (TEL_LIGHT_DATA*)realloc( wks[WksIdx].lights,
396 wks[WksIdx].lights_size*sizeof(TEL_LIGHT_DATA) );
397#else
398 cmn_resizemem<TEL_LIGHT_DATA>( wks[WksIdx].lights,
399 wks[WksIdx].lights_size );
400#endif
401 if (!wks[WksIdx].lights)
402 return -1;
403 }
404
405 return wks[WksIdx].lights_count++;
406}
407
408
409/*----------------------------------------------------------------------*/
410/*
411* Fonctions publiques
412*/
413
414
415/*-----------------------------------------------------------------*/
416/*
417* Ajout d'une lumiere dans la Wks
418*/
419TStatus AddLight(Tint WksID, Tint LightID, tel_light light)
420{
421 int wks_entry;
422 int light_entry;
423
424#if DEBUG
425 printf("AddLight %d dans wks %d [wds_count=%d]\n", LightID, WksID, wks_count);
426#endif
427
428 /* obtient le numero de la liste de lights de la wks */
429 wks_entry = find_wks(WksID, 1);
430 if (wks_entry == -1) return TFailure;
431
432 /* recherche le numero de la lampe si elle existe */
433 light_entry = find_light(wks_entry, LightID, 1);
434 if (light_entry == -1) return TFailure;
435
436 /* met a jour la light */
437 wks[wks_entry].lights[light_entry].LightID = LightID;
438 wks[wks_entry].lights[light_entry].light = *light;
439
440#if DEBUG
441 printf("ajout ok\n");
442#endif
443 return TSuccess;
444}
445
446
447/*-----------------------------------------------------------------*/
448/*
449* Maj des lumieres de la Wks
450*/
451TStatus UpdateLight(Tint WksID)
452{
453 int wks_entry;
454 int i;
455 int gl_lid;
456
457
458#if DEBUG
459 printf("UpdateLight %d\n", WksID);
460#endif
461
462 /* vire toutes les lights des le depart avant une re-init complete */
463 for (i=GL_LIGHT0; i<=GL_LIGHT7; i++)
464 glDisable(i);
465 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, default_amb);
466
467 /* recherche la liste de light de la wks */
468 wks_entry = find_wks(WksID, 0);
469 if (wks_entry == -1) return TFailure;
470
471#if DEBUG
472 printf("*** Update: nb = %d\n", wks[wks_entry].lights_count);
473#endif
474
475 /* set les lights */
476 gl_lid = GL_LIGHT0;
477 for (i=0; i<wks[wks_entry].lights_count; i++)
478 {
479#if DEBUG
480 printf("binding light %d\n", i);
481#endif
482 bind_light(&wks[wks_entry].lights[i].light, &gl_lid);
483 }
484
485 if (wks[wks_entry].lights_count > 0) LightOn();
486
487#if DEBUG
488 printf("update ok\n");
489#endif
490
491 return TSuccess;
492}
493
494
495/*-----------------------------------------------------------------*/
496/*
497* Remove une lumiere de la Wks
498*/
499TStatus RemoveLight(Tint WksID, Tint LightID)
500{
501 int wks_entry;
502 int light_entry;
503
504
505 /* recherche de la wks */
506 wks_entry = find_wks(WksID, 0);
507 if (wks_entry == -1) return TFailure;
508
509 /* recherche de la light */
510 light_entry = find_light(wks_entry, LightID, 0);
511 if (light_entry == -1) return TFailure;
512
513 /* retire la light */
514 memcpy(&wks[wks_entry].lights[light_entry],
515 &wks[wks_entry].lights[light_entry+1],
516 (wks[wks_entry].lights_count - light_entry - 1)*sizeof(TEL_LIGHT_DATA));
517 wks[wks_entry].lights_count--;
518
519#if DEBUG
520 printf("RemoveLight %d dans wks %d [wds_count=%d]\n", LightID, WksID, wks_count);
521#endif
522
523 return TSuccess;
524}
525
526
527/*-----------------------------------------------------------------*/
528/*
529* Remove des lumieres de la Wks
530*/
531TStatus RemoveWksLight(Tint WksID)
532{
533 int wks_entry;
534
535 /* recherche de la wks */
536 wks_entry = find_wks(WksID, 0);
537 if (wks_entry == -1) return TFailure;
538
539 /* destruction de toute la wks */
540 free(wks[wks_entry].lights);
541 memcpy(&wks[wks_entry],
542 &wks[wks_entry+1],
543 (wks_count - wks_entry - 1)*sizeof(TEL_LIGHT_WKS));
544 wks_count--;
545
546 return TSuccess;
547}
548
549
550/*-----------------------------------------------------------------*/
551/*
552* Reset de toutes les lights d'une Wks
553*/
554TStatus ResetWksLight(Tint WksID)
555{
556 int wks_entry;
557
558 /* recherche de la wks */
559 wks_entry = find_wks(WksID, 0);
560 if (wks_entry == -1) return TFailure;
561
562 /* destruction de toutes les lights */
563 wks[wks_entry].lights_count = 0;
564
565 return TSuccess;
566}
567
568
569/*-----------------------------------------------------------------*/
570/*
571* Enable des lights
572*/
573void LightOn(void)
574{
575#ifdef PRINT_DEBUG
576 if(IsLightOn())
577 printf("LightOn(): lighting already enabled!");
578 else
579 printf("LightOn() succeeded");
580#endif
581 glEnable(GL_LIGHTING);
582}
583
584
585/*-----------------------------------------------------------------*/
586/*
587* Disable des lights
588*/
589void LightOff(void)
590{
591#ifdef PRINT_DEBUG
592 if(!IsLightOn())
593 printf("LightOff(): lighting already disabled!");
594 else
595 printf("LightOff() succeeded");
596#endif
597 glDisable(GL_LIGHTING);
598}
599/*-----------------------------------------------------------------*/
600
601/*
602* IsEnable des lights
603*/
604
605GLboolean IsLightOn(void)
606{
607 return glIsEnabled(GL_LIGHTING);
608}
609/*-----------------------------------------------------------------*/