0
\$\begingroup\$

I've been trying for a while to implement a frustum culling method using a per-computed AABB in object space and transforming it's corners into clip space.

  bool 
  PlatformMath::OBBInFrustrum(const AABox& bounds,
                              const Matrix4& modelMatrix,
                              const Matrix4& viewMatrix,
                              const Matrix4& projMatrix) {

    //matrix to transfrom points to clip space 
    Matrix4 wvpMatrix = 
      (projMatrix * viewMatrix * modelMatrix).getTransposed();

    //transform all 8 box points to clip space 
    Vector4 obb_points[8];
    obb_points[0] = wvpMatrix * Vector4(bounds.m_min.x,
                                        bounds.m_min.y,
                                        bounds.m_min.z, 1.f);
    obb_points[1] = wvpMatrix * Vector4(bounds.m_max.x,
                                        bounds.m_min.y,
                                        bounds.m_min.z, 1.f);
    obb_points[2] = wvpMatrix * Vector4(bounds.m_min.x,
                                        bounds.m_max.y,
                                        bounds.m_min.z, 1.f);
    obb_points[3] = wvpMatrix * Vector4(bounds.m_max.x,
                                        bounds.m_max.y,
                                        bounds.m_min.z, 1.f);
    obb_points[4] = wvpMatrix * Vector4(bounds.m_min.x,
                                        bounds.m_min.y,
                                        bounds.m_max.z, 1.f);
    obb_points[5] = wvpMatrix * Vector4(bounds.m_max.x,
                                        bounds.m_min.y,
                                        bounds.m_max.z, 1.f);
    obb_points[6] = wvpMatrix * Vector4(bounds.m_min.x,
                                        bounds.m_max.y,
                                        bounds.m_max.z, 1.f);
    obb_points[7] = wvpMatrix * Vector4(bounds.m_max.x,
                                        bounds.m_max.y,
                                        bounds.m_max.z, 1.f);

    obb_points[0] *= (1 / obb_points[0].w);
    obb_points[1] *= (1 / obb_points[1].w);
    obb_points[2] *= (1 / obb_points[2].w);
    obb_points[3] *= (1 / obb_points[3].w);
    obb_points[4] *= (1 / obb_points[4].w);
    obb_points[5] *= (1 / obb_points[5].w);
    obb_points[6] *= (1 / obb_points[6].w);
    obb_points[7] *= (1 / obb_points[7].w);

    // Test z axis from 0 to 1
    {
      float maxVal = Math::NEG_INFINITY, minVal = Math::INFINITY;

      for (SIZET j = 0; j < 8; j++) {
        float proj = obb_points[j].z;

        maxVal = max(proj, maxVal);
        minVal = min(proj, minVal);
      }

      if (!rangeOverLap(minVal, maxVal, 0, 1)) {
        return false;
      }
    }

    // Test x and y axis from -1 to 1
    for (SIZET i = 0; i < 2; i++) {
      float maxVal = Math::NEG_INFINITY, minVal = Math::INFINITY;

      for (SIZET j = 0; j < 8; j++) {
        float proj = obb_points[j].comp[i];

        maxVal = max(proj, maxVal);
        minVal = min(proj, minVal);
      }

      if (!rangeOverLap(minVal, maxVal, -1, 1)) {
        return false;
      }
    }

    return true; 
  }

Using my directx graphics debugger, I know that the obb_points have been correctly calculated into homogeneous clip space (right before dividing by w). Despite this, objects that should be rendered are not. (They are out of the clip space range). What am I doing wrong?

\$\endgroup\$
  • \$\begingroup\$ Just because every corner is not in clip space range doesn't mean that the object itself is not in clip space range. Imagine moving very close to a wall, facing it straight ahead. All corners of the wall will be outside the clip space. \$\endgroup\$ – Magma Mar 17 at 14:46
  • \$\begingroup\$ That is unlikely to be the answer. I'm using a rangeOverLap() method to make sure I detect stuff even when they're right in the middle of the frustrum. \$\endgroup\$ – BioAbner J Mar 19 at 23:31

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.