SHOW:
|
|
- or go back to the newest paste.
1 | #include <windows.h> | |
2 | #include <GL/gl.h> | |
3 | #include <GL/glu.h> | |
4 | #include <stdio.h> | |
5 | #include <time.h> | |
6 | ||
7 | #define GET_X_LPARAM(a) ((short)LOWORD(a)) | |
8 | #define GET_Y_LPARAM(a) ((short)HIWORD(a)) | |
9 | ||
10 | unsigned short PlaneB[0x1000/2]; | |
11 | ||
12 | - | POINT camera={0,0}; |
12 | + | POINT camera = {0,0}; |
13 | POINT mouse; | |
14 | - | double zoom=1; |
14 | + | double zoom = 1; |
15 | bool showgray = false; | |
16 | int state = 0; | |
17 | ||
18 | struct Ground | |
19 | { | |
20 | int width; | |
21 | int height; | |
22 | double *data; | |
23 | Ground(int _width, int _height) | |
24 | { | |
25 | width = _width; | |
26 | height = _height; | |
27 | data = (double *)malloc(width*height*sizeof(double)); | |
28 | for (int x=0; x<width; ++x) | |
29 | for (int y=0; y<height; ++y) | |
30 | (*this)[x][y] = 0; | |
31 | } | |
32 | ||
33 | double *operator [](int x) | |
34 | { | |
35 | return data+x*height; | |
36 | } | |
37 | ||
38 | ~Ground() | |
39 | { | |
40 | if (data) | |
41 | free(data); | |
42 | } | |
43 | }; | |
44 | ||
45 | struct DuneGround | |
46 | { | |
47 | int width; | |
48 | int height; | |
49 | BYTE *data; | |
50 | DuneGround(int _width, int _height) | |
51 | { | |
52 | width = _width; | |
53 | height = _height; | |
54 | data = (BYTE *)malloc(width*height*sizeof(BYTE)); | |
55 | for (int x=0; x<width; ++x) | |
56 | for (int y=0; y<height; ++y) | |
57 | (*this)[x][y] = 0xB0; | |
58 | } | |
59 | ||
60 | BYTE *operator [](int x) | |
61 | { | |
62 | return data+x*height; | |
63 | } | |
64 | ||
65 | ~DuneGround() | |
66 | { | |
67 | if (data) | |
68 | free(data); | |
69 | } | |
70 | ||
71 | DuneGround(const DuneGround & g) | |
72 | { | |
73 | width = g.width; | |
74 | height = g.height; | |
75 | data = (BYTE *)malloc(width*height*sizeof(BYTE)); | |
76 | memcpy(data,g.data,width*height*sizeof(BYTE)); | |
77 | } | |
78 | ||
79 | const DuneGround & operator = (const DuneGround &g) | |
80 | { | |
81 | free(data); | |
82 | width = g.width; | |
83 | height = g.height; | |
84 | data = (BYTE *)malloc(width*height*sizeof(BYTE)); | |
85 | - | //DuneGround duneGroundPrev(64,64); |
85 | + | |
86 | return (*this); | |
87 | } | |
88 | }; | |
89 | ||
90 | /*struct Point | |
91 | { | |
92 | double x,y; | |
93 | }*/ | |
94 | ||
95 | DuneGround duneGround(64,64); | |
96 | DuneGround duneGroundNew(64,64); | |
97 | ||
98 | Ground g(2*64+1,2*64+1); | |
99 | GLuint GroundTiles; | |
100 | GLuint GroundGrey; | |
101 | ||
102 | // Declarations ////////////////////////////////////////////////////// | |
103 | ||
104 | GLuint LoadTextureRAW( const char * filename, int wrap ); | |
105 | GLuint LoadVRAM( const char * vram, const char * pal); | |
106 | GLuint GenerateGround(); | |
107 | void ChangeState(int _state); | |
108 | void RangeGround(double z); | |
109 | void LocalPick(int x, int y); | |
110 | void LoadMap( const char * filename ); | |
111 | void SaveMap( const char * filename ); | |
112 | void FreeTexture( GLuint texture ); | |
113 | ||
114 | LRESULT CALLBACK WndProc( HWND hWnd, UINT message, | |
115 | WPARAM wParam, LPARAM lParam ); | |
116 | ||
117 | VOID EnableOpenGL( HWND hWnd, HDC * hDC, HGLRC * hRC ); | |
118 | VOID DisableOpenGL( HWND hWnd, HDC hDC, HGLRC hRC ); | |
119 | void UpdateViewport(HWND hWnd); | |
120 | void Render(HWND hWnd, HDC hDC); | |
121 | ||
122 | ||
123 | ||
124 | // WinMain /////////////////////////////////////////////////////////// | |
125 | ||
126 | int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, | |
127 | LPSTR lpCmdLine, int iCmdShow ) | |
128 | { | |
129 | WNDCLASS wc; | |
130 | HWND hWnd; | |
131 | HDC hDC; | |
132 | HGLRC hRC; | |
133 | MSG msg; | |
134 | BOOL bQuit = FALSE; | |
135 | ||
136 | // register window class | |
137 | wc.style = CS_OWNDC; | |
138 | wc.lpfnWndProc = WndProc; | |
139 | wc.cbClsExtra = 0; | |
140 | wc.cbWndExtra = 0; | |
141 | wc.hInstance = hInstance; | |
142 | wc.hIcon = LoadIcon( NULL, IDI_APPLICATION ); | |
143 | wc.hCursor = LoadCursor( NULL, IDC_ARROW ); | |
144 | wc.hbrBackground = (HBRUSH)GetStockObject( BLACK_BRUSH ); | |
145 | wc.lpszMenuName = NULL; | |
146 | wc.lpszClassName = "GLSample"; | |
147 | RegisterClass( &wc ); | |
148 | ||
149 | // create main window | |
150 | - | LoadMap("map_18.bin"); |
150 | + | |
151 | "GLSample", "OpenGL Texture Sample", | |
152 | WS_CAPTION | WS_POPUPWINDOW | WS_VISIBLE | WS_MAXIMIZEBOX | WS_THICKFRAME, | |
153 | 0, 0, 800, 600, | |
154 | NULL, NULL, hInstance, NULL ); | |
155 | ||
156 | // enable OpenGL for the window | |
157 | EnableOpenGL( hWnd, &hDC, &hRC ); | |
158 | UpdateViewport( hWnd); | |
159 | ||
160 | // load our texture | |
161 | GroundTiles = LoadTextureRAW( "tex1.bmp", TRUE ); | |
162 | //LoadMap("map_18.bin"); | |
163 | ||
164 | srand(time(0)); | |
165 | GroundGrey = GenerateGround(); | |
166 | //texture = LoadVRAM( "vram.bin", "pal.bin" ); | |
167 | ||
168 | int startTime = GetTickCount(); | |
169 | int prevTime = startTime; | |
170 | ||
171 | // program main loop | |
172 | while ( !bQuit ) { | |
173 | ||
174 | // check for messages | |
175 | if ( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) ) { | |
176 | ||
177 | // handle or dispatch messages | |
178 | if ( msg.message == WM_QUIT ) { | |
179 | bQuit = TRUE; | |
180 | } else { | |
181 | TranslateMessage( &msg ); | |
182 | DispatchMessage( &msg ); | |
183 | } | |
184 | ||
185 | } else { | |
186 | int n = GetTickCount(); | |
187 | if (n - prevTime > 1000/40) | |
188 | { | |
189 | Render(hWnd, hDC); | |
190 | prevTime = n; | |
191 | } | |
192 | else | |
193 | Sleep(1); | |
194 | } | |
195 | ||
196 | } | |
197 | ||
198 | // free the texture | |
199 | FreeTexture( GroundTiles ); | |
200 | FreeTexture( GroundGrey ); | |
201 | ||
202 | // shutdown OpenGL | |
203 | DisableOpenGL( hWnd, hDC, hRC ); | |
204 | ||
205 | // destroy the window explicitly | |
206 | DestroyWindow( hWnd ); | |
207 | - | if ((int)(cx*2) <64*2+1 && (int)(cx*2)>=0 |
207 | + | |
208 | return msg.wParam; | |
209 | - | LocalPick(cx*2,cy*2);//RangeGround(g[(int)(cx*2)][(int)(cy*2)]); |
209 | + | |
210 | } | |
211 | ||
212 | void Render(HWND hWnd, HDC hDC) | |
213 | { | |
214 | // OpenGL animation code goes here | |
215 | RECT rc; | |
216 | GetClientRect(hWnd,&rc); | |
217 | double cx = int((camera.x+mouse.x-(rc.right/2))/32.0/zoom); | |
218 | double cy = int((camera.y+mouse.y-(rc.bottom/2))/32.0/zoom); | |
219 | if (state == 1 | |
220 | && (int)(cx*2) <64*2+1 && (int)(cx*2)>=0 | |
221 | && (int)(cy*2) <64*2+1 && (int)(cy*2)>=0) | |
222 | LocalPick(cx*2,cy*2);//RangeGround(g[(int)(cx*2)][(int)(cy*2)]);*/ | |
223 | ||
224 | glClearColor( 0.0f, 0.0f, 0.0f, 0.0f ); | |
225 | glClear( GL_COLOR_BUFFER_BIT ); | |
226 | ||
227 | // setup texture mapping | |
228 | glEnable( GL_TEXTURE_2D ); | |
229 | glBindTexture( GL_TEXTURE_2D, GroundTiles ); | |
230 | ||
231 | glPushMatrix(); | |
232 | glBegin( GL_QUADS ); | |
233 | ||
234 | // tiles | |
235 | /*double tw = 1.0/64; | |
236 | for (int i=0; i<32; ++i) | |
237 | { | |
238 | for (int j=0; j<64; ++j) | |
239 | { | |
240 | int id = PlaneB[i*64+j]&0x7FF; | |
241 | int idx = id&63; | |
242 | int idy = id>>6; | |
243 | glTexCoord2d(tw*(idx+0),tw*(idy+0)); glVertex2d(-1.0+tw*j,+1.0-tw*i); | |
244 | glTexCoord2d(tw*(idx+1),tw*(idy+0)); glVertex2d(-1.0+tw*(j+1),+1.0-tw*i); | |
245 | glTexCoord2d(tw*(idx+1),tw*(idy+1)); glVertex2d(-1.0+tw*(j+1),+1.0-tw*(i+1)); | |
246 | - | int id = duneGround[j][i]; |
246 | + | |
247 | } | |
248 | } | |
249 | glTexCoord2d(0.0,0.0); glVertex2d(-8.0,+8.0); | |
250 | glTexCoord2d(1.0,0.0); glVertex2d(+8.0,+8.0); | |
251 | glTexCoord2d(1.0,1.0); glVertex2d(+8.0,-8.0); | |
252 | glTexCoord2d(0.0,1.0); glVertex2d(-8.0,-8.0);*/ | |
253 | GetClientRect(hWnd, &rc); | |
254 | double tw = 1.0/16; | |
255 | for (int i=0; i<64; ++i) | |
256 | { | |
257 | for (int j=0; j<64; ++j) | |
258 | { | |
259 | int id; | |
260 | if (state == 1) | |
261 | id = duneGroundNew[j][i]; | |
262 | else | |
263 | id = duneGround[j][i]; | |
264 | int idx = id&15; | |
265 | int idy = (id>>4); | |
266 | glTexCoord2d(tw*(idx+0),1-tw*(idy+0)); glVertex2d(j,-i); | |
267 | glTexCoord2d(tw*(idx+1),1-tw*(idy+0)); glVertex2d(j+1,-i); | |
268 | glTexCoord2d(tw*(idx+1),1-tw*(idy+1)); glVertex2d(j+1,-(i+1)); | |
269 | glTexCoord2d(tw*(idx+0),1-tw*(idy+1)); glVertex2d(j,-(i+1)); | |
270 | ||
271 | } | |
272 | } | |
273 | glEnd(); | |
274 | ||
275 | if (showgray) | |
276 | { | |
277 | glBindTexture( GL_TEXTURE_2D, GroundGrey ); | |
278 | glBegin( GL_QUADS ); | |
279 | glTexCoord2d(0,0); glVertex2d(0,-0); | |
280 | glTexCoord2d(1,0); glVertex2d(64,-0); | |
281 | glTexCoord2d(1,1); glVertex2d(64,-64); | |
282 | glTexCoord2d(0,1); glVertex2d(0,-64); | |
283 | glEnd(); | |
284 | } | |
285 | ||
286 | /*glBindTexture( GL_TEXTURE_2D, texture ); | |
287 | glBegin( GL_QUADS ); | |
288 | ||
289 | glTexCoord2d(tw*(3+0),1-tw*(0+0)); glVertex2d(cx,-cy); | |
290 | glTexCoord2d(tw*(3+1),1-tw*(0+0)); glVertex2d(cx+1,-cy); | |
291 | glTexCoord2d(tw*(3+1),1-tw*(0+1)); glVertex2d(cx+1,-cy-1); | |
292 | glTexCoord2d(tw*(3+0),1-tw*(0+1)); glVertex2d(cx,-cy-1); | |
293 | glEnd();*/ | |
294 | glPopMatrix(); | |
295 | ||
296 | SwapBuffers( hDC ); | |
297 | } | |
298 | ||
299 | ||
300 | // Texture /////////////////////////////////////////////////////////// | |
301 | ||
302 | // load a 256x256 RGB .RAW file as a texture | |
303 | GLuint LoadTextureRAW( const char * filename, int wrap ) | |
304 | { | |
305 | GLuint texture; | |
306 | int width, height; | |
307 | BYTE * data; | |
308 | FILE * file; | |
309 | FILE *f; | |
310 | BYTE tmp; | |
311 | int i; | |
312 | ||
313 | // open texture data | |
314 | file = fopen( filename, "rb" ); | |
315 | if ( file == NULL ) return 0; | |
316 | ||
317 | // allocate buffer | |
318 | width = 512; | |
319 | height = 512; | |
320 | data = (BYTE*)malloc( width * height * 3 ); | |
321 | ||
322 | // read texture data | |
323 | ||
324 | fseek( file, 0x36, SEEK_SET); | |
325 | fread( data, width * height * 3, 1, file ); | |
326 | fclose( file ); | |
327 | ||
328 | for (i=0; i<width*height; ++i) | |
329 | { | |
330 | tmp = data[i*3]; | |
331 | data[i*3] = data[i*3+2]; | |
332 | data[i*3+2] = tmp; | |
333 | } | |
334 | ||
335 | // allocate a texture name | |
336 | glGenTextures( 1, &texture ); | |
337 | ||
338 | // select our current texture | |
339 | glBindTexture( GL_TEXTURE_2D, texture ); | |
340 | ||
341 | // select modulate to mix texture with color for shading | |
342 | glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ); | |
343 | ||
344 | // when texture area is small, bilinear filter the closest MIP map | |
345 | glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST ); | |
346 | ||
347 | // when texture area is large, bilinear filter the first MIP map | |
348 | glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST ); | |
349 | ||
350 | // if wrap is true, the texture wraps over at the edges (repeat) | |
351 | // ... false, the texture ends at the edges (clamp) | |
352 | glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, | |
353 | wrap ? GL_REPEAT : GL_CLAMP ); | |
354 | glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, | |
355 | wrap ? GL_REPEAT : GL_CLAMP ); | |
356 | ||
357 | // build our texture MIP maps | |
358 | //gluBuild2DMipmaps( GL_TEXTURE_2D, 3, width, | |
359 | // height, GL_RGB, GL_UNSIGNED_BYTE, data ); | |
360 | glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, width, | |
361 | height, 0, GL_RGB, GL_UNSIGNED_BYTE, data ); | |
362 | ||
363 | // free buffer | |
364 | free( data ); | |
365 | ||
366 | return texture; | |
367 | ||
368 | } | |
369 | ||
370 | double randf() | |
371 | { | |
372 | return rand()/double(RAND_MAX); | |
373 | } | |
374 | ||
375 | void GenerateGroundRecursive(Ground &g, int x, int y, int width, int height) | |
376 | { | |
377 | if (width <= 1 || height <= 1) | |
378 | return; | |
379 | double a,b,c,d; | |
380 | a = g[x ][y ]; | |
381 | b = g[x+width][y ]; | |
382 | c = g[x ][y+height]; | |
383 | d = g[x+width][y+height]; | |
384 | ||
385 | g[(x + (x + width))/2][ y ] = (a + b)/2; | |
386 | g[ x ][(y + (y + height))/2] = (a + c)/2; | |
387 | g[(x + (x + width))/2][ y + height ] = (c + d)/2; | |
388 | g[ x + width ][(y + (y + height))/2] = (b + d)/2; | |
389 | ||
390 | double z = (a+b+c+d)/4+((-1+randf()*2)*width/64/2); | |
391 | if (z > 1) | |
392 | z = 1; | |
393 | if (z < 0) | |
394 | z = 0; | |
395 | g[(x + (x + width))/2][(y + (y + height))/2] = z; | |
396 | ||
397 | GenerateGroundRecursive(g, x , y , width/2, height/2); | |
398 | GenerateGroundRecursive(g, x + width/2, y , width/2, height/2); | |
399 | GenerateGroundRecursive(g, x , y + height/2, width/2, height/2); | |
400 | GenerateGroundRecursive(g, x + width/2, y + height/2, width/2, height/2); | |
401 | } | |
402 | ||
403 | void LocalPick(int x, int y) | |
404 | { | |
405 | static bool was[2*64+1][2*64+1]; | |
406 | ||
407 | for (int i=0; i<2*64+1; ++i) | |
408 | for (int j=0; j<2*64+1; ++j) | |
409 | was[i][j] = false; | |
410 | ||
411 | static int X[(2*64+1)*(2*64+1)]; | |
412 | static int Y[(2*64+1)*(2*64+1)]; | |
413 | double z = g[x][y]; | |
414 | int s = 0,e = 0; | |
415 | X[e] = x; | |
416 | Y[e] = y; | |
417 | was[x][y] = true; | |
418 | ++e; | |
419 | while (s < e) | |
420 | { | |
421 | for (int i=-1; i<2; ++i) | |
422 | for (int j=-1; j<2; ++j) | |
423 | if (X[s]+i>=0 && X[s]+i<2*64+1 | |
424 | && Y[s]+j>=0 && Y[s]+j<2*64+1 | |
425 | && !was[X[s]+i][Y[s]+j] | |
426 | && g[X[s]+i][Y[s]+j]>=z) | |
427 | { | |
428 | X[e] = X[s]+i; | |
429 | Y[e] = Y[s]+j; | |
430 | was[X[e]][Y[e]] = true; | |
431 | ++e; | |
432 | } | |
433 | ++s; | |
434 | } | |
435 | ||
436 | for (int x=0; x<64; ++x) | |
437 | { | |
438 | for (int y=0; y<64; ++y) | |
439 | { | |
440 | int mask = 0; | |
441 | for (int i=0; i<3; ++i) | |
442 | for (int j=0; j<3; ++j) | |
443 | if (was[i+x*2][j+y*2]) | |
444 | mask |= 1<<(i+j*3); | |
445 | ||
446 | int k = 0; | |
447 | //1 2 4 | |
448 | //8 16 32 | |
449 | //64 128 256 | |
450 | if ( (mask&(1+2+4)) == (1+2+4)) | |
451 | k++; | |
452 | if ( (mask&(4+32+256)) == (4+32+256)) | |
453 | k |= 2; | |
454 | if ( (mask&(64+128+256)) == (64+128+256)) | |
455 | k |= 4; | |
456 | if ( (mask&(1+8+64)) == (1+8+64)) | |
457 | k |= 8; | |
458 | int id = 0x80+k; | |
459 | if ( k == 0) | |
460 | id = duneGround[x][y]; | |
461 | if ( k == 0 && (mask & 16)) | |
462 | id = 0x80; | |
463 | if ( k == 3 && !(mask & 16)) | |
464 | id = 0x3C; | |
465 | if ( k == 6 && !(mask & 16)) | |
466 | id = 0x3D; | |
467 | if ( k == 12 && !(mask & 16)) | |
468 | id = 0x3F; | |
469 | if ( k == 9 && !(mask & 16)) | |
470 | id = 0x3E; | |
471 | ||
472 | duneGroundNew[x][y] = id; | |
473 | } | |
474 | } | |
475 | } | |
476 | ||
477 | void RangeGround(double z) | |
478 | { | |
479 | for (int x=0; x<64; ++x) | |
480 | { | |
481 | for (int y=0; y<64; ++y) | |
482 | { | |
483 | int mask = 0; | |
484 | for (int i=0; i<3; ++i) | |
485 | for (int j=0; j<3; ++j) | |
486 | if (g[i+x*2][j+y*2]>z) | |
487 | mask |= 1<<(i+j*3); | |
488 | int k = 0; | |
489 | //1 2 4 | |
490 | //8 16 32 | |
491 | //64 128 256 | |
492 | if ( (mask&(1+2+4)) == (1+2+4)) | |
493 | k++; | |
494 | if ( (mask&(4+32+256)) == (4+32+256)) | |
495 | k |= 2; | |
496 | if ( (mask&(64+128+256)) == (64+128+256)) | |
497 | k |= 4; | |
498 | if ( (mask&(1+8+64)) == (1+8+64)) | |
499 | k |= 8; | |
500 | int id = 0x80+k; | |
501 | if ( k == 0) | |
502 | id = 0xB0; | |
503 | if ( k == 0 && (mask & 16)) | |
504 | id = 0x80; | |
505 | if ( k == 3 && !(mask & 16)) | |
506 | id = 0x3C; | |
507 | if ( k == 6 && !(mask & 16)) | |
508 | id = 0x3D; | |
509 | if ( k == 12 && !(mask & 16)) | |
510 | id = 0x3F; | |
511 | if ( k == 9 && !(mask & 16)) | |
512 | id = 0x3E; | |
513 | ||
514 | duneGround[x][y] = id; | |
515 | } | |
516 | } | |
517 | } | |
518 | ||
519 | GLuint GenerateGround() | |
520 | { | |
521 | g[ 0][ 0] = randf(); | |
522 | g[g.width-1][ 0] = randf(); | |
523 | g[ 0][g.height-1] = randf(); | |
524 | g[g.width-1][g.height-1] = randf(); | |
525 | ||
526 | GenerateGroundRecursive(g, 0, 0, g.width-1, g.height-1); | |
527 | ||
528 | BYTE *data = (BYTE*)malloc( (g.width-1) * (g.height-1) * 3 ); | |
529 | ||
530 | for (int x=0; x<g.width-1; ++x) | |
531 | { | |
532 | for (int y=0; y<g.height-1; ++y) | |
533 | { | |
534 | for (int i=0; i<3; ++i) | |
535 | data[(x + y*(g.width-1))*3 + i] = g[x][y]*255; | |
536 | } | |
537 | } | |
538 | ||
539 | GLuint texture; | |
540 | glGenTextures( 1, &texture ); | |
541 | ||
542 | glBindTexture( GL_TEXTURE_2D, texture ); | |
543 | ||
544 | glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ); | |
545 | ||
546 | // when texture area is small, bilinear filter the closest MIP map | |
547 | glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST ); | |
548 | ||
549 | // when texture area is large, bilinear filter the first MIP map | |
550 | glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST ); | |
551 | ||
552 | // if wrap is true, the texture wraps over at the edges (repeat) | |
553 | // ... false, the texture ends at the edges (clamp) | |
554 | glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP ); | |
555 | glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP ); | |
556 | ||
557 | glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, g.width-1, g.height-1, 0, GL_RGB, GL_UNSIGNED_BYTE, data ); | |
558 | ||
559 | free(data); | |
560 | ||
561 | ||
562 | /*for (int x=0; x<64; ++x) | |
563 | { | |
564 | for (int y=0; y<64; ++y) | |
565 | { | |
566 | int t; | |
567 | if (g[x*2][y*2]>0.5) | |
568 | t = 0x8F; | |
569 | else | |
570 | t = 0xB0; | |
571 | Map[x+y*64]=t; | |
572 | } | |
573 | } | |
574 | ||
575 | for (int x=0; x<64; ++x) | |
576 | { | |
577 | for (int y=0; y<64; ++y) | |
578 | { | |
579 | int t; | |
580 | if (g[x*2][y*2]>0.5) | |
581 | t = 0x8F; | |
582 | else | |
583 | t = 0xB0; | |
584 | Map[x+y*64]=t; | |
585 | } | |
586 | } | |
587 | for (int x=0; x<64; ++x) | |
588 | { | |
589 | for (int y=0; y<64; ++y) | |
590 | { | |
591 | int k = 0; | |
592 | if ( y > 0 && Map[x+(y-1)*64] == 0x8F) | |
593 | k++; | |
594 | if ( x < 63 && Map[x+1+y*64] == 0x8F) | |
595 | k |= 2; | |
596 | if ( y < 63 && Map[x+(y+1)*64] == 0x8F) | |
597 | k |= 4; | |
598 | if ( x > 0 && Map[x-1+y*64] == 0x8F) | |
599 | k |= 8; | |
600 | if (k != 0 && Map[x+y*64] != 0x8F) | |
601 | Map[x+y*64] = 0x80 + k; | |
602 | } | |
603 | }*/ | |
604 | return texture; | |
605 | } | |
606 | ||
607 | // load a 256x256 RGB .RAW file as a texture | |
608 | GLuint LoadVRAM( const char * vram, const char * pal) | |
609 | { | |
610 | GLuint texture; | |
611 | int width, height; | |
612 | BYTE palette[16*4][3]; | |
613 | BYTE * data; | |
614 | BYTE * vdata; | |
615 | FILE * file; | |
616 | FILE *f; | |
617 | int x; | |
618 | int y; | |
619 | ||
620 | file = fopen( pal, "rb" ); | |
621 | if ( file == NULL ) return 0; | |
622 | ||
623 | for (int i=0; i<16*4; ++i) | |
624 | { | |
625 | BYTE tmp = 0; | |
626 | short color; | |
627 | fread(&tmp, 1, 1, file); | |
628 | color = tmp << 8; | |
629 | fread(&tmp, 1, 1, file); | |
630 | color |= tmp; | |
631 | ||
632 | for (int j=0; j<3; ++j) | |
633 | { | |
634 | palette[i][j] = (((color >> (j*4))&0xE)/double(0xE))*0xFF; | |
635 | } | |
636 | } | |
637 | fclose( file ); | |
638 | ||
639 | // open texture data | |
640 | file = fopen( vram, "rb" ); | |
641 | if ( file == NULL ) return 0; | |
642 | ||
643 | // allocate buffer | |
644 | width = 512; | |
645 | height = 512; | |
646 | data = (BYTE*)malloc( width * height * 3 ); | |
647 | vdata = (BYTE*)malloc( 0x800 * 32 ); | |
648 | ||
649 | // read texture data | |
650 | ||
651 | fread( vdata, 0x800 * 32, 1, file ); | |
652 | fclose( file ); | |
653 | ||
654 | x = 0; | |
655 | y = 0; | |
656 | for (int i=0; i < 0x800; ++i) | |
657 | { | |
658 | for (int v = 0; v < 8; ++v) | |
659 | for (int u = 0; u < 4; ++u) | |
660 | { | |
661 | BYTE tmp = vdata[i*32+v*4+u]; | |
662 | BYTE *ptr = data+((y+v)*512+x+u*2)*3; | |
663 | for (int j=0; j<3; ++j) | |
664 | { | |
665 | ptr[j] = palette[tmp>>4][j]; | |
666 | ptr[j+3] = palette[tmp&0xF][j]; | |
667 | } | |
668 | /*for (int j=0; j<3; ++j) | |
669 | { | |
670 | ptr[j] = palette[i%17][j]; | |
671 | ptr[j+3] = palette[i%17][j]; | |
672 | }*/ | |
673 | } | |
674 | x += 8; | |
675 | if (x == 512) | |
676 | { | |
677 | x = 0; | |
678 | y += 8; | |
679 | } | |
680 | } | |
681 | ||
682 | for (int i=0; i<0x1000/2; ++i) | |
683 | { | |
684 | PlaneB[i]=(vdata[0xC000+i*2]<<8)|vdata[0xC000+i*2+1]; | |
685 | } | |
686 | ||
687 | // allocate a texture name | |
688 | glGenTextures( 1, &texture ); | |
689 | ||
690 | // select our current texture | |
691 | glBindTexture( GL_TEXTURE_2D, texture ); | |
692 | ||
693 | // select modulate to mix texture with color for shading | |
694 | glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ); | |
695 | ||
696 | // when texture area is small, bilinear filter the closest MIP map | |
697 | glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST ); | |
698 | // when texture area is large, bilinear filter the first MIP map | |
699 | glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST ); | |
700 | ||
701 | // if wrap is true, the texture wraps over at the edges (repeat) | |
702 | // ... false, the texture ends at the edges (clamp) | |
703 | glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); | |
704 | glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); | |
705 | ||
706 | // build our texture MIP maps | |
707 | gluBuild2DMipmaps( GL_TEXTURE_2D, 3, width, | |
708 | height, GL_RGB, GL_UNSIGNED_BYTE, data ); | |
709 | ||
710 | // free buffer | |
711 | free( data ); | |
712 | ||
713 | // free vram data | |
714 | free ( vdata ); | |
715 | ||
716 | return texture; | |
717 | ||
718 | } | |
719 | ||
720 | void LoadMap( const char * filename ) | |
721 | { | |
722 | FILE *f = fopen(filename, "rb"); | |
723 | if (!f) | |
724 | return; | |
725 | BYTE tmp; | |
726 | for (int y=0; y<64; ++y) | |
727 | for (int x=0; x<64; ++x) | |
728 | { | |
729 | fread(&tmp,1,1,f); | |
730 | duneGround[x][y]=tmp; | |
731 | } | |
732 | fclose(f); | |
733 | } | |
734 | ||
735 | void SaveMap( const char * filename ) | |
736 | { | |
737 | FILE *f = fopen(filename,"wb"); | |
738 | if (!f) | |
739 | return; | |
740 | for (int y=0; y<64; ++y) | |
741 | for (int x=0; x<64; ++x) | |
742 | fwrite(&duneGround[x][y],1,1,f); | |
743 | fclose(f); | |
744 | } | |
745 | ||
746 | void FreeTexture( GLuint texture ) | |
747 | { | |
748 | glDeleteTextures( 1, &texture ); | |
749 | } | |
750 | ||
751 | bool mousedown = false; | |
752 | ||
753 | void UpdateViewport(HWND hWnd) | |
754 | { | |
755 | RECT rc; | |
756 | GetClientRect(hWnd, &rc); | |
757 | glViewport( 0, 0, rc.right, rc.bottom); | |
758 | glMatrixMode( GL_PROJECTION ); | |
759 | glLoadIdentity(); | |
760 | //gluOrtho2D( 0,0,500,500);//camera.x, camera.y, camera.x+rc.right, camera.y+rc.bottom); | |
761 | double scale = 1/32.0/zoom; | |
762 | glScalef(64.0/rc.right*zoom,64.0/rc.bottom*zoom,1); | |
763 | glTranslatef( -camera.x*scale, camera.y*scale, 0); | |
764 | glMatrixMode( GL_MODELVIEW ); | |
765 | } | |
766 | ||
767 | void ChangeState(int _state) | |
768 | { | |
769 | state = _state; | |
770 | if (state == 1) | |
771 | duneGroundNew = duneGround; | |
772 | } | |
773 | ||
774 | // Window Proc /////////////////////////////////////////////////////// | |
775 | ||
776 | LRESULT CALLBACK WndProc( HWND hWnd, UINT message, | |
777 | WPARAM wParam, LPARAM lParam ) | |
778 | { | |
779 | switch ( message ) { | |
780 | ||
781 | case WM_CREATE: | |
782 | return 0; | |
783 | ||
784 | case WM_CLOSE: | |
785 | PostQuitMessage( 0 ); | |
786 | return 0; | |
787 | ||
788 | case WM_SIZE: | |
789 | UpdateViewport(hWnd); | |
790 | break; | |
791 | ||
792 | case WM_DESTROY: | |
793 | return 0; | |
794 | ||
795 | case WM_KEYDOWN: | |
796 | switch ( wParam ) { | |
797 | ||
798 | case VK_ESCAPE: | |
799 | PostQuitMessage( 0 ); | |
800 | return 0; | |
801 | ||
802 | case 'S': | |
803 | SaveMap("map.bin"); | |
804 | return 0; | |
805 | ||
806 | case 'R': | |
807 | FreeTexture(GroundGrey); | |
808 | GroundGrey = GenerateGround(); | |
809 | return 0; | |
810 | case 'E': | |
811 | ChangeState(state^1); | |
812 | return 0; | |
813 | ||
814 | case VK_SPACE: | |
815 | showgray = !showgray; | |
816 | return 0; | |
817 | } | |
818 | return 0; | |
819 | ||
820 | case WM_MOUSEWHEEL: | |
821 | { | |
822 | RECT rc; | |
823 | GetClientRect(hWnd,&rc); | |
824 | mouse.x = GET_X_LPARAM(lParam); | |
825 | - | //Map[cx+cy*64] = 3; |
825 | + | |
826 | short zDelta = HIWORD(wParam); | |
827 | if (zDelta > 0) | |
828 | { | |
829 | zoom *= 1.2; | |
830 | camera.x *= 1.2;//(camera.x + mouse.x) * (zoom/(zoom-0.1)) - mouse.x; | |
831 | camera.y *= 1.2;//(camera.y + mouse.y) * (zoom/(zoom-0.1)) - mouse.y; | |
832 | } | |
833 | else | |
834 | { | |
835 | zoom /= 1.2; | |
836 | camera.x /= 1.2; | |
837 | camera.y /= 1.2; | |
838 | } | |
839 | ||
840 | UpdateViewport(hWnd); | |
841 | } | |
842 | break; | |
843 | case WM_LBUTTONDOWN: | |
844 | { | |
845 | SetCapture(hWnd); | |
846 | mouse.x = GET_X_LPARAM(lParam); | |
847 | mouse.y = GET_Y_LPARAM(lParam); | |
848 | RECT rc; | |
849 | GetClientRect(hWnd,&rc); | |
850 | int cx = int((camera.x+mouse.x-(rc.right/2))/32.0/zoom); | |
851 | int cy = int((camera.y+mouse.y-(rc.bottom/2))/32.0/zoom); | |
852 | if (state == 1) | |
853 | duneGround = duneGroundNew; | |
854 | mousedown = true; | |
855 | } | |
856 | break; | |
857 | case WM_MOUSEMOVE: | |
858 | if (mousedown) | |
859 | { | |
860 | int xPos = mouse.x; mouse.x = GET_X_LPARAM(lParam); | |
861 | int yPos = mouse.y; mouse.y = GET_Y_LPARAM(lParam); | |
862 | camera.x -= mouse.x-xPos; | |
863 | camera.y -= mouse.y-yPos; | |
864 | UpdateViewport(hWnd); | |
865 | } | |
866 | mouse.x = GET_X_LPARAM(lParam); | |
867 | mouse.y = GET_Y_LPARAM(lParam); | |
868 | break; | |
869 | case WM_LBUTTONUP: | |
870 | ReleaseCapture(); | |
871 | mousedown = false; | |
872 | break; | |
873 | } | |
874 | return DefWindowProc( hWnd, message, wParam, lParam ); | |
875 | } | |
876 | ||
877 | ||
878 | // OpenGL //////////////////////////////////////////////////////////// | |
879 | ||
880 | // Enable OpenGL | |
881 | ||
882 | VOID EnableOpenGL( HWND hWnd, HDC * hDC, HGLRC * hRC ) | |
883 | { | |
884 | PIXELFORMATDESCRIPTOR pfd; | |
885 | int iFormat; | |
886 | ||
887 | // get the device context (DC) | |
888 | *hDC = GetDC( hWnd ); | |
889 | ||
890 | // set the pixel format for the DC | |
891 | ZeroMemory( &pfd, sizeof( pfd ) ); | |
892 | pfd.nSize = sizeof( pfd ); | |
893 | pfd.nVersion = 1; | |
894 | pfd.dwFlags = PFD_DRAW_TO_WINDOW | | |
895 | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER; | |
896 | pfd.iPixelType = PFD_TYPE_RGBA; | |
897 | pfd.cColorBits = 24; | |
898 | pfd.cDepthBits = 16; | |
899 | pfd.iLayerType = PFD_MAIN_PLANE; | |
900 | iFormat = ChoosePixelFormat( *hDC, &pfd ); | |
901 | SetPixelFormat( *hDC, iFormat, &pfd ); | |
902 | ||
903 | // create and enable the render context (RC) | |
904 | *hRC = wglCreateContext( *hDC ); | |
905 | wglMakeCurrent( *hDC, *hRC ); | |
906 | ||
907 | } | |
908 | ||
909 | // Disable OpenGL | |
910 | ||
911 | VOID DisableOpenGL( HWND hWnd, HDC hDC, HGLRC hRC ) | |
912 | { | |
913 | wglMakeCurrent( NULL, NULL ); | |
914 | wglDeleteContext( hRC ); | |
915 | ReleaseDC( hWnd, hDC ); | |
916 | } |