📄 teengine.cpp
字号:
* This function can be called only once and this should be done after adding * all desired objects and correctly setting the active one, after attaching * scene and HUD cameras. Repeated calls are simply ignored. */void TeEngine::initialize(){ static SbBool initialized = FALSE; if (!initialized) { if ( !sceneRoot || !HUDRoot || !sceneCamera || !HUDCamera || !objectList.getLength() || !activeObject ) { SoDebugError::post("TeEngine::initialize", "Some vital TeEngine's attribute is not set or there is no active object in the engine.\n\nThe application will close now."); exit(0); } // schedule creation of patches below inserted objects... for (int i=0; i<objectList.getLength(); i++) updateGraph(objectList[i]); // ...and force the generation while (taskQueue.getLength()) { if (this->genTick()) done(); } activeObject->createHUD(); initialized = TRUE; }}//-----------------------------------------------------------------------------/** * Time tick function of the engine. * * This function has to be called continuously by application that uses engine * in order to have chance to do its work. This function is responsible for * giving generators chance to work (it calls genTick() method) and checking * if all cameras have whole visible terain ready to render (it calls * updateGraph() for all engine objects and TeObject::timeTick() as well). * * \param delta Time elapsed since last call. */void TeEngine::timeTick(const SbTime delta){ // fps static SbTime lastUpdate = SbTime::getTimeOfDay(); SbTime current = SbTime::getTimeOfDay(); if (current-lastUpdate >= 0.1) { fps = 1.0f/float(delta.getValue()); lastUpdate = current; } // generator tick, should go first, because we don't want searching // in patch tree and first step of generation in one timeTick call if (taskQueue.getLength()) if (this->genTick()) done(); // update scenegraph to satisfy objects' needs, insert tasks to taskQueue // here, after genTick() call#if 0 // Shall be this enabled? PCJohn 2005-08-27 for (int i=0; i<objectList.getLength(); i++) { objectList[i]->timeTick(delta); updateGraph(objectList[i]); }#endif}//-----------------------------------------------------------------------------/** * Internal patch generator tick function. * * This method performs one TeGenerator::genStep() for the 1st task in the * queue. Process is controlled by the TeETask::TeETaskStatus values. * * \return TRUE if task finished and result is ready; done() should be called * in this case. * * \todo Consider creating high-level "TePatchGenerator" that will do this * work and make this function obsolete. */SbBool TeEngine::genTick(){ TePatch *p = taskQueue[0].p; switch(taskQueue[0].status) { case TeETask::BM0: if (!p->getBuildMap(0)) { p->findBuildMap(0); if (!p->getBuildMap(0)) { p->setBuildMap(0, new TeHeightMap(getBuildMapResolution())); switch (taskQueue[0].gm) { case FAULT_FORMATION: generator = &faultFormation; break; } generator->setHMap(p->getBuildMap(0)); ((TeFaultFormation*)generator)->seed = int(taskQueue[0].p->getArea().getMin()[0] + taskQueue[0].p->getArea().getMin()[1] * 257.f); taskQueue[0].status = TeETask::BM0G; } else taskQueue[0].status = TeETask::BM1; } else taskQueue[0].status = TeETask::BM1; break; case TeETask::BM0G: if (generator->genStep()) { taskQueue[0].status = TeETask::BM0F; switch (taskQueue[0].fm) { case NONE: taskQueue[0].status = TeETask::BM1; break; case LINEAR: generator = &linearFilter; break; } generator->setHMap(p->getBuildMap(0)); } break; case TeETask::BM0F: if (generator->genStep()) taskQueue[0].status = TeETask::BM0; break; case TeETask::BM1: if (!p->getBuildMap(1)) { p->findBuildMap(1); if (!p->getBuildMap(1)) { p->setBuildMap(1, new TeHeightMap(getBuildMapResolution())); switch (taskQueue[0].gm) { case FAULT_FORMATION: generator = &faultFormation; break; } generator->setHMap(p->getBuildMap(1)); ((TeFaultFormation*)generator)->seed = int(taskQueue[0].p->getArea().getMin()[0] + taskQueue[0].p->getArea().getMin()[1] * 257.f); taskQueue[0].status = TeETask::BM1G; } else taskQueue[0].status = TeETask::BM2; } else taskQueue[0].status = TeETask::BM2; break; case TeETask::BM1G: if (generator->genStep()) { taskQueue[0].status = TeETask::BM1F; switch (taskQueue[0].fm) { case NONE: taskQueue[0].status = TeETask::BM2; break; case LINEAR: generator = &linearFilter; break; } generator->setHMap(p->getBuildMap(1)); } break; case TeETask::BM1F: if (generator->genStep()) taskQueue[0].status = TeETask::BM1; break; case TeETask::BM2: if (!p->getBuildMap(2)) { p->findBuildMap(2); if (!p->getBuildMap(2)) { p->setBuildMap(2, new TeHeightMap(getBuildMapResolution())); switch (taskQueue[0].gm) { case FAULT_FORMATION: generator = &faultFormation; break; } generator->setHMap(p->getBuildMap(2)); ((TeFaultFormation*)generator)->seed = int(taskQueue[0].p->getArea().getMin()[0] + taskQueue[0].p->getArea().getMin()[1] * 257.f); taskQueue[0].status = TeETask::BM2G; } else taskQueue[0].status = TeETask::BM3; } else taskQueue[0].status = TeETask::BM3; break; case TeETask::BM2G: if (generator->genStep()) { taskQueue[0].status = TeETask::BM2F; switch (taskQueue[0].fm) { case NONE: taskQueue[0].status = TeETask::BM3; break; case LINEAR: generator = &linearFilter; break; } generator->setHMap(p->getBuildMap(2)); } break; case TeETask::BM2F: if (generator->genStep()) taskQueue[0].status = TeETask::BM2; break; case TeETask::BM3: if (!p->getBuildMap(3)) { p->findBuildMap(3); if (!p->getBuildMap(3)) { p->setBuildMap(3, new TeHeightMap(getBuildMapResolution())); switch (taskQueue[0].gm) { case FAULT_FORMATION: generator = &faultFormation; break; } generator->setHMap(p->getBuildMap(3)); ((TeFaultFormation*)generator)->seed = int(taskQueue[0].p->getArea().getMin()[0] + taskQueue[0].p->getArea().getMin()[1] * 257.f); taskQueue[0].status = TeETask::BM3G; } else taskQueue[0].status = TeETask::HM; } else taskQueue[0].status = TeETask::HM; break; case TeETask::BM3G: if (generator->genStep()) { taskQueue[0].status = TeETask::BM3F; switch (taskQueue[0].fm) { case NONE: taskQueue[0].status = TeETask::HM; break; case LINEAR: generator = &linearFilter; break; } generator->setHMap(p->getBuildMap(3)); } break; case TeETask::BM3F: if (generator->genStep()) taskQueue[0].status = TeETask::HM; break; case TeETask::HM: if (!p->getHMap()) p->buildHMapFromBuildMaps(); taskQueue[0].status = TeETask::GRAPH; break; case TeETask::GRAPH: p->getPatchGraph(); taskQueue[0].status = TeETask::SEAMS; break; case TeETask::SEAMS: for (int i=0; i<8; i++) { if (p->generateSeamMap(TePatch::Direction(i))) p->getSeamGraph(TePatch::Direction(i)); } return TRUE; break; } return FALSE;}//-----------------------------------------------------------------------------/** * Tests whether the patch is already generated or not. * * Patch is specified by its center in the world-space coordinates passed * to this function in the \a patchPos argument. This is way how to * uniquely describe each patch. * * \param patchPos Position of the center of the patch in world-space. * \return TRUE if the specified patch is ready, FALSE if it isn't * * \todo Is the attribute TeEngine::patchReadyTree necessary? Try to use * getPatch() with TePatch::DONT_CREATE policy instead. * * \sa patchReadyTree */SbBool TeEngine::isReady(SbVec2f patchPos){ return (patchReadyTree.findPoint(SbVec3f(patchPos[0],patchPos[1],0.0f)) != -1);}//-----------------------------------------------------------------------------/** * Tests whether the patch is scheduled for generating or not. * * Patch is specified by its center in the world-space coordinates passed * to this function in the \a patchPos argument. This is way how to * uniquely describe each patch. * * \param patchPos Position of the center of the patch in world-space. * \return TRUE if the specified patch is scheduled, FALSE if it isn't * * \sa schedule(), patchScheduledTree */SbBool TeEngine::isScheduled(SbVec2f patchPos){ return (patchScheduledTree.findPoint(SbVec3f(patchPos[0],patchPos[1],0.0f)) != -1);}//-----------------------------------------------------------------------------/** * Schedule generation of patch at \a patchPos. * * This function creates TeETask object, fills all its attributes and * inserts it into the TeEngine::taskQueue. To control the generation process, * modify TeEngine::currGen and TeEngine::currFilter attributes before * calling this method. * * \param patchPos Position of the center of the patch in world-space. * * \sa TeETask, setCurrGen(), setCurrFilter() */void TeEngine::schedule(SbVec2f patchPos){ TeETask task; task.p = getPatch(patchPos); task.patchPos = patchPos; task.status = TeETask::BM0; task.gm = currGen; task.fm = currFilter; taskQueue.append(task); tasksInQueue++; patchScheduledTree.addPoint(SbVec3f(patchPos[0],patchPos[1],0.0f));}//-----------------------------------------------------------------------------/** * Removes task from the queue and marks the patch as ready. * * Called after succesfull completion of each task. * * \sa taskQueue */void TeEngine::done(){ patchScheduledTree.removePoint(SbVec3f(taskQueue[0].patchPos[0],taskQueue[0].patchPos[1],0.0f)); patchReadyTree.addPoint(SbVec3f(taskQueue[0].patchPos[0],taskQueue[0].patchPos[1],0.0f)); taskQueue.remove(0); tasksInQueue--; patchesNum++;}//-----------------------------------------------------------------------------/** * Schedules generation of all not existing neighbours of the patch at * \a patchPos. * * Patch at \a patchPos is likely to be under camera in a few moments, so look * in scheduled and ready patches and schedule generation of all necessary * neighbours. * * Little trick is used in this method: Count from 7 backwards is here because * NORTH neighbour is represented by nr.7 and with the camera currently * pointing to the north it is good to create north neighbour as the first * one. * * \param patchPos Position of the center of the patch in world-space. * * \todo Additional logic to assure that patches will be in the queue * in optimal order (according to the movement speed vector). This will * make the trick mentioned above obsolete. */void TeEngine::prepareNeighbours(SbVec2f patchPos){ for (int i=7; i>=0; i--) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -