#include <iostream>
#include <string>
#include <sstream>
#include <vector>
class Terrainheightselection{
public:
Terrainheightselection(Ogre::TerrainGroup* mTerraingroup, Ogre::Vector3 pos, double selsize);
std::vector<Ogre::Vector3> getSelectionVerts(void);
private:
Ogre::TerrainGroup* cmTerraingroup;
Ogre::Terrain* cterrain;
float* cheightdata;
double cselsize;
Ogre::Vector3 cpos;
//std::vector<Ogre::Vector3> getSelectionVerts(void);
};
Terrainheightselection::Terrainheightselection(Ogre::TerrainGroup* mTerraingroup, Ogre::Vector3 pos, double selsize){
cmTerraingroup = mTerraingroup;
cterrain = cmTerraingroup->getTerrain(0,0);
cheightdata = cterrain->getHeightData();
cselsize = selsize;
cpos = pos;
std::vector<Ogre::Vector3> selverts = getSelectionVerts();
Ogre::Log* tlog = Ogre::LogManager::getSingleton().getLog("test.log");
std::ostringstream ss;
ss<< sizeof(cheightdata);
tlog->logMessage(ss.str());
ss.str(std::string());
ss<< cheightdata[9];
tlog->logMessage(ss.str());
Ogre::Real x = cterrain->getSize();
ss.str(std::string());
ss<< x;
tlog->logMessage(ss.str());
float xd = cterrain->getHeightAtWorldPosition(200,3000,200);
ss.str(std::string());
ss<< xd;
tlog->logMessage(ss.str());
ss.str(std::string());
ss<< selverts.size();
tlog->logMessage(ss.str());
}
std::vector<Ogre::Vector3> Terrainheightselection::getSelectionVerts(void){
Ogre::Real posx, posz;
Ogre::Real posxmin, posxmax, poszmin, poszmax;
posx = cpos.x;
posz = cpos.z;
posxmin = posx - cselsize;
posxmax = posx + cselsize;
poszmin = posz - cselsize;
poszmax = posz + cselsize;
std::vector<Ogre::Vector3> veccont;
for (int i = posxmin; i<posxmax+1; i++){
for(int j = poszmin; j<poszmax+1; j++){
double dist = pow(pow(i-posx,2)+pow(j-posz,2),.5);
if (dist <= cselsize){
// float y = cterrain->getHeightAtWorldPosition(i,3000,j);
Ogre::Vector3 retvec;
cterrain->getPoint(i,j,&retvec);
veccont.push_back(Ogre::Vector3(i,retvec.y,j));
}
}
}
return veccont;
}
This class iterates a set of terrain space points using a boundary geometry (square) which the selection tool is confined inside (a circle can be confined in a square whose sides center coincides with the circle's center and whose sides are a distance of 2 * r where r is the radius of the circle.
I iterate this confining geometry of points to avoid needless computations of points outside such geometry making both point selection faster. I then point test by checking the the distance such point is less than the falloff radii of the terrain tool (default or user supplied).
Here's a code snippet implementation inside my mouse left button pressed listener
rlterrVector = Ogre::Vector3(ovec.x,theight,ovec.z);
//conver rlterrVector to terrainspace vector
Ogre::Vector3 rlterrVectorts;
Ogre::Terrain* cterrain = mTerrainGroup->getTerrain(0,0);
cterrain->getTerrainPosition(rlterrVector,&rlterrVectorts);
//terrain space coordinate stored like world space
crlterrVectorts = Ogre::Vector3(513*rlterrVectorts.x,rlterrVectorts.z,513*rlterrVectorts.y);
Terrainheightselection* a = new Terrainheightselection(mTerrainGroup, crlterrVectorts,
falloffwidth);
falloffSelection = a->getSelectionVerts();
In this case I converted the given fixed terrain selection spot, that is, where the user pressed the left mouse button on the given viewport and its corresponding intersection on the given terrain topology, and I converted this from a corresponding world space terrain coordinate selection point (see my blog post on terrain ray query ray testing for tutorial on terrain ray query testing workaround) to terrain space coordinates, and then I pass this to the Terrainheightselection class and grab the selection vertices. You should supply to the this class a position that is in terrain space coordinates but has world space ordering that is, TSvec = (TSvec.x, TSvec.z, TSvec.y) as is shown above.
I haven't robustly written this by the way for terrain edges (not sure if this will crash if you are for instance adjusting terrain nearest the terrain's edge).
No comments:
Post a Comment