[SOLVED]HieghtField Collision

Report any bugs here and we'll post fixes

Moderators: Sascha Willems, Thomas

Re: HieghtField Collision

Postby SFCBias » Wed Jul 28, 2010 1:01 pm

This what i came up with, i beleive I'm on the right track but needless to say it doesn't work as expected. I did find a function in Ogre that will return the Height of the terrain at any given X,Y coords so I'm no longer using the .raw file for them.

Code: Select all
void PhysX::ObjectParser::createHieghtFieldCollision(String& filename,
         Terrain* terrain, int* shapeIdArray)
   {
      int width;
      int height;
      char* attributes;
      uint16* HeightMap;
      FILE* file;

#define CELL_SIZE            24.0f
#define ELEVATION_SCALE         512.0f
#define TEXTURE_SCALE         (1.0f / 16.0f)
#define ELEVATION_SCALE_INV      (1.0f / ELEVATION_SCALE)

      file = fopen(filename.c_str(), "r");
      assert (file && "File could not be found.");

      width = 512;
      height = width;

      // load the data

      HeightMap = (short unsigned int*) malloc((width* height) * sizeof(uint16));
      attributes = (char*) malloc(width * width * sizeof(char));

      int c = 0;
      for(int Y = 0; Y < height - 1 ; Y++)
      {
         for(int X = 0; X < width - 1; X++)
         {
            HeightMap[c] = (uint16)terrain->getHeightAtPoint(X,Y);
            DataLog.LogMessage(LogDataManager::MT_DEFAULT,"HeightAt %i,%i: %i",X,Y,HeightMap[c]);
            c++;
         }

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

      collision = NewtonCreateHeightFieldCollision(WORLD, width, height, 0,
            HeightMap, attributes, CELL_SIZE, ELEVATION_SCALE_INV, 0);
      free(HeightMap);
      free(attributes);
      fclose(file);

      PhysX::getSingleton().createRigidBody(PhysX::getSingleton().getWorld(),
            NULL, collision, 0.0f, "GroundMateruint16*ial", terrain);

      NewtonReleaseCollision(PhysX::getSingleton().getWorld(), collision);
SFCBias
 
Posts: 54
Joined: Tue Jun 22, 2010 12:40 am
Location: Hephzibah,GA

Re: HieghtField Collision

Postby Julio Jerez » Wed Jul 28, 2010 1:48 pm

Is i sno that simpel you cna no use the same const and expect the terrain to wiork
define CELL_SIZE 24.0f
#define ELEVATION_SCALE 512.0f
#define TEXTURE_SCALE (1.0f / 16.0f)
#define ELEVATION_SCALE_INV (1.0f / ELEVATION_SCALE)


for ELEVATION_SCALE basically you need to fin teh min and max high or you high map, and us that you slale the point,

ELEVATION_SCALE = (max_terrainpoint - min_terrainPoint)
the for each point is the map

for(int Y = 0; Y < height - 1 ; Y++)
{
for(int X = 0; X < width - 1; X++)
{
HeightMap[c] = (uint16) (terrain->getHeightAtPoint(X,Y) - min_terrainPoint) * 65536.0f / ELEVATION_SCALE;
c++;
}


then CELL_SIZE is no 24 in hwo much a cell in teh map represent in units.
do people in Ogre do terrain stuff routinely, this si quite trivial?
Julio Jerez
Moderator
Moderator
 
Posts: 12249
Joined: Sun Sep 14, 2003 2:18 pm
Location: Los Angeles

Re: HieghtField Collision

Postby Julio Jerez » Fri Jul 30, 2010 1:39 pm

I am a litle confuse, does OgerNewt have a demo using hightfiled collision? does that wokr for you?

all you nee to do is to conver teh array of 32 bit float into an array of 16 float,
using the Min and Max of the original 32 bit map as scale, here is some pseudo code to do that.
Code: Select all
int size = width * hight;
float* array32;

// find the min am max in the map
float min = 1e10;
float max = -1e10;
for (i = 0; i < size; i ++) {
   min = min < array32[i] ? min : array32[i];
   max = max > array32[i] ? max : array32[i];
}

// crate the new map
unsigned short* elevation = new [size];
float scale = max - min;
if (scale > 0.0f) {
   scale = 1.0f / scale;
} else {
   scale = 1.0f;
}
// nwo populate the elavation map
for (i = 0; i < size; i ++) {
   elevation = unsigned short (65535.0f * (array32 - min) * scale);
}
Julio Jerez
Moderator
Moderator
 
Posts: 12249
Joined: Sun Sep 14, 2003 2:18 pm
Location: Los Angeles

Re: HieghtField Collision

Postby SFCBias » Sun Aug 01, 2010 9:54 pm

No OgreNewt does not have a sample and the provided heightfield collision doesn't work. I don't believe that was implemented by walaber either. Also there is a compile error with your code
Code: Select all
elevation = (unsigned short) (65535.0f * (array32 - min) * scale);
with the error
Code: Select all
invalid operands of types ‘float*’ and ‘float’ to binary ‘operator-’
Im only asking you for a fix so nothing changes.

This is the code i used to try and fix the error:
Code: Select all
   void PhysX::ObjectParser::createHieghtFieldCollision(String& filename,
         Terrain* terrain, int* shapeIdArray)
   {
      int width,height;
      width = height = terrain->getSize();
      int size = width * height;
      float* array32 = terrain->getHeightData();
      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;
      if (scale > 0.0f)
      {
         scale = 1.0f / scale;
      }
      else
      {
         scale = 1.0f;
      }
      // nwo populate the elavation map
      for (int i = 0; i < size; i++)
      {
         elevation[i] = (unsigned short) (65535.0f * (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]);
            }
         }

         collision = NewtonCreateHeightFieldCollision (WORLD, width, height, 0, elevation, attributes, 12, scale, 0);
         free (elevation);
         free (attributes);

      PhysX::getSingleton().createRigidBody(PhysX::getSingleton().getWorld(),
            NULL, collision, 0.0f, "GroundMaterial", terrain);

      NewtonReleaseCollision(PhysX::getSingleton().getWorld(), collision);
   }


Also i think it's necessary to note that there are dramatic drops in certain points in the map. if that makes any difference.
SFCBias
 
Posts: 54
Joined: Tue Jun 22, 2010 12:40 am
Location: Hephzibah,GA

Re: HieghtField Collision

Postby Julio Jerez » Sun Aug 01, 2010 11:07 pm

yes you fix is ok, I did not test the code, I wrote it the forum editor.
what do you mean dramatic drops?
Julio Jerez
Moderator
Moderator
 
Posts: 12249
Joined: Sun Sep 14, 2003 2:18 pm
Location: Los Angeles

Re: HieghtField Collision

Postby SFCBias » Sun Aug 01, 2010 11:16 pm

When i test you're code, the collison happens slightly under the graphical terrain but only in some areas. In the rest of the terrain there is no collision. Im attempting to create a visual representation of the collision SO i should have that soon. The dramatic drops don't seem relevent anymore because i changed the heightmap that i was using and it made no difference.
Last edited by SFCBias on Sun Aug 01, 2010 11:37 pm, edited 2 times in total.
SFCBias
 
Posts: 54
Joined: Tue Jun 22, 2010 12:40 am
Location: Hephzibah,GA

Re: HieghtField Collision

Postby Julio Jerez » Sun Aug 01, 2010 11:22 pm

I can not believe it is amosl tow weeks and you do no get that, it is not that difficult.
can you post the funtion you are using to do this? I think is better if I see what you are doing.

also do you have debug display so that you can see how the terrain looks like?
Julio Jerez
Moderator
Moderator
 
Posts: 12249
Joined: Sun Sep 14, 2003 2:18 pm
Location: Los Angeles

Re: HieghtField Collision

Postby SFCBias » Sun Aug 01, 2010 11:40 pm

Image

Uploaded with ImageShack.us

This is the function i use to create the collision.
Code: Select all
void PhysX::ObjectParser::createHieghtFieldCollision(String& filename,
         Terrain* terrain, int* shapeIdArray)
   {
      int width, height;
      width = height = terrain->getSize();
      int size = width * height;
      float* array32 = terrain->getHeightData();
      char* attributes;

#define CELL_SIZE            12.0f
#define TEXTURE_SCALE         (1.0f / 16.0f)

      // 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;
      if (scale > 0.0f)
      {
         scale = 1.0f / scale;
      }
      else
      {
         scale = 1.0f;
      }
      // nwo populate the elavation map

      for (int i = 0; i < size; i++)
      {
         elevation[i] = (unsigned short) (65535.0f * (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]);
         }
      }

      collision = NewtonCreateHeightFieldCollision(WORLD, width, height, 1,
            elevation, attributes, CELL_SIZE, scale, 0);

      free(elevation);
      free(attributes);

      PhysX::getSingleton().createRigidBody(PhysX::getSingleton().getWorld(),
            NULL, collision, 0.0f, "GroundMaterial", terrain);


      NewtonReleaseCollision(PhysX::getSingleton().getWorld(), collision);
   }


This is the function that i use to make the rigid body:
Code: Select all
   void PhysX::createRigidBody(NewtonWorld* world, SceneNode* sourceNode,
         NewtonCollision* m_col, dFloat mass, const String& materialId,
         Terrain* terrain)
   {
      NewtonBody* body = NewtonCreateBody(mWorld, m_col);

      float matrix[16];
      if (sourceNode != NULL)
      {
         PhysXTools::QuatPosToMatrix(sourceNode->getOrientation(),
               sourceNode->getPosition(), &matrix[0]);
         _matManager->assignMaterial(body, materialId);
      }
      else
      {
         SceneNode* sn = SceneHandler::getSingleton().getSceneManager(
               "Octree1")->getRootSceneNode();
         PhysXTools::QuatPosToMatrix(sn->getOrientation(),
               sn->getPosition(), &matrix[0]);
         _matManager->assignMaterial(body, "GroundMaterial");
      }

      NewtonBodySetMatrix(body, &matrix[0]);

      Ogre::Vector3 inertia, offset;
      NewtonConvexCollisionCalculateInertialMatrix(m_col, &inertia[0],
            &offset[0]);

      NewtonBodySetCentreOfMass(body, &offset[0]);
      NewtonBodySetMassMatrix(body, mass, mass * inertia.x, mass * inertia.y,
            mass * inertia.z);
      NewtonBodySetForceAndTorqueCallback(body, globalForceCallback);
      NewtonBodySetTransformCallback(body, globalTransformCallback);

      NewtonBodySetUserData(body, sourceNode);
      DataLog.LogMessage(LogDataManager::MT_OBJ_CREATED,
            "NewtonBody created at: %p", body);

   }
SFCBias
 
Posts: 54
Joined: Tue Jun 22, 2010 12:40 am
Location: Hephzibah,GA

Re: HieghtField Collision

Postby Julio Jerez » Mon Aug 02, 2010 12:19 am

why do you use #define CELL_SIZE 12.0f
is the size of each grad 12 meters by 12 meters? it looks to me that the shape is bigger than the mesh


also I think your scale should be
s = scale / 65535.0f;
collision = NewtonCreateHeightFieldCollision(WORLD, width, height, 1, elevation, attributes, CELL_SIZE, s, 0);

hightfield are static body you should not use these functions
NewtonConvexCollisionCalculateInertialMatrix(m_col, &inertia[0], &offset[0]);
NewtonBodySetCentreOfMass(body, &offset[0]);
NewtonBodySetMassMatrix(body, mass, mass * inertia.x, mass * inertia.y, mass * inertia.z);

if the terrain matrix does no consider the minimu high, then yo should offset the body matix by tha value.
float matrix[16];
PhysXTools::QuatPosToMatrix(sourceNode->getOrientation(), sourceNode->getPosition(), &matrix[0]); _matManager->assignMaterial(body, materialId);

maytrox.pist .y += min

do that an dthe only thing you are missing is the horizontal scale of each a cell in meter,
you are passing 12 but better make sure that is correct. maybe ther is a fuintion to read tha form the graphic Terrain too,

teh you nee to impelne dbig display to make sur ethe digonal is aligned teh same way in teh the terrain does.
there are only two value diagnal from lower left to upper right of a cell, of digonal form teh upper left to teh lower right of a cell.
Julio Jerez
Moderator
Moderator
 
Posts: 12249
Joined: Sun Sep 14, 2003 2:18 pm
Location: Los Angeles

Re: HieghtField Collision

Postby SFCBias » Mon Aug 02, 2010 3:03 am

Well one thing, the collision isn't lined up with the terrain i found an equation for the cell size and im playing with numbers for the vertical scale. but i obviously don't understand so you don't have to worry about it any more.
SFCBias
 
Posts: 54
Joined: Tue Jun 22, 2010 12:40 am
Location: Hephzibah,GA

Re: HieghtField Collision

Postby Julio Jerez » Mon Aug 02, 2010 8:55 am

do no worrie bing lien up, ther are so many problems,
It si not that difficult to make the collision to the map

can you make a simple terrain that is flat and 2 cell by 2 cell?
the take a crenn shot of how it look, tha will clarify more what is going on.
Julio Jerez
Moderator
Moderator
 
Posts: 12249
Joined: Sun Sep 14, 2003 2:18 pm
Location: Los Angeles

Re: HieghtField Collision

Postby SFCBias » Mon Aug 02, 2010 10:05 am

Here you are. I found out that Ogre terrain quad size (cells) can be calculated by terrainWorldSize /( terrainSize - 1)

Image

Uploaded with ImageShack.us

Also where you see the terrain and the collision overlap is the size of on cell
SFCBias
 
Posts: 54
Joined: Tue Jun 22, 2010 12:40 am
Location: Hephzibah,GA

Re: HieghtField Collision

Postby Julio Jerez » Mon Aug 02, 2010 1:44 pm

Ok let us do one problem at a time.

That picture indicate that the Terrain Origin in Ogre is at the center of the hightmap, while in newton in teh lower left corner of teh bit map.
I think all you need to do is translate the origin of the body by distan to teh center of the bitmap
in you function tah crate teh body it is something like this

Code: Select all
 void PhysX::createRigidBody(NewtonWorld* world, SceneNode* sourceNode,
         NewtonCollision* m_col, dFloat mass, const String& materialId,
         Terrain* terrain)
   {
      NewtonBody* body = NewtonCreateBody(mWorld, m_col);

      float matrix[16];
      if (sourceNode != NULL)
      {
         PhysXTools::QuatPosToMatrix(sourceNode->getOrientation(),
               sourceNode->getPosition(), &matrix[0]);
         _matManager->assignMaterial(body, materialId);
      }
      else
      {
         SceneNode* sn = SceneHandler::getSingleton().getSceneManager(
               "Octree1")->getRootSceneNode();
         PhysXTools::QuatPosToMatrix(sn->getOrientation(),
               sn->getPosition(), &matrix[0]);
         _matManager->assignMaterial(body, "GroundMaterial");
      }

             // here trans late the origin of the body by the diatne to teh center of the map
            x =   width / 2 * OgreTerrainGetCellSize();
            z =   height / 2 * OgreTerrainGetCellSize();
             matrix[3 * 4 + 0] -= x;
             matrix[3 * 4 + 2] -= z;


      NewtonBodySetMatrix(body, &matrix[0]);


Try that and see if the collision match the visual mesh.
Julio Jerez
Moderator
Moderator
 
Posts: 12249
Joined: Sun Sep 14, 2003 2:18 pm
Location: Los Angeles

Re: HieghtField Collision

Postby SFCBias » Mon Aug 02, 2010 3:49 pm

I'm still trying different things to be sure that my code isn't the problem but the debug display's position doesn't move from you're code. (for the DD i'm using OgreNewt's method)
SFCBias
 
Posts: 54
Joined: Tue Jun 22, 2010 12:40 am
Location: Hephzibah,GA

Re: HieghtField Collision

Postby Julio Jerez » Mon Aug 02, 2010 4:08 pm

if it does no move is because
x = width / 2 * OgreTerrainGetCellSize();
z = height / 2 * OgreTerrainGetCellSize();

are zero, chek that x and z are actule the coordinate of the center for the Hieghtfield.
Julio Jerez
Moderator
Moderator
 
Posts: 12249
Joined: Sun Sep 14, 2003 2:18 pm
Location: Los Angeles

PreviousNext

Return to Bugs and Fixes

Who is online

Users browsing this forum: No registered users and 18 guests