📄 tepatch.cpp
字号:
* \sa WhichHMap, hmap, buildMap */void TePatch::generateHMapFF(WhichHMap which, const unsigned int seed, const int num_faults, const float min_delta, const float max_delta){ assert(which>=0 && which<5 && "Wrong which parameter."); TeHeightMap* &p = (which == 4) ? hmap : buildMap[which]; if (!p) p = new TeHeightMap; p->setResolution(engine->getHMapResolution()); p->generate_FaultFormation(seed, num_faults, min_delta, max_delta);}//-----------------------------------------------------------------------------/** * Tries to find build map by looking in the neighbours. * * We suppose that correct info is in all of them, therefore we grab the * first one. Info propagation is assured by setBuildMap() method. * * The function returns void, the effect is visible right inside the * buildMap attribute. * * \param i Buildmap selector (TePatch::WhichHMap should be used here). * * \sa WhichHMap, buildMap, buildHMapFromBuildMaps() */void TePatch::findBuildMap(const int i){ switch (i) { case 0: if (!buildMap[0]) { if (neighbour[WEST] && neighbour[WEST]->getBuildMap(1)) this->setBuildMap(0, neighbour[WEST]->getBuildMap(1)); else if (neighbour[SOUTH_WEST] && neighbour[SOUTH_WEST]->getBuildMap(3)) this->setBuildMap(0, neighbour[SOUTH_WEST]->getBuildMap(3)); else if (neighbour[SOUTH] && neighbour[SOUTH]->getBuildMap(2)) this->setBuildMap(0, neighbour[SOUTH]->getBuildMap(2)); } break; case 1: if (!buildMap[1]) { if (neighbour[SOUTH] && neighbour[SOUTH]->getBuildMap(3)) this->setBuildMap(1, neighbour[SOUTH]->getBuildMap(3)); else if (neighbour[SOUTH_EAST] && neighbour[SOUTH_EAST]->getBuildMap(2)) this->setBuildMap(1, neighbour[SOUTH_EAST]->getBuildMap(2)); else if (neighbour[EAST] && neighbour[EAST]->getBuildMap(0)) this->setBuildMap(1, neighbour[EAST]->getBuildMap(0)); } break; case 2: if (!buildMap[2]) { if (neighbour[WEST] && neighbour[WEST]->getBuildMap(3)) this->setBuildMap(2, neighbour[WEST]->getBuildMap(3)); else if (neighbour[NORTH_WEST] && neighbour[NORTH_WEST]->getBuildMap(1)) this->setBuildMap(2, neighbour[NORTH_WEST]->getBuildMap(1)); else if (neighbour[NORTH] && neighbour[NORTH]->getBuildMap(0)) this->setBuildMap(2, neighbour[NORTH]->getBuildMap(0)); } break; case 3: if (!buildMap[3]) { if (neighbour[NORTH] && neighbour[NORTH]->getBuildMap(1)) this->setBuildMap(3, neighbour[NORTH]->getBuildMap(1)); else if (neighbour[NORTH_EAST] && neighbour[NORTH_EAST]->getBuildMap(0)) this->setBuildMap(3, neighbour[NORTH_EAST]->getBuildMap(0)); else if (neighbour[EAST] && neighbour[EAST]->getBuildMap(2)) this->setBuildMap(3, neighbour[EAST]->getBuildMap(2)); } break; }}//-----------------------------------------------------------------------------/** * High-level function that prepares all build maps. * * Tries to find build maps in the neighbours. If map is not found, asks * engine to generate new one. * * \sa buildMap, TeEngine::generateHMap(), buildHMapFromBuildMaps() */void TePatch::prepareBuildMaps(){ for (int i=0; i<4; i++) { this->findBuildMap(i); if (!buildMap[i]) { engine->faultFormation.seed = (unsigned int)time(NULL)+(rand()%10000); this->setBuildMap(i, engine->generateHMap(engine->getBuildMapResolution())); } }}//-----------------------------------------------------------------------------/** * Computes patch height map from four build maps. * * All build maps have to be set before calling this method. * * \sa buildMap, setBuildMap() * * \todo More detailed documentation. */void TePatch::buildHMapFromBuildMaps(){ if (!buildMap[0] || !buildMap[1] || !buildMap[2] || !buildMap[3]) { SoDebugError::post("TePatch::buildHMapFromBuildMaps", "Not all build maps were set. Can not build HeightMap."); return; } SbVec2s h_res = engine->getHMapResolution(); // height map resolution SbVec2s b_res = engine->getBuildMapResolution(); // build map resolution assert((buildMap[0]->getResolution() == b_res) && (buildMap[1]->getResolution() == b_res) && (buildMap[2]->getResolution() == b_res) && (buildMap[3]->getResolution() == b_res) && "buildMaps resolutions are not the same."); int shift = b_res[0] - h_res[0]; if (hmap) delete hmap; hmap = new TeHeightMap(h_res); float *dest = hmap->startEditing(); const float *m1 = &buildMap[0]->getValues()[b_res[0]*(h_res[1]-1) + h_res[0]-1]; const float *m2 = &buildMap[1]->getValues()[b_res[0]*(h_res[1]-1)]; const float *m3 = &buildMap[2]->getValues()[h_res[0]-1]; const float *m4 = &buildMap[3]->getValues()[0]; int x,y; int index; float qf; // koeficient "going forward" - increasing from 0 on the first row to 1 on the last row float qb; // koeficient "going backward" - decreasing from 1 on the first row to 0 on the last row float q1; // koeficient decreasing from qb to 0 on each row float q2; // koeficient increasing from 0 to qb on each row float q3; // koeficient decreasing from qf to 0 on each row float q4; // koeficient increasing from 0 to qf on each row float dy = 1.f/float(h_res[1]-1); float dxf,dxb; // size of q1,q2,q3, and q4 step qf = 0.f; qb = 1.f; index = 0; for (y=0; y<h_res[1]; y++) { q1 = qb; q2 = 0.f; q3 = qf; q4 = 0.f; dxf = qf / (h_res[0]-1); dxb = qb / (h_res[0]-1); for (x=0; x<h_res[0]; x++) { *dest++ = (*m1++)*q1 + (*m2++)*q2 + (*m3++)*q3 + (*m4++)*q4; q1 -= dxb; q2 += dxb; q3 -= dxf; q4 += dxf; } m1 += shift; m2 += shift; m3 += shift; m4 += shift; qf += dy; qb -= dy; } hmap->finishEditing();}//-----------------------------------------------------------------------------/** * Validates seamMap pointer in desired direction if possible. * * Tries to look for the desired map in the neighbours. If not found, tries * to compute it and propagate the info to all interested neighbours. This * assures that each seam map will be computed only once. User does not * need to worry about the way how the data are obtained. This function * says if the private seam map pointer is valid or not. * * Note that properly set hmap attributes of all necessary neighbours are * needed to succesfully complete this task. * * \param which Seam map selector. * \return TRUE if the seam map pointer is valid and the graph can be created. * * \sa seamMap, getSeamMap() */SbBool TePatch::generateSeamMap(const Direction which){ // map already set if (seamMap[which]) return TRUE; // do we have all neighbours and hmaps ready? if (!this->hmap) return FALSE; if (which == SOUTH || which == WEST || which == EAST || which == NORTH) { if (!neighbour[which]) return FALSE; else if (!neighbour[which]->hmap) return FALSE; } else { if (!neighbour[which]) return FALSE; else if (!neighbour[which]->hmap) return FALSE; switch (which) { case SOUTH_WEST: if (!neighbour[SOUTH] || !neighbour[WEST]) return FALSE; else if (!neighbour[SOUTH]->hmap || !neighbour[WEST]->hmap) return FALSE; break; case SOUTH_EAST: if (!neighbour[SOUTH] || !neighbour[EAST]) return FALSE; else if (!neighbour[SOUTH]->hmap || !neighbour[EAST]->hmap) return FALSE; break; case NORTH_WEST: if (!neighbour[NORTH] || !neighbour[WEST]) return FALSE; else if (!neighbour[NORTH]->hmap || !neighbour[WEST]->hmap) return FALSE; break; case NORTH_EAST: if (!neighbour[NORTH] || !neighbour[EAST]) return FALSE; else if (!neighbour[NORTH]->hmap || !neighbour[EAST]->hmap) return FALSE; break; } } // if yes, try to look for the map in one of the neighbours (we rely on // correct info to be in all of them) TeHeightMap *tmp = neighbour[which]->seamMap[getOppositeDirection(which)]; if (tmp) { seamMap[which] = tmp; return TRUE; } int x, y = 0; int resx = engine->getHMapResolution()[0]; int resy = engine->getHMapResolution()[1]; // if not found, compute map from neighbour data and update neighbour's // seamMap-pointer switch (which) { case SOUTH_WEST: tmp = new TeHeightMap(5, 5); for (y=2; y<5; y++) for (x=0; x<3; x++) tmp->setValue(x, y, neighbour[WEST]->hmap->getValue(resx-3+x, y-2)); for (y=2; y<5; y++) for (x=3; x<5; x++) tmp->setValue(x, y, this->hmap->getValue(x-2, y-2)); for (y=0; y<2; y++) for (x=0; x<3; x++) tmp->setValue(x, y, neighbour[SOUTH_WEST]->hmap->getValue(resx-3+x, resy-3+y)); for (y=0; y<2; y++) for (x=3; x<5; x++) tmp->setValue(x, y, neighbour[SOUTH]->hmap->getValue(x-2, resy-3+y)); neighbour[WEST]->setSeamMap(SOUTH_EAST, tmp); neighbour[SOUTH]->setSeamMap(NORTH_WEST, tmp); break; case SOUTH_EAST: tmp = new TeHeightMap(5, 5); for (y=2; y<5; y++) for (x=0; x<3; x++) tmp->setValue(x, y, this->hmap->getValue(resx-3+x, y-2)); for (y=2; y<5; y++) for (x=3; x<5; x++) tmp->setValue(x, y, neighbour[EAST]->hmap->getValue(x-2, y-2)); for (y=0; y<2; y++) for (x=0; x<3; x++) tmp->setValue(x, y, neighbour[SOUTH]->hmap->getValue(resx-3+x, resy-3+y)); for (y=0; y<2; y++) for (x=3; x<5; x++) tmp->setValue(x, y, neighbour[SOUTH_EAST]->hmap->getValue(x-2, resy-3+y)); neighbour[EAST]->setSeamMap(SOUTH_WEST, tmp); neighbour[SOUTH]->setSeamMap(NORTH_EAST, tmp); break; case NORTH_WEST: tmp = new TeHeightMap(5, 5); for (y=2; y<5; y++) for (x=0; x<3; x++) tmp->setValue(x, y, neighbour[NORTH_WEST]->hmap->getValue(resx-3+x, y-2)); for (y=2; y<5; y++) for (x=3; x<5; x++) tmp->setValue(x, y, neighbour[NORTH]->hmap->getValue(x-2, y-2)); for (y=0; y<2; y++) for (x=0; x<3; x++) tmp->setValue(x, y, neighbour[WEST]->hmap->getValue(resx-3+x, resy-3+y)); for (y=0; y<2; y++) for (x=3; x<5; x++) tmp->setValue(x, y, this->hmap->getValue(x-2, resy-3+y)); neighbour[NORTH]->setSeamMap(SOUTH_WEST, tmp); neighbour[WEST]->setSeamMap(NORTH_EAST, tmp); break; case NORTH_EAST: tmp = new TeHeightMap(5, 5); for (y=2; y<5; y++) for (x=0; x<3; x++) tmp->setValue(x, y, neighbour[NORTH]->hmap->getValue(resx-3+x, y-2)); for (y=2; y<5; y++) for (x=3; x<5; x++) tmp->setValue(x, y, neighbour[NORTH_EAST]->hmap->getValue(x-2, y-2)); for (y=0; y<2; y++) for (x=0; x<3; x++) tmp->setValue(x, y, this->hmap->getValue(resx-3+x, resy-3+y)); for (y=0; y<2; y++) for (x=3; x<5; x++) tmp->setValue(x, y, neighbour[EAST]->hmap->getValue(x-2, resy-3+y)); neighbour[NORTH]->setSeamMap(SOUTH_EAST, tmp); neighbour[EAST]->setSeamMap(NORTH_WEST, tmp); break; case SOUTH: tmp = new TeHeightMap(SbVec2s(engine->getHMapResolution()[0], 5)); tmp->copyFrom(neighbour[which]->hmap, SbVec2s(0, engine->getHMapResolution()[1]-3), SbVec2s(engine->getHMapResolution()[0], 3)); tmp->copyFrom(this->hmap, SbVec2s(0, 1), SbVec2s(engine->getHMapResolution()[0], 2), SbVec2s(0, 3)); break; case WEST: tmp = new TeHeightMap(SbVec2s(5, engine->getHMapResolution()[1])); tmp->copyFrom(neighbour[which]->hmap, SbVec2s(engine->getHMapResolution()[0]-3, 0), SbVec2s(3, engine->getHMapResolution()[1])); tmp->copyFrom(this->hmap, SbVec2s(1, 0), SbVec2s(2, engine->getHMapResolution()[1]), SbVec2s(3, 0)); break; case EAST: tmp = new TeHeightMap(SbVec2s(5, engine->getHMapResolution()[1])); tmp->copyFrom(this->hmap, SbVec2s(engine->getHMapResolution()[0]-3, 0), SbVec2s(3, engine->getHMapResolution()[1])); tmp->copyFrom(neighbour[which]->hmap, SbVec2s(1, 0), SbVec2s(2, engine->getHMapResolution()[1]), SbVec2s(3, 0)); break; case NORTH: tmp = new TeHeightMap(SbVec2s(engine->getHMapResolution()[0], 5)); tmp->copyFrom(this->hmap, SbVec2s(0, engine->getHMapResolution()[1]-3), SbVec2s(engine->getHMapResolution()[0], 3)); tmp->copyFrom( neighbour[which]->hmap, SbVec2s(0, 1), SbVec2s(engine->getHMapResolution()[0], 2), SbVec2s(0, 3)); break; } // always this->setSeamMap(which, tmp); neighbour[which]->setSeamMap(Direction(getOppositeDirection(which)), tmp); // more inside the switch above return TRUE;}//-----------------------------------------------------------------------------/** * Calculates normal at the specified point in the heightmap. * * \param map Pointer to the height map. * \param x X-coordinate of the point. * \param y Y-coordinate of the point. * \param sx ??? * \param sy ??? * \return Normal at the specified point (\a x, \a y). * * \todo More detailed documentation. Parameters sx, sy ??? */SbVec3f TePatch::calculateNormal(const TeHeightMap *map, const int x, const int y, const float sx, const float sy){ float dx,dy; int resx,resy; map->getResolution(resx,resy); const float *values = map->getValues(); // 趆el v ose X if (x>=1 && x<=resx-2) // V齪o鑕t ze dvou sousedn韈h bod
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -