00001 #include <assert.h>
00002 #include <stdio.h>
00003
00004 #include <iostream>
00005
00006 #include <vrs/box.h>
00007 #include <vrs/container/dataiterator.h>
00008 #include <vrs/mesh.h>
00009 #include <vrs/sg/scenething.h>
00010 #include <vrs/translation.h>
00011
00012 #include "MeshBeautifier.h"
00013 #include "TerrainGenerator.h"
00014 #include "ControlPointContainer.h"
00015
00016 #include "VRSTerrainLoader.h"
00017
00018 using namespace VRS;
00019
00020
00021
00022
00023 namespace random_racer
00024 {
00025
00026 VRSTerrainLoader::VRSTerrainLoader(
00027 SO<SceneThing> p_thing,
00028 SO<ControlPointContainer> p_container,
00029 double p_boxSize,
00030 double p_viewSize) : TerrainLoader(p_thing, p_boxSize, p_viewSize)
00031 {
00032 assert(sizeof(m_terrainCache) == 4*sizeof(TerrainPart));
00033
00034 const unsigned int levelOfDetail = 64;
00035
00036
00037 m_thing->clear();
00038
00039 m_translation = new Translation((m_viewSize/-2.0), 0.0, (m_viewSize/-2.0));
00040
00041 m_vertexIter = new DataIterator<Vector>();
00042 m_textureIter = new DataIterator<Vector>();
00043 m_colorIter = new DataIterator<Color>();
00044
00045 m_generator = new TerrainGenerator(
00046 p_container, m_viewSize, 32.0, levelOfDetail);
00047
00048 m_generator->generate(0.0, 0.0, &(m_vertexIter->data));
00049
00050 m_beautifier = new MeshBeautifier(
00051 this,
00052 p_container->minHeight(),
00053 p_container->maxHeight());
00054
00055 m_mesh = new Mesh(levelOfDetail, levelOfDetail, m_vertexIter);
00056
00057 m_thing->append(m_translation);
00058
00059 m_beautifier->initializeSceneThing(m_thing);
00060
00061 beautifyMesh();
00062
00063 m_mesh->setColorIterator(m_colorIter);
00064 m_mesh->setTextureIterator(m_textureIter);
00065
00066
00067 m_thing->append(m_mesh);
00068
00069
00070 m_terminateWorker = false;
00071
00072 m_signalWhenDoneWith= -2;
00073 m_workerIsWaiting = false;
00074
00075 m_vertexMutex = SDL_CreateMutex();
00076 m_controlMutex = SDL_CreateMutex();
00077 m_generateWakeMutex = SDL_CreateMutex();
00078
00079 m_replaceWakeCond = SDL_CreateCond();
00080 m_generateWakeCond = SDL_CreateCond();
00081
00082 assert(m_vertexMutex != NULL);
00083 assert(m_controlMutex != NULL && m_generateWakeMutex != NULL);
00084 assert(m_replaceWakeCond != NULL && m_generateWakeCond != NULL);
00085
00086
00087 m_worker = SDL_CreateThread(&VRSTerrainLoader::workerWrapper, this);
00088 assert(m_worker != NULL);
00089
00090
00091 for(;;)
00092 {
00093 SDL_LockMutex(m_generateWakeMutex);
00094
00095 if(m_workerIsWaiting)
00096 break;
00097
00098 SDL_UnlockMutex(m_generateWakeMutex);
00099
00100 #ifdef RR_DEBUG_LOADER_THREADING
00101 std::cout << "worker not yet waiting (postCtor)" << std::endl;
00102 #endif
00103 }
00104
00105 #ifdef RR_DEBUG_LOADER_THREADING
00106 std::cout << "SIGNALING worker (postCtor)" << std::endl;
00107 #endif
00108
00109 SDL_UnlockMutex(m_generateWakeMutex);
00110 SDL_CondSignal(m_generateWakeCond);
00111 }
00112
00113
00114
00115 void
00116 VRSTerrainLoader::replaceTerrain(
00117 const Vector& p_position, const Vector& p_center)
00118 {
00119 #ifdef RR_DEBUG_LOADER_THREADING
00120 std::cout << "replaceTerrain()" << std::endl
00121 << " p_position: " << p_position << std::endl
00122 << " diff: " << (p_position - m_position) << std::endl;
00123 #endif
00124
00125
00126 unsigned int nearest;
00127 bool indexIsDone;
00128
00129
00130 SDL_LockMutex(m_controlMutex);
00131 #ifdef RR_DEBUG_LOADER_THREADING
00132 std::cout << "locked m_controlMutex" << std::endl;
00133 #endif
00134
00135
00136 nearest = nearestIndex(
00137 p_position[0], p_position[2], m_terrainCache, 4);
00138
00139 indexIsDone = m_terrainCache[nearest].isDone;
00140
00141
00142 #ifdef RR_DEBUG_LOADER_THREADING
00143 std::cout << "nearest is " << nearest << " and it is ";
00144 #endif
00145
00146
00147 if(!indexIsDone)
00148 {
00149 #ifdef RR_DEBUG_LOADER_THREADING
00150 std::cout << "NOT done" << std::endl
00151 << "waiting..." << std::endl;
00152 #endif
00153 m_signalWhenDoneWith = nearest;
00154
00155 SDL_CondWait(m_replaceWakeCond, m_controlMutex);
00156
00157 #ifdef RR_DEBUG_LOADER_THREADING
00158 std::cout << "ok, i'm back" << std::endl;
00159 #endif
00160 }
00161 else
00162 {
00163 #ifdef RR_DEBUG_LOADER_THREADING
00164 std::cout << "DONE" << std::endl
00165 << "continuing" << std::endl;
00166 #endif
00167 m_signalWhenDoneWith = -1;
00168 }
00169
00170
00171 Vector translate;
00172
00173 translate[0] = m_terrainCache[nearest].x - (m_viewSize/2.0);
00174 translate[1] = 0.0;
00175 translate[2] = m_terrainCache[nearest].y - (m_viewSize/2.0);
00176
00177
00178 lock();
00179
00180 m_translation->setTranslate(translate);
00181
00182
00183 m_vertexIter->data = m_terrainCache[nearest].points;
00184
00185 unlock();
00186
00187
00188 #ifdef RR_DEBUG_LOADER_THREADING
00189 std::cout << "COPIED the points" << std::endl;
00190 #endif
00191
00192
00193
00194 m_position = p_center;
00195
00196
00197 if(!indexIsDone || m_workerIsWaiting)
00198 {
00199 SDL_UnlockMutex(m_controlMutex);
00200 #ifdef RR_DEBUG_LOADER_THREADING
00201 std::cout << "UNlocked m_controlMutex" << std::endl
00202 << "waking the worker" << std::endl;
00203 #endif
00204
00205 for(;;)
00206 {
00207 SDL_LockMutex(m_generateWakeMutex);
00208
00209 if(m_workerIsWaiting)
00210 break;
00211
00212 SDL_UnlockMutex(m_generateWakeMutex);
00213
00214 #ifdef RR_DEBUG_LOADER_THREADING
00215 std::cout << "worker not yet waiting (replaceTerrain)" << std::endl;
00216 #endif
00217 }
00218
00219 m_signalWhenDoneWith = -2;
00220
00221 #ifdef RR_DEBUG_LOADER_THREADING
00222 std::cout << "SIGNALING worker (replaceTerrain)" << std::endl;
00223 #endif
00224
00225 SDL_UnlockMutex(m_generateWakeMutex);
00226 SDL_CondSignal(m_generateWakeCond);
00227 }
00228 else
00229 {
00230 SDL_UnlockMutex(m_controlMutex);
00231
00232 #ifdef RR_DEBUG_LOADER_THREADING
00233 std::cout << "BEST CASE" << std::endl
00234 << "UNlocked m_controlMutex" << std::endl;
00235 #endif
00236 }
00237
00238
00239 beautifyMesh();
00240
00241 #ifdef RR_DEBUG_LOADER_THREADING
00242 std::cout << "DONE" << std::endl;
00243 #endif
00244
00245 }
00246
00247 int
00248 VRSTerrainLoader::workerWrapper(void* p_self)
00249 {
00250 return ((VRSTerrainLoader*)p_self)->generate();
00251 }
00252
00253 int
00254 VRSTerrainLoader::generate()
00255 {
00256 #ifdef RR_DEBUG_LOADER_THREADING
00257 std::cout << "\tworker started" << std::endl;
00258 #endif
00259
00260
00261
00262 enum {SIGNAL, GOTO, CONTINUE} loopResult = CONTINUE;
00263
00264
00265 double h = m_boxSize*0.5;
00266
00267
00268 SDL_LockMutex(m_generateWakeMutex);
00269 #ifdef RR_DEBUG_LOADER_THREADING
00270 std::cout << "\tlocked m_generateWakeMutex" << std::endl;
00271 #endif
00272
00273
00274
00275 for(;;)
00276 {
00277 if(loopResult != GOTO)
00278 {
00279 SDL_LockMutex(m_controlMutex);
00280 #ifdef RR_DEBUG_LOADER_THREADING
00281 std::cout << "\tlocked m_controlMutex for waiting = true"
00282 << std::endl;
00283 #endif
00284
00285 m_workerIsWaiting = true;
00286
00287 SDL_UnlockMutex(m_controlMutex);
00288 #ifdef RR_DEBUG_LOADER_THREADING
00289 std::cout << "\tUNlocked m_controlMutex" << std::endl;
00290 #endif
00291
00292
00293 #ifdef RR_DEBUG_LOADER_THREADING
00294 std::cout << "\twaiting..." << std::endl;
00295 #endif
00296 SDL_CondWait(m_generateWakeCond, m_generateWakeMutex);
00297 }
00298 else
00299 m_signalWhenDoneWith = -2;
00300
00301
00302 SDL_LockMutex(m_controlMutex);
00303 #ifdef RR_DEBUG_LOADER_THREADING
00304 std::cout << "\tlocked m_controlMutex for waiting = false" << std::endl;
00305 #endif
00306
00307
00308 if(m_terminateWorker)
00309 {
00310 SDL_UnlockMutex(m_controlMutex);
00311 return 1;
00312 }
00313
00314 m_workerIsWaiting = false;
00315
00316 #ifdef RR_DEBUG_LOADER_THREADING
00317 std::cout << "\ti am awake" << std::endl;
00318 #endif
00319
00320
00321 for(unsigned int i = 0; i < 4; i++)
00322 {
00323
00324
00325
00326
00327 switch(i)
00328 {
00329
00330 case 0:
00331 m_terrainCache[i].x = m_position[0]-h;
00332 m_terrainCache[i].y = m_position[2]+h;
00333 break;
00334
00335 case 1:
00336 m_terrainCache[i].x = m_position[0]-h;
00337 m_terrainCache[i].y = m_position[2]-h;
00338 break;
00339
00340 case 2:
00341 m_terrainCache[i].x = m_position[0]+h;
00342 m_terrainCache[i].y = m_position[2]-h;
00343 break;
00344
00345 case 3:
00346 m_terrainCache[i].x = m_position[0]+h;
00347 m_terrainCache[i].y = m_position[2]+h;
00348 break;
00349 }
00350
00351 m_terrainCache[i].isDone = false;
00352 }
00353
00354 SDL_UnlockMutex(m_controlMutex);
00355 #ifdef RR_DEBUG_LOADER_THREADING
00356 std::cout << "\tUNlocked m_controlMutex" << std::endl;
00357 #endif
00358
00359 loopResult = CONTINUE;
00360
00361
00362
00363 for(unsigned int i = 0; i < 4; i++)
00364 {
00365 m_terrainCache[i].points.clear();
00366
00367 m_generator->generate(
00368 m_terrainCache[i].x,
00369 m_terrainCache[i].y,
00370 &(m_terrainCache[i].points));
00371
00372
00373 SDL_LockMutex(m_controlMutex);
00374 #ifdef RR_DEBUG_LOADER_THREADING
00375 std::cout << "\tlocked m_controlMutex" << std::endl;
00376 #endif
00377
00378 m_terrainCache[i].isDone = true;
00379
00380
00381 #ifdef RR_DEBUG_LOADER_THREADING
00382 std::cout << '\t' << i << " is done" << std::endl;
00383 #endif
00384
00385 if(m_signalWhenDoneWith == -1)
00386 {
00387 #ifdef RR_DEBUG_LOADER_THREADING
00388 std::cout << "\tm_signalWhenDoneWith == -1" << std::endl;
00389 #endif
00390 loopResult = GOTO;
00391
00392 SDL_UnlockMutex(m_controlMutex);
00393 #ifdef RR_DEBUG_LOADER_THREADING
00394 std::cout << "\tUNlocked m_controlMutex" << std::endl;
00395 #endif
00396 break;
00397 }
00398 else if(m_signalWhenDoneWith >= 0 && m_signalWhenDoneWith <= int(i))
00399 {
00400 #ifdef RR_DEBUG_LOADER_THREADING
00401 std::cout << "\tm_signalWhenDoneWith <= i" << std::endl;
00402 #endif
00403 loopResult = SIGNAL;
00404
00405 SDL_UnlockMutex(m_controlMutex);
00406 #ifdef RR_DEBUG_LOADER_THREADING
00407 std::cout << "\tUNlocked m_controlMutex" << std::endl;
00408 #endif
00409 break;
00410 }
00411 else
00412 {
00413 SDL_UnlockMutex(m_controlMutex);
00414
00415 #ifdef RR_DEBUG_LOADER_THREADING
00416 std::cout << "\tm_signalWhenDoneWith ELSE" << std::endl
00417 << "\tUNlocked m_controlMutex" << std::endl;
00418 #endif
00419 }
00420 }
00421
00422 #ifdef RR_DEBUG_LOADER_THREADING
00423 std::cout << "\tDONE" << std::endl;
00424 #endif
00425
00426 if(loopResult == SIGNAL)
00427 {
00428 #ifdef RR_DEBUG_LOADER_THREADING
00429 std::cout << "\ti have to SIGNAL replaceTerrain()" << std::endl;
00430 #endif
00431 SDL_CondSignal(m_replaceWakeCond);
00432 }
00433
00434 }
00435
00436 return 0;
00437 }
00438
00439 VRSTerrainLoader::~VRSTerrainLoader()
00440 {
00441 m_thing->clear();
00442
00443 }
00444
00445 void
00446 VRSTerrainLoader::beautifyMesh()
00447 {
00448 m_mesh->setNormalIterator(m_mesh->constructNormalIterator(false, false));
00449
00450 m_textureIter->data.clear();
00451 m_colorIter->data.clear();
00452
00453 m_beautifier->generateColorsAndTexCoords(
00454 m_vertexIter->data.begin(),
00455 m_vertexIter->data.end(),
00456 &(m_textureIter->data),
00457 &(m_colorIter->data),
00458 m_translation->getTranslate());
00459 }
00460
00461 void
00462 VRSTerrainLoader::terminate()
00463 {
00464 for(;;)
00465 {
00466 SDL_LockMutex(m_generateWakeMutex);
00467
00468 if(m_workerIsWaiting)
00469 break;
00470
00471 SDL_UnlockMutex(m_generateWakeMutex);
00472
00473 #ifdef RR_DEBUG_LOADER_THREADING
00474 std::cout << "worker not yet waiting (terminate)" << std::endl;
00475 #endif
00476 }
00477
00478 #ifdef RR_DEBUG_LOADER_THREADING
00479 std::cout << "SIGNALING worker (terminate)" << std::endl;
00480 #endif
00481
00482 SDL_LockMutex(m_controlMutex);
00483 m_terminateWorker = true;
00484 SDL_UnlockMutex(m_controlMutex);
00485
00486 SDL_UnlockMutex(m_generateWakeMutex);
00487 SDL_CondSignal(m_generateWakeCond);
00488
00489
00490
00491 SDL_WaitThread(m_worker, NULL);
00492
00493 #ifdef RR_DEBUG_LOADER_THREADING
00494 std::cout << "WORKER TERMINATED" << std::endl;
00495 #endif
00496 }
00497
00498 VRS::SO<VRS::Mesh>
00499 VRSTerrainLoader::mesh()
00500 {
00501 return m_mesh;
00502 }
00503
00504 VRS::Vector
00505 VRSTerrainLoader::heightAt(double p_x, double p_z)
00506 {
00507 double lodSpacing = 8.0;
00508
00509 VRS::Vector position = VRS::Vector(p_x, 0, p_z);
00510 VRS::Vector translation = m_vertexIter->data[0] +
00511 m_translation->getTranslate();
00512
00513 position -= translation;
00514
00515 position[0] = round(position[0] / lodSpacing);
00516 position[2] = round(position[2] / lodSpacing);
00517
00518
00519 VRS::Vector result = m_vertexIter->data[(position[2] * 64) + position[0]];
00520 result += m_translation->getTranslate();
00521
00522 return result;
00523 }
00524
00525 }