terrain questions - ODE asks for wrong coordinates

foxbat

02-09-2006 06:13:25

Hi.
I'm currently having two terrain problems.

I'm using PLSM terrain with the terrain geometry getHeightAt() listener, and finding that the positions ODE ask for are completely wrong, compared to the actual locations of my objects. For example, I have one object positioned at say (1000,0,1000) and ODE will try to get the terrain height at (200,0,200).

My second problem, is that if my static tri mesh for the game level intersets with the terrain, the game will freeze. Is there some way to disable collision between these two geometries?

tuan kuranes

02-09-2006 08:42:13

I'm using PLSM terrain with the terrain geometry getHeightAt() listener, and finding that the positions ODE ask for are completely wrong
did you change the center parameter (last terrain geom parameter, no ?) TSM and PLSM2 doesn't have the same center, TSM is at terrain corner, PLSM2 is at terrain center.

Is there some way to disable collision between these two geometries?
- return false in the collision listener in this particular case ?
- handle yourself collision, and therefore not calling collision between terrain - static and all static- static.

foxbat

02-09-2006 12:13:53

This is really two posts in one (sorry), so I've created a new post to handle the second issue.


In the TSM terrain sample, the last parameter is given as false, and the comment says 'use true for PLSM'. So I tried using true, but had no sucess. I looked at the source, and it looks as though the the center of the heightfield is placed at the origin when using the false option. Is this how it's ment to work?

I eventually managed to have partial success, by using the option as false, and multiplying the ODE requested positions by a scaling factor. The factor I used was: (terrain width / number of width verts - 1 ).
This produces perfect results, but only in the quadrent of the terrain where x and z are positive. As soon as x or z are negative, my vehicle falls right through the terrain, and the getHeightAt isn't even called.

foxbat

05-09-2006 04:02:14

How exactly does the ODE heightfield collider decide which position vector to ask the height for? I can't find any information about how this works in the ODE documentation or wiki.

I would have thought that if an object collides in the game at (100,0,100) then it will ask for the height at (100,0,100). But the result is clearly getting scaled by some kind of factor.

tuan kuranes

05-09-2006 08:26:33

It uses the terrain width and height, and steps per heights/width.
Didn't found time yet to investigate that, until I have some, You'll have to find the right combination of all those.
But really, "center" parameter should be different between plsm2 and TSM as terrain center is not the same.

foxbat

06-09-2006 08:23:39

Thanks, I've worked it out now. I used the 'true' option, and then modified the requested coordinates as follows:


pos.x-=(num verts -1)/2
pos.x*=(terrain world width )/(num verts -1)
pos.z-=(num verts -1)/2
pos.z*=(terrain world width )/(num verts -1)

tuan kuranes

06-09-2006 08:46:11

Would be great if we can add this in OgreOde core directly !
We would replace the center parameter by an enum {TSM, PLSM}
Where did you make the change ?
in TerrainGeometry::getHeightAt() ?

syedhs

06-09-2006 17:23:28

Tuan,

Perhaps if you have the time, you can add support for PSM to use OgreODE :wink: I myself probably will be adding some basic gear support for vehicle demo, once it is done right.

tuan kuranes

06-09-2006 17:43:19

Would be easier to add support if foxbat gives some hints.
But I certainly will.

Idea would be to modify Landscape Demo to use PLSM or TSM just enabling a #define

foxbat

09-09-2006 03:51:12

Here's how I did it. In my explainations I've used the sizes for my particular terrain - 513x513 verticies, and 150000x150000 units for the entire width and height.

This is for creating the terrain collider:

// Setup PLSM heightfield
Vector3 scale = Vector3::ZERO;
int nodes_per_side = 0;

scale = Vector3(150000/512 , 7000, 150000 / 512);

_terrain = new OgreOde::TerrainGeometry(staticSpace, scale, nodes_per_side, true);// true if plsm2
_terrain->setHeightListener(this);


The scale x and z values are the maximum terrain width (150000 units) divided by the number of quads per column or row (513 verticies -1).

When OgreOde gets this scale information, it actually multiplies it back again by 512, and creates an Ode heightfield of width 150000.

If the scene manager get option function is used to get the scale automatically, the x and z values returned are actually 150000/513 . So you can see that if you pass this scale, you'll end up with inaccuracies, since (150000/513) * 512 gives you an incorrect terrain size.

The way to get around this would be to modify the OgreOde terrain geometary function to multiply by 513 if PLSM, and 512 if TSM. That would represent [number of row verts] for PLSM, and [number of row verts -1] for TSM. Maybe there could also be a flag for passing the terrain dimensions directly without having to worry about the divisions and multiplications.


That's only the first part. Some code also needs to go in the getHeightAt() function:


//this is the ODE get height callback
Real PhysicsManager::heightAt(const Vector3& position)
{
Vector3 pos = position;
pos.x-=256; //half the number of row quads
pos.x*=(150000/512); //terrain width / number of row quads
pos.z-=256;
pos.z*=(150000/512);

return terrainManager->getHeightAt(pos); //this is the PLSM get height function
}

Anonymous

21-09-2006 13:37:06

I am trying to do the same thing...
First,
int nodes_per_side = 0;
This has to be the actual nodes per side, right? Otherwise ODE asserts.
Also, if you have several pages in you terrain, scale will still be actual_page_width / (nodes_per_page-1))
, but in the heigthAt function it is the whole width of the terrain:

pos.x -= (nodes_per_page-1) * num_pages_x;
pos.x *= actual_page_width/(nodes_per_page-1)


also, the code from foxbats post will only work if you make all the constants into floats... maybe this is obvious.

Second (main) thing: my heightat callback always gets called with integer numbers, even though I know the position has a fraction part. This is driving me crazy... Can anyone explain this?

tuan kuranes

21-09-2006 15:16:08

the code from foxbats post will only work if you make all the constants into floats...
what do you mean ?

second : not always. But anyw ode heighfield code try to get surrounding nodes vertices height before trying to get real height at a point. I pointed that on ode mailing list and asked for a version that will not depend on regular grid spacing (in case of stitching, answer will be wrong sometimes.)

tuan kuranes

21-09-2006 16:05:17

@martin.enge
what do you mean ?

sorry, understood what you meant. pseudo code is lacking .f precision.

I'll try to look into foxbat suggestion (nodes and nodes-1), etc...

@foxbat: are you positive that if you remove your adjustement code in getheightat and make center flag true, it doesn't work ?
Because what you do in your code is exaclty recentering...
pos.x-=256; //half the number of row quads
pos.x*=(150000/512); //terrain width / number of row quads

is equivalent to

pos.x = (pos.x - 256) * (150000/512);

which gives
pos.x = pos.x - 150000 / 2);

and that's centering...

foxbat

22-09-2006 09:37:18

My code does have the centered flag set to true.

If the flag is set to false, the adjustment isn't required, but terrain collision will only occur in the positive quadrent (x>0, y>0). On the other three quadrents everything falls straight through.

tuan kuranes

25-09-2006 20:16:15

Ok, it's now fixed in CVS.