I am having some problems with btPairCachingGhostObject implementation.
It seems to detect my objects (heightmap to be precise) as visible even when they're way outside my view (I suspect it uses AABB instead of frustum). Here's my implementation:
Culling Physics World initialization:
Code: Select all
mCullingConfiguration = new btDefaultCollisionConfiguration();
mCullingDispatcher = new btCollisionDispatcher(mCullingConfiguration);
mCullingBroadphase = new btDbvtBroadphase();
mCullingSolver = new btSequentialImpulseConstraintSolver();
mCulling = new btDiscreteDynamicsWorld(mCullingDispatcher, mCullingBroadphase, mCullingSolver, mCullingConfiguration);
mGhostPairCallback = new btGhostPairCallback();
mCulling->getBroadphase()->getOverlappingPairCache()->setInternalGhostPairCallback(mGhostPairCallback);
Object's shape for culling (using simple box for speed instead of precise shape):
Code: Select all
if(mCullingObject)
mCulling->removeCollisionObject(mCullingObject);
mCullingShape = new btBoxShape(btVector3(mHeightmapSize * 0.5f, (Min + Max) * 0.5f, mHeightmapSize * 0.5f));
mCullingObject = new btCollisionObject();
mCullingObject->setCollisionShape(mCullingShape);
mCullingObject->setUserPointer(this);
// setup transformation, heightmaps possess no rotation
mCullingObject->setWorldTransform(btTransform(btMatrix3x3::getIdentity(), btVector3(mTransformation.col0[3], Offset, mTransformation.col2[3])));
mCulling->addCollisionObject(mCullingObject);
Construction of frustum shape:
Code: Select all
const btScalar nearPlane = gCamera.mNear;
const btScalar farPlane = gCamera.mFar;
const btScalar planesFraction = farPlane / nearPlane;
const btScalar centralPlane = (farPlane - nearPlane) * 0.5f;
btScalar left, right, bottom, top, farLeft, farRight, farBottom, farTop;
const btScalar aspect = gCamera.mAspect;
if(aspect >= 1) {
left = -aspect;
right = aspect;
bottom = -1.0;
top = 1.0;
}
else {
left = -1.0;
right = 1.0;
bottom = -aspect;
top = aspect;
}
farLeft = left * planesFraction;
farRight = right * planesFraction;
farBottom = bottom * planesFraction;
farTop = top * planesFraction;
btConvexHullShape ConvexShape;
ConvexShape.addPoint(btVector3(left, top, -nearPlane));
ConvexShape.addPoint(btVector3(right, top, -nearPlane));
ConvexShape.addPoint(btVector3(left, bottom, -nearPlane));
ConvexShape.addPoint(btVector3(right, bottom, -nearPlane));
ConvexShape.addPoint(btVector3(farLeft, farTop, -farPlane));
ConvexShape.addPoint(btVector3(farRight, farTop, -farPlane));
ConvexShape.addPoint(btVector3(farLeft, farBottom, -farPlane));
ConvexShape.addPoint(btVector3(farRight, farBottom, -farPlane));
btPairCachingGhostObject GhostObject;
GhostObject.setCollisionShape(&ConvexShape);
GhostObject.setCollisionFlags(btCollisionObject::CF_NO_CONTACT_RESPONSE);
btMatrix3x3 Rotation;
// angles might seem weird, but according to debug draw frustum's direction does match my camera's direction
Rotation.setEulerZYX(-gCamera.mRotY, -gCamera.mRotX + MyEngine::PI * 0.5f, 0);
btTransform Transform(Rotation, btVector3(gCamera.mEye.x, gCamera.mEye.y, gCamera.mEye.z));
GhostObject.setWorldTransform(Transform);
mCulling->addCollisionObject(&GhostObject);
Actual culling:
Code: Select all
mCulling->getDispatcher()->dispatchAllCollisionPairs(GhostObject.getOverlappingPairCache(), mCulling->getDispatchInfo(), mCulling->getDispatcher());
btBroadphasePairArray &CollisionPairs = GhostObject.getOverlappingPairCache()->getOverlappingPairArray();
int VisibleCount = 0;
for(int i = 0; i < CollisionPairs.size(); ++i) {
const btBroadphasePair &CollisionPair = CollisionPairs[i];
btManifoldArray ManifoldArray;
CollisionPair.m_algorithm->getAllContactManifolds(ManifoldArray);
for(int j = 0; j < ManifoldArray.size(); ++j) {
btPersistentManifold *Manifold = ManifoldArray[j];
for(int p = 0; p < Manifold->getNumContacts(); ++p) {
const btManifoldPoint &Point = Manifold->getContactPoint(p);
if(Point.getDistance() < 0.0) {
// it's always Body0; sorry for pointer mess, I just set heightmap's bool to true, so it gets rendered
((Heightmap*)((btCollisionObject*)(Manifold->getBody0()))->getUserPointer())->mVisible = true;
++VisibleCount;
}
}
}
}
Just an image:
According to
VisibleCount variable it draws all 61 heightmaps, though only 5 are visible in the image. Other heightmaps are to the left and right, in similar manner as visible ones (single heightmap is 128 units, so last ones are over 3000 units away from center). Cross on the screen is frustum's shape drawn by debug drawer.
Anyone know what I have done wrong?
Thank you in advance.