⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 teengine.cpp

📁 海量地形数据漫游系统,对于OPENGL开发人员具有一定的参考
💻 CPP
📖 第 1 页 / 共 4 页
字号:
    if ( !isReady(computeNeighbourPos(patchPos, TePatch::Direction(i))) &&         !isScheduled(computeNeighbourPos(patchPos, TePatch::Direction(i))) ) {      schedule(computeNeighbourPos(patchPos, TePatch::Direction(i)));    }  }}//-----------------------------------------------------------------------------/** * Updates scene graph to match object needs. * * This function is called continuously from the timeTick() method and * works in three steps: * \li Pre-generating: schedules patches that are going to be visible shortly. * \li Removes the patches that moved out of camera's field of view. * \li Checks if all visible terrain components (patches and seams) are *     in the scene graph. * * \param obj Object used for visibility checking. * * \todo Some optimization should be done here. */void TeEngine::updateGraph(TeObject *obj){  SbVec3f objPos = obj->getPosition();  SbVec2f patchPos = computePatchPosUnderPoint(objPos);  TePatch::Direction objPosInside = computePosInsidePatch(patchPos, objPos);  TePatch *p = getPatch(patchPos);  int i = 0;  // first call with this object -> prepare initial 3x3 landscape  if (!obj->initialized) {    if (!isReady(patchPos) && !isScheduled(patchPos)) schedule(patchPos);    prepareNeighbours(patchPos);    obj->initialized = TRUE;    obj->patchPosUnder = patchPos;    obj->posInsidePatch = objPosInside;  }  // 1) Pre-generating  // object is moving, so pre-generate patches in the direction of movement  // TODO: aditional logic to select the best according to the movement  //       speed vector.  //       - first compare old and current "posInsidePatch" and then  //         make decision about what to schedule  if ( (obj->patchPosUnder == patchPos)         // no new patch       && (obj->posInsidePatch != objPosInside) // object pos changed       && (objPosInside != -1) ) {              // not in the middle    prepareNeighbours(computeNeighbourPos(patchPos, objPosInside));  }  // 2) Removing  // - should go first, because later in this function we check if all  //   visible things are shown and there we'll have a chance to undo  //   incorrect changes made here.  if ( obj->patchPosUnder != patchPos ) {    switch (objPosInside) {      case TePatch::SOUTH_WEST: switch (obj->posInsidePatch) {                                        case TePatch::EAST:                                  case TePatch::SOUTH_EAST: // same as WEST case below                                                            removePatch(p->neighbour[TePatch::WEST]->neighbour[TePatch::NORTH_WEST]);                                                            removePatch(p->neighbour[TePatch::WEST]->neighbour[TePatch::WEST]);                                                            removePatch(p->neighbour[TePatch::WEST]->neighbour[TePatch::SOUTH_WEST]);                                                            break;                                  case TePatch::NORTH_EAST: // diagonal                                                            removePatch(p->neighbour[TePatch::SOUTH_WEST]->neighbour[TePatch::NORTH_WEST]);                                                            removePatch(p->neighbour[TePatch::SOUTH_WEST]->neighbour[TePatch::WEST]);                                                            removePatch(p->neighbour[TePatch::SOUTH_WEST]->neighbour[TePatch::SOUTH_WEST]);                                                            removePatch(p->neighbour[TePatch::SOUTH_WEST]->neighbour[TePatch::SOUTH]);                                                            removePatch(p->neighbour[TePatch::SOUTH_WEST]->neighbour[TePatch::SOUTH_EAST]);                                                            break;                                  case TePatch::NORTH_WEST:                                       case TePatch::NORTH: // same as SOUTH case below                                                            removePatch(p->neighbour[TePatch::SOUTH]->neighbour[TePatch::SOUTH_WEST]);                                                            removePatch(p->neighbour[TePatch::SOUTH]->neighbour[TePatch::SOUTH]);                                                            removePatch(p->neighbour[TePatch::SOUTH]->neighbour[TePatch::SOUTH_EAST]);                                                            break;                                                   default: break; // this will never happen                                }                                break;      case TePatch::SOUTH_EAST: switch (obj->posInsidePatch) {                                        case TePatch::WEST:                                  case TePatch::SOUTH_WEST: // same as EAST case below                                                            removePatch(p->neighbour[TePatch::EAST]->neighbour[TePatch::NORTH_EAST]);                                                            removePatch(p->neighbour[TePatch::EAST]->neighbour[TePatch::EAST]);                                                            removePatch(p->neighbour[TePatch::EAST]->neighbour[TePatch::SOUTH_EAST]);                                                            break;                                  case TePatch::NORTH_WEST: // diagonal                                                            removePatch(p->neighbour[TePatch::SOUTH_EAST]->neighbour[TePatch::NORTH_EAST]);                                                            removePatch(p->neighbour[TePatch::SOUTH_EAST]->neighbour[TePatch::EAST]);                                                            removePatch(p->neighbour[TePatch::SOUTH_EAST]->neighbour[TePatch::SOUTH_EAST]);                                                            removePatch(p->neighbour[TePatch::SOUTH_EAST]->neighbour[TePatch::SOUTH]);                                                            removePatch(p->neighbour[TePatch::SOUTH_EAST]->neighbour[TePatch::SOUTH_WEST]);                                                            break;                                  case TePatch::NORTH_EAST:                                       case TePatch::NORTH: // same as SOUTH case below                                                            removePatch(p->neighbour[TePatch::SOUTH]->neighbour[TePatch::SOUTH_WEST]);                                                            removePatch(p->neighbour[TePatch::SOUTH]->neighbour[TePatch::SOUTH]);                                                            removePatch(p->neighbour[TePatch::SOUTH]->neighbour[TePatch::SOUTH_EAST]);                                                            break;                                                   default: break; // this will never happen                                }                                break;      case TePatch::NORTH_WEST: switch (obj->posInsidePatch) {                                       case TePatch::SOUTH:                                  case TePatch::SOUTH_WEST: // same as NORTH case below                                                            removePatch(p->neighbour[TePatch::NORTH]->neighbour[TePatch::NORTH_WEST]);                                                            removePatch(p->neighbour[TePatch::NORTH]->neighbour[TePatch::NORTH]);                                                            removePatch(p->neighbour[TePatch::NORTH]->neighbour[TePatch::NORTH_EAST]);                                                            break;                                  case TePatch::SOUTH_EAST: // diagonal                                                            removePatch(p->neighbour[TePatch::NORTH_WEST]->neighbour[TePatch::NORTH_EAST]);                                                            removePatch(p->neighbour[TePatch::NORTH_WEST]->neighbour[TePatch::NORTH]);                                                            removePatch(p->neighbour[TePatch::NORTH_WEST]->neighbour[TePatch::NORTH_WEST]);                                                            removePatch(p->neighbour[TePatch::NORTH_WEST]->neighbour[TePatch::WEST]);                                                            removePatch(p->neighbour[TePatch::NORTH_WEST]->neighbour[TePatch::SOUTH_WEST]);                                                            break;                                  case TePatch::NORTH_EAST:                                        case TePatch::EAST: // same as WEST case below                                                            removePatch(p->neighbour[TePatch::WEST]->neighbour[TePatch::NORTH_WEST]);                                                            removePatch(p->neighbour[TePatch::WEST]->neighbour[TePatch::WEST]);                                                            removePatch(p->neighbour[TePatch::WEST]->neighbour[TePatch::SOUTH_WEST]);                                                            break;                                                   default: break; // this will never happen                                }                                break;      case TePatch::NORTH_EAST: switch (obj->posInsidePatch) {                                       case TePatch::SOUTH:                                  case TePatch::SOUTH_EAST: // same as NORTH case below                                                            removePatch(p->neighbour[TePatch::NORTH]->neighbour[TePatch::NORTH_WEST]);                                                            removePatch(p->neighbour[TePatch::NORTH]->neighbour[TePatch::NORTH]);                                                            removePatch(p->neighbour[TePatch::NORTH]->neighbour[TePatch::NORTH_EAST]);                                                            break;                                  case TePatch::SOUTH_WEST: // diagonal - TODO                                                            removePatch(p->neighbour[TePatch::NORTH_EAST]->neighbour[TePatch::NORTH_WEST]);                                                            removePatch(p->neighbour[TePatch::NORTH_EAST]->neighbour[TePatch::NORTH]);                                                            removePatch(p->neighbour[TePatch::NORTH_EAST]->neighbour[TePatch::NORTH_EAST]);                                                            removePatch(p->neighbour[TePatch::NORTH_EAST]->neighbour[TePatch::EAST]);                                                            removePatch(p->neighbour[TePatch::NORTH_EAST]->neighbour[TePatch::SOUTH_EAST]);                                                            break;                                  case TePatch::NORTH_WEST:                                        case TePatch::WEST: // same as EAST case below                                                            removePatch(p->neighbour[TePatch::EAST]->neighbour[TePatch::NORTH_EAST]);                                                            removePatch(p->neighbour[TePatch::EAST]->neighbour[TePatch::EAST]);                                                            removePatch(p->neighbour[TePatch::EAST]->neighbour[TePatch::SOUTH_EAST]);                                                            break;                                                   default: break; // this will never happen                                }                                break;           case TePatch::SOUTH: removePatch(p->neighbour[TePatch::SOUTH]->neighbour[TePatch::SOUTH_WEST]);                                removePatch(p->neighbour[TePatch::SOUTH]->neighbour[TePatch::SOUTH]);                                removePatch(p->neighbour[TePatch::SOUTH]->neighbour[TePatch::SOUTH_EAST]);                                break;            case TePatch::WEST: removePatch(p->neighbour[TePatch::WEST]->neighbour[TePatch::NORTH_WEST]);                                removePatch(p->neighbour[TePatch::WEST]->neighbour[TePatch::WEST]);                                removePatch(p->neighbour[TePatch::WEST]->neighbour[TePatch::SOUTH_WEST]);                                break;            case TePatch::EAST: removePatch(p->neighbour[TePatch::EAST]->neighbour[TePatch::NORTH_EAST]);                                removePatch(p->neighbour[TePatch::EAST]->neighbour[TePatch::EAST]);                                removePatch(p->neighbour[TePatch::EAST]->neighbour[TePatch::SOUTH_EAST]);                                break;           case TePatch::NORTH: removePatch(p->neighbour[TePatch::NORTH]->neighbour[TePatch::NORTH_WEST]);                                removePatch(p->neighbour[TePatch::NORTH]->neighbour[TePatch::NORTH]);                                removePatch(p->neighbour[TePatch::NORTH]->neighbour[TePatch::NORTH_EAST]);                                break;                       default: break; // -1, this will never happen    }  }  obj->posInsidePatch = objPosInside; // finally update info  // 3) Adding  // really simple :( way how to keep scenegraph updated  // ---------------------------------------------------------------------  // TODO: we are doing this every tick, this SHOULD be done differently  //       although the performance seems to be quite good  // ---------------------------------------------------------------------  if (isReady(patchPos)) { // center patch and its seams    addNode(p->graph);    for (i=0; i<8; i++) {      if (p->seamMap[i]) addNode(p->seamGraph[i]);    }  }  if (obj == activeObject) { // only active obj 9x9, all others only 1 under    for (i=0; i<8; i++) { // neighbours and theirs seams      if (isReady(computeNeighbourPos(patchPos, TePatch::Direction(i)))) {        addNode(p->neighbour[i]->graph);        switch (i) {           case 0: if (p->neighbour[i]->seamMap[TePatch::NORTH]) addNode(p->neighbour[i]->seamGraph[TePatch::NORTH]);                   if (p->neighbour[i]->seamMap[TePatch::EAST]) addNode(p->neighbour[i]->seamGraph[TePatch::EAST]);                   break;           case 1: if (p->neighbour[i]->seamMap[TePatch::NORTH]) addNode(p->neighbour[i]->seamGraph[TePatch::NORTH]);                   if (p->neighbour[i]->seamMap[TePatch::WEST]) addNode(p->neighbour[i]->seamGraph[TePatch::WEST]);                   break;           case 2: if (p->neighbour[i]->seamMap[TePatch::SOUTH]) addNode(p->neighbour[i]->seamGraph[TePatch::SOUTH]);                   if (p->neighbour[i]->seamMap[TePatch::EAST]) addNode(p->neighbour[i]->seamGraph[TePatch::EAST]);                   break;           case 3: if (p->neighbour[i]->seamMap[TePatch::SOUTH]) addNode(p->neighbour[i]->seamGraph[TePatch::SOUTH]);                   if (p->neighbour[i]->seamMap[TePatch::WEST]) addNode(p->neighbour[i]->seamGraph[TePatch::WEST]);                   break;          default: break;        }      }    }  }  obj->patchPosUnder = patchPos; // finally update info}//-----------------------------------------------------------------------------/** * Computes position of the patch that is right under the point \a pt. * * The position can be used to get the patch using getPatch() method. * * \param pt Point in 3D space. * \return Position of the patch under the point \a pt. * * \sa getPatch(), computeNeighbourPos() */SbVec2f TeEngine::computePatchPosUnderPoint(SbVec3f pt){  float px = patch0Size.getValue()[0];  float py = patch0Size.getValue()[1];  float divx = pt.getValue()[0]/px;  float divy = pt.getValue()[1]/py;  float x,y = 0;  if (divx - floor(divx) > 0.5f) x = (float)(floor(divx)+1)*px;  else x = (float)floor(divx)*px;  if (divy - floor(divy) > 0.5f) y = (float)(floor(divy)+1)*py;  else y = (float)floor(divy)*py;  return SbVec2f(x, y);}//-----------------------------------------------------------------------------/** * Computes position of the selected neighbour of the patch. * * The position can be used to get the neighbour using getPatch() method. * * \param patchPos Position of the center of the patch in world-space. * \param which Neighbour selector. * \return Position of the selected neighbour. * * \sa getPatch(), computePatchPosUnderPoint() */SbVec2f TeEngine::computeNeighbourPos(SbVec2f patchPos,                                      TePatch::Direction which){  // if we put these directly down into switch, will it be faster??  float px = patch0Size.getValue()[0];  float py = patch0Size.getValue()[1];  switch (which) {    case TePatch::SOUTH_WEST: return patchPos + SbVec2f(-px, -py); break;    case TePatch::SOUTH_EAST: return patchPos + SbVec2f( px, -py); break;    case TePatch::NORTH_WEST: return patchPos + SbVec2f(-px,  py); break;    case TePatch::NORTH_EAST: return patchPos + SbVec2f( px,  py); break;         case TePatch::SOUTH: return patchPos + SbVec2f(  0, -py); break;          case TePatch::WEST: return patchPos + SbVec2f(-px,   0); break;          case TePatch::EAST: return patchPos + SbVec2f( px,   0); break;         case TePatch::NORTH: return patchPos + SbVec2f(  0,  py); break;                     default: return SbVec2f(0.0f, 0.0f); break; // to avoid warning, this will never happen  }}//-----------------------------------------------------------------------------/** * Computes position of the point \a pt above patch at \a patchPos relatively * to the patch borders. * * The position can be used to determine the direction the object is moving. * * \param patchPos Position of the center of the patch in world-space. * \param pt Point in 3D space. * \return TePatch::Direction, if above the central area, returns *         Direction(-1). */TePatch::Direction TeEngine::computePosInsidePatch(SbVec2f patchPos,                                                   SbVec3f pt){  float px6 = patch0Size.getValue()[0] / 6.0f;  float py6 = patch0Size.getValue()[1] / 6.0f;  float northBorder = patchPos.getValue()[1] + py6;  float southBorder = patchPos.getValue()[1] - py6;  float  westBorder = patchPos.getValue()[0] - px6;  float  eastBorder = patchPos.getValue()[0] + px6;  float ptx = pt.getValue()[0];  float pty = pt.getValue()[1];  if (ptx < westBorder) {      // NW, W, SW    if (pty < southBorder) return TePatch::SOUTH_WEST;    else if (pty < northBorder) return TePatch::WEST;    else return TePatch::NORTH_WEST;  }  else if (ptx < eastBorder) { // N, -1, S    if (pty < southBorder) return TePatch::SOUTH;    else if (pty < northBorder) return TePatch::Direction(-1);    else return TePatch::NORTH;  }  else {                       // NE, E, SE    if (pty < southBorder) return TePatch::SOUTH_EAST;    else if (pty < northBorder) return TePatch::EAST;    else return TePatch::NORTH_EAST;  }}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -