(OGRE3D) Kinematic Character Controller - Interior Triangles

Post Reply
namwenio
Posts: 2
Joined: Tue Apr 08, 2014 12:33 am

(OGRE3D) Kinematic Character Controller - Interior Triangles

Post by namwenio »

Here is my situation,

I'm using the Kinematic Controller for OGRE3D, you can also see my post here.
http://www.ogre3d.org/forums/viewtopic. ... 03#p505203

What happens is once the FPS goes above 60, it seems to start colliding with the interior terrain triangles (I THINK). It seems to push my character in weird directions when moving. Anything 60FPS or below the issue doesn't happen.
I replaced the terrain with a GAINT cube to cover the area of the terrain and the issue DID NOT HAPPEN. regardless of the FPS.

Which from my research may be caused by?
http://code.google.com/p/bullet/issues/detail?id=27

However inside of OGRE3D the terrain code I have doesn't use that trimesh type.

Code: Select all

if(!mTerrainPhysics[_id])
	{
		int terrainPageSize = _terrain->getSize();
		int terrainWorldSize = _terrain->getWorldSize();
        
		// >>> 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 = _terrain->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* terrainShape = new btHeightfieldTerrainShape(terrainPageSize, terrainPageSize, pTerrainHeightDataConvert, 1, _terrain->getMinHeight(), _terrain->getMaxHeight(), 1, PHY_FLOAT, true);


		// Scale the mesh along x/z
		float unitsBetweenVertices = _terrain->getWorldSize() / (terrainPageSize - 1);
		btVector3 scaling(unitsBetweenVertices, 1, unitsBetweenVertices);
		terrainShape->setLocalScaling(scaling);
        
		// Ogre uses DiamonSubdivision for Terrain-mesh, so bullet should use it too
		terrainShape->setUseDiamondSubdivision(true);
        
		// Now we create a btRigidBody
		btRigidBody* terrainBody = new btRigidBody(0.0, new btDefaultMotionState(), terrainShape);



		Ogre::Vector3 terrainPosition = Ogre::Vector3((terrainWorldSize - 1) * _page.x, 0, (terrainWorldSize - 1) * (_page.y * - 1)); //_terrain->getPosition();
		terrainBody->getWorldTransform().setOrigin(btVector3(terrainPosition.x, terrainPosition.y  + (_terrain->getMaxHeight() - _terrain->getMinHeight()) / 2, terrainPosition.z));
		terrainBody->getWorldTransform().setRotation(btQuaternion(Ogre::Quaternion::IDENTITY.x, Ogre::Quaternion::IDENTITY.y, Ogre::Quaternion::IDENTITY.z, Ogre::Quaternion::IDENTITY.w));
		
		// Disable - Debug Lines
		terrainBody->setCollisionFlags(terrainBody->getCollisionFlags() | btCollisionObject::CF_DISABLE_VISUALIZE_OBJECT | btCollisionObject::CF_ANISOTROPIC_FRICTION_DISABLED);

		mWorld->getBulletDynamicsWorld()->addRigidBody(terrainBody);

		mTerrainPhysics[_id] =new TerrainPhysics(terrainShape, terrainBody, pTerrainHeightDataConvert);
	}

So i'm wondering if that's even the issue? Since that bug was from 2010.
Also is there just a flag or something I not setting to fix this issue?
namwenio
Posts: 2
Joined: Tue Apr 08, 2014 12:33 am

Re: (OGRE3D) Kinematic Character Controller - Interior Trian

Post by namwenio »

Alright!!!

I figured out what was causing the weird movement, this piece of code here.

Code: Select all

bool CharacterController_Physics::recoverFromPenetration(btCollisionWorld * collisionWorld)
{
	bool penetration = false;

	collisionWorld->getDispatcher()->dispatchAllCollisionPairs(mGhostObject->getOverlappingPairCache(), collisionWorld->getDispatchInfo(), collisionWorld->getDispatcher());

	mCurrentPosition = mGhostObject->getWorldTransform().getOrigin();

	btScalar maxPen = 0;

	for (int i = 0; i < mGhostObject->getOverlappingPairCache()->getNumOverlappingPairs(); i++)
	{
		mManifoldArray.resize(0);

		btBroadphasePair* collisionPair = &mGhostObject->getOverlappingPairCache()->getOverlappingPairArray()[i];

		if (collisionPair->m_algorithm)
			collisionPair->m_algorithm->getAllContactManifolds(mManifoldArray);

		for (int j = 0; j < mManifoldArray.size(); j++)
		{
			btPersistentManifold * manifold = mManifoldArray[j];
			btScalar directionSign = manifold->getBody0() == mGhostObject ? btScalar(-1) : btScalar(1);

			for (int p = 0; p < manifold->getNumContacts(); p++)
			{
				const btManifoldPoint & pt = manifold->getContactPoint(p);

				btScalar dist = pt.getDistance();

				if (dist < 0)
				{
					maxPen = dist;
					mTouchingNormal = pt.m_normalWorldOnB * directionSign;
					penetration = true;
				}

				mCurrentPosition += pt.m_normalWorldOnB * directionSign * dist * btScalar(0.2);


			}
		}
	}

	btTransform newTrans = mGhostObject->getWorldTransform();
	newTrans.setOrigin(mCurrentPosition);
	mGhostObject->setWorldTransform(newTrans);

	return penetration;
}
What's interesting is when I remove it, everything works fine and i'm able to move around without jitter and also object collision still works.

However anything that is not a flat surface, a hill or slope I now fall through as I would expect.
How can I modify this to now cause issues on flat terrain.
Post Reply