Просмотр исходного кода

core: fix extracting frustum planes from MVP matrix

Daniele Bartolini 10 месяцев назад
Родитель
Сommit
39e2f79ff1
2 измененных файлов с 70 добавлено и 41 удалено
  1. 68 0
      src/core/math/frustum.cpp
  2. 2 41
      src/core/math/frustum.inl

+ 68 - 0
src/core/math/frustum.cpp

@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2012-2025 Daniele Bartolini et al.
+ * SPDX-License-Identifier: MIT
+ */
+
+#include "core/math/frustum.inl"
+
+namespace crown
+{
+namespace frustum
+{
+	void from_matrix(Frustum &f, const Matrix4x4 &m, bool homogeneous_ndc, int handedness)
+	{
+		// See: https://www8.cs.umu.se/kurser/5DV051/HT12/lab/plane_extraction.pdf
+		// Left plane.
+		f.planes[0].n.x = m.x.w + m.x.y;
+		f.planes[0].n.y = m.y.w + m.y.y;
+		f.planes[0].n.z = m.z.w + m.z.y;
+		f.planes[0].d = -(m.t.w + m.t.y);
+		plane3::normalize(f.planes[0]);
+
+		// Right plane.
+		f.planes[1].n.x = m.x.w - m.x.x;
+		f.planes[1].n.y = m.y.w - m.y.x;
+		f.planes[1].n.z = m.z.w - m.z.x;
+		f.planes[1].d = -(m.t.w - m.t.x);
+		plane3::normalize(f.planes[1]);
+
+		// Bottom plane.
+		f.planes[2].n.x = m.x.w - m.x.y;
+		f.planes[2].n.y = m.y.w - m.y.y;
+		f.planes[2].n.z = m.z.w - m.z.y;
+		f.planes[2].d = -(m.t.w - m.t.y);
+		plane3::normalize(f.planes[2]);
+
+		// Top plane.
+		f.planes[3].n.x = m.x.w + m.x.x;
+		f.planes[3].n.y = m.y.w + m.y.x;
+		f.planes[3].n.z = m.z.w + m.z.x;
+		f.planes[3].d = -(m.t.w + m.t.x);
+		plane3::normalize(f.planes[3]);
+
+		// Near plane.
+		const f32 near_x = homogeneous_ndc ? m.x.w + m.x.z : m.x.z;
+		const f32 near_y = homogeneous_ndc ? m.y.w + m.y.z : m.y.z;
+		const f32 near_z = homogeneous_ndc ? m.z.w + m.z.z : m.z.z;
+		const f32 near_d = homogeneous_ndc ? -(m.t.w + m.t.z) : -m.t.z;
+		f.planes[4].n.x = handedness == 0 ? -near_x : near_x;
+		f.planes[4].n.y = handedness == 0 ? -near_y : near_y;
+		f.planes[4].n.z = handedness == 0 ? -near_z : near_z;
+		f.planes[4].d   = handedness == 0 ? -near_d : near_d;
+		plane3::normalize(f.planes[4]);
+
+		// Far plane.
+		const f32 far_x = m.x.w - m.x.z;
+		const f32 far_y = m.y.w - m.y.z;
+		const f32 far_z = m.z.w - m.z.z;
+		const f32 far_d = -(m.t.w - m.t.z);
+		f.planes[5].n.x = handedness == 0 ? -far_x : far_x;
+		f.planes[5].n.y = handedness == 0 ? -far_y : far_y;
+		f.planes[5].n.z = handedness == 0 ? -far_z : far_z;
+		f.planes[5].d   = handedness == 0 ? -far_d : far_d;
+		plane3::normalize(f.planes[5]);
+	}
+
+} // namespace frustum
+
+} // namespace crown

+ 2 - 41
src/core/math/frustum.inl

@@ -16,8 +16,8 @@ namespace crown
 /// @ingroup Math
 namespace frustum
 {
-	/// Builds the frustum @a f from the view matrix @a m.
-	void from_matrix(Frustum &f, const Matrix4x4 &m);
+	/// Builds the frustum @a f from the matrix @a m.
+	void from_matrix(Frustum &f, const Matrix4x4 &m, bool homogeneous_ndc = false, int handedness = 1);
 
 	/// Returns whether the frustum @a f contains the point @a p.
 	bool contains_point(const Frustum &f, const Vector3 &p);
@@ -41,45 +41,6 @@ namespace frustum
 
 namespace frustum
 {
-	inline void from_matrix(Frustum &f, const Matrix4x4 &m)
-	{
-		f.planes[0].n.x = m.x.w + m.x.y;
-		f.planes[0].n.y = m.y.w + m.y.y;
-		f.planes[0].n.z = m.z.w + m.z.y;
-		f.planes[0].d = -(m.t.w + m.t.y);
-		plane3::normalize(f.planes[0]);
-
-		f.planes[1].n.x = m.x.w - m.x.x;
-		f.planes[1].n.y = m.y.w - m.y.x;
-		f.planes[1].n.z = m.z.w - m.z.x;
-		f.planes[1].d = -(m.t.w - m.t.x);
-		plane3::normalize(f.planes[1]);
-
-		f.planes[2].n.x = m.x.w - m.x.y;
-		f.planes[2].n.y = m.y.w - m.y.y;
-		f.planes[2].n.z = m.z.w - m.z.y;
-		f.planes[2].d = -(m.t.w - m.t.y);
-		plane3::normalize(f.planes[2]);
-
-		f.planes[3].n.x = m.x.w + m.x.x;
-		f.planes[3].n.y = m.y.w + m.y.x;
-		f.planes[3].n.z = m.z.w + m.z.x;
-		f.planes[3].d = -(m.t.w + m.t.x);
-		plane3::normalize(f.planes[3]);
-
-		f.planes[4].n.x = m.x.z;
-		f.planes[4].n.y = m.y.z;
-		f.planes[4].n.z = m.z.z;
-		f.planes[4].d = -(m.t.z);
-		plane3::normalize(f.planes[4]);
-
-		f.planes[5].n.x = m.x.w - m.x.z;
-		f.planes[5].n.y = m.y.w - m.y.z;
-		f.planes[5].n.z = m.z.w - m.z.z;
-		f.planes[5].d = -(m.t.w - m.t.z);
-		plane3::normalize(f.planes[5]);
-	}
-
 	inline bool contains_point(const Frustum &f, const Vector3 &p)
 	{
 		for (u32 ii = 0; ii < 6; ++ii) {