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 | } |