Dynamically loaded object models thanks to Bjorn.
[crack-attack.git] / src / Displayer.cxx
blob7dfcf9479363eaa2a07f7a40ff25debe90372846
1 /*
2 * Displayer.cxx
3 * Daniel Nelson - 8/26/0
5 * Copyright (C) 2000 Daniel Nelson
6 * Copyright (C) 2004 Andrew Sayman
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 * Daniel Nelson - aluminumangel.org
23 * 174 W. 18th Ave.
24 * Columbus, OH 43210
26 * Handles all the prettyness; or uglyness, as it now stands.
29 #include <cstring>
30 #include <cctype>
31 #include <GL/glut.h>
33 //FIXME: This file may need GL/glext.h
34 #include "glext.h"
36 #ifdef DEVELOPMENT
37 #include <iomanip>
38 #include "sstream.h"
39 #endif
41 #include <sys/time.h>
43 using namespace std;
45 #include "TextureLoader.h"
46 #include "Game.h"
47 #include "Displayer.h"
48 #include "CelebrationManager.h"
49 #include "GarbageFlavorImage.h"
50 #include "SignManager.h"
51 #include "LightManager.h"
52 #include "MetaState.h"
53 #include "SparkleManager.h"
54 #include "String.h"
55 #include "ScoreRecordManager.h"
56 #include "Score.h"
58 GLenum Displayer::rescale_method;
59 bool Displayer::opengl_version_1_2;
61 int Displayer::state;
62 int Displayer::main_window;
63 GLfloat Displayer::play_offset_y;
65 #ifndef NO_MULTITEXTURING
66 # ifndef _WIN32
67 # else
68 # ifndef __MINGW32__
69 PFNGLACTIVETEXTUREARBPROC Displayer::glActiveTextureARB;
70 PFNGLCLIENTACTIVETEXTUREARBPROC Displayer::glClientActiveTextureARB;
71 # endif
72 # endif
73 #endif
75 #ifdef DEVELOPMENT
76 GLint Displayer::screen_length;
77 #endif
79 void Displayer::initialize ( int width, int height )
81 glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
82 if (width != -1 && height != -1) {
83 glutInitWindowSize(width, height);
84 } else {
85 glutInitWindowSize(DC_WINDOW_PIXEL_STARTING_WIDTH,
86 DC_WINDOW_PIXEL_STARTING_HEIGHT);
88 main_window = glutCreateWindow(GC_NAME);
90 state = 0;
92 opengl_version_1_2 = false;
93 char *string = (char *) glGetString(GL_VERSION);
94 if (string[0] > '1' || (string[0] == '1' && string[2] >= '2'))
95 opengl_version_1_2 = true;
97 // determine rescaling method for normals
98 if (opengl_version_1_2)
99 rescale_method = GL_RESCALE_NORMAL;
100 else
101 rescale_method = GL_NORMALIZE;
103 #ifndef NO_MULTITEXTURING
104 // check for multitexturing
105 if (checkExtension("GL_ARB_multitexture")) {
106 GLint n;
107 glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &n);
108 if (n > 1) state |= DS_MULTITEXTURING;
111 # ifndef _WIN32
112 # else
113 // locate the extension function pointers
114 if (state & DS_MULTITEXTURING) {
115 glActiveTextureARB
116 = (PFNGLACTIVETEXTUREARBPROC) wglGetProcAddress("glActiveTextureARB");
117 glClientActiveTextureARB
118 = (PFNGLCLIENTACTIVETEXTUREARBPROC) wglGetProcAddress("glClientActiveTextureARB");
120 # endif
121 #endif
122 SparkleManager::initialize();
123 SignManager::initialize();
124 LightManager::initialize();
125 GarbageFlavorImage::initialize();
126 CelebrationManager::initialize();
127 ScoreRecordManager::initialize();
129 glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
131 glEnable(GL_TEXTURE_2D);
132 glEnable(GL_BLEND);
134 glEnable(GL_CLIP_PLANE_PLAY_FLOOR);
135 const GLdouble play_bottom[]
136 = { 0.0, 1.0, 0.0, DC_PLAY_HEIGHT * DC_CAMERA_HEIGHT_RATIO };
137 glClipPlane(GL_CLIP_PLANE_PLAY_FLOOR, play_bottom);
139 glEnable(GL_LIGHT0);
140 const GLfloat headlight_position[]
141 = { 0.0f, DC_HEADLIGHT_Y_OFFSET, DC_HEADLIGHT_Z_OFFSET, 1.0f };
142 glLightfv(GL_LIGHT0, GL_POSITION, headlight_position);
144 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
146 GLfloat white[] = { 1.0f, 1.0f, 1.0f, 1.0f };
147 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, white);
148 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
150 generateBlockDisplayList();
151 generateGarbageExtras();
152 generateGarbageThinMiddleList();
153 generateGarbageThinCapList();
154 generateGarbageThickCornerList();
155 generateGarbageThickEdgeList();
156 generateGarbageThickMiddleList();
157 generateGarbageSmallList();
158 generateSparkleList();
159 generateSignList();
160 generateSwapperList();
161 generateExternalCandy();
162 generateLevelLights();
163 generateClock();
164 generateMessages();
166 String::readyLetterTextures();
167 generateNameTexture();
168 generateScoreRecord();
170 glMatrixMode(GL_PROJECTION);
171 glLoadIdentity();
172 glFrustum(-(DC_PLAY_PIXEL_OFFSET_X / DC_PLAY_PIXEL_WIDTH + 0.5f)
173 * DC_PLAY_WIDTH, ((1.0f - DC_PLAY_PIXEL_OFFSET_X - DC_PLAY_PIXEL_WIDTH)
174 / DC_PLAY_PIXEL_WIDTH + 0.5f) * DC_PLAY_WIDTH, -DC_PLAY_HEIGHT
175 * DC_CAMERA_HEIGHT_RATIO, DC_PLAY_HEIGHT * (1.0 - DC_CAMERA_HEIGHT_RATIO),
176 40.0, 65.0);
177 glMatrixMode(GL_MODELVIEW);
180 void Displayer::gameStart ( )
182 LightManager::resetHeadLight();
183 ScoreRecordManager::gameStart();
186 void Displayer::gameFinish ( )
188 CelebrationManager::gameFinish();
189 ScoreRecordManager::gameFinish();
192 void Displayer::cleanUp ( )
194 glutDestroyWindow(main_window);
195 for (int n = DC_NUMBER_USE_GARBAGE_TEX; n--; )
196 if (garbage_texture_data[n] != null) {
197 delete [] garbage_texture_data[n];
198 garbage_texture_data[n] = null;
200 for (int n = DC_NUMBER_MESSAGE_TEX; n--; )
201 if (message_texture_data[n] != null) {
202 delete [] message_texture_data[n];
203 message_texture_data[n] = null;
206 if (player_rank_texture_data != null) {
207 delete [] player_rank_texture_data;
208 player_rank_texture_data = null;
210 if (MetaState::mode & CM_SOLO)
211 for (int n = GC_SCORE_REC_LENGTH - 1; n--; )
212 if (record_texture_data[n] != null) {
213 delete [] record_texture_data[n];
214 record_texture_data[n] = null;
216 if (record_texture_data != null) {
217 delete [] record_texture_data;
218 record_texture_data = null;
221 String::freeLetterTextures();
224 void Displayer::reshape ( int width, int height )
226 if (DC_WINDOW_PIXEL_WIDTH * height / DC_WINDOW_PIXEL_HEIGHT != width) {
227 height = (height + width) >> 1;
228 glutReshapeWindow(DC_WINDOW_PIXEL_WIDTH * height / DC_WINDOW_PIXEL_HEIGHT,
229 height);
230 } else {
231 glViewport(0, 0, width, height);
232 #ifdef DEVELOPMENT
233 screen_length = width;
234 #endif
238 void Displayer::displayMeta ( )
240 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
242 glLoadIdentity();
244 // disables GL_BLEND internally
245 drawExternalCandy();
247 drawScoreToBeatMessage();
249 glDisable(GL_TEXTURE_2D);
251 if (!(MetaState::mode & CM_REALLY_LOW_GRAPHICS))
252 glEnable(GL_LIGHTING);
253 glEnable(GL_COLOR_MATERIAL);
255 if (!(MetaState::mode & CM_REALLY_LOW_GRAPHICS))
256 drawLevelLights();
258 if (CelebrationManager::draw_game) {
260 LightManager::timeStepInitialize();
262 int hold_time_step = Game::time_step;
263 Game::time_step = MetaState::final_time_step;
265 calculatePlayOffset();
267 glEnable(GL_DEPTH_TEST);
268 glEnable(GL_CULL_FACE);
270 LightManager::setupHeadLightMeta();
272 drawBlocks();
274 glEnable(GL_TEXTURE_2D);
276 drawGarbage();
278 glDisable(GL_CULL_FACE);
279 glDisable(GL_TEXTURE_2D);
281 drawSwapper();
283 glDisable(GL_DEPTH_TEST);
285 LightManager::resetHeadLight();
287 Game::time_step = hold_time_step;
290 if (!(MetaState::mode & CM_REALLY_LOW_GRAPHICS))
291 glDisable(GL_LIGHTING);
292 glDisable(GL_COLOR_MATERIAL);
294 glEnable(GL_BLEND);
295 glEnable(GL_TEXTURE_2D);
297 drawMessage();
299 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_BLEND);
301 if (!(MetaState::mode & CM_REALLY_LOW_GRAPHICS)) {
302 drawWinRecord();
303 // calls glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE)
304 // internally
305 drawCandy();
308 drawScoreRecord();
310 glutSwapBuffers();
313 void Displayer::displayPlay ( )
315 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
317 glLoadIdentity();
319 // calls glDisable(GL_BLEND) internally
320 drawExternalCandy();
322 glDisable(GL_TEXTURE_2D);
324 if (!(MetaState::mode & CM_REALLY_LOW_GRAPHICS))
325 glEnable(GL_LIGHTING);
326 glEnable(GL_COLOR_MATERIAL);
328 if (!(MetaState::mode & CM_REALLY_LOW_GRAPHICS))
329 drawLevelLights();
331 if (!((Game::state & (GS_PAUSED | GS_SYNC_WAIT)) == GS_PAUSED)) {
333 LightManager::timeStepInitialize();
335 calculatePlayOffset();
337 glEnable(GL_DEPTH_TEST);
338 glEnable(GL_CULL_FACE);
340 LightManager::setupHeadLightPlay();
342 drawBlocks();
344 glEnable(GL_TEXTURE_2D);
346 drawGarbage();
348 glDisable(GL_CULL_FACE);
349 glDisable(GL_TEXTURE_2D);
351 drawSwapper();
353 glDisable(GL_DEPTH_TEST);
355 LightManager::resetHeadLight();
358 if (!(MetaState::mode & CM_REALLY_LOW_GRAPHICS))
359 glDisable(GL_LIGHTING);
360 glDisable(GL_COLOR_MATERIAL);
362 glEnable(GL_BLEND);
363 glEnable(GL_TEXTURE_2D);
365 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_BLEND);
367 if (!(MetaState::mode & CM_REALLY_LOW_GRAPHICS)) {
368 drawWinRecord();
369 // calls glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE)
370 // internally
371 drawCandy();
374 if (!(Game::state & GS_PAUSED))
375 drawCountDown();
376 else
377 drawMessage();
379 glutSwapBuffers();
382 bool Displayer::checkExtension ( char *extension_name )
384 char *extensions = (char *) glGetString(GL_EXTENSIONS);
386 if (!extensions) return false;
388 int length = strlen(extension_name);
389 char *end = extensions + strlen(extensions);
391 while (extensions < end) {
392 int n = strcspn(extensions, " ");
394 if (n == length && strncmp(extension_name, extensions, n) == 0)
395 return true;
397 extensions += n + 1;
400 return false;
403 #ifdef DEVELOPMENT
404 void Displayer::screenShot ( )
406 static int count = 0;
407 GLubyte *image = new GLubyte[4 * screen_length * screen_length];
409 glReadPixels(0, 0, screen_length, screen_length, GL_RGBA, GL_UNSIGNED_BYTE,
410 image);
412 ostringstream file_name;
413 file_name << DC_SCREEN_SHOT_FILE_NAME_BASE "_" << setw(GC_GARBAGE_TEX_NUMBER_DIGITS)
414 << setfill('0') << count << ".tga" << ends;
415 TextureLoader::createTGA(file_name.str().c_str(), image, screen_length, screen_length,
416 TL_SCREEN_SHOT_TGA_ID);
418 MESSAGE("creating " << file_name.str());
420 count++;
422 if (image != null) {
423 delete [] image;
424 image = null;
427 #endif