frustum culling

pull/4/head
cosmonaut 2020-10-19 18:22:54 -07:00
parent cb0baf0bf0
commit 8fa22260d2
4 changed files with 72 additions and 4 deletions

View File

@ -1,12 +1,23 @@
using Microsoft.Xna.Framework;
namespace Kav
{
public class Mesh
{
public MeshPart[] MeshParts { get; }
public BoundingBox BoundingBox { get; }
public Mesh(MeshPart[] meshParts)
{
MeshParts = meshParts;
BoundingBox boundingBox = new BoundingBox();
foreach (var meshPart in MeshParts)
{
boundingBox = BoundingBox.CreateMerged(boundingBox, meshPart.BoundingBox);
}
BoundingBox = boundingBox;
}
}
}

View File

@ -9,6 +9,8 @@ namespace Kav
public VertexBuffer VertexBuffer { get; }
public Triangle[] Triangles { get; }
public Vector3[] Positions { get; }
public BoundingBox BoundingBox { get; }
private Texture2D albedoTexture = null;
private Texture2D normalTexture = null;
@ -50,6 +52,8 @@ namespace Kav
IndexBuffer = indexBuffer;
Positions = positions;
Triangles = triangles;
BoundingBox = BoundingBox.CreateFromPoints(Positions);
}
}
}

View File

@ -5,6 +5,7 @@ namespace Kav
public class Model
{
public Mesh[] Meshes { get; }
public BoundingBox BoundingBox { get; }
public Color Albedo
{
@ -51,6 +52,14 @@ namespace Kav
public Model(Mesh[] meshes)
{
Meshes = meshes;
BoundingBox boundingBox = new BoundingBox();
foreach (var mesh in Meshes)
{
boundingBox = BoundingBox.CreateMerged(boundingBox, mesh.BoundingBox);
}
BoundingBox = boundingBox;
}
public void DisableAlbedoMaps()

View File

@ -240,7 +240,9 @@ namespace Kav
PerspectiveCamera camera,
IEnumerable<(Model, Matrix)> modelTransforms
) {
foreach (var (model, transform) in modelTransforms)
var boundingFrustum = new BoundingFrustum(camera.View * camera.Projection);
foreach (var (model, transform) in FrustumCull(boundingFrustum, modelTransforms))
{
foreach (var modelMesh in model.Meshes)
{
@ -312,7 +314,9 @@ namespace Kav
GraphicsDevice.DepthStencilState = DepthStencilState.Default;
GraphicsDevice.BlendState = BlendState.Opaque;
foreach (var (model, transform) in modelTransforms)
var boundingFrustum = new BoundingFrustum(camera.View * camera.Projection);
foreach (var (model, transform) in FrustumCull(boundingFrustum, modelTransforms))
{
foreach (var modelMesh in model.Meshes)
{
@ -581,7 +585,9 @@ namespace Kav
effect.LightSpaceMatrixFour = lightSpaceMatrix;
}
foreach (var (model, transform) in modelTransforms)
var boundingFrustum = new BoundingFrustum(lightSpaceMatrix);
foreach (var (model, transform) in FrustumCull(boundingFrustum, modelTransforms))
{
foreach (var modelMesh in model.Meshes)
{
@ -677,7 +683,9 @@ namespace Kav
targetUpDirection
);
foreach (var (model, transform) in modelTransforms)
var boundingFrustum = new BoundingFrustum(LinearDepthEffect.View * LinearDepthEffect.Projection);
foreach (var (model, transform) in FrustumCull(boundingFrustum, modelTransforms))
{
foreach (var modelMesh in model.Meshes)
{
@ -706,5 +714,41 @@ namespace Kav
}
}
}
private static IEnumerable<(Model, Matrix)> FrustumCull(
BoundingFrustum boundingFrustum,
IEnumerable<(Model, Matrix)> modelTransforms
) {
foreach (var modelTransform in modelTransforms)
{
var boundingBox = TransformedBoundingBox(modelTransform.Item1.BoundingBox, modelTransform.Item2);
var containment = boundingFrustum.Contains(boundingBox);
if (containment != ContainmentType.Disjoint)
{
yield return modelTransform;
}
}
}
private static BoundingBox TransformedBoundingBox(BoundingBox boundingBox, Matrix matrix)
{
var center = (boundingBox.Min + boundingBox.Max) / 2f;
var extent = (boundingBox.Max - boundingBox.Min) / 2f;
var newCenter = Vector3.Transform(center, matrix);
var newExtent = Vector3.TransformNormal(extent, AbsoluteMatrix(matrix));
return new BoundingBox(newCenter - newExtent, newCenter + newExtent);
}
private static Matrix AbsoluteMatrix(Matrix matrix)
{
return new Matrix(
Math.Abs(matrix.M11), Math.Abs(matrix.M12), Math.Abs(matrix.M13), Math.Abs(matrix.M14),
Math.Abs(matrix.M21), Math.Abs(matrix.M22), Math.Abs(matrix.M23), Math.Abs(matrix.M24),
Math.Abs(matrix.M31), Math.Abs(matrix.M32), Math.Abs(matrix.M33), Math.Abs(matrix.M34),
Math.Abs(matrix.M41), Math.Abs(matrix.M42), Math.Abs(matrix.M43), Math.Abs(matrix.M44)
);
}
}
}