i've achieved a working vertex data getter:
Code: Select all
/* .h */
// get position in tiles relative to terrain
bool getTilePos(vector3df pos, u32& x, u32& y);
// get vertex set
bool getVertexSet(u32 x, u32 y, u32 size, vector3df *vertices);
/* .cpp */
bool ShTlTerrainSceneNode::getTilePos(vector3df pos, u32& x, u32& y) {
x = 0;
y = 0;
// get position relative to terrain
pos = pos - getPosition();
// check if position is outside terrain
if(pos.X < 0 || pos.X >= (f32)Size.Width*TileSize ||
pos.Z < 0 || pos.Z >= (f32)Size.Height*TileSize)
return false;
// calculate coordinates of tile
x = (u32) (pos.X / TileSize);
y = (u32) (pos.Z / TileSize);
return true;
}
// get set of tiles around tile(x,y)
// fills array with size*size*4 vertices
// returns true on success
bool ShTlTerrainSceneNode::getVertexSet(u32 x, u32 y, u32 size, vector3df *vertices) {
// check if size is even
if(size % 2 == 0)
return false;
// check if pos is outside terrain
if(x > Size.Width || y > Size.Height)
return false;
// "radius" of the set
u32 o = (size-1)/2;
// avoid border tiles depending on size
if(x < o) x = o;
if(y < o) y = o;
if(x >= Size.Width-o) x = Size.Width -o-1;
if(y >= Size.Height-o) y = Size.Height -o-1;
// make tiles
u32 k = 0;
for(u32 j = y-o ; j <= y+o; j++) {
for(u32 i = x-o; i <= x+o; i++) {
vertices[k++] = vector3df(i*TileSize, Data(i,j).Height, j*TileSize) + getPosition();
vertices[k++] = vector3df(i*TileSize, Data(i,j+1).Height, (j+1)*TileSize) + getPosition();
vertices[k++] = vector3df((i+1)*TileSize, Data(i+1,j+1).Height, (j+1)*TileSize) + getPosition();
vertices[k++] = vector3df((i+1)*TileSize, Data(i+1,j).Height, j*TileSize) + getPosition();
}
}
return true;
}
/* use */
#define COLL_PATCH_SIZE 3
u32 x, y;
if(terrain->getTilePos(YourObject->getPosition(), x, y)) {
vector3df vertices[COLL_PATCH_SIZE*4];
if(terrain->getVertexSet(x,y, COLL_PATCH_SIZE, vertices)) {
// do something with the vertices.
}
}
what it basically does is:
1. get the current 2d position of your object in tiles relative to the terrain.
2. with these coordinates, generate vertices of a size*size patch in the terrain. note that size may only be an odd number, like 1,3,5. usually, you would NOT use 1 because otherwise there could be problems at the border of the current tile.
3. you'll have to deal with the data yourself, it is much dependent on the collision system you use.
i think it must be a lot more efficient than a huge collision mesh, especially for bigger terrains. collision and physics engines might have their own implementation to efficiently handle such big meshes, but i believe most of the terrain (about 50-90%, depending on your game) will not need to check for collision.
edit: this vertex getter is absolutely independent of what part of the terrain is currently rendered or where the active camera is.