Not sure if this is still accurate, but here's what I've come up with:
Main stuct for btDbvt handling:
Code: Select all
struct DbvtBroadphaseFrustumCulling : btDbvt::ICollide {
btAlignedObjectArray<btCollisionObject*>* m_pCollisionObjectArray;
short int m_collisionFilterMask;
btCollisionObject* m_additionalCollisionObjectToExclude; // Unused in this demo
DbvtBroadphaseFrustumCulling(btAlignedObjectArray<btCollisionObject*>* _pArray = NULL)
: m_pCollisionObjectArray(_pArray), m_collisionFilterMask(btBroadphaseProxy::AllFilter & ~btBroadphaseProxy::SensorTrigger), m_additionalCollisionObjectToExclude(NULL)
{}
void Process(const btDbvtNode* node, btScalar depth) { Process(node); }
void Process(const btDbvtNode* leaf)
{
btBroadphaseProxy* proxy = static_cast <btBroadphaseProxy*> (leaf->data);
btCollisionObject* co = static_cast <btCollisionObject*> (proxy->m_clientObject);
if ((proxy->m_collisionFilterGroup & m_collisionFilterMask) != 0 && co != m_additionalCollisionObjectToExclude)
{
m_pCollisionObjectArray->push_back(co);
}
}
} g_DBFC;
Code: Select all
void performFrustumCulling(glm::mat4 &Mat) {
m_objectsInFrustum.resize(0); // clear() is probably slower
Frustum Frst(Mat);
btVector3 planes_n[5]{};
btScalar planes_o[5]{};
for (int i = 0; i < 5; i++)
{
planes_n[i].setX(Frst.planes[i].normal.x);
planes_n[i].setY(Frst.planes[i].normal.y);
planes_n[i].setZ(Frst.planes[i].normal.z);
planes_o[i] = Frst.planes[i].d;
}
//=======================================================
// OK, now the pure btDbvt code starts here:
//=======================================================
g_DBFC.m_pCollisionObjectArray = &m_objectsInFrustum;
g_DBFC.m_collisionFilterMask = btBroadphaseProxy::AllFilter & ~btBroadphaseProxy::SensorTrigger; // This won't display sensors...
g_DBFC.m_additionalCollisionObjectToExclude = NULL;
btDbvt::collideKDOP(broadphase_->m_sets[1].m_root, planes_n, planes_o, 5, g_DBFC);
btDbvt::collideKDOP(broadphase_->m_sets[0].m_root, planes_n, planes_o, 5, g_DBFC);
// btDbvt::collideKDOP(root,normals,offsets,count,icollide):
}
Code: Select all
class Plane
{
public:
Plane() {}
Plane(const glm::vec4& abcd)
: normal(abcd.x, abcd.y, abcd.z), d(abcd.w) {}
void normalize()
{
float mag = glm::length(normal);
normal /= mag;
d /= mag;
}
glm::vec3 normal;
float d; // distance from origin
};
class Frustum
{
public:
Frustum(const glm::mat4& mat, bool normalize_planes = true)
// create frustum from matrix
// if extracted from projection matrix only, planes will be in eye-space
// if extracted from view*projection, planes will be in world space
// if extracted from model*view*projection planes will be in model space
{
// create non-normalized clipping planes
planes[0] = Plane(mat[3] - mat[0]); // right
planes[1] = Plane(mat[3] + mat[0]); // left
planes[2] = Plane(mat[3] - mat[1]); // top
planes[3] = Plane(mat[3] + mat[1]); // bottom
planes[4] = Plane(mat[3] - mat[2]); // far
planes[5] = Plane(mat[3] + mat[2]); // near
// normalize the plane equations, if requested
if (normalize_planes)
{
planes[0].normalize();
planes[1].normalize();
planes[2].normalize();
planes[3].normalize();
planes[4].normalize();
planes[5].normalize();
}
}
Plane planes[6]; // plane normals point into frustum
};
Any suggestions as to what I might be doing wrong..?
Called every frame to compute View Projection matrix:
Code: Select all
const CameraPushConstant& GetCPC(const float& ScrWidth, const float& ScrHeight, const float& zNear, const float& zFar, const float& FOV)
{
CPC.view_proj = glm::perspective(glm::radians(FOV), ScrWidth/ScrHeight, zNear, zFar);
CPC.view_proj[1][1] *= -1;
CPC.view_proj *= View;
View_Proj = CPC.view_proj;
CPC.pos = glm::vec4(Pos.x, Pos.y, Pos.z, 0.0f);
return CPC;
}
Code: Select all
if (deltaFrame > 0.0f)
{
//if (isWorld) {
dynamicsWorld->stepSimulation(deltaFrame, 5, 1.f/66.f);
//}
SceneGraph::updateUniformBuffer(currentFrame);
//
// Frustum Culling
performFrustumCulling(SceneGraph::GetCamera().View_Proj);
if (m_objectsInFrustum.size() > 0)
//printf("Frustum %i\n", m_objectsInFrustum.size());
for (int i = 0; i < m_objectsInFrustum.size(); i++)
{
btCollisionObject* Obj = m_objectsInFrustum[i];
SceneNode* Nd = reinterpret_cast<SceneNode*>(Obj->getUserPointer());
printf("Frustum Name: %s\n", Nd->Name.c_str());
}
//
// Draw Frame
Render();
}