public void Constructor_MinMax() { var actual = new AABBf(new float3(0, 0, 0), new float3(1, 1, 1)); Assert.Equal(new float3(0, 0, 0), actual.min); Assert.Equal(new float3(1, 1, 1), actual.max); }
private void UserSideFrustumCulling(IList <SceneNode> nodeChildren, Frustum frustum) { foreach (SceneNode node in nodeChildren) { if (node.Name == "Frustum" || node.Name.Contains("Cam")) { continue; } Mesh mesh = node.GetComponent <Mesh>(); if (mesh != null) { //We only perform the test for meshes that do have a calculated - non-zero sized - bounding box. if (mesh.BoundingBox.Size != float3.Zero) { AABBf worldSpaceBoundingBox = node.GetComponent <Transform>().Matrix() * mesh.BoundingBox; if (!worldSpaceBoundingBox.InsideOrIntersectingFrustum(frustum)) { mesh.Active = false; } else { mesh.Active = true; } } } if (node.Children.Count != 0) { UserSideFrustumCulling(node.Children, frustum); } } }
public void Size_Is1() { var aabbf = new AABBf(new float3(0, 0, 0), new float3(1, 1, 1)); var actual = aabbf.Size; Assert.Equal(new float3(1, 1, 1), actual); }
public void Center_Is1() { var aabbf = new AABBf(new float3(0, 0, 0), new float3(2, 2, 2)); var actual = aabbf.Center; Assert.Equal(new float3(1, 1, 1), actual); }
public static IEnumerable <object[]> GetUnion() { var a = new AABBf(new float3(0, 0, 0), new float3(1, 1, 1)); var b = new AABBf(new float3(1, 1, 1), new float3(2, 2, 2)); yield return(new object[] { a, b, new AABBf(new float3(0, 0, 0), new float3(2, 2, 2)) }); yield return(new object[] { b, a, new AABBf(new float3(0, 0, 0), new float3(2, 2, 2)) }); }
public void IntersectsAABBf_IsTrue() { var aabb = new AABBf(new float3(0, 0, -1), new float3(6, 1, 1)); var plane = new PlaneF() { A = 1, B = 0, C = 0, D = 5 }; Assert.True(plane.Intersects(aabb)); }
public void InsideOrIntersectingOBBf_IsFalse() { var aabb = new AABBf(new float3(6, 0, 0), new float3(7, 1, 1)); var plane = new PlaneF() { A = 1, B = 0, C = 0, D = 5 }; Assert.False(plane.InsideOrIntersecting(aabb)); }
public void ComputeCoverage(RenderableMesh mesh, AABBf meshBounds, out long sideCoverage, out long topCoverage) { float longestSide = Math.Max(Math.Max(meshBounds.MaxX - meshBounds.MinX, meshBounds.MaxY - meshBounds.MinY), meshBounds.MaxZ - meshBounds.MinZ); float farPlane = longestSide * 2.0f; float x = (meshBounds.MinX + meshBounds.MaxX) / 2.0f; float y = meshBounds.MinY; float z = (meshBounds.MinZ + meshBounds.MaxZ) / 2.0f; Vector3 origin = new Vector3(x, y, z); Vector3 up = Vector3.UnitY; Vector3 look = -Vector3.UnitX; for (int i = 0; i < m_occlusionQueries.Length; i++) { Matrix4 orbit = Matrix4.CreateRotationY(MathHelper.DegreesToRadians((365 / 64.0f) * i)); Matrix4 projection = Matrix4.CreatePerspectiveFieldOfView(MathHelper.DegreesToRadians(90), 1.0f, 0.1f, farPlane); Matrix4 view = Matrix4.LookAt(origin + Vector3.Transform(new Vector3(longestSide, 0, 0), orbit), origin, Vector3.TransformNormal(up, orbit)); RenderView(view, projection, mesh, m_occlusionQueries[i]); //Bitmap bmp = GLEx.BitmapColorBuffer(m_pixelWidth, m_pixelHeight); //bmp.Save("C:\\test_" + i + ".bmp"); } // Gather all the occlusion queries we performed long[] m_occlusionQueryResults = new long[64]; for (int i = 0; i < m_occlusionQueries.Length; i++) { int ready = 0; while (ready == 0) { GL.GetQueryObject(m_occlusionQueries[i], GetQueryObjectParam.QueryResultAvailable, out ready); } GL.GetQueryObject(m_occlusionQueries[i], GetQueryObjectParam.QueryResult, out m_occlusionQueryResults[i]); } // Reset the current frame buffer. GL.Ext.BindFramebuffer(FramebufferTarget.FramebufferExt, 0); long totalSidePixels = 0; long totalTopPixels = 0; for (int i = 0; i < m_occlusionQueries.Length; i++) { totalSidePixels += m_occlusionQueryResults[i]; } sideCoverage = totalSidePixels; topCoverage = totalTopPixels; }
public void OnMesh(Mesh mesh) { var box = _state.ModelView * mesh.BoundingBox; if (!_boxValid) { _result = box; _boxValid = true; } else { _result = AABBf.Union(_result, box); } }
public static IEnumerable <object[]> GetTransform() { var a = new AABBf(new float3(0, 0, 0), new float3(1, 1, 1)); var xRot = new float4x4(1, 0, 0, 0, 0, 0, -1, 0, 0, 1, 0, 0, 0, 0, 0, 1); var yRot = new float4x4(0, 0, 1, 0, 0, 1, 0, 0, -1, 0, 0, 0, 0, 0, 0, 1); var zRot = new float4x4(0, -1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); yield return(new object[] { xRot, a, new AABBf(new float3(0, -1, 0), new float3(1, 0, 1)) }); yield return(new object[] { yRot, a, new AABBf(new float3(0, 0, -1), new float3(1, 1, 0)) }); yield return(new object[] { zRot, a, new AABBf(new float3(-1, 0, 0), new float3(0, 1, 1)) }); }
public void OnMesh(MeshComponent meshComponent) { AABBf box = _state.ModelView * meshComponent.BoundingBox; if (!_boxValid) { _result = box; _boxValid = true; } else { _result = AABBf.Union((AABBf)_result, box); } }
/// <summary> /// Creates a orthographic projection matrix from a bounding box. This matrix is named "crop" matrix in the literature. /// </summary> /// <param name="aabb">The bounding box.</param> /// <returns></returns> public static float4x4 CreateOrthographic(AABBf aabb) { aabb.min.z = 0; var scaleX = 2.0f / (aabb.max.x - aabb.min.x); var scaleY = 2.0f / (aabb.max.y - aabb.min.y); var offsetX = -0.5f * (aabb.max.x + aabb.min.x) * scaleX; var offsetY = -0.5f * (aabb.max.y + aabb.min.y) * scaleY; var scaleZ = 1.0f / (aabb.max.z - aabb.min.z); var offsetZ = -aabb.min.z * scaleZ; return(new float4x4(scaleX, 0, 0, offsetX, 0, scaleY, 0, offsetY, 0, 0, scaleZ, offsetZ, 0, 0, 0, 1)); }
/// <summary> /// Calculates the axis aligned bounding box in light space. /// </summary> /// <param name="lightView">The view matrix of the light.</param> /// <param name="frustumCorners">The world space frustum corners of a cascade.</param> /// <returns></returns> private static AABBf FrustumAABBLightSpace(float4x4 lightView, float3[] frustumCorners) { for (int i = 0; i < frustumCorners.Length; i++) { var corner = frustumCorners[i]; corner = lightView * corner; //light space frustum corners frustumCorners[i] = corner; } var lightSpaceFrustumAABB = new AABBf(frustumCorners[0], frustumCorners[0]); foreach (var p in frustumCorners) { lightSpaceFrustumAABB |= p; } return(lightSpaceFrustumAABB); }
public static Mesh BuildMesh(AABBf aabb, Vector3 delta_p, List<AABBi> boxList) { Mesh mesh = BuildMesh(boxList); Vector4 aabb_min = new Vector4(aabb.MinX, aabb.MinY, aabb.MinZ, 0); Vector4 delta_p4 = new Vector4(delta_p, 1); for (int i = 0; i < mesh.Vertices.Length; i++) { mesh.Vertices[i] = aabb_min + Vector4.Multiply(mesh.Vertices[i], delta_p4); } return mesh; }
public VoxelizingOctreeCell(VoxelizingOctree tree, VoxelizingOctreeCell root, Vector3 center, float length, int level) { Tree = tree; Root = root; Center = center; Length = length; Level = level; float half_length = length / 2.0f; Bounds = new AABBf(); Bounds.MinX = center.X - half_length; Bounds.MinY = center.Y - half_length; Bounds.MinZ = center.Z - half_length; Bounds.MaxX = center.X + half_length; Bounds.MaxY = center.Y + half_length; Bounds.MaxZ = center.Z + half_length; VoxelBounds = new AABBi( (int)Math.Round((Bounds.MinX - tree.VoxelBounds.MinX) / tree.SmallestVoxelSideLength, MidpointRounding.AwayFromZero), (int)Math.Round((Bounds.MinY - tree.VoxelBounds.MinY) / tree.SmallestVoxelSideLength, MidpointRounding.AwayFromZero), (int)Math.Round((Bounds.MinZ - tree.VoxelBounds.MinZ) / tree.SmallestVoxelSideLength, MidpointRounding.AwayFromZero), (int)Math.Round((Bounds.MaxX - tree.VoxelBounds.MinX) / tree.SmallestVoxelSideLength, MidpointRounding.AwayFromZero), (int)Math.Round((Bounds.MaxY - tree.VoxelBounds.MinY) / tree.SmallestVoxelSideLength, MidpointRounding.AwayFromZero), (int)Math.Round((Bounds.MaxZ - tree.VoxelBounds.MinZ) / tree.SmallestVoxelSideLength, MidpointRounding.AwayFromZero)); }
// computes the OBB for this set of points relative to this transform matrix. public static void ComputeOBB(Vector3[] points, ref Matrix4 matrix, out float[] sides) { AABBf aabb = new AABBf(); Matrix4 matrixInverse = matrix; matrixInverse.Invert(); for (int i = 0; i < points.Length; i++) { Vector3 t = Vector3.Transform(points[i], matrixInverse); // inverse rotate translate aabb.Add(t); } sides = new float[3]; sides[0] = aabb.MaxX - aabb.MinX; sides[1] = aabb.MaxY - aabb.MinY; sides[2] = aabb.MaxZ - aabb.MinZ; Vector3 center = new Vector3(); center.X = sides[0] * 0.5f + aabb.MinX; center.Y = sides[1] * 0.5f + aabb.MinY; center.Z = sides[2] * 0.5f + aabb.MinZ; Vector3 ocenter = Vector3.Transform(center, matrix); matrix = matrix * Matrix4.CreateTranslation(ocenter); }
public static void ComputeBestFitOBB(Vector3[] points, out float[] sides, out Matrix4 matrix, FitStrategy strategy) { matrix = Matrix4.Identity; AABBf aabb = new AABBf(); for (int i = 0; i < points.Length; i++) aabb.Add(points[i]); float avolume = (aabb.MaxX - aabb.MinX) * (aabb.MaxY - aabb.MinY) * (aabb.MaxZ - aabb.MinZ); Plane plane; ComputeBestFitPlane(points, out plane); plane.ToMatrix(ref matrix); ComputeOBB(points, ref matrix, out sides); Matrix4 refmatrix = new Matrix4(); refmatrix = matrix; float volume = sides[0] * sides[1] * sides[2]; float stepSize = 5; switch (strategy) { case BestFit.FitStrategy.FS_FAST_FIT: stepSize = 13; // 15 degree increments break; case BestFit.FitStrategy.FS_MEDIUM_FIT: stepSize = 7; // 10 degree increments break; case BestFit.FitStrategy.FS_SLOW_FIT: stepSize = 3; // 5 degree increments break; case BestFit.FitStrategy.FS_SLOWEST_FIT: stepSize = 1; // 1 degree increments break; } Quaternion quat = new Quaternion(); for (float a = 0; a < 180; a += stepSize) { Matrix4 temp; Matrix4.CreateRotationY(MathHelper.DegreesToRadians(a), out temp); QuaternionEx.CreateFromMatrix(ref temp, ref quat); Matrix4 pmatrix; Matrix4.Mult(ref temp, ref refmatrix, out pmatrix); float[] psides; ComputeOBB(points, ref pmatrix, out psides); float v = psides[0] * psides[1] * psides[2]; if (v < volume) { volume = v; matrix = pmatrix; sides[0] = psides[0]; sides[1] = psides[1]; sides[2] = psides[2]; } } if (avolume < volume) { matrix = Matrix4.CreateTranslation( (aabb.MinX + aabb.MaxX) * 0.5f, (aabb.MinY + aabb.MaxY) * 0.5f, (aabb.MinZ + aabb.MaxZ) * 0.5f); sides[0] = aabb.MaxX - aabb.MinX; sides[1] = aabb.MaxY - aabb.MinY; sides[2] = aabb.MaxZ - aabb.MinZ; } }
public void InsideOrIntersectingAABBf_IsTrue(PlaneF plane, AABBf aabb) { Assert.True(plane.InsideOrIntersecting(aabb)); }
public void IntersectsAABBf_IsFalse(PlaneF plane, AABBf aabb) { Assert.False(plane.Intersects(aabb)); }
private void CreateUniformBoundingBox(List<Triangle> triangles, out AABBf originalBounds, out AABBf voxelBounds, out Vector3 center, out float length) { originalBounds = Triangle.CreateBoundingBox(triangles); Vector3 size = new Vector3(originalBounds.MaxX - originalBounds.MinX, originalBounds.MaxY - originalBounds.MinY, originalBounds.MaxZ - originalBounds.MinZ); float maxSize = Math.Max(size.X, Math.Max(size.Y, size.Z)); center = new Vector3( originalBounds.MinX + (size.X / 2.0f), originalBounds.MinY + (size.Y / 2.0f), originalBounds.MinZ + (size.Z / 2.0f)); length = maxSize; voxelBounds = new AABBf(); voxelBounds.MinX = center.X - (length * 0.5f); voxelBounds.MinY = center.Y - (length * 0.5f); voxelBounds.MinZ = center.Z - (length * 0.5f); voxelBounds.MaxX = center.X + (length * 0.5f); voxelBounds.MaxY = center.Y + (length * 0.5f); voxelBounds.MaxZ = center.Z + (length * 0.5f); }
public void Transform_IsTransform(float4x4 m, AABBf box, AABBf expected) { var actual = m * box; Assert.Equal(expected, actual); }
public void Union_IsUnion(AABBf a, AABBf b, AABBf expected) { var actual = AABBf.Union(a, b); Assert.Equal(expected, actual); }