00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include <fstream>
00012 #include <math.h>
00013
00014 #include "common/wave_ex.h"
00015 #include "glut-font/glut-font.h"
00016 #include "perf/perf.h"
00017 #include "pgmppm/pgmppm.h"
00018 #include "wave-glut/camera.h"
00019 #include "wave-glut/glut_2d.h"
00020 #include "wave-glut/wave-glut.h"
00021
00022
00023 #include "terrain/mini.h"
00024
00025 static const int s_defaultWidth = 800;
00026 static const int s_defaultHeight = 600;
00027
00028 static int s_screenWidth = s_defaultWidth;
00029 static int s_screenHeight = s_defaultHeight;
00030
00031
00032 typedef short int height_t;
00033
00034 static int s_winid = -1;
00035 static int s_wmode = 0;
00036
00037
00038 static const int s_delay = 100;
00039 static int s_ignoreInput = s_delay;
00040
00041
00042 static minitile * s_tileset = NULL;
00043 static minicache * s_cache = NULL;
00044 static int s_updates = 5;
00045
00046
00047 static point3d_t s_lightPosition(0.0, 0.0, 0.0);
00048 static point3d_t s_lightVelocity(0.0, 0.0, -0.01);
00049
00050 static int s_retval = 0;
00051
00052
00053
00054
00055
00056
00057
00058
00059 static void
00060 onExit
00061 (
00062 void
00063 )
00064 {
00065
00066 glutDestroyWindow(s_winid);
00067
00068
00069 std::string summary;
00070 perf::getTimingSummary(summary);
00071 DPRINTF("Timers:\n%s\n", summary.c_str());
00072
00073
00074 exit(s_retval);
00075 }
00076
00077
00078
00079 static bool
00080 notifyPgmSize
00081 (
00082 IN void * ctx,
00083 IN int width,
00084 IN int height,
00085 IN int max_val
00086 )
00087 {
00088 int * pWidth = (int *) ctx;
00089 ASSERT(pWidth, "bad context");
00090 ASSERT(width > 0, "Bad pgm width: %d", width);
00091 ASSERT(height == width, "require height == width!");
00092
00093 *pWidth = width;
00094
00095 return false;
00096 }
00097
00098
00099
00100 static void
00101 notifyPgmPixel
00102 (
00103 IN void * ctx,
00104 IN int x,
00105 IN int y,
00106 IN int height
00107 )
00108 {
00109
00110 }
00111
00112
00113
00114 static void
00115 setTerrain
00116 (
00117 IN const char * pgm_file,
00118 IN const char * ppm_file
00119 )
00120 {
00121 perf::Timer timer("setTerrain");
00122 ASSERT(pgm_file, "null");
00123 ASSERT(ppm_file, "null");
00124
00125 DPRINTF("About to init...");
00126 float xzScale = 10.0;
00127 float yScale = 1;
00128
00129 const char * hfield_files[] = { pgm_file };
00130 const char * texture_files[] = { ppm_file };
00131
00132
00133 std::ifstream infile(hfield_files[0]);
00134 if (!infile.good()) {
00135 WAVE_EX(wex);
00136 wex << "Failed to open terrain file for reading: ";
00137 wex << hfield_files[0];
00138 }
00139 int width = -1;
00140 pgmppm::readPgm(infile, notifyPgmSize, notifyPgmPixel, &width);
00141 DPRINTF("PGM image width: %d pixels", width);
00142 ASSERT(width > 0, "Bad pgm width: %d", width);
00143
00144
00145 float dim = (width - 1) * xzScale;
00146
00147
00148 int nRows = 1;
00149 int nCols = 1;
00150 s_tileset = new minitile((const unsigned char **) hfield_files,
00151 (const unsigned char **) texture_files,
00152 nRows, nCols,
00153 dim, dim, yScale);
00154 ASSERT(s_tileset, "null");
00155
00156 s_cache = new minicache();
00157 ASSERT(s_cache, "out of memory");
00158 s_cache->attach(s_tileset);
00159 }
00160
00161
00162
00163 static void
00164 addLight
00165 (
00166 IN int gl_enum,
00167 IN const point3d_t& position
00168 )
00169 {
00170 float x = position.x;
00171 float y = position.y;
00172 float z = position.z;
00173
00174 float lightPos[] = { x, y, z, 1.0 };
00175 glLightfv(gl_enum, GL_POSITION, lightPos);
00176
00177 float lightAmbient[] = { 0.2, 0.2, 0.2, 1.0 };
00178 glLightfv(gl_enum, GL_AMBIENT, lightAmbient);
00179
00180 float str = 1.0;
00181 float lightDiffuse[] = { str, str / 3, str / 9, 1.0 };
00182 glLightfv(gl_enum, GL_DIFFUSE, lightDiffuse);
00183 glLightfv(gl_enum, GL_SPECULAR, lightDiffuse);
00184
00185 glLightf(gl_enum, GL_QUADRATIC_ATTENUATION, .02);
00186
00187 glColor3f(str, str / 3, str / 9);
00188 glPushMatrix();
00189 glTranslatef(x, y, z);
00190 glutSolidSphere(0.5, 8, 8);
00191 glPopMatrix();
00192 }
00193
00194
00195
00196 static void
00197 setLights
00198 (
00199 IN const glut::Viewer& walker
00200 )
00201 {
00202
00203 float lightAmbient[] = { 0.5, 0.5, 0.5, 1.0 };
00204 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lightAmbient);
00205
00206
00207 s_lightPosition.increment(s_lightVelocity);
00208 s_lightPosition.y = mini::getheight(s_lightPosition.x, s_lightPosition.z);
00209 s_lightPosition.y += 5.0;
00210 addLight(GL_LIGHT0, s_lightPosition);
00211
00212 addLight(GL_LIGHT1, walker.getPosition());
00213
00214 glEnable(GL_LIGHTING);
00215 glEnable(GL_LIGHT0);
00216 glEnable(GL_LIGHT1);
00217 }
00218
00219
00220
00221 static void
00222 debugInfo
00223 (
00224 IN const glut::Viewer& viewer
00225 )
00226 {
00227 DPRINTF("Debug Information");
00228 point3d_t v;
00229
00230 v = viewer.getPosition();
00231 v.dump(" Viewer is at");
00232 DPRINTF(" mini says height at camera is: %f",
00233 mini::getheight(v.x, v.z));
00234
00235 v = viewer.getFacing();
00236 v.dump(" Viewer is facing");
00237 }
00238
00239
00240
00241 static void
00242 updatePosition
00243 (
00244 IO glut::Viewer& view
00245 )
00246 {
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273 if (s_ignoreInput) {
00274 s_ignoreInput--;
00275 return;
00276 }
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297 if (0) {
00298 debugInfo(view);
00299 s_ignoreInput = s_delay;
00300 }
00301 }
00302
00303
00304
00305 static void
00306 onDisplay
00307 (
00308 void
00309 )
00310 {
00311 perf::Timer timer("onDisplay");
00312
00313 static glut::Viewer viewer;
00314 static glut::camera_t camera;
00315 static float t = 0.0;
00316 const float dt = 0.002;
00317 t += dt;
00318
00319
00320 updatePosition(viewer);
00321 viewer.setPosition(point3d_t(1000.0 * sin(0.1 * t), 0, 1000.0 * cos(0.1 * t)));
00322 point3d_t vpos = viewer.getPosition();
00323 float min_y = mini::getheight(vpos.x, vpos.z) + 10.0;
00324 float dy = (min_y - vpos.y);
00325 if (dy > 0.0) {
00326 viewer.move(0, 0, dy);
00327 }
00328
00329
00330 viewer.rotateY(0.5 * dt);
00331
00332
00333 static glut::fps_t myFps(perf::getNow());
00334 myFps.tick(perf::getNow());
00335
00336
00337
00338 glEnable(GL_DEPTH_TEST);
00339 glEnable(GL_COLOR_MATERIAL);
00340
00341
00342 glClearColor(0.2, 0.4, 0.8, 1.0);
00343 glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
00344
00345
00346 glut::setOpenGLProjection(camera);
00347 glut::setOpenGLViewer(viewer);
00348
00349
00350 glColor3f(1.0, 1.0, 1.0);
00351 if (s_updates) {
00352 glut::Viewer bogus = viewer;
00353 bogus.move(100.0, 0, 0);
00354 setLights(bogus);
00355 }
00356
00357
00358 float resolution = 1000.0;
00359 point3d_t view = viewer.getFacing();
00360 point3d_t eye = viewer.getPosition();
00361 point3d_t up = viewer.getUp();
00362
00363 glNormal3f(0.0, 1.0, 0.0);
00364 s_tileset->draw(resolution,
00365 eye.x, eye.y, eye.z,
00366
00367 view.x, view.y, view.z,
00368 up.x, up.y, up.z,
00369 camera.getFovy(),
00370 camera.getAspect(),
00371 camera.getZNear(),
00372 camera.getZFar(),
00373 s_updates);
00374
00375
00376 s_cache->rendercache();
00377
00378
00379
00380 glut::push2D(s_screenWidth, s_screenHeight);
00381 glColor3f(0, 0, 0);
00382 glut::Font * font = glut::getDefaultFont();
00383 char buffer[1024];
00384 sprintf(buffer, "%5.1f FPS", myFps.getFPS());
00385 font->display(10, 15, 0.0, buffer);
00386 glut::pop2D();
00387
00388
00389 glDisable(GL_COLOR_MATERIAL);
00390 glDisable(GL_DEPTH_TEST);
00391
00392
00393 glutSwapBuffers();
00394 }
00395
00396
00397
00398 static void
00399 onIdle
00400 (
00401 void
00402 )
00403 {
00404 glutPostRedisplay();
00405 }
00406
00407
00408
00409 static void
00410 onKeys
00411 (
00412 IN byte_t key,
00413 IN int x,
00414 IN int y
00415 )
00416 {
00417 DPRINTF("Pressed %d = '%c' at (%d, %d)", key, key, x, y);
00418
00419 int mods = glutGetModifiers();
00420 if (GLUT_ACTIVE_SHIFT & mods) {
00421 DPRINTF(" 'shift' is pressed");
00422 } else if (GLUT_ACTIVE_CTRL & mods) {
00423 DPRINTF(" 'ctrl' is pressed");
00424 } else if (GLUT_ACTIVE_ALT & mods) {
00425 DPRINTF(" 'alt' is pressed");
00426 }
00427
00428 if ('w' == key) {
00429 s_wmode = 1 - s_wmode;
00430 if (s_wmode) {
00431 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
00432 } else {
00433 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
00434 }
00435 }
00436
00437 if (27 == key || 'q' == key || 'Q' == key) {
00438 onExit();
00439 }
00440 }
00441
00442
00443
00444 static void
00445 onSpecial
00446 (
00447 IN int key,
00448 IN int x,
00449 IN int y
00450 )
00451 {
00452 DPRINTF("Pressed 0x%02x at (%d, %d)", key, x, y);
00453 }
00454
00455
00456
00457 static void
00458 onReshape
00459 (
00460 IN int w,
00461 IN int h
00462 )
00463 {
00464 DPRINTF("Screen size: %d x %d", w, h);
00465 s_screenWidth = w;
00466 s_screenHeight = h;
00467
00468 glViewport(0, 0, w, h);
00469 }
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479 int
00480 main
00481 (
00482 IN int argc,
00483 IN const char * argv[]
00484 )
00485 {
00486 ASSERT(3 == argc,
00487 "usage: mini-test <pgm-file> <ppm-file>");
00488
00489 const char * pgm_file = argv[1];
00490 const char * ppm_file = argv[2];
00491
00492
00493 glutInit(&argc, (char **) argv);
00494
00495
00496 glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
00497 glutInitWindowSize(s_defaultWidth, s_defaultHeight);
00498 s_winid = glutCreateWindow("test_glut");
00499 ASSERT(s_winid > 0, "Bad window id: %d", s_winid);
00500
00501
00502 glutDisplayFunc(onDisplay);
00503 glutIdleFunc(onIdle);
00504 glutKeyboardFunc(onKeys);
00505 glutSpecialFunc(onSpecial);
00506 glutReshapeFunc(onReshape);
00507 glutCloseFunc(onExit);
00508
00509
00510
00511 try {
00512
00513 setTerrain(pgm_file, ppm_file);
00514
00515 } catch (std::exception& e) {
00516 DPRINTF("Exception: %s", e.what());
00517 s_retval = 1;
00518 onExit();
00519 }
00520
00521
00522
00523
00524 glutMainLoop();
00525
00526 return 0;
00527 }
00528