void Frustum::GetCornerPoints(vec *outPointArray) const { assume(outPointArray); #ifndef MATH_ENABLE_INSECURE_OPTIMIZATIONS if (!outPointArray) return; #endif if (type == PerspectiveFrustum) { float tanhfov = Tan(horizontalFov*0.5f); float tanvfov = Tan(verticalFov*0.5f); float frontPlaneHalfWidth = tanhfov*nearPlaneDistance; float frontPlaneHalfHeight = tanvfov*nearPlaneDistance; float farPlaneHalfWidth = tanhfov*farPlaneDistance; float farPlaneHalfHeight = tanvfov*farPlaneDistance; vec right = WorldRight(); vec nearCenter = pos + front * nearPlaneDistance; vec nearHalfWidth = frontPlaneHalfWidth*right; vec nearHalfHeight = frontPlaneHalfHeight*up; outPointArray[0] = nearCenter - nearHalfWidth - nearHalfHeight; outPointArray[1] = nearCenter + nearHalfWidth - nearHalfHeight; outPointArray[2] = nearCenter - nearHalfWidth + nearHalfHeight; outPointArray[3] = nearCenter + nearHalfWidth + nearHalfHeight; vec farCenter = pos + front * farPlaneDistance; vec farHalfWidth = farPlaneHalfWidth*right; vec farHalfHeight = farPlaneHalfHeight*up; outPointArray[4] = farCenter - farHalfWidth - farHalfHeight; outPointArray[5] = farCenter + farHalfWidth - farHalfHeight; outPointArray[6] = farCenter - farHalfWidth + farHalfHeight; outPointArray[7] = farCenter + farHalfWidth + farHalfHeight; } else { vec right = WorldRight(); vec nearCenter = pos + front * nearPlaneDistance; vec farCenter = pos + front * farPlaneDistance; vec halfWidth = orthographicWidth * 0.5f * right; vec halfHeight = orthographicHeight * 0.5f * up; outPointArray[0] = nearCenter - halfWidth - halfHeight; outPointArray[1] = nearCenter + halfWidth - halfHeight; outPointArray[2] = nearCenter - halfWidth + halfHeight; outPointArray[3] = nearCenter + halfWidth + halfHeight; outPointArray[4] = farCenter - halfWidth - halfHeight; outPointArray[5] = farCenter + halfWidth - halfHeight; outPointArray[6] = farCenter - halfWidth + halfHeight; outPointArray[7] = farCenter + halfWidth + halfHeight; } }
Plane Frustum::BottomPlane() const { float3 bottomSide = front - Tan(verticalFov * 0.5f) * up; float3 left = -WorldRight(); float3 bottomSideNormal = Cross(left, bottomSide).Normalized(); return Plane(pos, bottomSideNormal); }
Plane Frustum::TopPlane() const { float3 topSide = front + Tan(verticalFov * 0.5f) * up; float3 right = WorldRight(); float3 topSideNormal = Cross(right, topSide).Normalized(); return Plane(pos, topSideNormal); }
Plane Frustum::RightPlane() const { if (type == PerspectiveFrustum) { vec right = WorldRight(); right.ScaleToLength(Tan(horizontalFov*0.5f)); vec rightSide = front + right; vec rightSideNormal = ((handedness == FrustumRightHanded) ? Cross(rightSide, up) : Cross(up, rightSide)).Normalized(); return Plane(pos, rightSideNormal); } else { vec right = WorldRight(); return Plane(NearPlanePos(1.f, 0.f), right.Normalized()); } }
Plane Frustum::LeftPlane() const { if (type == PerspectiveFrustum) { vec left = -WorldRight(); left.ScaleToLength(Tan(horizontalFov*0.5f)); vec leftSide = front + left; vec leftSideNormal = ((handedness == FrustumRightHanded) ? Cross(up, leftSide) : Cross(leftSide, up)).Normalized(); return Plane(pos, leftSideNormal); } else { vec left = -WorldRight(); return Plane(NearPlanePos(-1.f, 0.f), left.Normalized()); } }
Plane Frustum::RightPlane() const { float3 right = WorldRight(); right.ScaleToLength(Tan(horizontalFov*0.5f)); float3 rightSide = front + right; float3 rightSideNormal = Cross(rightSide, up).Normalized(); return Plane(pos, rightSideNormal); }
Plane Frustum::LeftPlane() const { float3 left = -WorldRight(); left.ScaleToLength(Tan(horizontalFov*0.5f)); float3 leftSide = front + left; float3 leftSideNormal = Cross(up, leftSide).Normalized(); return Plane(pos, leftSideNormal); }
float3 Frustum::FarPlanePos(float x, float y) const { assume(type == PerspectiveFrustum || type == OrthographicFrustum); if (type == PerspectiveFrustum) { float farPlaneHalfWidth = Tan(horizontalFov*0.5f)*farPlaneDistance; float farPlaneHalfHeight = Tan(verticalFov*0.5f)*farPlaneDistance; x = x * farPlaneHalfWidth; y = y * farPlaneHalfHeight; float3 right = WorldRight(); return pos + front * farPlaneDistance + x * right + y * up; } else { float3 right = WorldRight(); return pos + front * farPlaneDistance + x * orthographicWidth * 0.5f * right + y * orthographicHeight * 0.5f * up; } }
float3 Frustum::NearPlanePos(float x, float y) const { assume(type == PerspectiveFrustum || type == OrthographicFrustum); if (type == PerspectiveFrustum) { float frontPlaneHalfWidth = Tan(horizontalFov*0.5f)*nearPlaneDistance; float frontPlaneHalfHeight = Tan(verticalFov*0.5f)*nearPlaneDistance; x = x * frontPlaneHalfWidth; // Map [-1,1] to [-width/2, width/2]. y = y * frontPlaneHalfHeight; // Map [-1,1] to [-height/2, height/2]. float3 right = WorldRight(); return pos + front * nearPlaneDistance + x * right + y * up; } else { float3 right = WorldRight(); return pos + front * nearPlaneDistance + x * orthographicWidth * 0.5f * right + y * orthographicHeight * 0.5f * up; } }
Plane Frustum::BottomPlane() const { if (type == PerspectiveFrustum) { vec bottomSide = front - Tan(verticalFov * 0.5f) * up; vec left = -WorldRight(); vec bottomSideNormal = ((handedness == FrustumRightHanded) ? Cross(left, bottomSide) : Cross(bottomSide, left)).Normalized(); return Plane(pos, bottomSideNormal); } else { return Plane(NearPlanePos(0.f, -1.f), -up); } }
Plane Frustum::TopPlane() const { if (type == PerspectiveFrustum) { vec topSide = front + Tan(verticalFov * 0.5f) * up; vec right = WorldRight(); vec topSideNormal = ((handedness == FrustumRightHanded) ? Cross(right, topSide) : Cross(topSide, right)).Normalized(); return Plane(pos, topSideNormal); } else { return Plane(NearPlanePos(0.f, 1.f), up); } }
float3x4 Frustum::WorldMatrix() const { assume(up.IsNormalized()); assume(front.IsNormalized()); float3x4 m; m.SetCol(0, WorldRight().Normalized()); m.SetCol(1, up); if (handedness == FrustumRightHanded) m.SetCol(2, -front); // In right-handed convention, the -Z axis must map towards the front vector. (so +Z maps to -front) else m.SetCol(2, front); // In left-handed convention, the +Z axis must map towards the front vector. m.SetCol(3, pos); assume(!m.HasNegativeScale()); return m; }