📄 tepatch.cpp
字号:
} engine->advanceRootToPos(pos); return engine->getRootPatch(); } // not intersecting => go up if (!area.intersect(pos)) { if (parent) // find recursivelly return parent->getPatchHierarchRelative(pos, relativeLevel-1, policy); else { // this item has no parent => it is the root if (policy == DONT_CREATE) return NULL; else { if (!engine) { SoDebugError::post("TePatch::getPatchHierarchRelative", "The patch must be appended to the TePatch tree\n" "before the call of this function."); return NULL; } engine->advanceRootToPos(pos); TePatch *root = engine->getRootPatch(); if (policy == LOWER_DETAIL) return root; else return root->getPatchHierarchRelative(pos, relativeLevel + (this->getLevel()-root->getLevel()), policy); } } } else { if (relativeLevel == 0) return this; Direction d = getDirectionXFromVec(pos-area.getCenter()); if (detail[d]) // find recursivelly return detail[d]->getPatchHierarchRelative(pos, relativeLevel+1, policy); else { // requested detail is missing => handle it switch (policy) { case DONT_CREATE: return NULL; case LOWER_DETAIL: return this; case CREATE: { this->setDetail(d, new TePatch(engine)); return detail[d]->getPatchHierarchRelative(pos, relativeLevel+1, policy); } default: assert(0 && "Wrong policy value."); return NULL; } } }}//-----------------------------------------------------------------------------/** * Documentation not available. * * \todo More detailed documentation. */TePatch* TePatch::getPatch(const SbVec2f &pos, const int level, PatchMissedPolicy policy){ return getPatchRelative(pos, level - this->getLevel(), policy);}//-----------------------------------------------------------------------------/** * Documentation not available. * * \todo More detailed documentation. * \todo Make some optimization here using neighbour list. */TePatch* TePatch::getPatchRelative(const SbVec2f &pos, const int relativeLevel, PatchMissedPolicy policy){ // FIXME: make some optimization here using neighbour list return getPatchHierarchRelative(pos, relativeLevel, policy);}//-----------------------------------------------------------------------------/** * Private attribute accessor. * * \param which Detail selector. * \return Specified detail patch. * * \sa detail */TePatch* TePatch::getDetail(const Direction which){ assert(which>=0 && which<4 && "Wrong which parameter."); return detail[which];}//-----------------------------------------------------------------------------/** * Documentation not available. * * \todo More detailed documentation. */void TePatch::setDetail(const Direction which, TePatch *patch){ assert(which>=0 && which<4 && "Wrong which parameter."); if (detail[which] == patch) return; TePatch *tmp = detail[which]; detail[which] = patch; if (patch) { patch->engine = this->engine; patch->parent = this; // optimization: if previous detail exist, use some of // its values instead of computing them if (tmp) { // area patch->area = tmp->area; // neighbours for (int i=0;i<8;i++) patch->neighbour[i] = tmp->neighbour[i]; } else { // area SbVec2f min,max; if (which==SOUTH_WEST || which==NORTH_WEST) { min[0] = this->area.getMin()[0]; max[0] = this->area.getCenter()[0]; } else { min[0] = this->area.getCenter()[0]; max[0] = this->area.getMax()[0]; } if (which==SOUTH_WEST || which==SOUTH_EAST) { min[1] = this->area.getMin()[1]; max[1] = this->area.getCenter()[1]; } else { min[1] = this->area.getCenter()[1]; max[1] = this->area.getMax()[1]; } patch->area = SbBox2f(min,max); // neighbours patch->updateNeighbours(); } } // nullify old detail pointers if (tmp != NULL) { tmp->engine = NULL; tmp->parent = NULL; for (int i=0;i<8;i++) tmp->neighbour[i] = NULL; }}//-----------------------------------------------------------------------------/** * Updates local neighbour list and references in that neighbours too. * * \sa neighbour */void TePatch::updateNeighbours(){ int i; float size_x, size_y; area.getSize(size_x, size_y); SbVec2f center = area.getCenter(); // update my neighbour list neighbour[SOUTH_WEST] = getPatchHierarchRelative(center + SbVec2f(-size_x,-size_y), 0, DONT_CREATE); neighbour[SOUTH_EAST] = getPatchHierarchRelative(center + SbVec2f( size_x,-size_y), 0, DONT_CREATE); neighbour[NORTH_WEST] = getPatchHierarchRelative(center + SbVec2f(-size_x, size_y), 0, DONT_CREATE); neighbour[NORTH_EAST] = getPatchHierarchRelative(center + SbVec2f( size_x, size_y), 0, DONT_CREATE); neighbour[SOUTH] = getPatchHierarchRelative(center + SbVec2f( 0.f,-size_y), 0, DONT_CREATE); neighbour[WEST] = getPatchHierarchRelative(center + SbVec2f(-size_x, 0.f), 0, DONT_CREATE); neighbour[EAST] = getPatchHierarchRelative(center + SbVec2f( size_x, 0.f), 0, DONT_CREATE); neighbour[NORTH] = getPatchHierarchRelative(center + SbVec2f( 0.f,+size_y), 0, DONT_CREATE); // update references from neighbours for (i=0;i<8;i++) if (neighbour[i]) neighbour[i]->neighbour[getOppositeDirection(i)] = this;}//-----------------------------------------------------------------------------/** * Documentation not available. * * \todo More detailed documentation. */void TePatch::removeDetail(TePatch *patch){ assert(patch->parent == this && "Parent/detail integrity error. This should never happen."); Direction d = patch->getDirectionWithinParent(); if (d<0) { SoDebugError::postWarning("TePatch::removeDetail", "Attempt to remove detail that is not present in this patch."); return; } this->setDetail(d, NULL);}//-----------------------------------------------------------------------------/** * Documentation not available. * * \todo More detailed documentation. */void TePatch::makeRoot(const SbBox2f &area, TeEngine *engine){ if (this->parent) parent->removeDetail(this); this->area = area; this->engine = engine;}//-----------------------------------------------------------------------------/** * Documentation not available. * * \todo More detailed documentation. */TePatch::Direction TePatch::getDirectionWithinParent() const{ if (!parent) return Direction(-1); for (int i=0; i<4; i++) if (detail[i] == this) return Direction(i); return Direction(-1);}//-----------------------------------------------------------------------------/** * Documentation not available. * * \todo More detailed documentation. */TePatch::Direction TePatch::getDetailDirection(const SbVec2f &point) const{ if (!area.intersect(point)) return Direction(-1); return getDirectionXFromVec(point - area.getCenter());}//-----------------------------------------------------------------------------/** * Private attribute accessor. * * \param i Buildmap selector (TePatch::WhichHMap should be used here). * \return Const pointer to the specified build map. * * \sa WhichHMap, buildMap, setBuildMap(), buildHMapFromBuildMaps() */const TeHeightMap* TePatch::getBuildMap(const int i) const{ assert(i>=0 && i<4 && "Wrong which parameter."); return buildMap[i];}//-----------------------------------------------------------------------------/** * Private attribute accessor. * * \param i Build map selector (TePatch::WhichHMap should be used here). * \return Pointer to the specified build map. * * \sa WhichHMap, buildMap, setBuildMap(), buildHMapFromBuildMaps() */TeHeightMap* TePatch::getBuildMap(const int i){ assert(i>=0 && i<4 && "Wrong which parameter."); return buildMap[i];}//-----------------------------------------------------------------------------/** * Sets single build map. * * This function checks whether the resolution of the heightmap \a hmap * correspondes with the one set in the engine. The resolution must be equal * to the one returned by TeEngine::getBuildMapResolution() function. If the * resolution is incorrect, nothing happens. * * Info is propagated to all existing neighbours. * * \param i Buildmap selector (TePatch::WhichHMap should be used here). * \param hmap Pointer to the heightmap. * * \sa setBuildMaps(), WhichHMap, buildMap, getBuildMap(), buildHMapFromBuildMaps() */void TePatch::setBuildMap(const int i, TeHeightMap *hmap){ assert(i>=0 && i<4 && "Wrong which parameter."); if (hmap->getResolution() != engine->getBuildMapResolution()) { SoDebugError::post("TePatch::setBuildMap", "BuildMap must have resolution equal to the one returned by\n" "TeEngine::getBuildMapResolution(). The resolution is based on the value\n" "passed to TeEngine constructor. For now, this call is ignored."); return; } buildMap[i] = hmap; // propagate info to neighbours // - uses short evaluation // - second check is maybe redundant and probably will be deleted in the // near future switch (i) { case 0: if (neighbour[WEST] && !neighbour[WEST]->getBuildMap(1)) neighbour[WEST]->setBuildMap(1, hmap); if (neighbour[SOUTH_WEST] && !neighbour[SOUTH_WEST]->getBuildMap(3)) neighbour[SOUTH_WEST]->setBuildMap(3, hmap); if (neighbour[SOUTH] && !neighbour[SOUTH]->getBuildMap(2)) neighbour[SOUTH]->setBuildMap(2, hmap); break; case 1: if (neighbour[SOUTH] && !neighbour[SOUTH]->getBuildMap(3)) neighbour[SOUTH]->setBuildMap(3, hmap); if (neighbour[SOUTH_EAST] && !neighbour[SOUTH_EAST]->getBuildMap(2)) neighbour[SOUTH_EAST]->setBuildMap(2, hmap); if (neighbour[EAST] && !neighbour[EAST]->getBuildMap(0)) neighbour[EAST]->setBuildMap(0, hmap); break; case 2: if (neighbour[WEST] && !neighbour[WEST]->getBuildMap(3)) neighbour[WEST]->setBuildMap(3, hmap); if (neighbour[NORTH_WEST] && !neighbour[NORTH_WEST]->getBuildMap(1)) neighbour[NORTH_WEST]->setBuildMap(1, hmap); if (neighbour[NORTH] && !neighbour[NORTH]->getBuildMap(0)) neighbour[NORTH]->setBuildMap(0, hmap); break; case 3: if (neighbour[NORTH] && !neighbour[NORTH]->getBuildMap(1)) neighbour[NORTH]->setBuildMap(1, hmap); if (neighbour[NORTH_EAST] && !neighbour[NORTH_EAST]->getBuildMap(0)) neighbour[NORTH_EAST]->setBuildMap(0, hmap); if (neighbour[EAST] && !neighbour[EAST]->getBuildMap(2)) neighbour[EAST]->setBuildMap(2, hmap); break; }}//-----------------------------------------------------------------------------/** * Sets all build maps in a single step. * * This function simply calls setBuildMap() four times. All restrictions * on the heightmaps resolution are therefore applied too. * * \param sw Pointer to the heightmap, it will become south-west build map. * \param se Pointer to the heightmap, it will become south-east build map. * \param nw Pointer to the heightmap, it will become north-west build map. * \param ne Pointer to the heightmap, it will become north-east build map. * * \sa buildMap, getBuildMap(), buildHMapFromBuildMaps() */void TePatch::setBuildMaps(TeHeightMap *sw, TeHeightMap *se, TeHeightMap *nw, TeHeightMap *ne){ setBuildMap(HMAP_SOUTH_WEST, sw); setBuildMap(HMAP_SOUTH_EAST, se); setBuildMap(HMAP_NORTH_WEST, nw); setBuildMap(HMAP_NORTH_EAST, ne);}//-----------------------------------------------------------------------------/** * Generates heightmap of this patch using fault-formation algorithm. * * Which height map will be generated is specified by the \a which parameter. * * More details about how this algorithm works can be found at * TeHeightMap::generate_FaultFormation(). * * \param which Which height map will be generated selector. * \param seed Random seed that defines terrain shape. * \param num_faults Number of faults to be generated (number of iterations). * \param min_delta Minimal fault height. * \param max_delta Maximal fault height. *
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -