📄 teheightmap.cpp
字号:
}//----------------------------------------------------------------------------/** * Two heightmaps specified-values subtracting. * * Values from source heightmap will be subtracted from "this" heightmap * according to a "blend-rate" \a rate. This should be greater than 0.0f. All * source values are multiplied by \a rate before subtracting from target * values. * * Selected source area is specified by its top-left corner \a sorogin and its * \a size. Target area is specified by its top-left corner \a dorogin. * * \param hmap Pointer to the source heightmap. * \param sorigin Top-left corner of selected area in source heightmap. * \param size Size of selected area. * \param dorigin Top-left corner of area in target heightmap. * \param rate Blend-rate showing how much of source heightmap to be subtracted * from the target. */void TeHeightMap::subtractFrom(const TeHeightMap *hmap, const SbVec2s &sorigin, const SbVec2s &size, const SbVec2s &dorigin, const float rate){ if (sorigin[0]<hmap->resx && sorigin[1]<hmap->resy && size[0]>0 && size[1]>0 && rate>0) { // dimension-check in source int sizex = ((sorigin[0]+size[0]<=hmap->resx) ? size[0] : hmap->resx-sorigin[0] ); int sizey = ((sorigin[1]+size[1]<=hmap->resy) ? size[1] : hmap->resy-sorigin[1] ); // dimension-check in target if (sizex>this->resx-dorigin[0]) sizex = this->resx-dorigin[0]; if (sizey>this->resy-dorigin[1]) sizey = this->resy-dorigin[1]; if (sizex>0 && sizey>0) { // adding for (int y=0; y<sizey; y++) { for (int x=0; x<sizex; x++) { values[(y*this->resx)+(dorigin[1]*this->resx)+dorigin[0]+x] -= hmap->values[(y*hmap->resx)+(sorigin[1]*hmap->resx)+sorigin[0]+x]*rate; } } resetFlags(); } }}//----------------------------------------------------------------------------/** * Subtracts constant from all heightmap values. * * Same as shift(-value). * * \param value Constant to be subtracted from all heightmap values. * * \sa shift() */void TeHeightMap::subtractAll(const float value){ shift(-value);}//----------------------------------------------------------------------------/** * Two heightmaps all-values multiplying. * * Values in target heightmap will be multiplied by values in the source * heightmap according to a "blend-rate" \a rate. This should be greater than * 0.0f. All source values are multiplied by \a rate before multiplying the * target values. * * All possible values will be multiplied, both source and target top-left * corners are in (0,0) coordinates. * * \param hmap Pointer to the source heightmap. * \param rate Blend-rate showing how much of source heightmap to be * multiplied with. */void TeHeightMap::multiplyFrom(const TeHeightMap *hmap, const float rate){ multiplyFrom(hmap, SbVec2s(0,0), getResolution(), SbVec2s(0,0), rate);}//----------------------------------------------------------------------------/** * Two heightmaps specified-values multiplying. * * Values in target heightmap will be multiplied by values in the source * heightmap according to a "blend-rate" \a rate. This should be greater than * 0.0f. All source values are multiplied by \a rate before multiplying the * target values. * * Selected source area is specified by its top-left corner \a sorogin and its * \a size. Target area is specified by its top-left corner \a dorogin. * * \param hmap Pointer to the source heightmap. * \param sorigin Top-left corner of selected area in source heightmap. * \param size Size of selected area. * \param dorigin Top-left corner of area in target heightmap. * \param rate Blend-rate showing how much of source heightmap to be * multiplied with. */void TeHeightMap::multiplyFrom(const TeHeightMap *hmap, const SbVec2s &sorigin, const SbVec2s &size, const SbVec2s &dorigin, const float rate){ if (sorigin[0]<hmap->resx && sorigin[1]<hmap->resy && size[0]>0 && size[1]>0 && rate>0) { // dimension-check in source int sizex = ((sorigin[0]+size[0]<=hmap->resx) ? size[0] : hmap->resx-sorigin[0] ); int sizey = ((sorigin[1]+size[1]<=hmap->resy) ? size[1] : hmap->resy-sorigin[1] ); // dimension-check in target if (sizex>this->resx-dorigin[0]) sizex = this->resx-dorigin[0]; if (sizey>this->resy-dorigin[1]) sizey = this->resy-dorigin[1]; if (sizex>0 && sizey>0) { // adding for (int y=0; y<sizey; y++) { for (int x=0; x<sizex; x++) { values[(y*this->resx)+(dorigin[1]*this->resx)+dorigin[0]+x] *= hmap->values[(y*hmap->resx)+(sorigin[1]*hmap->resx)+sorigin[0]+x]*rate; } } resetFlags(); } }}//----------------------------------------------------------------------------/** * Multiplies all heightmap values by a constant. * * \param value All heightmap values will be multiplied by this constant. */void TeHeightMap::multiplyAll(const float value){ for (int i=0; i<resx*resy; i++) values[i] *= value; resetFlags();}//----------------------------------------------------------------------------/** * Linear filtering of heightmap values * * In one cycle, the filter goes through the data in all rows and columns * in both directions and changes the values according to the neighbours and * filtration coefficient \a coef. This value should be between * (0.0f-1.0f). When large - smaller changes, when small - huge filtering will * be done. This cycle will be done \a times -times. * * \param coef Filtration coefficient, when large - little change, when small - huge filtering. * \param times Filtering will be done times -times * * \sa TeLinearFilter */void TeHeightMap::filter_Linear(const float coef, const int times){ if (coef<1.0 && coef>0.0) { int x = 0; int y = 0; for (int i=0; i<times; i++) { // rows for (y=0; y<resy; y++) { // from left to right x = 1; while (x < resx-1) { values[(y*resx)+x] = values[(y*resx)+x-1]*(1-coef)+values[(y*resx)+x]*coef; x++; } // from right to left x = resx-2; while (x > -1) { values[(y*resx)+x] = values[(y*resx)+x+1]*(1-coef)+values[(y*resx)+x]*coef; x--; } } // columns for(x=0; x<resx; x++) { // columns top to bottom y = 1; while (y < resy) { values[(y*resx)+x] = values[((y-1)*resx)+x]*(1-coef)+values[(y*resx)+x]*coef; y++; } // columns bottom to top y = resy-2; while (y > -1) { values[(y*resx)+x] = values[((y+1)*resx)+x]*(1-coef)+values[(y*resx)+x]*coef; y--; } } } // for resetFlags(); } // if}//----------------------------------------------------------------------------/** * Generates mask that can used when building heightmap from 4 others. * * Heightmaps have to be squares sized (2^x)+1 !!! * * \todo This method is obsolete and should be removed. */void TeHeightMap::generate_4HMOverlap_Mask(){ int size = resx; // square !!! float step = (float)(1.0/floor(size/2)); int base = (int)(floor(size/2)); int center = base*size + base; int idx1 = center; int idx2 = idx1; int idx3 = idx1; int idx4 = idx1; int i, j = 0; float value; // init values[idx1] = 1.0; // center cross for (i=1; i<base; i++) { idx1--; idx2 -= size; idx3++; idx4 += size; value = (float)(1.0 - i*step); values[idx1] = values[idx2] = values[idx3] = values[idx4] = value; } // remaining values (the same for 4 quadrants do it "in parallel") for (i=1; i<base; i++) { for (j=1; j<base; j++) { idx1 = center - i*size - j; idx2 = center - i*size + j; idx3 = center + i*size - j; idx4 = center + i*size + j; value = values[center+j]*values[center+i*size]; values[idx1] = values[idx2] = values[idx3] = values[idx4] = value; } }}//----------------------------------------------------------------------------/** * Generates heightmap values using fault-formation algorithm. * * The algorithm works as follows: * \li Two points in the heightmap are selected. These points define the fault * vector. The selection is done randomly (the generator is initialized * with \a seed as random seed). * \li According to current iteration number, \a min_delta and * \a max_delta, the height of the fault is computed. * \li All values in one half-plane specified by the fault are increased * by computed value. Rest of values is left unchanged. * \li This cycle is done \a num_faults -times. * * \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. * * \sa TeFaultFormation */void TeHeightMap::generate_FaultFormation(const unsigned int seed, const int num_faults, const float min_delta, const float max_delta){ // init setAllValues(0); float Delta = 0; unsigned int Rand1X, Rand1Y, Rand2X, Rand2Y; int FaultVectorX, FaultVectorY; int ToPointVectorX, ToPointVectorY; for (int i = 0; i < num_faults; i++) { Rand1X = rand() % resx; Rand1Y = rand() % resy; Rand2X = rand() % resx; Rand2Y = rand() % resy; // fault vector FaultVectorX = Rand2X - Rand1X; FaultVectorY = Rand2Y - Rand1Y; // value to be added to one side of the fault Delta = static_cast<float> (max_delta - ((max_delta-min_delta) * i) / num_faults); int idx=0; for (int y = 0; y < resy; y++) { for (int x = 0; x < resx; x++) { // vector to the current map position ToPointVectorX = x - Rand1X; ToPointVectorY = y - Rand1Y; if ((ToPointVectorX*FaultVectorY-FaultVectorX*ToPointVectorY) > 0) values[idx] += Delta; idx++; } } } resetFlags();}//----------------------------------------------------------------------------// FOR DEBUGGING ONLY//----------------------------------------------------------------------------#include <cstdio>/** * Dumps itself to stdout. * * This method is meant to be for DEBUGGING only and can be removed at any * time. */void TeHeightMap::dump(){ printf("\n\n----- TeHeightMap::dump() ---------------------------------\n\n"); printf(" Width: %d\n", resx); printf("Height: %d\n\n", resy); printf("Memory: %d B\n\n", sizeof(TeHeightMap)+(resx*resy*sizeof(float))); printf(" minValue: %6.2f (flag: %d)\n", minValue, flags.minUpdated); printf(" maxValue: %6.2f (flag: %d)\n", maxValue, flags.maxUpdated); printf("averageValue: %6.2f (flag: %d)\n\n", averageValue, flags.averageUpdated); if (values!=NULL) { printf(" Values: "); for (int i=0; i<resx*resy; i++) { if ((i%resx)==0 && (i!=0)) printf("\n "); printf("%6.2f, ", values[i]); } } else printf(" Values: NULL"); printf("\n\n-----------------------------------------------------------\n\n");}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -