Terrain collision for 1.7 OgreTerrain

SFCBias

06-09-2010 03:48:43

I tried to make this as portable as possible so that all you have to do is pass the OgreTerrain you're using. Sorry it took me so long to post this for those who were waiting.

void createHieghtFieldCollision(
Terrain* terrain, int* shapeIdArray,OgreNewt::World* world)
{
NewtonWorld* WORLD = world->getNewtonWorld();
int width, height;
width = height = terrain->getSize() - 1;
int size = width * height;
float* array32 = new float[size];
char* attributes;

// find the min am max in the map
float min = terrain->getMinHeight();
float max = terrain->getMaxHeight();

// crate the new map
unsigned short* elevation = new unsigned short[size];
attributes = (char*) malloc(width * width * sizeof(char));
//float scale = max - min;
float scale = (fabs(max - min) > 1.0e-1f) ? 1.0 : 66535.0f
/ (max - min);
// nwo populate the elavation map
Ogre::Real horizontalScale = (terrain->getWorldSize()
/ (terrain->getSize() - 2));

int x = 0;
for (int i = 0; i < width; i++)
{
for (int k = 0; k < height; k++)
{
array32[x] = terrain->getHeightAtPoint(i, k);
x++;
}
}

for (int i = 0; i < size; i++)
{
elevation[i] = (unsigned short) ((array32[i] - min) * scale);
}

memset(attributes, 1, width * height * sizeof(char));
if (shapeIdArray)
{
for (int i = 0; i < width * height; i++)
{
attributes[i] = char(shapeIdArray[0]);
}
}

float verticalScale = (1.0f / (scale));

NewtonCollision* collision = NewtonCreateHeightFieldCollision(WORLD, width, height, 1,
elevation, attributes, horizontalScale, verticalScale, 2);

delete[] elevation;
delete[] array32;
free(attributes);

createRigidBody(WORLD,
collision, terrain);

NewtonReleaseCollision(WORLD, collision);
}

void createRigidBody(NewtonWorld* world, NewtonCollision* m_col,
Terrain* terrain)
{
NewtonBody* body = NewtonCreateBody(mWorld, m_col);
SceneNode * sn = GETSCENEMANAGER->getRootSceneNode();

Ogre::Real horizontalScale = terrain->getWorldSize()
/ (terrain->getSize() - 2);

float matrix[16];
Quaternion rot(Degree(90), Vector3(0, 1, 0));
rot = rot * sn->getOrientation();

OgreNewt::Converters::QuatPosToMatrix(rot, Vector3::ZERO, &matrix[0]);

int width = terrain->getSize() - 1;
int height = terrain->getSize() - 1;

float x = width / 2 * horizontalScale;
float z = height / 2 * horizontalScale;
float min = terrain->getMinHeight();
matrix[12] -= x;
matrix[13] += min;
matrix[14] += z;

NewtonBodySetMatrix(body, &matrix[0]);

NewtonBodySetUserData(body, sn);
#ifdef DEBUG
/*ManualObject* object = new ManualObject("Terrain");

object->begin("BaseWhiteNoLighting", RenderOperation::OT_LINE_LIST);
object->colour(ColourValue::White);
NewtonCollisionForEachPolygonDo(m_col, &matrix[0], newtonPerPoly,
object);
object->end();

GETSCENEMANAGER->getRootSceneNode()->createChildSceneNode()->attachObject(
object);*/
#endif
}



You should be able to just add these two functions to your code without any problems and make sure you call createHeightfieldCollision somewhere after your world has been created and that should be it.

Ok so i think this should do what you need. Again this is almost straight out of my own code so theres some stuff that may not compile so the things in the #DEFINE block can all be removed its only for debug purposes. and i'm certain ALL of the OgreNewt functions i put in are right but i may have some namespace issues. Last... any thing with the qualifiers "PhysX" or "PhysX::whatever" can be removed. hope this helps. Reply if there are any problems.