Unexpected result of Terrain collision simulation

FriedChicken

20-04-2008 16:48:28

I used Bleeding to simulate hundreds of cubes falling onto the terrain which was generated from heightmap. Although most of the cubes fall and roll on the ground nicely, just a few of them float above or buried into the terrain when coming to rest, which isn't what I want. So I wonder how to fix it.


Here is snapshot.



And here is my code :

Resources::Heightfield* createHeightfield(const std::string& heightmap)
{
Ogre::Image img;
img.load(heightmap, "General");

int w = img.getWidth();
int h = img.getHeight();

Resources::ManualHeightfield mh;
// Nothing of the below helps
//mh.setDefaultMaterial0((NxMaterialIndex)0);
//mh.setDefaultMaterial1((NxMaterialIndex)0);
// Setting both vertical extent and thickness makes the app crash (NxHeightmap creation fails)
//mh.setVerticalExtent(1.0f);
//mh.setThickness(1.0f);
mh.begin(w, h);

// Tesselation direction
bool tessltr = false;
for (int y = 0; y < h; ++y) {
for (int x = 0; x < w; ++x) {
short height = img.getColourAt(x, y, 0).r * 32767;
mh.sample(height, tessltr);
}
tessltr = !tessltr;
}

return mh.end(true);
}

...
mSceneMgr->setWorldGeometry("terrain.cfg");

mSceneMgr->setSkyDome(true, "Examples/CloudySky", 5, 8, 500);
mWorld = new World("log: html, time-controller: ogre");
mScene = mWorld->createScene("Main", mSceneMgr, "gravity: 0 -9.8 0, floor: no, renderer: ogre");

mWorld->getSDK()->getFoundationSDK().getRemoteDebugger()->connect("localhost");

Resources::Heightfield* hf = createHeightfield("terrain.png");

NxOgre::ShapeParams sp;
sp.setToDefault();
sp.mFlags |= NX_SF_VISUALIZATION;

mScene->createActor("Terrain", new Terrain(hf, float3(1500.0f, 100.0f, 1500.0f), sp, "centering: xz-above, hole-material: 65535"), Ogre::Vector3(750, -100, 750), "static: yes");

for(int i=0;i<10;i++)
{
for(int j=0;j<10;j++)
{
Body* body = mScene->createBody("cube", new Cube(10), Vector3(0, 0, 0), "model: cube.1m.mesh, scale: 10 10 10", "mass: 10");
body->setGlobalPosition(Ogre::Vector3(150*i, 300, 150*j));
}
}
...


And here is my 'terrain.cfg' file:

# The main world texture (if you wish the terrain manager to create a material for you)
WorldTexture=terrain_texture.jpg

# The detail texture (if you wish the terrain manager to create a material for you)
DetailTexture=terrain_detail.jpg

#number of times the detail texture will tile in a terrain tile
DetailTile=3

# Heightmap source
PageSource=Heightmap

# Heightmap-source specific settings
Heightmap.image=terrain.png

# If you use RAW, fill in the below too
# RAW-specific setting - size (horizontal/vertical)
#Heightmap.raw.size=513
# RAW-specific setting - bytes per pixel (1 = 8bit, 2=16bit)
#Heightmap.raw.bpp=1

# How large is a page of tiles (in vertices)? Must be (2^n)+1
PageSize=513

# How large is each tile? Must be (2^n)+1 and be smaller than PageSize
TileSize=65

# The maximum error allowed when determining which LOD to use
MaxPixelError=3

# The size of a terrain page, in world units
PageWorldX=1500
PageWorldZ=1500
# Maximum height of the terrain
MaxHeight=100

# Upper LOD limit
MaxMipMapLevel=5

#VertexNormals=yes
#VertexColors=yes
#UseTriStrips=yes

# Use vertex program to morph LODs, if available
VertexProgramMorph=yes

# The proportional distance range at which the LOD morph starts to take effect
# This is as a proportion of the distance between the current LODs effective range,
# and the effective range of the next lower LOD
LODMorphStart=0.2

# This following section is for if you want to provide your own terrain shading routine
# Note that since you define your textures within the material this makes the
# WorldTexture and DetailTexture settings redundant

# The name of the vertex program parameter you wish to bind the morph LOD factor to
# this is 0 when there is no adjustment (highest) to 1 when the morph takes it completely
# to the same position as the next lower LOD
# USE THIS IF YOU USE HIGH-LEVEL VERTEX PROGRAMS WITH LOD MORPHING
#MorphLODFactorParamName=morphFactor

# The index of the vertex program parameter you wish to bind the morph LOD factor to
# this is 0 when there is no adjustment (highest) to 1 when the morph takes it completely
# to the same position as the next lower LOD
# USE THIS IF YOU USE ASSEMBLER VERTEX PROGRAMS WITH LOD MORPHING
#MorphLODFactorParamIndex=4

# The name of the material you will define to shade the terrain
#CustomMaterialName=TestTerrainMaterial

betajaen

20-04-2008 16:57:24

If I remember correctly. The image must be horizontally flipped to work with the Ogre terrain scene manager (which also flips the image).

VerticalExtent is deprecated, and Thickness must be negative. It says in the documentation and the javadoc comment of those functions.

Also; Flour will flip the image for you, and of course save it as a xhf rather than you just converting it each time you run the program.

FriedChicken

21-04-2008 11:02:13

horizontally flips? Do you mean by that:


for (int y = 0; y < h; ++y) {
for (int x = 0; x < w; ++x) {
//short height = static_cast<short>(img.getColourAt(x, y, 0).r * 65535 - 32768);
short height = img.getColourAt(w - 1 - x, y, 0).r * 32767;
//short height = ((TerrainSceneManager*) (mRoot->getSceneManager("ST_EXTERIOR_CLOSE"))) -> getHeightAt(x*1500/513,y*1500/513);
mh.sample(height, tessltr);
}
tessltr = !tessltr;
}


But still don't work.

betajaen

21-04-2008 11:36:39

Have you tried converting the image in flour?

FriedChicken

21-04-2008 16:11:48

Yes! I have tried, but still get more weird result. My image size is 513 × 513. But when converting to .xhf , I got this:


C:\Program Files\Flour>flour heightfield in:terrain.png, out:terrain.xhf
[NxOgre] NxOgre 1.0.22 Bleeding Edge started. Working with
[NxOgre] - PhysX => 2.8.0 (280)
[NxOgre] - Ogre => 1.4.6 (Eihort)
[NxOgre] - Hardware => Probably
[NxOgre] - Platform => Windows (Debug)
[NxOgre]
leng:103088
Sqrt:185.37
Image is 227x227 px @ 16-bit.
Combined wh is 51529 (227, 227)
Byte = 206116
Size of hfs = 4
[NxOgre] PhysX SDK has stopped.


And I convert the image to raw format, then use flour. I got this:

C:\Program Files\Flour>flour heightfield in:terrain.raw, out:terrain1.xhf
[NxOgre] NxOgre 1.0.22 Bleeding Edge started. Working with
[NxOgre] - PhysX => 2.8.0 (280)
[NxOgre] - Ogre => 1.4.6 (Eihort)
[NxOgre] - Hardware => Probably
[NxOgre] - Platform => Windows (Debug)
[NxOgre]
leng:263169
Sqrt:296.181
Image is 362x362 px @ 16-bit.
Combined wh is 131044 (362, 362)
Byte = 524176
Size of hfs = 4
[NxOgre] PhysX SDK has stopped.


Flour is somehow undependable undependable, I found.

betajaen

21-04-2008 17:49:11

It has to be in a raw format, image size a power of 2 and either 8-bit or 16-bit.

FriedChicken

22-04-2008 05:28:38

My image has only one channel, so the calculated size is wrong.
After adding two more channels to it, it can be converted with correct size.

But anthother thing is that OGRE constrains the size of heightfield image to (2^n)+1.

I used the converted .xhf file in my program, but still got the wierd result -- some floating above and some burried into the terrain.


mSceneMgr->setWorldGeometry("terrain.cfg");

mWorld = new World("log: html, time-controller: ogre");
mScene = mWorld->createScene("Main", mSceneMgr, "gravity: yes, floor: no, renderer: ogre");

//mWorld->createDebugRenderer(mSceneMgr);


//Resources::Heightfield* hf = createHeightfield("terrain.png");
Resources::ResourceSystem::getSingleton()->addHeightfieldAs("file://terrain.xhf", "wave");
Resources::Heightfield* hf = Resources::ResourceSystem::getSingleton()->getHeightfield("wave");

ShapeParams sp;
sp.setToDefault();
sp.mFlags |= NX_SF_VISUALIZATION;

mScene->createActor("Terrain", new Terrain(hf, float3(1500.0f, 50.0f, 1500.0f), sp, "centering: xz-above, hole-material: 65535"), Ogre::Vector3(750, 0, 750), "static: yes");

betajaen

22-04-2008 09:34:06

Of course - the Ogre Terrain SceneManager uses images like 513x513, 257x257, I forgot.

I have some free time later this week, I'll try and come up with a solution before I release '22.

FriedChicken

22-04-2008 10:41:27

And the Terrain Scene Manager only accept heightfield image (raw) with one channel, I think.

betajaen

22-04-2008 10:45:04

I'm pretty sure it can use three channels. Besides flour would have to have a three channel image to work from, how else would it know what material's to assign to each face, and which is a hole and what isn't?

FriedChicken

23-04-2008 10:28:20

I've dived into the souce code of Flour. It seems that arbitrary image size works fine.