Beispiel #1
0
		private void RenderBounds(AxisAlignedBoundingBox aabb)
		{
			RGBA_Bytes color = RGBA_Bytes.Red;

			// the bottom
			RenderLine(transform.Peek(), aabb.GetBottomCorner(0), aabb.GetBottomCorner(1), color);
			RenderLine(transform.Peek(), aabb.GetBottomCorner(1), aabb.GetBottomCorner(2), color);
			RenderLine(transform.Peek(), aabb.GetBottomCorner(2), aabb.GetBottomCorner(3), color);
			RenderLine(transform.Peek(), aabb.GetBottomCorner(3), aabb.GetBottomCorner(0), color);

			// the top
			RenderLine(transform.Peek(), aabb.GetTopCorner(0), aabb.GetTopCorner(1), color);
			RenderLine(transform.Peek(), aabb.GetTopCorner(1), aabb.GetTopCorner(2), color);
			RenderLine(transform.Peek(), aabb.GetTopCorner(2), aabb.GetTopCorner(3), color);
			RenderLine(transform.Peek(), aabb.GetTopCorner(3), aabb.GetTopCorner(0), color);

			// the sides
			RenderLine(transform.Peek(),
				new Vector3(aabb.minXYZ.x, aabb.minXYZ.y, aabb.minXYZ.z),
				new Vector3(aabb.minXYZ.x, aabb.minXYZ.y, aabb.maxXYZ.z),
				color);
			RenderLine(transform.Peek(),
				new Vector3(aabb.maxXYZ.x, aabb.minXYZ.y, aabb.minXYZ.z),
				new Vector3(aabb.maxXYZ.x, aabb.minXYZ.y, aabb.maxXYZ.z),
				color);
			RenderLine(transform.Peek(),
				new Vector3(aabb.minXYZ.x, aabb.maxXYZ.y, aabb.minXYZ.z),
				new Vector3(aabb.minXYZ.x, aabb.maxXYZ.y, aabb.maxXYZ.z),
				color);
			RenderLine(transform.Peek(),
				new Vector3(aabb.maxXYZ.x, aabb.maxXYZ.y, aabb.minXYZ.z),
				new Vector3(aabb.maxXYZ.x, aabb.maxXYZ.y, aabb.maxXYZ.z),
				color);
		}
Beispiel #2
0
        public override bool CheckIfBundleHitsAabb(AxisAlignedBoundingBox aabbToCheck)
        {
            if (frustumForRays.GetIntersect(aabbToCheck) == FrustumIntersection.Outside)
            {
                return false;
            }

            return true;
        }
		public bool GetContained(List<IPrimitive> results, AxisAlignedBoundingBox subRegion)
		{
			bool foundItem = false;
			foreach (IPrimitive item in items)
			{
				foundItem |= item.GetContained(results, subRegion);
			}

			return foundItem;
		}
Beispiel #4
0
		public bool GetContained(List<IPrimitive> results, AxisAlignedBoundingBox subRegion)
		{
			AxisAlignedBoundingBox bounds = GetAxisAlignedBoundingBox();
			if (bounds.Contains(subRegion))
			{
				results.Add(this);
				return true;
			}

			return false;
		}
		public AxisAlignedBoundingBox GetAxisAlignedBoundingBox()
		{
			if (cachedAABB.minXYZ.x == double.NegativeInfinity)
			{
				cachedAABB = items[0].GetAxisAlignedBoundingBox();
				for (int i = 1; i < items.Count; i++)
				{
					cachedAABB += items[i].GetAxisAlignedBoundingBox();
				}
			}

			return cachedAABB;
		}
		private void CalculateIntersectCostsAndSaveToFile()
		{
			int numInterations = 5000000;
			AxisAlignedBoundingBox referenceCostObject = new AxisAlignedBoundingBox(new Vector3(-.5, -.5, -.5), new Vector3(.5, .5, .5));

			Stopwatch timer = new Stopwatch();
			Vector3 accumulation = new Vector3();
			timer.Start();
			for (int i = 0; i < numInterations; i++)
			{
				accumulation += GetRandomIntersectingRay().directionNormal;
			}
			long notIntersectStuff = timer.ElapsedMilliseconds;
			timer.Restart();
			for (int i = 0; i < numInterations; i++)
			{
				GetRandomIntersectingRay().Intersection(referenceCostObject);
			}
			long referenceMiliseconds = timer.ElapsedMilliseconds;

			SolidMaterial material = new SolidMaterial(RGBA_Floats.Black, 0, 0, 1);
			long sphereMiliseconds = CalculateIntersectCostsForItem(new SphereShape(new Vector3(), .5, material), numInterations);
			long cylinderMiliseconds = CalculateIntersectCostsForItem(new CylinderShape(.5, 1, material), numInterations);
			long boxMiliseconds = CalculateIntersectCostsForItem(new BoxShape(new Vector3(-.5, -.5, -.5), new Vector3(.5, .5, .5), material), numInterations);
			long planeMiliseconds = CalculateIntersectCostsForItem(new PlaneShape(new Vector3(0, 0, 1), 0, material), numInterations);
			BaseShape triangleTest = new TriangleShape(new Vector3(-1, 0, 0), new Vector3(0, 1, 0), new Vector3(0, 0, 0), material);
			long triangleMiliseconds = CalculateIntersectCostsForItem(triangleTest, numInterations);

			System.IO.File.WriteAllText("Cost Of Primitive.txt",
				"Cost of Primitives"
				+ "\r\n" + numInterations.ToString("N0") + " intersections per primitive."
				+ "\r\nTest Overhead: " + notIntersectStuff.ToString()
				+ GetStringForFile("AABB", referenceMiliseconds, notIntersectStuff)
				+ GetStringForFile("Sphere", sphereMiliseconds, notIntersectStuff)
				+ GetStringForFile("Cylider", cylinderMiliseconds, notIntersectStuff)
				+ GetStringForFile("Box", boxMiliseconds, notIntersectStuff)
				+ GetStringForFile("Plane", planeMiliseconds, notIntersectStuff)
				+ GetStringForFile("Triangle", triangleMiliseconds, notIntersectStuff)
				);
		}
Beispiel #7
0
		public void SplitOnAllEdgeIntersections(CsgAcceleratedMesh meshWidthEdges)
		{
			foreach (var meshEdge in meshWidthEdges.mesh.MeshEdges)
			{
				// Check the mesh edge bounds agains all polygons. If there is an intersection
				// subdivide the mesh edge and if the face that is hit. If hit face on an edge only split the edge.
				Vector3 end0 = meshEdge.VertexOnEnd[0].Position;
				Vector3 end1 = meshEdge.VertexOnEnd[1].Position;
				AxisAlignedBoundingBox edgeBounds = new AxisAlignedBoundingBox(Vector3.ComponentMin(end0, end1), Vector3.ComponentMax(end0, end1));

				foreach (Face face in GetFacesTouching(edgeBounds))
				{
					Vector3 intersectionPosition;
					// intersect the face with the edge
					switch (face.Intersection(end0, end1, out intersectionPosition))
					{
						case FaceHelper.IntersectionType.Vertex:
							break;

						case FaceHelper.IntersectionType.MeshEdge:
							{
								SplitMeshEdgeIfRequired(meshEdge, intersectionPosition);
								// split the face at intersectionPosition
								SplitMeshEdgeAtPosition(face, intersectionPosition);
							}
							break;

						case FaceHelper.IntersectionType.Face:
							{
								SplitMeshEdgeIfRequired(meshEdge, intersectionPosition);
								// split the face at intersectionPosition
								SplitFaceAtPosition(face, intersectionPosition);
							}
							break;
					}
				}
			}
		}
        private double GetAlignToOffset(Aabb anchorBounds, int axis, Align alignTo)
        {
            switch (alignTo)
            {
            case Align.None:
                return(0);

            case Align.Min:
                return(anchorBounds.MinXYZ[axis]);

            case Align.Center:
                return(anchorBounds.Center[axis]);

            case Align.Max:
                return(anchorBounds.MaxXYZ[axis]);

            case Align.Origin:
                return(Vector3Ex.Transform(Vector3.Zero, SelectedObject.WorldMatrix())[axis]);

            default:
                throw new NotImplementedException();
            }
        }
Beispiel #9
0
		public static PolygonMesh.Mesh CreateBox(AxisAlignedBoundingBox aabb)
		{
			PolygonMesh.Mesh cube = new PolygonMesh.Mesh();
			Vertex[] verts = new Vertex[8];
			//verts[0] = cube.CreateVertex(new Vector3(-1, -1, 1));
			//verts[1] = cube.CreateVertex(new Vector3(1, -1, 1));
			//verts[2] = cube.CreateVertex(new Vector3(1, 1, 1));
			//verts[3] = cube.CreateVertex(new Vector3(-1, 1, 1));
			//verts[4] = cube.CreateVertex(new Vector3(-1, -1, -1));
			//verts[5] = cube.CreateVertex(new Vector3(1, -1, -1));
			//verts[6] = cube.CreateVertex(new Vector3(1, 1, -1));
			//verts[7] = cube.CreateVertex(new Vector3(-1, 1, -1));

			verts[0] = cube.CreateVertex(new Vector3(aabb.minXYZ.x, aabb.minXYZ.y, aabb.maxXYZ.z));
			verts[1] = cube.CreateVertex(new Vector3(aabb.maxXYZ.x, aabb.minXYZ.y, aabb.maxXYZ.z));
			verts[2] = cube.CreateVertex(new Vector3(aabb.maxXYZ.x, aabb.maxXYZ.y, aabb.maxXYZ.z));
			verts[3] = cube.CreateVertex(new Vector3(aabb.minXYZ.x, aabb.maxXYZ.y, aabb.maxXYZ.z));
			verts[4] = cube.CreateVertex(new Vector3(aabb.minXYZ.x, aabb.minXYZ.y, aabb.minXYZ.z));
			verts[5] = cube.CreateVertex(new Vector3(aabb.maxXYZ.x, aabb.minXYZ.y, aabb.minXYZ.z));
			verts[6] = cube.CreateVertex(new Vector3(aabb.maxXYZ.x, aabb.maxXYZ.y, aabb.minXYZ.z));
			verts[7] = cube.CreateVertex(new Vector3(aabb.minXYZ.x, aabb.maxXYZ.y, aabb.minXYZ.z));

			// front
			cube.CreateFace(new Vertex[] { verts[0], verts[1], verts[2], verts[3] });
			// left
			cube.CreateFace(new Vertex[] { verts[4], verts[0], verts[3], verts[7] });
			// right
			cube.CreateFace(new Vertex[] { verts[1], verts[5], verts[6], verts[2] });
			// back
			cube.CreateFace(new Vertex[] { verts[4], verts[7], verts[6], verts[5] });
			// top
			cube.CreateFace(new Vertex[] { verts[3], verts[2], verts[6], verts[7] });
			// bottom
			cube.CreateFace(new Vertex[] { verts[4], verts[5], verts[1], verts[0] });

			return cube;
		}
Beispiel #10
0
		public bool GetContained(List<IPrimitive> results, AxisAlignedBoundingBox subRegion)
		{
			throw new NotImplementedException();
		}
Beispiel #11
0
 public BvhTreeItemData(T item, AxisAlignedBoundingBox bounds)
 {
     this.Item = item;
     Aabb      = bounds;
 }
Beispiel #12
0
		public AxisAlignedBoundingBox GetAxisAlignedBoundingBox(Matrix4X4 transform)
		{
			if (fastAABBTransform == transform && fastAABBCache != null)
			{
				return fastAABBCache;
			}
			else
			{
				Vector3 minXYZ = new Vector3(double.MaxValue, double.MaxValue, double.MaxValue);
				Vector3 maxXYZ = new Vector3(double.MinValue, double.MinValue, double.MinValue);

				foreach (Vertex vertex in vertices)
				{
					Vector3 position = Vector3.Transform(vertex.Position, transform);
					minXYZ.x = Math.Min(minXYZ.x, position.x);
					minXYZ.y = Math.Min(minXYZ.y, position.y);
					minXYZ.z = Math.Min(minXYZ.z, position.z);

					maxXYZ.x = Math.Max(maxXYZ.x, position.x);
					maxXYZ.y = Math.Max(maxXYZ.y, position.y);
					maxXYZ.z = Math.Max(maxXYZ.z, position.z);
				}

				fastAABBTransform = transform;
				fastAABBCache = new AxisAlignedBoundingBox(minXYZ, maxXYZ);
			}

			return fastAABBCache;
		}
Beispiel #13
0
		public FrustumIntersection GetIntersect(AxisAlignedBoundingBox boundingBox)
		{
			FrustumIntersection returnValue = FrustumIntersection.Inside;
			Vector3 vmin, vmax;

			for (int i = 0; i < plane.Length; ++i)
			{
				// X axis
				if (plane[i].planeNormal.x > 0)
				{
					vmin.x = boundingBox.minXYZ.x;
					vmax.x = boundingBox.maxXYZ.x;
				}
				else
				{
					vmin.x = boundingBox.maxXYZ.x;
					vmax.x = boundingBox.minXYZ.x;
				}

				// Y axis
				if (plane[i].planeNormal.y > 0)
				{
					vmin.y = boundingBox.minXYZ.y;
					vmax.y = boundingBox.maxXYZ.y;
				}
				else
				{
					vmin.y = boundingBox.maxXYZ.y;
					vmax.y = boundingBox.minXYZ.y;
				}

				// Z axis
				if (plane[i].planeNormal.z > 0)
				{
					vmin.z = boundingBox.minXYZ.z;
					vmax.z = boundingBox.maxXYZ.z;
				}
				else
				{
					vmin.z = boundingBox.maxXYZ.z;
					vmax.z = boundingBox.minXYZ.z;
				}

				if (Vector3.Dot(plane[i].planeNormal, vmin) - plane[i].distanceToPlaneFromOrigin > 0)
				{
					if (Vector3.Dot(plane[i].planeNormal, vmax) - plane[i].distanceToPlaneFromOrigin >= 0)
					{
						return FrustumIntersection.Outside;
					}
				}

				if (Vector3.Dot(plane[i].planeNormal, vmax) - plane[i].distanceToPlaneFromOrigin >= 0)
				{
					returnValue = FrustumIntersection.Intersect;
				}
			}

			return returnValue;
		}
Beispiel #14
0
 public abstract bool CheckIfBundleHitsAabb(AxisAlignedBoundingBox aabbToCheck);
Beispiel #15
0
 public void SearchBounds(AxisAlignedBoundingBox bounds)
 {
     QueryResults.Clear();
     root.SearchBounds(bounds, QueryResults);
 }
Beispiel #16
0
 public double GetIntersectCost()
 {
     return(AxisAlignedBoundingBox.GetIntersectCost());
 }
Beispiel #17
0
		private IEnumerable<Face> GetFacesTouching(AxisAlignedBoundingBox edgeBounds)
		{
			// TODO: make this only get the right faces
			foreach(var face in mesh.Faces)
			{
				yield return face;
			}
		}
Beispiel #18
0
 internal Branch(AxisAlignedBoundingBox bounds)
 {
     this.Bounds = bounds;
 }
		public BoundingVolumeHierarchy(IPrimitive nodeA, IPrimitive nodeB, int splitingPlane)
		{
			this.splitingPlane = splitingPlane;
			this.nodeA = nodeA;
			this.nodeB = nodeB;
			this.Aabb = nodeA.GetAxisAlignedBoundingBox() + nodeB.GetAxisAlignedBoundingBox(); // we can cache this because it is not allowed to change.
		}
Beispiel #20
0
        /// <summary>
        /// Find all values touching in the specified area.
        /// </summary>
        /// <returns>True if any values were found.</returns>
        /// <param name="x">X position to search.</param>
        /// <param name="y">Y position to search.</param>
        /// <param name="xSize">xSize of the search area.</param>
        /// <param name="ySize">ySize of the search area.</param>
        /// <param name="values">A list to populate with the results. If null, this function will create the list for you.</param>
        public void SearchBounds(double x, double y, double z, double xSize, double ySize, double zSize)
        {
            var bounds = new AxisAlignedBoundingBox(x, y, z, x + xSize, y + ySize, z + zSize);

            SearchBounds(bounds);
        }
 public bool Equals(AxisAlignedBoundingBox bounds, double equalityTolerance = 0)
 {
     return(this.minXYZ.Equals(bounds.minXYZ, equalityTolerance) && this.maxXYZ.Equals(bounds.maxXYZ, equalityTolerance));
 }
        public static AxisAlignedBoundingBox Intersection(AxisAlignedBoundingBox boundsA, AxisAlignedBoundingBox boundsB)
        {
            Vector3 minXYZ = new Vector3(
                Math.Max(boundsA.minXYZ.X, boundsB.minXYZ.X),
                Math.Max(boundsA.minXYZ.Y, boundsB.minXYZ.Y),
                Math.Max(boundsA.minXYZ.Z, boundsB.minXYZ.Z));

            Vector3 maxXYZ = new Vector3(
                Math.Max(minXYZ.X, Math.Min(boundsA.maxXYZ.X, boundsB.maxXYZ.X)),
                Math.Max(minXYZ.Y, Math.Min(boundsA.maxXYZ.Y, boundsB.maxXYZ.Y)),
                Math.Max(minXYZ.Z, Math.Min(boundsA.maxXYZ.Z, boundsB.maxXYZ.Z)));

            return(new AxisAlignedBoundingBox(minXYZ, maxXYZ));
        }
Beispiel #23
0
		public bool Intersection(AxisAlignedBoundingBox bounds)
		{
			Ray ray = this;
			// we calculate distance to the intersection with the x planes of the box
			double minDistFound = (bounds[(int)ray.sign[0]].x - ray.origin.x) * ray.oneOverDirection.x;
			double maxDistFound = (bounds[1 - (int)ray.sign[0]].x - ray.origin.x) * ray.oneOverDirection.x;

			// now find the distance to the y planes of the box
			double minDistToY = (bounds[(int)ray.sign[1]].y - ray.origin.y) * ray.oneOverDirection.y;
			double maxDistToY = (bounds[1 - (int)ray.sign[1]].y - ray.origin.y) * ray.oneOverDirection.y;

			if ((minDistFound > maxDistToY) || (minDistToY > maxDistFound))
			{
				return false;
			}

			if (minDistToY > minDistFound)
			{
				minDistFound = minDistToY;
			}

			if (maxDistToY < maxDistFound)
			{
				maxDistFound = maxDistToY;
			}

			// and finaly the z planes
			double minDistToZ = (bounds[(int)ray.sign[2]].z - ray.origin.z) * ray.oneOverDirection.z;
			double maxDistToZ = (bounds[1 - (int)ray.sign[2]].z - ray.origin.z) * ray.oneOverDirection.z;

			if ((minDistFound > maxDistToZ) || (minDistToZ > maxDistFound))
			{
				return false;
			}

			if (minDistToZ > minDistFound)
			{
				minDistFound = minDistToZ;
			}

			if (maxDistToZ < maxDistFound)
			{
				maxDistFound = maxDistToZ;
			}

			bool withinDistanceToConsider = (minDistFound < ray.maxDistanceToConsider) && (maxDistFound > ray.minDistanceToConsider);
			return withinDistanceToConsider;
		}
Beispiel #24
0
        public static AxisAlignedBoundingBox Intersection(AxisAlignedBoundingBox boundsA, AxisAlignedBoundingBox boundsB)
        {
            Vector3 minXYZ = Vector3.Zero;

            minXYZ.x = Math.Max(boundsA.minXYZ.x, boundsB.minXYZ.x);
            minXYZ.y = Math.Max(boundsA.minXYZ.y, boundsB.minXYZ.y);
            minXYZ.z = Math.Max(boundsA.minXYZ.z, boundsB.minXYZ.z);

            Vector3 maxXYZ = Vector3.Zero;

            maxXYZ.x = Math.Max(minXYZ.x, Math.Min(boundsA.maxXYZ.x, boundsB.maxXYZ.x));
            maxXYZ.y = Math.Max(minXYZ.y, Math.Min(boundsA.maxXYZ.y, boundsB.maxXYZ.y));
            maxXYZ.z = Math.Max(minXYZ.z, Math.Min(boundsA.maxXYZ.z, boundsB.maxXYZ.z));

            return(new AxisAlignedBoundingBox(minXYZ, maxXYZ));
        }
Beispiel #25
0
		public static Matrix4X4 ApplyAtCenter(AxisAlignedBoundingBox boundsToApplyTo, Matrix4X4 currentTransform, Matrix4X4 transformToApply)
		{
			return ApplyAtPosition(currentTransform, transformToApply, boundsToApplyTo.Center);
		}
		public bool GetContained(List<IPrimitive> results, AxisAlignedBoundingBox subRegion)
		{
			AxisAlignedBoundingBox bounds = GetAxisAlignedBoundingBox();
			if (bounds.Contains(subRegion))
			{
				bool resultA = this.nodeA.GetContained(results, subRegion);
				bool resultB = this.nodeB.GetContained(results, subRegion);
				return resultA | resultB;
			}

			return false;
		}
Beispiel #27
0
 /// <summary>
 /// Creates a new Octree.
 /// </summary>
 /// <param name="splitCount">How many leaves a branch can hold before it splits into sub-branches.</param>
 /// <param name="region">The region that your Octree occupies, all inserted bounds should fit into this.</param>
 public Octree(int splitCount, AxisAlignedBoundingBox region)
 {
     this.splitCount = splitCount;
     root            = CreateBranch(this, null, region);
 }
		public static AxisAlignedBoundingBox Intersection(AxisAlignedBoundingBox boundsA, AxisAlignedBoundingBox boundsB)
		{
			Vector3 minXYZ = Vector3.Zero;
			minXYZ.x = Math.Max(boundsA.minXYZ.x, boundsB.minXYZ.x);
			minXYZ.y = Math.Max(boundsA.minXYZ.y, boundsB.minXYZ.y);
			minXYZ.z = Math.Max(boundsA.minXYZ.z, boundsB.minXYZ.z);

			Vector3 maxXYZ = Vector3.Zero;
			maxXYZ.x = Math.Max(minXYZ.x, Math.Min(boundsA.maxXYZ.x, boundsB.maxXYZ.x));
			maxXYZ.y = Math.Max(minXYZ.y, Math.Min(boundsA.maxXYZ.y, boundsB.maxXYZ.y));
			maxXYZ.z = Math.Max(minXYZ.z, Math.Min(boundsA.maxXYZ.z, boundsB.maxXYZ.z));

			return new AxisAlignedBoundingBox(minXYZ, maxXYZ);
		}
		public bool Contains(AxisAlignedBoundingBox bounds)
		{
			if (this.minXYZ.x <= bounds.minXYZ.x
				&& this.maxXYZ.x >= bounds.maxXYZ.x
				&& this.minXYZ.y <= bounds.minXYZ.y
				&& this.maxXYZ.y >= bounds.maxXYZ.y
				&& this.minXYZ.z <= bounds.minXYZ.z
				&& this.maxXYZ.z >= bounds.maxXYZ.z)
			{
				return true;
			}

			return false;
		}
		public void SetMeshAfterLoad(List<MeshGroup> loadedMeshGroups, CenterPartAfterLoad centerPart, Vector2 bedCenter)
		{
			MeshGroups.Clear();

			if (loadedMeshGroups == null)
			{
				partProcessingInfo.centeredInfoText.Text = string.Format("Sorry! No 3D view available\nfor this file.");
			}
			else
			{
				CreateGlDataForMeshes(loadedMeshGroups);

				AxisAlignedBoundingBox bounds = new AxisAlignedBoundingBox(Vector3.Zero, Vector3.Zero);
				bool first = true;
				foreach (MeshGroup meshGroup in loadedMeshGroups)
				{
					if (first)
					{
						bounds = meshGroup.GetAxisAlignedBoundingBox();
						first = false;
					}
					else
					{
						bounds = AxisAlignedBoundingBox.Union(bounds, meshGroup.GetAxisAlignedBoundingBox());
					}
				}

				foreach (MeshGroup meshGroup in loadedMeshGroups)
				{
					// make sure the mesh is centered about the origin so rotations will come from a reasonable place
					ScaleRotateTranslate centering = ScaleRotateTranslate.Identity();
					centering.SetCenteringForMeshGroup(meshGroup);
					meshTransforms.Add(centering);
					MeshGroups.Add(meshGroup);
				}

				if (centerPart == CenterPartAfterLoad.DO)
				{
					// make sure the entire load is centered and on the bed
					Vector3 boundsCenter = (bounds.maxXYZ + bounds.minXYZ) / 2;
					for (int i = 0; i < MeshGroups.Count; i++)
					{
						ScaleRotateTranslate moved = meshTransforms[i];
						moved.translation *= Matrix4X4.CreateTranslation(-boundsCenter + new Vector3(0, 0, bounds.ZSize / 2) + new Vector3(bedCenter));
						meshTransforms[i] = moved;
					}
				}
				
				trackballTumbleWidget.TrackBallController = new TrackBallController();
				trackballTumbleWidget.OnBoundsChanged(null);
				trackballTumbleWidget.TrackBallController.Scale = .03;
				trackballTumbleWidget.TrackBallController.Translate(-new Vector3(BedCenter));
				trackballTumbleWidget.TrackBallController.Rotate(Quaternion.FromEulerAngles(new Vector3(0, 0, MathHelper.Tau / 16)));
				trackballTumbleWidget.TrackBallController.Rotate(Quaternion.FromEulerAngles(new Vector3(-MathHelper.Tau * .19, 0, 0)));
			}
		}
		AxisAlignedBoundingBox GetAxisAlignedBoundingBox(List<MeshGroup> meshGroups)
		{
			AxisAlignedBoundingBox totalMeshBounds = new AxisAlignedBoundingBox(Vector3.NegativeInfinity, Vector3.NegativeInfinity);
			bool first = true;
			foreach (MeshGroup meshGroup in meshGroups)
			{
				AxisAlignedBoundingBox meshBounds = meshGroup.GetAxisAlignedBoundingBox();
				if (first)
				{
					totalMeshBounds = meshBounds;
					first = false;
				}
				else
				{
					totalMeshBounds = AxisAlignedBoundingBox.Union(totalMeshBounds, meshBounds);
				}
			}

			return totalMeshBounds;
		}
		public static AxisAlignedBoundingBox operator +(AxisAlignedBoundingBox A, AxisAlignedBoundingBox B)
		{
#if true
			return Union(A, B);
#else
            Vector3 calcMinXYZ = new Vector3();
            calcMinXYZ.x = Math.Min(A.minXYZ.x, B.minXYZ.x);
            calcMinXYZ.y = Math.Min(A.minXYZ.y, B.minXYZ.y);
            calcMinXYZ.z = Math.Min(A.minXYZ.z, B.minXYZ.z);

            Vector3 calcMaxXYZ = new Vector3();
            calcMaxXYZ.x = Math.Max(A.maxXYZ.x, B.maxXYZ.x);
            calcMaxXYZ.y = Math.Max(A.maxXYZ.y, B.maxXYZ.y);
            calcMaxXYZ.z = Math.Max(A.maxXYZ.z, B.maxXYZ.z);

            AxisAlignedBoundingBox combinedBounds = new AxisAlignedBoundingBox(calcMinXYZ, calcMaxXYZ);

            return combinedBounds;
#endif
		}
Beispiel #33
0
        /// <summary>
        /// Insert a new leaf node into the Octree.
        /// </summary>
        /// <param name="value">The leaf value.</param>
        /// <param name="x">X position of the leaf.</param>
        /// <param name="y">Y position of the leaf.</param>
        /// <param name="xSize">xSize of the leaf.</param>
        /// <param name="ySize">ySize of the leaf.</param>
        public void Insert(T value, double x, double y, double z, double xSize, double ySize, double zSize)
        {
            var bounds = new AxisAlignedBoundingBox(x, y, z, x + xSize, y + ySize, z + zSize);

            Insert(value, bounds);
        }
		public static AxisAlignedBoundingBox Union(AxisAlignedBoundingBox bounds, Vector3 vertex)
		{
			Vector3 minXYZ = Vector3.Zero;
			minXYZ.x = Math.Min(bounds.minXYZ.x, vertex.x);
			minXYZ.y = Math.Min(bounds.minXYZ.y, vertex.y);
			minXYZ.z = Math.Min(bounds.minXYZ.z, vertex.z);

			Vector3 maxXYZ = Vector3.Zero;
			maxXYZ.x = Math.Max(bounds.maxXYZ.x, vertex.x);
			maxXYZ.y = Math.Max(bounds.maxXYZ.y, vertex.y);
			maxXYZ.z = Math.Max(bounds.maxXYZ.z, vertex.z);

			return new AxisAlignedBoundingBox(minXYZ, maxXYZ);
		}
Beispiel #35
0
        private static BvhTree <T> CreateNewHierachy(List <BvhTreeItemData <T> > itemsToAdd,
                                                     int maxRecursion,
                                                     int recursionDepth,
                                                     SortingAccelerator accelerator)
        {
            if (accelerator == null)
            {
                accelerator = new SortingAccelerator();
            }

            int numItems = itemsToAdd.Count;

            if (numItems == 0)
            {
                return(null);
            }

            if (numItems == 1)
            {
                return(new BvhTree <T>(itemsToAdd));
            }

            int bestAxis           = -1;
            int bestIndexToSplitOn = -1;
            var axisSorter         = new AxisSorter(0);

            if (recursionDepth < maxRecursion)
            {
                if (numItems > 5000)
                {
                    bestAxis           = accelerator.NextAxis;
                    bestIndexToSplitOn = numItems / 2;
                }
                else
                {
                    double totalIntersectCost = 0;
                    int    skipInterval       = 1;
                    for (int i = 0; i < numItems; i += skipInterval)
                    {
                        var item = itemsToAdd[i];
                        if (item.Item is IIntersectable intersectable)
                        {
                            totalIntersectCost += intersectable.GetIntersectCost();
                        }
                        else
                        {
                            totalIntersectCost += AxisAlignedBoundingBox.GetIntersectCost();
                        }
                    }

                    // get the bounding box of all the items we are going to consider.
                    AxisAlignedBoundingBox OverallBox = itemsToAdd[0].Aabb;
                    for (int i = skipInterval; i < numItems; i += skipInterval)
                    {
                        OverallBox += itemsToAdd[i].Aabb;
                    }
                    double areaOfTotalBounds = OverallBox.GetSurfaceArea();

                    double bestCost = totalIntersectCost;

                    Vector3  totalDeviationOnAxis = new Vector3();
                    double[] surfaceArreaOfItem   = new double[numItems - 1];
                    double[] rightBoundsAtItem    = new double[numItems - 1];

                    for (int axis = 0; axis < 3; axis++)
                    {
                        double intersectCostOnLeft = 0;

                        axisSorter.WhichAxis = axis;
                        itemsToAdd.Sort(axisSorter);

                        // Get all left bounds
                        AxisAlignedBoundingBox currentLeftBounds = itemsToAdd[0].Aabb;
                        surfaceArreaOfItem[0] = currentLeftBounds.GetSurfaceArea();
                        for (int itemIndex = 1; itemIndex < numItems - 1; itemIndex += skipInterval)
                        {
                            currentLeftBounds            += itemsToAdd[itemIndex].Aabb;
                            surfaceArreaOfItem[itemIndex] = currentLeftBounds.GetSurfaceArea();

                            totalDeviationOnAxis[axis] += Math.Abs(itemsToAdd[itemIndex].Center[axis] - itemsToAdd[itemIndex - 1].Center[axis]);
                        }

                        // Get all right bounds
                        if (numItems > 1)
                        {
                            AxisAlignedBoundingBox currentRightBounds = itemsToAdd[numItems - 1].Aabb;
                            rightBoundsAtItem[numItems - 2] = currentRightBounds.GetSurfaceArea();
                            for (int itemIndex = numItems - 1; itemIndex > 1; itemIndex -= skipInterval)
                            {
                                currentRightBounds += itemsToAdd[itemIndex - 1].Aabb;
                                rightBoundsAtItem[itemIndex - 2] = currentRightBounds.GetSurfaceArea();
                            }
                        }

                        // Sweep from left
                        for (int itemIndex = 0; itemIndex < numItems - 1; itemIndex += skipInterval)
                        {
                            double thisCost = 0;

                            {
                                // Evaluate Surface Cost Equation
                                double costOfTwoAABB = 2 * AxisAlignedBoundingBox.GetIntersectCost();                                 // the cost of the two children AABB tests

                                // do the left cost
                                if (itemsToAdd[itemIndex].Item is IIntersectable intersectable)
                                {
                                    intersectCostOnLeft += intersectable.GetIntersectCost();
                                }
                                else
                                {
                                    intersectCostOnLeft += AxisAlignedBoundingBox.GetIntersectCost();
                                }
                                double leftCost = (surfaceArreaOfItem[itemIndex] / areaOfTotalBounds) * intersectCostOnLeft;

                                // do the right cost
                                double intersectCostOnRight = totalIntersectCost - intersectCostOnLeft;
                                double rightCost            = (rightBoundsAtItem[itemIndex] / areaOfTotalBounds) * intersectCostOnRight;

                                thisCost = costOfTwoAABB + leftCost + rightCost;
                            }

                            if (thisCost < bestCost + .000000001)                             // if it is less within some tiny error
                            {
                                if (thisCost > bestCost - .000000001)
                                {
                                    // they are the same within the error
                                    if (axis > 0 && bestAxis != axis)                                     // we have changed axis since last best and we need to decide if this is better than the last axis best
                                    {
                                        if (totalDeviationOnAxis[axis] > totalDeviationOnAxis[axis - 1])
                                        {
                                            // this new axis is better and we'll switch to it.  Otherwise don't switch.
                                            bestCost           = thisCost;
                                            bestIndexToSplitOn = itemIndex;
                                            bestAxis           = axis;
                                        }
                                    }
                                }
                                else                                 // this is just better
                                {
                                    bestCost           = thisCost;
                                    bestIndexToSplitOn = itemIndex;
                                    bestAxis           = axis;
                                }
                            }
                        }
                    }
                }
            }

            if (bestAxis == -1)
            {
                // No better partition found
                return(new BvhTree <T>(itemsToAdd));
            }
            else
            {
                axisSorter.WhichAxis = bestAxis;
                itemsToAdd.Sort(axisSorter);
                var leftItems  = new List <BvhTreeItemData <T> >(bestIndexToSplitOn + 1);
                var rightItems = new List <BvhTreeItemData <T> >(numItems - bestIndexToSplitOn + 1);
                for (int i = 0; i <= bestIndexToSplitOn; i++)
                {
                    leftItems.Add(itemsToAdd[i]);
                }
                for (int i = bestIndexToSplitOn + 1; i < numItems; i++)
                {
                    rightItems.Add(itemsToAdd[i]);
                }
                var leftGroup  = CreateNewHierachy(leftItems, maxRecursion, recursionDepth + 1, accelerator);
                var rightGroup = CreateNewHierachy(rightItems, maxRecursion, recursionDepth + 1, accelerator);
                var newBVHNode = new BvhTree <T>(leftGroup, rightGroup, bestAxis);
                return(newBVHNode);
            }
        }
        public static void CenterMeshesXY(List<Mesh> meshesList, List<ScaleRotateTranslate> meshTransforms)
        {
            bool first = true;
            AxisAlignedBoundingBox totalBounds = new AxisAlignedBoundingBox(new Vector3(), new Vector3());
            for(int index= 0; index<meshesList.Count; index++)
            {
                if(first)
                {
                    totalBounds = meshesList[index].GetAxisAlignedBoundingBox(meshTransforms[index].TotalTransform);
                    first = false;
                }
                else
                {
                    AxisAlignedBoundingBox bounds = meshesList[index].GetAxisAlignedBoundingBox(meshTransforms[index].TotalTransform);
                    totalBounds = AxisAlignedBoundingBox.Union(totalBounds, bounds);
                }
            }

            Vector3 boundsCenter = (totalBounds.maxXYZ + totalBounds.minXYZ) / 2;
            boundsCenter.z = 0;

            for (int index = 0; index < meshesList.Count; index++)
            {
                ScaleRotateTranslate moved = meshTransforms[index];
                moved.translation *= Matrix4X4.CreateTranslation(-boundsCenter);
                meshTransforms[index] = moved;
            }
        }
Beispiel #37
0
		public void FrustumIntersetAABBTests()
		{
			{
				Frustum frustum = new Frustum(
					new Plane(new Vector3(1, 0, 0), 20),
					new Plane(new Vector3(-1, 0, 0), 20),
					new Plane(new Vector3(0, 1, 0), 20),
					new Plane(new Vector3(0, -1, 0), 20),
					new Plane(new Vector3(0, 0, 1), 20),
					new Plane(new Vector3(0, 0, -1), 20));

				// outside to left
				{
					AxisAlignedBoundingBox aabb = new AxisAlignedBoundingBox(new Vector3(-30, -10, -10), new Vector3(-25, 10, 10));
					FrustumIntersection intersection = frustum.GetIntersect(aabb);
					Assert.IsTrue(intersection == FrustumIntersection.Outside);
				}

				// intersect
				{
					AxisAlignedBoundingBox aabb = new AxisAlignedBoundingBox(new Vector3(-25, 0, -10), new Vector3(-15, 10, 10));
					FrustumIntersection intersection = frustum.GetIntersect(aabb);
					Assert.IsTrue(intersection == FrustumIntersection.Intersect);
				}

				// inside
				{
					AxisAlignedBoundingBox aabb = new AxisAlignedBoundingBox(new Vector3(-5, -5, -5), new Vector3(5, 5, 5));
					FrustumIntersection intersection = frustum.GetIntersect(aabb);
					Assert.IsTrue(intersection == FrustumIntersection.Inside);
				}
			}

			{
				Frustum frustum = new Frustum(
					new Plane(new Vector3(-1, -1, 0), 0),
					new Plane(new Vector3(1, -1, 0), 0),
					new Plane(new Vector3(0, -1, -1), 0),
					new Plane(new Vector3(0, -1, 1), 0),
					new Plane(new Vector3(0, -1, 0), 0),
					new Plane(new Vector3(0, 1, 0), 10000));

				// outside to left
				{
					AxisAlignedBoundingBox aabb = new AxisAlignedBoundingBox(new Vector3(-110, 0, -10), new Vector3(-100, 10, 10));
					FrustumIntersection intersection = frustum.GetIntersect(aabb);
					Assert.IsTrue(intersection == FrustumIntersection.Outside);
				}

				// intersect with origin (front)
				{
					AxisAlignedBoundingBox aabb = new AxisAlignedBoundingBox(new Vector3(-10, -10, -10), new Vector3(10, 10, 10));
					FrustumIntersection intersection = frustum.GetIntersect(aabb);
					Assert.IsTrue(intersection == FrustumIntersection.Intersect);
				}

				// inside
				{
					AxisAlignedBoundingBox aabb = new AxisAlignedBoundingBox(new Vector3(-5, 100, -5), new Vector3(5, 110, 5));
					FrustumIntersection intersection = frustum.GetIntersect(aabb);
					Assert.IsTrue(intersection == FrustumIntersection.Inside);
				}
			}

			{
				// looking down -z
				Frustum frustum5PlaneNegZ = new Frustum(
					new Vector3(-1, 0, 1),
					new Vector3(-1, 0, 1),
					new Vector3(0, 1, 1),
					new Vector3(0, -1, 1),
					new Vector3(0, 0, -1), 10000);

				// outside to left
				{
					AxisAlignedBoundingBox aabb = new AxisAlignedBoundingBox(new Vector3(-110, 0, -10), new Vector3(-100, 10, 10));
					FrustumIntersection intersection = frustum5PlaneNegZ.GetIntersect(aabb);
					Assert.IsTrue(intersection == FrustumIntersection.Outside);
				}

				// intersect with origin (front)
				{
					AxisAlignedBoundingBox aabb = new AxisAlignedBoundingBox(new Vector3(-10, -10, -10), new Vector3(10, 10, 10));
					FrustumIntersection intersection = frustum5PlaneNegZ.GetIntersect(aabb);
					Assert.IsTrue(intersection == FrustumIntersection.Intersect);
				}

				// inside
				{
					AxisAlignedBoundingBox aabb = new AxisAlignedBoundingBox(new Vector3(-5, -5, -110), new Vector3(5, 5, -100));
					FrustumIntersection intersection = frustum5PlaneNegZ.GetIntersect(aabb);
					Assert.IsTrue(intersection == FrustumIntersection.Inside);
				}
			}
		}
		private RectangleDouble GetScreenBounds(AxisAlignedBoundingBox meshBounds)
		{
			RectangleDouble screenBounds = RectangleDouble.ZeroIntersection;

			screenBounds.ExpandToInclude(trackballTumbleWidget.GetScreenPosition(new Vector3(meshBounds.minXYZ.x, meshBounds.minXYZ.y, meshBounds.minXYZ.z)));
			screenBounds.ExpandToInclude(trackballTumbleWidget.GetScreenPosition(new Vector3(meshBounds.maxXYZ.x, meshBounds.minXYZ.y, meshBounds.minXYZ.z)));
			screenBounds.ExpandToInclude(trackballTumbleWidget.GetScreenPosition(new Vector3(meshBounds.maxXYZ.x, meshBounds.maxXYZ.y, meshBounds.minXYZ.z)));
			screenBounds.ExpandToInclude(trackballTumbleWidget.GetScreenPosition(new Vector3(meshBounds.minXYZ.x, meshBounds.maxXYZ.y, meshBounds.minXYZ.z)));

			screenBounds.ExpandToInclude(trackballTumbleWidget.GetScreenPosition(new Vector3(meshBounds.minXYZ.x, meshBounds.minXYZ.y, meshBounds.maxXYZ.z)));
			screenBounds.ExpandToInclude(trackballTumbleWidget.GetScreenPosition(new Vector3(meshBounds.maxXYZ.x, meshBounds.minXYZ.y, meshBounds.maxXYZ.z)));
			screenBounds.ExpandToInclude(trackballTumbleWidget.GetScreenPosition(new Vector3(meshBounds.maxXYZ.x, meshBounds.maxXYZ.y, meshBounds.maxXYZ.z)));
			screenBounds.ExpandToInclude(trackballTumbleWidget.GetScreenPosition(new Vector3(meshBounds.minXYZ.x, meshBounds.maxXYZ.y, meshBounds.maxXYZ.z)));
			return screenBounds;
		}
Beispiel #39
0
		private static bool CheckPosition(int meshGroupToMoveIndex, List<MeshGroup> allMeshGroups, List<ScaleRotateTranslate> meshTransforms, MeshGroup meshGroupToMove, AxisAlignedBoundingBox meshToMoveBounds, int yStep, int xStep, ref Matrix4X4 transform)
		{
			double xStepAmount = 5;
			double yStepAmount = 5;

			Matrix4X4 positionTransform = Matrix4X4.CreateTranslation(xStep * xStepAmount, yStep * yStepAmount, 0);
			Vector3 newPosition = Vector3.Transform(Vector3.Zero, positionTransform);
			transform = Matrix4X4.CreateTranslation(newPosition);
			AxisAlignedBoundingBox testBounds = meshToMoveBounds.NewTransformed(transform);
			bool foundHit = false;
			for (int i = 0; i < meshGroupToMoveIndex; i++)
			{
				MeshGroup meshToTest = allMeshGroups[i];
				if (meshToTest != meshGroupToMove)
				{
					AxisAlignedBoundingBox existingMeshBounds = GetAxisAlignedBoundingBox(meshToTest, meshTransforms[i].TotalTransform);
					AxisAlignedBoundingBox intersection = AxisAlignedBoundingBox.Intersection(testBounds, existingMeshBounds);
					if (intersection.XSize > 0 && intersection.YSize > 0)
					{
						foundHit = true;
						break;
					}
				}
			}

			if (!foundHit)
			{
				return true;
			}

			return false;
		}