Terrain with Newton 2.0 (API NewtonHeightFieldCollision)

Beauty

26-11-2009 14:16:27

The feature HeightFieldCollision (used by library function NewtonHeightFieldCollision) isn't implemented until now.
(as I see in Walabers notes in OgreNewt.h, v2.09)

Would it generally be possible to use this feature with the Terrain Scene Manager?

As I read in very old threads, this scene manager was not supported by OgreNewt 1.x.
But the paging scene manager (PLS2) could do (which is an improvement of the terrain scene manager).

On the other hand I found an old code snippet (3 years old) how to do with the Terrain Scene Manager.
viewtopic.php?p=11998#p11998

Are there plans to add the heigh field feature?
With which scene managers will it work?

baiqian

01-02-2010 02:56:44

I would like to ask the same question. As OGRE 1.7 RC1 released, would you add the heightfield collision for OGRE 1.7 new paging terrain system?

Chookaa

04-02-2010 14:31:41

i've made a basic implementation of the heightfield collision. this way is much faster and no need to serialize the collisions.
you can use raw data or create directly from the new terrain system.

in OgreNewt_Prerequisites.h add: #include<OgreTerrain.h>

dont forget to add OgreTerrain.lib or OgreTerrain_d.lib to your linker and update the include and linker paths


OgreNewt_CollisionPrimitives.h

//! HeightField Collision
/*!
builds a HeightField collision from raw data or directly from a OgreTerrain page

more info: http://newtondynamics.com/wiki/index.php5?title=NewtonCreateHeightFieldCollision
*/
class _OgreNewtExport HeightField : public OgreNewt::Collision
{
public:
HeightField(const World* world): OgreNewt::Collision(world){}

HeightField(const World* world,int width,int height,int gridsDiagonals,unsigned short *elevationMap,char *attributeMap,Ogre::Real horizontalScale,Ogre::Real verticleScale,int shapeID);

HeightField(const World* world, Ogre::Terrain *terrain, int shapeID);

~HeightField(){}

private:
/*
Used internally to create the newton Heightfield collision
*/
void createHeightFieldCollision(const World *world,int width,int height,int gridsDiagonals,unsigned short *elevationMap,char *attributeMap,Ogre::Real horizontalScale,Ogre::Real verticleScale,int shapeID);

};


OgreNewt_CollisionPrimitives.cpp

HeightField::HeightField(const OgreNewt::World *world, int width, int height, int gridsDiagonals, unsigned short *elevationMap, char *attributeMap, Ogre::Real horizontalScale, Ogre::Real verticleScale, int shapeID) : OgreNewt::Collision (world)
{
m_col = NewtonCreateHeightFieldCollision(world->getNewtonWorld(),width,height,gridsDiagonals,elevationMap,attributeMap,float(horizontalScale),float(verticleScale),shapeID);
}

HeightField::HeightField(const OgreNewt::World *world, Ogre::Terrain *terrain, int shapeID) : OgreNewt::Collision (world)
{
int width = terrain->getSize();
int height = width;
int gridsDiagonals = 0;
char *attributes;
unsigned short *elevations;

float *hData = terrain->getHeightData();
float verticleScale = 65535 / (terrain->getMaxHeight()-terrain->getMinHeight());
Ogre::Real horizontalScale = terrain->getWorldSize()/(terrain->getSize()-1);

elevations = (unsigned short*) malloc (width * height * sizeof (unsigned short));
attributes = (char*) malloc (width * height * sizeof (char));
memset (attributes, 1, width * height * sizeof (char));

//HeightData reversed and mirror on X axis
int x = 0;
for(int i=width*height-1;i>=0;i--)
{
elevations[i-width+(x*2)+1] = unsigned short(*(hData)*verticleScale);
hData++;
x++;
if(x==width)x=0;
}

createHeightFieldCollision(world,width,height,gridsDiagonals,elevations,attributes,horizontalScale,float(1/verticleScale),shapeID);

free (elevations);
free (attributes);

}
void HeightField::createHeightFieldCollision(const OgreNewt::World *world, int width, int height, int gridsDiagonals, unsigned short *elevationMap, char *attributeMap, Ogre::Real horizontalScale, Ogre::Real verticleScale, int shapeID)
{
m_col = NewtonCreateHeightFieldCollision(world->getNewtonWorld(),width,height,gridsDiagonals,elevationMap,attributeMap,float(horizontalScale),float(verticleScale),shapeID);
}



hope this helps someone :)

Edit; i almost forgot once you create a body from the collision youll need to do a setPositionOrientation on it to line it up with your terrain. just grab x and z from a AABB and leave y at 0 and it should be all good.

tod

20-02-2010 11:16:48

Thanks very much for your code, it works great :D
The only thing I changed was to pass the terrain data and terrain dimensions directly, as I didn't want it to be dependent on a single terrain type.

The body position was set like this, as it seems Ogre uses the center as the reference and Newton uses a corner.
terrain->getPosition() - Vector3(TERRAIN_WORLD_SIZE/2,0,TERRAIN_WORLD_SIZE/2)

Any change to get this added to Ogre Newt repository???

kallaspriit

24-02-2010 11:04:47

I'd love to add it, but this is 1.7 only right? I would not like to move to 1.7 before it is the stable version of Ogre.

Jack000

07-03-2010 04:28:09

wow, this is incredible. I have to do terrain in Ogre 1.7 and I wouldn't even known where to start without your code. Thanks! :D

kane7777

07-05-2010 16:17:42

Thanks very much for your code, it works great :D
The only thing I changed was to pass the terrain data and terrain dimensions directly, as I didn't want it to be dependent on a single terrain type.

The body position was set like this, as it seems Ogre uses the center as the reference and Newton uses a corner.
terrain->getPosition() - Vector3(TERRAIN_WORLD_SIZE/2,0,TERRAIN_WORLD_SIZE/2)

Any change to get this added to Ogre Newt repository???


Hi tod,

I have been trying very hard to implement and create the terrain from the Ogre 1.7 Samples, and use Heightfield collision using OgreNewt but it doesn't work. Moreover when I try to show the Newton debug lines and text, the whole program crashes. Do you mind sharing your codes? Many thanks in advance!

I would also like to ask is there any way to resize the terrain to a smaller size (the terrain from the Sample is very big)? Cause I tried manipulating the TERRAIN_WORLD_SIZE and TERRAIN_SIZE but the terrain seemed to be equally big.

tod

10-05-2010 13:03:15

I don't have the code with me right now, but I don't remember doing anything special. If I remember I'll paste some code when I get home.
The best way would be for you to show your own code/ogre log so people can give you pointers on it.

As for terrain size, you must realize size is relative, you must decide what size means. I use one ogre unit == 1m for example. It takes some time to adjust when using terrain generated from other applications that have different camera settings by default, for example my terrains looks small in Ogitor and big in my engine, it's all a matter of perception.

kane7777

14-05-2010 11:18:56

I don't have the code with me right now, but I don't remember doing anything special. If I remember I'll paste some code when I get home.
The best way would be for you to show your own code/ogre log so people can give you pointers on it.

As for terrain size, you must realize size is relative, you must decide what size means. I use one ogre unit == 1m for example. It takes some time to adjust when using terrain generated from other applications that have different camera settings by default, for example my terrains looks small in Ogitor and big in my engine, it's all a matter of perception.

Thanks for your help! :) I got the Terrain working with Heightfield collision. Will now try to make the Terrain smaller.

raven_coda

22-07-2010 13:22:00

I was able to get it to work by first making my raw data into an Image then Terrain then into Newton Like shown below

unsigned short* heightMap =(unsigned short*) malloc(width*height*sizeof(unsigned short));
char* attribMap = (char*)malloc(width*height);

build_Terrain(width, height, heightMap, attribMap);

Ogre::Image* mapImage = OGRE_NEW Ogre::Image();
mapImage->loadDynamicImage((Ogre::uchar*)heightMap, width, height, 1, Ogre::PF_L16);

Ogre::Terrain::ImportData imp;
imp.inputScale= 1000;
imp.terrainSize = width;
imp.worldSize = width-1;
imp.inputImage = mapImage;
imp.pos = Ogre::Vector3(imp.worldSize/2,0,imp.worldSize/2);
imp.layerList.resize(1);
imp.layerList[0].textureNames.push_back("terrain-texture.jpg");
imp.layerList[0].textureNames.push_back("terrain-texture-norm.jpg"); //Normal

Ogre::Terrain* mTerrain = OGRE_NEW Ogre::Terrain(sceneManager);
mTerrain->prepare(imp);
mTerrain->load();

OgreNewt::CollisionPtr mapcol = OgreNewt::CollisionPtr(new OgreNewt::CollisionPrimitives::HeightField(world, mTerrain, 200));
OgreNewt::Body* bod = new OgreNewt::Body( world, mapcol );



I also found like posted above that the Newton location and the Ogre location differed by Vector3(worldSize/2,0,worldSize/2);

Morth

28-07-2010 18:26:54

First post :)

I am a bit of an ogre newb, I am trying to have collision detecting from a map created with ogitor. Loaded with the dotscene loader.

Stealing part of your code, my code looks something like this:
Ogre::TerrainGroup::TerrainIterator terIt = pDotSceneLoader->getTerrainGroup()->getTerrainIterator();
while(terIt.hasMoreElements())
{
OgreNewt::CollisionPtr mapcol = OgreNewt::CollisionPtr(new OgreNewt::CollisionPrimitives::HeightField(nWorld, terIt.getNext()->instance,id));
id++;
newtonBodies.push_back(new OgreNewt::Body(nWorld, mapcol ));
}



No compile errors, but I am still falling through the terrain. Any suggestions?

tod

02-08-2010 16:08:53

Just enable the debugging (?) mode for Newton. It will show your bodies and you will see where your terrain actually is, how small it is, were your player is and other fun stuff like that. It's a great help :D