1 // BASE_APP.CPP
2
3 // Copyright (C) 2005 Tommi Hassinen.
4
5 // This package is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation; either version 2 of the License, or
8 // (at your option) any later version.
9
10 // This package is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
14
15 // You should have received a copy of the GNU General Public License
16 // along with this package; if not, write to the Free Software
17 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18
19 /*################################################################################################*/
20
21 #include "base_app.h"
22
23 #include <stdlib.h> // the definition for NULL...
24
25 #include <algorithm> // for WIN32...
26 using namespace std;
27
28 // NOT_DEFINED is defined here the same way as in libghemical.
29
30 #ifndef NOT_DEFINED
31 #define NOT_DEFINED -1
32 #endif // NOT_DEFINED
33
34 /*################################################################################################*/
35
36 mouseinfo::mi_state mouseinfo::state = mouseinfo::sUnknown;
37 mouseinfo::mi_button mouseinfo::button = mouseinfo::bNone;
38
39 bool mouseinfo::shift_down = false;
40 bool mouseinfo::ctrl_down = false;
41
42 float mouseinfo::ang_sensitivity = 180.0;
43 float mouseinfo::dist_sensitivity = 2.0;
44
45 int mouseinfo::latest_x = -1;
46 int mouseinfo::latest_y = -1;
47
48 /*################################################################################################*/
49
50 base_app * base_app::app = NULL;
51
base_app(void)52 base_app::base_app(void)
53 {
54 if (app != NULL) // prevent multiple instances...
55 {
56 app->ErrorMessage("liboglappth : base_app ctor failed!");
57 exit(EXIT_FAILURE);
58 }
59
60 app = this;
61
62 glname_counter = 1; // reserve value 0 for UNREGISTERED.
63 }
64
~base_app(void)65 base_app::~base_app(void)
66 {
67 }
68
GetAppB(void)69 base_app * base_app::GetAppB(void)
70 {
71 return app;
72 }
73
AddCamera(ogl_camera * cam)74 void base_app::AddCamera(ogl_camera * cam)
75 {
76 vector<ogl_camera *>::iterator it = find(camera_vector.begin(), camera_vector.end(), cam);
77 if (it != camera_vector.end())
78 {
79 cout << "liboglappth : duplicate cam record!" << endl;
80 exit(EXIT_FAILURE);
81 }
82
83 camera_vector.push_back(cam);
84 }
85
RemoveCamera(ogl_camera * cam)86 bool base_app::RemoveCamera(ogl_camera * cam)
87 {
88 vector<ogl_camera *>::iterator it = find(camera_vector.begin(), camera_vector.end(), cam);
89 if (it == camera_vector.end()) return false;
90
91 // make sure that the related lights are removed as well...
92
93 int n1 = 0;
94 while (n1 < (int) light_vector.size())
95 {
96 if (light_vector[n1]->owner == cam)
97 {
98 RemoveLight(light_vector[n1]);
99 }
100 else n1++;
101 }
102
103 // do not delete the object, just remove it from the vector...
104 // do not delete the object, just remove it from the vector...
105 // do not delete the object, just remove it from the vector...
106
107 camera_vector.erase(it);
108 return true;
109 }
110
AddGlobalLight(ogl_light * light)111 bool base_app::AddGlobalLight(ogl_light * light)
112 {
113 GLint max_local_size = 0;
114 for (unsigned int n1 = 0;n1 < camera_vector.size();n1++)
115 {
116 GLint local_size = CountLocalLights(camera_vector[n1]);
117 if (local_size > max_local_size) max_local_size = local_size;
118 }
119
120 GLint total_lights = CountGlobalLights() + max_local_size;
121
122 // we really can't do this test here ; see SetupLights()...
123 // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
124 //GLint max_lights; glGetIntegerv(GL_MAX_LIGHTS, & max_lights);
125 //if (total_lights == max_lights) return false;
126
127 light_vector.push_back(light);
128 SetGlobalLightNumbers();
129
130 for (unsigned int n1 = 0;n1 < camera_vector.size();n1++)
131 {
132 SetLocalLightNumbers(camera_vector[n1]);
133 SetupLights(camera_vector[n1]);
134 }
135
136 return true;
137 }
138
AddLocalLight(ogl_light * light,ogl_camera * cam)139 bool base_app::AddLocalLight(ogl_light * light, ogl_camera * cam)
140 {
141 GLint total_lights = CountGlobalLights() + CountLocalLights(cam);
142
143 // we really can't do this test here ; see SetupLights()...
144 // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
145 //GLint max_lights; glGetIntegerv(GL_MAX_LIGHTS, & max_lights);
146 //if (total_lights == max_lights) return false;
147
148 light->owner = cam; light_vector.push_back(light);
149 SetLocalLightNumbers(cam);
150 SetupLights(cam);
151
152 return true;
153 }
154
RemoveLight(ogl_dummy_object * obj)155 bool base_app::RemoveLight(ogl_dummy_object * obj)
156 {
157 int n1 = IsLight(obj);
158 if (n1 < 0) return false;
159
160 ogl_camera * owner = light_vector[n1]->owner;
161
162 // do not delete the object, just remove it from the vector...
163 // do not delete the object, just remove it from the vector...
164 // do not delete the object, just remove it from the vector...
165
166 light_vector.erase(light_vector.begin() + n1);
167
168 if (owner != NULL)
169 {
170 SetLocalLightNumbers(owner);
171 SetupLights(owner);
172 }
173 else
174 {
175 SetGlobalLightNumbers();
176 for (unsigned int n1 = 0;n1 < camera_vector.size();n1++)
177 {
178 SetLocalLightNumbers(camera_vector[n1]);
179 SetupLights(camera_vector[n1]);
180 }
181 }
182
183 return true;
184 }
185
IsLight(const ogl_dummy_object * obj)186 int base_app::IsLight(const ogl_dummy_object * obj)
187 {
188 int index = NOT_DEFINED;
189 for (unsigned int n1 = 0;n1 < light_vector.size();n1++)
190 {
191 if (light_vector[n1] == obj) index = (int) n1;
192 }
193
194 return index;
195 }
196
CountGlobalLights(void)197 GLint base_app::CountGlobalLights(void)
198 {
199 GLint sum = 0;
200 unsigned int n1 = 0;
201 while (n1 < light_vector.size())
202 {
203 if (light_vector[n1++]->owner == NULL) sum++;
204 }
205
206 return sum;
207 }
208
CountLocalLights(ogl_camera * cam)209 GLint base_app::CountLocalLights(ogl_camera * cam)
210 {
211 GLint sum = 0;
212 unsigned int n1 = 0;
213 while (n1 < light_vector.size())
214 {
215 if (light_vector[n1++]->owner == cam) sum++;
216 }
217
218 return sum;
219 }
220
SetupLights(ogl_camera * cam)221 void base_app::SetupLights(ogl_camera * cam)
222 {
223 for (unsigned int n1 = 0;n1 < cam->wnd_vector.size();n1++)
224 {
225 if (!cam->wnd_vector[n1]->SetCurrent())
226 {
227 cout << "liboglappth : GL is not yet initialized -> skipping light setup!" << endl;
228 continue;
229 }
230
231 GLint max_lights;
232 glGetIntegerv(GL_MAX_LIGHTS, & max_lights);
233
234 for (GLint n2 = 0;n2 < max_lights;n2++)
235 {
236 glDisable((GLenum) (GL_LIGHT0 + n2));
237 }
238
239 for (unsigned int n2 = 0;n2 < light_vector.size();n2++)
240 {
241 bool test1 = (light_vector[n2]->owner != NULL);
242 bool test2 = (light_vector[n2]->owner != cam);
243 if (test1 && test2) continue;
244
245 light_vector[n2]->SetupProperties(); bool test = false;
246 if (light_vector[n2]->owner == NULL && cam->use_global_lights) test = true;
247 if (light_vector[n2]->owner == cam && cam->use_local_lights) test = true;
248 if (test) glEnable((GLenum) light_vector[n2]->number);
249 }
250 }
251 }
252
SetGlobalLightNumbers(void)253 void base_app::SetGlobalLightNumbers(void)
254 {
255 GLint counter = 0;
256 for (unsigned int n1 = 0;n1 < light_vector.size();n1++)
257 {
258 if (light_vector[n1]->owner != NULL) continue;
259 light_vector[n1]->number = GL_LIGHT0 + counter++;
260 }
261 }
262
SetLocalLightNumbers(ogl_camera * cam)263 void base_app::SetLocalLightNumbers(ogl_camera * cam)
264 {
265 GLint counter = CountGlobalLights();
266 for (unsigned int n1 = 0;n1 < light_vector.size();n1++)
267 {
268 if (light_vector[n1]->owner != cam) continue;
269 light_vector[n1]->number = GL_LIGHT0 + counter++;
270 }
271 }
272
UpdateLocalLightLocations(ogl_camera * cam)273 void base_app::UpdateLocalLightLocations(ogl_camera * cam)
274 {
275 for (unsigned int n1 = 0;n1 < light_vector.size();n1++)
276 {
277 ogl_camera * owner = light_vector[n1]->owner;
278 if (owner != NULL && owner != cam) continue;
279
280 light_vector[n1]->SetupLocation();
281 }
282 }
283
RenderLights(ogl_camera * cam)284 void base_app::RenderLights(ogl_camera * cam)
285 {
286 for (unsigned int n1 = 0;n1 < light_vector.size();n1++)
287 {
288 ogl_camera * owner = light_vector[n1]->owner;
289 if (owner != NULL && owner != cam) continue;
290
291 light_vector[n1]->Render();
292 }
293 }
294
295 //////////////////////////////////////////////////
296 //////////////////////////////////////////////////
297
RegisterGLName(void * ptr)298 GLuint base_app::RegisterGLName(void * ptr)
299 {
300 GLuint newkey = glname_counter++;
301
302 pair<GLuint, void *> p(newkey, ptr);
303 glname_map.insert(p);
304
305 return newkey;
306 }
307
UnregisterGLNameByName(GLuint key)308 void base_app::UnregisterGLNameByName(GLuint key)
309 {
310 map<GLuint, void *>::iterator it = glname_map.find(key);
311 if (it != glname_map.end())
312 {
313 glname_map.erase(it);
314 return;
315 }
316
317 ErrorMessage("liboglappth : UnregisterGLNameByName() failed!");
318 }
319
UnregisterGLNameByPtr(void * ptr)320 void base_app::UnregisterGLNameByPtr(void * ptr)
321 {
322 // warning!!! this is the slower way to unregister.
323 // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
324
325 map<GLuint, void *>::iterator it = glname_map.begin();
326 while (it != glname_map.end())
327 {
328 if ((* it).second == ptr)
329 {
330 glname_map.erase(it);
331 return;
332 }
333 else it++;
334 }
335
336 ErrorMessage("liboglappth : UnregisterGLNameByPtr() failed!");
337 }
338
FindPtrByGLName(GLuint key)339 void * base_app::FindPtrByGLName(GLuint key)
340 {
341 map<GLuint, void *>::iterator it = glname_map.find(key);
342 if (it != glname_map.end()) return (* it).second;
343 else
344 {
345 ErrorMessage("liboglappth : FindPtrByGLName() failed!");;
346 return NULL;
347 }
348 }
349
AddTP(void * owner,transparent_primitive & tp)350 bool base_app::AddTP(void * owner, transparent_primitive & tp)
351 {
352 if (!tp.TestOwner(owner)) return false; // this is just a double check, to make
353 tp_vector.push_back(tp); return true; // sure that we have correct "owner"...
354 }
355
UpdateMPsForAllTPs(void * owner)356 void base_app::UpdateMPsForAllTPs(void * owner)
357 {
358 for (unsigned int n1 = 0;n1 < tp_vector.size();n1++)
359 {
360 if (tp_vector[n1].TestOwner(owner)) tp_vector[n1].GetData()->UpdateMP();
361 }
362 }
363
RenderAllTPs(ogl_camera * cam)364 void base_app::RenderAllTPs(ogl_camera * cam)
365 {
366 // here we will render those transparent primitives...
367 // all views should call this last when rendering the contents!
368
369 // first we must update the distances for all TP's, and sort them...
370
371 const GLfloat * ref1 = cam->GetSafeLD()->crd;
372 const GLfloat * ref2 = cam->GetSafeLD()->zdir.data;
373
374 for (unsigned int n1 = 0;n1 < tp_vector.size();n1++)
375 {
376 tp_vector[n1].UpdateDistance(ref1, ref2);
377 }
378
379 sort(tp_vector.begin(), tp_vector.end());
380
381 // and then we will just render them...
382 // it looks better if we disable depth buffer changes...
383
384 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
385 glDepthMask(false); glEnable(GL_BLEND);
386
387 for (unsigned int n1 = 0;n1 < tp_vector.size();n1++)
388 {
389 tp_vector[n1].GetData()->Render();
390 }
391
392 glDisable(GL_BLEND); glDepthMask(true);
393 }
394
RemoveAllTPs(void * owner)395 void base_app::RemoveAllTPs(void * owner)
396 {
397 unsigned int n1 = 0;
398 while (n1 < tp_vector.size())
399 {
400 vector<transparent_primitive>::iterator iter;
401
402 if (!tp_vector[n1].TestOwner(owner))
403 {
404 n1++;
405 }
406 else
407 {
408 delete tp_vector[n1].GetData(); // destroy the data object!!!
409
410 iter = (tp_vector.begin() + n1);
411 tp_vector.erase(iter);
412 }
413 }
414 }
415
416 /*################################################################################################*/
417
418 // eof
419