New Tiled Terrain Scene Node [works with Irr 1.5]

Announce new projects or updates of Irrlicht Engine related tools, games, and applications.
Also check the Wiki
Vsk
Posts: 343
Joined: Thu Sep 27, 2007 4:43 pm

Post by Vsk »

morris wrote: also i found it quite hard to get out the (global) geometry data out of the node :D for collision. it seems that calling updateVertices() on all sectors somehow deleted some tiles or made them invalid. i got around that with copying all the code where tile data is "created" and building up all the geometry manually, which works okay for me.

other than that - very great work ;) keep it up!
cya
But you are obtaining ALL the gloabl geometry?
In case you do, could please send me the code here or to pm.
I have to do the same I've no tried yet, but if someone has already done it even better!.
if you don't want to, any help would be apprecieated.

I need it for newton.

Thanks in advance.!
morris
Posts: 36
Joined: Tue Jul 10, 2007 10:10 am

Post by morris »

in fact, after doing that, i realized that some other method would be way faster and cooler:

for each colliding object, check if terrain->getHeight(pos) is smaller than it's potential collision radius. if so, place a simple flat box geom right at below the object at terrains height. havent tested that but could work for simple collision.

here's my solution (i've added this to the header file, its quite hacky i think because i basically copied to methods which where already there without simplifying anything):

EDIT: code is useless and doesnt fulfill its purpose, see below
Last edited by morris on Thu Jan 31, 2008 9:36 pm, edited 1 time in total.
Vsk
Posts: 343
Joined: Thu Sep 27, 2007 4:43 pm

Post by Vsk »

Well thanks :) I'll try it!.
morris
Posts: 36
Joined: Tue Jul 10, 2007 10:10 am

Post by morris »

oh god!! i've just realized why i didnt understand the size parameters. i never even thought about using follow(node) :shock: this of course answers my question, + makes my code useless and not global anymore, but only gets the tiles of the startup sectors. gonna have to redo that, sorry @Vsk!!!!

Edit: i'm currently working on a sort of "retrieve potential collision tiles" algorithm so that you will not have to load the whole terrain into one big collision object. instead, i'll dynamically add and remove collision triangles for each object. this, however, will be very dependent on the physics engine you are using.
sp00n
Posts: 114
Joined: Wed Sep 13, 2006 9:39 am

Post by sp00n »

Birdman wrote:
Material[0].setTexture(1,CTexture);
Material[0].setFlag(video::EMF_TEXTURE_WRAP, true);
hmmm, i used:

Code: Select all

Material[0].TextureLayer[1].Texture = CTexture;
Material[0].TextureLayer[1].TextureWrap = video::ETC_CLAMP_TO_EDGE;
and all works well :)
arras
Posts: 1622
Joined: Mon Apr 05, 2004 8:35 am
Location: Slovakia
Contact:

Post by arras »

For collision use getHeight(core::vector3df pos) whenever possible which is fast. Most of the time, you just need to place your node on terrain and this function is just for that. If you have something like car or tank, you can run that function under each wheel, from that you can calculate also its rotation.

For some more complex collision detections like line of sight or bullet path tracking you can use getIntersectionWithLine() which is slower than getHeight() but still faster than Irrlicht functions since it is optimized for my terrain.

getHeight() and getIntersectionWithLine() works anywhere on terrain, means they are not dependent on position of visible (rendered) part of terrain.

If you need to run it with physic engine of kind, you have to adapt it yourself. I am not using them. This node was made as extension of Irrlicht and was not intended to work with any physic engine. Which does not mean it can't.

All info about terrain is stored in Data array from which array of vertices and indices is rebuild dynamically. You can find code which does that in constructor and updateVertices(). You can build Irrlicht SMeshBuffers and SMesh if you want in similar way but beware, if your terrain is large (and it was made to be capable of) you can get mesh too large. In case of demo: 2000 x 2000 tiles x 4 vertices each = 16 000 000 vertices!!!

So you probably want to manage that somehow dynamically too. If you want access to visible (rendered) vertices you can access them either via Tile array or get access directly to vertex and index arrays of mesh buffers via Sector array (one sector is effectively one mesh buffer similar to IMeshBuffer).
Beware however that these mesh buffers are updated dynamically based on Step attribute. It is decided in update() function.
morris
Posts: 36
Joined: Tue Jul 10, 2007 10:10 am

Post by morris »

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.
Vsk
Posts: 343
Joined: Thu Sep 27, 2007 4:43 pm

Post by Vsk »

Yes I need use a physic engine. I need the facilities and consistense that bring using a physic engine. If not, I would not using it.
Of course that it is about 70% 90% of terrain withoug collsion but painfully in the application that I'am building this 10-30% of collsion is (and must be normaly) in extremes of terrain. And hasn't nothing to do with where the camera is.

Newton use some kind of optimization on high level for big meshes like terrains. So if one zone isn't colliding that will not checked. I suppous it is something like a physic occtree or something like that.
Anyway don't worry both of you. I see what can I do. And when find an answer I will tell you. :o

Thanks. seeya.
Birdman
Posts: 25
Joined: Mon Jan 28, 2008 5:45 am
Location: Buenos Aires

Post by Birdman »

sp00n wrote:Birdman wrote:
Material[0].setTexture(1,CTexture);
Material[0].setFlag(video::EMF_TEXTURE_WRAP, true);
hmmm, i used:

Code: Select all

Material[0].TextureLayer[1].Texture = CTexture;
Material[0].TextureLayer[1].TextureWrap = video::ETC_CLAMP_TO_EDGE;
and all works well :)
Thanks for the addition, this worked well as well :)

Now a silly question what could this error means?

E:\Source\TestJor\Terrain Node\Makefile.win [Build Error] [ShTlTerrainDemo.exe] Error 1

Im honestly competely lost here, i used the .dev provided by arras on the last version of DEVC++.

Edited: Bleh it was a simple error on the project that linked with the Irrlicht.a library in a 1.3 directory, wich of course doesn't exist on my computer.
Finally i managed to get this working in 1.4 thanks everybody.. Arras maybe you could publish the 1.4 version, its just few modifications to get it working.
The sleeper must awaken!
morris
Posts: 36
Joined: Tue Jul 10, 2007 10:10 am

Post by morris »

Vsk wrote:Yes I need use a physic engine. I need the facilities and consistense that bring using a physic engine. If not, I would not using it.
Of course that it is about 70% 90% of terrain withoug collsion but painfully in the application that I'am building this 10-30% of collsion is (and must be normaly) in extremes of terrain. And hasn't nothing to do with where the camera is.

Newton use some kind of optimization on high level for big meshes like terrains. So if one zone isn't colliding that will not checked. I suppous it is something like a physic occtree or something like that.
Anyway don't worry both of you. I see what can I do. And when find an answer I will tell you. :o

Thanks. seeya.
you could easily change my code to get all vertex data. i still dont think this is a good idea ;) i also use a physics engine, and i also get collision data independent of the camera position. but, do as your project demands.
morris
Posts: 36
Joined: Tue Jul 10, 2007 10:10 am

Post by morris »

me again, there's a memory leak in updateVertices() of the terrain node. meshes & meshbuffers are new'd and they are a) not deleted and b) not used in any way, so if anyone is using the node just remove those lines.
arras
Posts: 1622
Joined: Mon Apr 05, 2004 8:35 am
Location: Slovakia
Contact:

Post by arras »

Those were added by elvman ...he was sending me code he recompiled in order to get rid of some complains on some compilers. He probably left that stuff there by accident.

You can delete it altogether...
B@z
Posts: 876
Joined: Thu Jan 31, 2008 5:05 pm
Location: Hungary

Post by B@z »

did somebody get it work with newton?
i was searching a lot, but everywhere is just "you can edit it", "depends on you'll have to deal with yourself" and so on.
did somebody get work it? and can show me an example please? :roll:
B@z
Posts: 876
Joined: Thu Jan 31, 2008 5:05 pm
Location: Hungary

Post by B@z »

nobody?
Halifax
Posts: 1424
Joined: Sun Apr 29, 2007 10:40 pm
Location: $9D95

Post by Halifax »

Okay this just seemed a little odd to me, so I figured I would post about it.

I ran the demo, provided in the first post, in both OpenGL. This is how it stacks up:

OGL Terrain - 1.79 ms
OGL Terrain with normals - 3.15 ms
DX Terrain - .781 ms
DX Terrain with normals - 25 ms

Now look at those differences! The OGL differences are not even noticeable really, but the DX difference is ridiculous. It seems to have something to do with the handling of drawing lines with DirectX. I don't know if you used your own, or Irrlicht's, but it is certainly crazy. I am assuming the DX's beginScene() is being called everytime a line is being drawen because that seems like that only possible cause of a drop in rendering like that.

My computer setup is the following:
866 Mhz AMD Sempron Moblie 2600+
256 MB RAM
ATI Raedon 200M Xpress

I have never had this problem before with drawing lines like this in DirectX. Any ideas?
TheQuestion = 2B || !2B
Post Reply