Alessio89
13-04-2014 11:22:53
Hi! I'm fairly new to Ogre and Bullet. I managed to get through all the basic stuff: collision shapes, gravity and so on.
Now i wanted to get my objects to collide with a proper Ogre terrain instead of a basic plane.
I followed this: http://www.ogre3d.org/addonforums/viewtopic.php?f=12&t=14583. The code compile with no errors, but my objects don't collide with the terrain.
Not only that, but i get a really weird visual effect on the terrain: http://i61.tinypic.com/2dgnabl.png, http://i62.tinypic.com/nyd9tz.png
I get this weird effect even if i don't add the terrain shape to the bullet dynamics world.
I'm going crazy, I really want to get this to work, but I need help.
I wrapped the ogre terrain class into my own terrain class. It just wraps the basic tutorial 3 terrain into a class that's easier to call.
I don't use OgreBullet, but pure Bullet. I don't use terrain paging system (I'm still not sure what it is and how it's used). Object to object collisions work fine.
This is my Terrain wrapper class:
And this is how I call the createTerrain in my physics class:
Basically a copy\paste of the thread I linked. I really need help because I'm unable to figure out this one myself.
Now i wanted to get my objects to collide with a proper Ogre terrain instead of a basic plane.
I followed this: http://www.ogre3d.org/addonforums/viewtopic.php?f=12&t=14583. The code compile with no errors, but my objects don't collide with the terrain.
Not only that, but i get a really weird visual effect on the terrain: http://i61.tinypic.com/2dgnabl.png, http://i62.tinypic.com/nyd9tz.png
I get this weird effect even if i don't add the terrain shape to the bullet dynamics world.
I'm going crazy, I really want to get this to work, but I need help.
I wrapped the ogre terrain class into my own terrain class. It just wraps the basic tutorial 3 terrain into a class that's easier to call.
I don't use OgreBullet, but pure Bullet. I don't use terrain paging system (I'm still not sure what it is and how it's used). Object to object collisions work fine.
This is my Terrain wrapper class:
namespace BFL
{
Terrain::Terrain(Ogre::SceneManager* mSceneMgr, Ogre::Light* light)
{
this->mSceneMgr = mSceneMgr;
mTerrainGlobal = OGRE_NEW Ogre::TerrainGlobalOptions();
mTerrainGroup = OGRE_NEW Ogre::TerrainGroup(mSceneMgr, Ogre::Terrain::ALIGN_X_Z, 513, 12000.0f);
mTerrainGroup->setFilenameConvention(Ogre::String("terrain"), Ogre::String(".dat"));
mTerrainGroup->setOrigin(Ogre::Vector3::ZERO);
configureTerrainDefaults(light);
for (long x = 0; x <= 0; ++x)
for (long y = 0; y <= 0; ++y)
defineTerrain(x,y);
mTerrainGroup->loadAllTerrains(true);
if (mTerrainsImported)
{
Ogre::TerrainGroup::TerrainIterator ti = mTerrainGroup->getTerrainIterator();
while(ti.hasMoreElements())
{
Ogre::Terrain* t = ti.getNext()->instance;
initBlendMaps(t);
}
}
mTerrainGroup->freeTemporaryResources();
}
void Terrain::configureTerrainDefaults(Ogre::Light* light)
{
mTerrainGlobal->setMaxPixelError(0);
mTerrainGlobal->setCompositeMapDistance(3000);
mTerrainGlobal->setLightMapDirection(light->getDerivedDirection());
mTerrainGlobal->setCompositeMapAmbient(mSceneMgr->getAmbientLight());
mTerrainGlobal->setCompositeMapDiffuse(light->getDiffuseColour());
Ogre::Terrain::ImportData& defaultimp = mTerrainGroup->getDefaultImportSettings();
defaultimp.terrainSize = 513;
defaultimp.worldSize = 12000.0f;
defaultimp.inputScale = 600; // due terrain.png is 8 bpp
defaultimp.minBatchSize = 33;
defaultimp.maxBatchSize = 65;
defaultimp.layerList.resize(3);
defaultimp.layerList[0].worldSize = 100;
defaultimp.layerList[0].textureNames.push_back("dirt_grayrocky_diffusespecular.dds");
defaultimp.layerList[0].textureNames.push_back("dirt_grayrocky_normalheight.dds");
defaultimp.layerList[1].worldSize = 30;
defaultimp.layerList[1].textureNames.push_back("grass_green-01_diffusespecular.dds");
defaultimp.layerList[1].textureNames.push_back("grass_green-01_normalheight.dds");
defaultimp.layerList[2].worldSize = 200;
defaultimp.layerList[2].textureNames.push_back("growth_weirdfungus-03_diffusespecular.dds");
defaultimp.layerList[2].textureNames.push_back("growth_weirdfungus-03_normalheight.dds");
}
void Terrain::defineTerrain(long x, long y)
{
Ogre::String filename = mTerrainGroup->generateFilename(x, y);
if (Ogre::ResourceGroupManager::getSingleton().resourceExists(mTerrainGroup->getResourceGroup(), filename))
{
mTerrainGroup->defineTerrain(x, y);
}
else
{
Ogre::Image img;
getTerrainImage(x % 2 != 0, y % 2 != 0, img);
mTerrainGroup->defineTerrain(x, y, &img);
mTerrainsImported = true;
}
}
void Terrain::getTerrainImage(bool flipX, bool flipY, Ogre::Image& img)
{
img.load("terrain.png", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
if (flipX)
img.flipAroundY();
if (flipY)
img.flipAroundX();
}
void Terrain::initBlendMaps(Ogre::Terrain* terrain)
{
Ogre::TerrainLayerBlendMap* blendMap0 = terrain->getLayerBlendMap(1);
Ogre::TerrainLayerBlendMap* blendMap1 = terrain->getLayerBlendMap(2);
Ogre::Real minHeight0 = 70;
Ogre::Real fadeDist0 = 40;
Ogre::Real minHeight1 = 70;
Ogre::Real fadeDist1 = 15;
float* pBlend0 = blendMap0->getBlendPointer();
float* pBlend1 = blendMap1->getBlendPointer();
for (Ogre::uint16 y = 0; y < terrain->getLayerBlendMapSize(); ++y)
{
for (Ogre::uint16 x = 0; x < terrain->getLayerBlendMapSize(); ++x)
{
Ogre::Real tx, ty;
blendMap0->convertImageToTerrainSpace(x, y, &tx, &ty);
Ogre::Real height = terrain->getHeightAtTerrainPosition(tx, ty);
Ogre::Real val = (height - minHeight0) / fadeDist0;
val = Ogre::Math::Clamp(val, (Ogre::Real)0, (Ogre::Real)1);
*pBlend0++ = val;
val = (height - minHeight1) / fadeDist1;
val = Ogre::Math::Clamp(val, (Ogre::Real)0, (Ogre::Real)1);
*pBlend1++ = val;
}
}
blendMap0->dirty();
blendMap1->dirty();
blendMap0->update();
blendMap1->update();
}
}
And this is how I call the createTerrain in my physics class:
void Physics::createTerrain(BFL::Terrain* t)
{
Ogre::Terrain* pTerrain = t->mTerrainGroup->getTerrain(0,0);
int terrainPageSize = pTerrain->getSize(); // Number of vertices along x/z axe
// >>> We need to mirror the ogre-height-data along the z axis first!
// This is related to how Ogre and Bullet differ in heighmap storing
float *pTerrainHeightData = pTerrain->getHeightData();
float *pTerrainHeightDataConvert = new float[terrainPageSize * terrainPageSize];
for(int i = 0; i < terrainPageSize; ++i)
{
memcpy(pTerrainHeightDataConvert + terrainPageSize * i,
pTerrainHeightData + terrainPageSize * (terrainPageSize - i - 1),
sizeof(float)*(terrainPageSize));
}
// <<< End of conversion
btHeightfieldTerrainShape* pHeightShape
= new btHeightfieldTerrainShape(terrainPageSize,
terrainPageSize,
pTerrainHeightDataConvert,
1, /* Terrains getHeightData() is already scaled perfectly */
pTerrain->getMinHeight(),
pTerrain->getMaxHeight(),
1, /* upVector is Y positive in ogre-, bullet- and our world */
PHY_FLOAT,
true);
// Scale the mesh along x/z
float unitsBetweenVertices = pTerrain->getWorldSize() / (terrainPageSize - 1);
btVector3 scaling(unitsBetweenVertices, 1, unitsBetweenVertices);
pHeightShape->setLocalScaling(scaling);
// Ogre uses DiamonSubdivision for Terrain-mesh, so bullet should use it too
pHeightShape->setUseDiamondSubdivision(true);
// Now we create a btRigidBody
btRigidBody *pBody = new btRigidBody(0.0 /* mass 0.0 means static */,
new btDefaultMotionState(),
pHeightShape);
//
Ogre::Vector3 terrainPosition = pTerrain->getPosition();
pBody->getWorldTransform().setOrigin(btVector3(terrainPosition.x,
terrainPosition.y
+ (pTerrain->getMaxHeight() - pTerrain->getMinHeight()) / 2, // Bullet's position differs from Ogre's. Ogre's y is at the bottom, bullet needs the middle if the height to be positioned right
terrainPosition.z));
pBody->getWorldTransform().setRotation(btQuaternion(Ogre::Quaternion::IDENTITY.x,
Ogre::Quaternion::IDENTITY.y,
Ogre::Quaternion::IDENTITY.z,
Ogre::Quaternion::IDENTITY.w));
dynamicsWorld->addRigidBody(pBody);
// Advanced Body configuration ->
// You can play with these or just leave the defaults:
// pBody->setFriction(1.0);
// pBody->setRestitution(0.0);
// pBody->setHitFraction(0.0);
// pBody->setDamping(0.2, 0.2);
}
Basically a copy\paste of the thread I linked. I really need help because I'm unable to figure out this one myself.