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