示例#1
0
        public void Move()
        {
            int[] testArray = Enumerable.Range(0, 10).ToArray();
            RawList<int> intList = new RawList<int>();

            intList.AddRange(testArray);
            intList.Move(0, 3, 1);
            CollectionAssert.AreEqual(new int[] { 0, 0, 1, 2, 4, 5, 6, 7, 8, 9 }, intList);
            intList.Clear();

            intList.AddRange(testArray);
            intList.Move(0, 3, 3);
            CollectionAssert.AreEqual(new int[] { 0, 1, 2, 0, 1, 2, 6, 7, 8, 9 }, intList);
            intList.Clear();

            intList.AddRange(testArray);
            intList.Move(0, 3, 5);
            CollectionAssert.AreEqual(new int[] { 0, 1, 2, 3, 4, 0, 1, 2, 8, 9 }, intList);
            intList.Clear();

            intList.AddRange(testArray);
            intList.Move(7, 3, -1);
            CollectionAssert.AreEqual(new int[] { 0, 1, 2, 3, 4, 5, 7, 8, 9, 9 }, intList);
            intList.Clear();

            intList.AddRange(testArray);
            intList.Move(7, 3, -3);
            CollectionAssert.AreEqual(new int[] { 0, 1, 2, 3, 7, 8, 9, 7, 8, 9 }, intList);
            intList.Clear();

            intList.AddRange(testArray);
            intList.Move(7, 3, -5);
            CollectionAssert.AreEqual(new int[] { 0, 1, 7, 8, 9, 5, 6, 7, 8, 9 }, intList);
            intList.Clear();
        }
 /// <summary>
 /// Returns a resource to the pool.
 /// </summary>
 /// <param name="list">List to return.</param>
 public static void GiveBack(RawList<BroadPhaseEntry> list)
 {
     if (SubPoolBroadPhaseEntryList == null)
         SubPoolBroadPhaseEntryList = new UnsafeResourcePool<RawList<BroadPhaseEntry>>();
     list.Clear();
     SubPoolBroadPhaseEntryList.GiveBack(list);
 }
 /// <summary>
 /// Returns a resource to the pool.
 /// </summary>
 /// <param name="list">List to return.</param>
 public static void GiveBack(RawList<RayCastResult> list)
 {
     if (SubPoolRayCastResultList == null)
         SubPoolRayCastResultList = new UnsafeResourcePool<RawList<RayCastResult>>();
     list.Clear();
     SubPoolRayCastResultList.GiveBack(list);
 }
示例#4
0
		[Test] public void Basics()
		{
			RawList<int> intList = new RawList<int>();
			intList.Add(10);
			intList.AddRange(new int[] { 17, 42, 94 });

			Assert.AreEqual(4, intList.Count);
			Assert.IsTrue(intList.Contains(42));
			Assert.AreEqual(2, intList.IndexOf(42));
			CollectionAssert.AreEqual(new int[] { 10, 17, 42, 94 }, intList);
			CollectionAssert.AreEqual(new int[] { 10, 17, 42, 94 }, intList.Data.Take(4));

			intList.ShrinkToFit();
			Assert.AreEqual(intList.Count, intList.Capacity);

			intList.Remove(42);
			Assert.AreEqual(3, intList.Count);
			Assert.IsTrue(!intList.Contains(42));
			Assert.AreEqual(-1, intList.IndexOf(42));
			CollectionAssert.AreEqual(new int[] { 10, 17, 94 }, intList);
			CollectionAssert.AreEqual(new int[] { 10, 17, 94 }, intList.Data.Take(3));

			intList.Insert(1, 100);
			CollectionAssert.AreEqual(new int[] { 10, 100, 17, 94 }, intList);
			CollectionAssert.AreEqual(new int[] { 10, 100, 17, 94 }, intList.Data.Take(4));

			intList.InsertRange(2, new int[] { 150, 200, 250, 300 });
			CollectionAssert.AreEqual(new int[] { 10, 100, 150, 200, 250, 300, 17, 94 }, intList);
			CollectionAssert.AreEqual(new int[] { 10, 100, 150, 200, 250, 300, 17, 94 }, intList.Data.Take(8));

			intList.Clear();
			Assert.AreEqual(0, intList.Count);
			Assert.IsTrue(!intList.Contains(94));
		}
示例#5
0
 /// <summary>
 /// Returns a resource to the pool.
 /// </summary>
 /// <param name="list">List to return.</param>
 public static void GiveBack(RawList <RayHit> list)
 {
     list.Clear();
     SubPoolRayHitList.GiveBack(list);
 }
示例#6
0
 public static void GetClosestPointOnTriangleToPoint(RawList<Vector3> q, int i, int j, int k, ref Vector3 p, RawList<int> subsimplex, RawList<float> baryCoords, out Vector3 closestPoint)
 {
     subsimplex.Clear();
     baryCoords.Clear();
     float v, w;
     Vector3 a = q[i];
     Vector3 b = q[j];
     Vector3 c = q[k];
     Vector3 ab;
     Vector3.Subtract(ref b, ref a, out ab);
     Vector3 ac;
     Vector3.Subtract(ref c, ref a, out ac);
     //Vertex region A?
     Vector3 ap;
     Vector3.Subtract(ref p, ref a, out ap);
     float d1;
     Vector3.Dot(ref ab, ref ap, out d1);
     float d2;
     Vector3.Dot(ref ac, ref ap, out d2);
     if (d1 <= 0 && d2 < 0)
     {
         subsimplex.Add(i);
         baryCoords.Add(1);
         closestPoint = a;
         return; //barycentric coordinates (1,0,0)
     }
     //Vertex region B?
     Vector3 bp;
     Vector3.Subtract(ref p, ref b, out bp);
     float d3;
     Vector3.Dot(ref ab, ref bp, out d3);
     float d4;
     Vector3.Dot(ref ac, ref bp, out d4);
     if (d3 >= 0 && d4 <= d3)
     {
         subsimplex.Add(j);
         baryCoords.Add(1);
         closestPoint = b;
         return; //barycentric coordinates (0,1,0)
     }
     //Edge region AB?
     float vc = d1 * d4 - d3 * d2;
     if (vc <= 0 && d1 >= 0 && d3 <= 0)
     {
         subsimplex.Add(i);
         subsimplex.Add(j);
         v = d1 / (d1 - d3);
         baryCoords.Add(1 - v);
         baryCoords.Add(v);
         Vector3.Multiply(ref ab, v, out closestPoint);
         Vector3.Add(ref closestPoint, ref a, out closestPoint);
         return; //barycentric coordinates (1-v, v, 0)
     }
     //Vertex region C?
     Vector3 cp;
     Vector3.Subtract(ref p, ref c, out cp);
     float d5;
     Vector3.Dot(ref ab, ref cp, out d5);
     float d6;
     Vector3.Dot(ref ac, ref cp, out d6);
     if (d6 >= 0 && d5 <= d6)
     {
         subsimplex.Add(k);
         baryCoords.Add(1);
         closestPoint = c;
         return; //barycentric coordinates (0,0,1)
     }
     //Edge region AC?
     float vb = d5 * d2 - d1 * d6;
     if (vb <= 0 && d2 >= 0 && d6 <= 0)
     {
         subsimplex.Add(i);
         subsimplex.Add(k);
         w = d2 / (d2 - d6);
         baryCoords.Add(1 - w);
         baryCoords.Add(w);
         Vector3.Multiply(ref ac, w, out closestPoint);
         Vector3.Add(ref closestPoint, ref a, out closestPoint);
         return; //barycentric coordinates (1-w, 0, w)
     }
     //Edge region BC?
     float va = d3 * d6 - d5 * d4;
     if (va <= 0 && (d4 - d3) >= 0 && (d5 - d6) >= 0)
     {
         subsimplex.Add(j);
         subsimplex.Add(k);
         w = (d4 - d3) / ((d4 - d3) + (d5 - d6));
         baryCoords.Add(1 - w);
         baryCoords.Add(w);
         Vector3.Subtract(ref c, ref b, out closestPoint);
         Vector3.Multiply(ref closestPoint, w, out closestPoint);
         Vector3.Add(ref closestPoint, ref b, out closestPoint);
         return; //barycentric coordinates (0, 1 - w ,w)
     }
     //Inside triangle?
     subsimplex.Add(i);
     subsimplex.Add(j);
     subsimplex.Add(k);
     float denom = 1 / (va + vb + vc);
     v = vb * denom;
     w = vc * denom;
     baryCoords.Add(1 - v - w);
     baryCoords.Add(v);
     baryCoords.Add(w);
     Vector3 abv;
     Vector3.Multiply(ref ab, v, out abv);
     Vector3 acw;
     Vector3.Multiply(ref ac, w, out acw);
     Vector3.Add(ref a, ref abv, out closestPoint);
     Vector3.Add(ref closestPoint, ref acw, out closestPoint);
     //return a + ab * v + ac * w; //barycentric coordinates (1 - v - w, v, w)
 }
示例#7
0
 /// <summary>
 /// Returns a resource to the pool.
 /// </summary>
 /// <param name="list">List to return.</param>
 public static void GiveBack(RawList<Entity> list)
 {
     list.Clear();
     SubPoolEntityRawList.GiveBack(list);
 }
        private static void GetTileAreaOutlines(IReadOnlyGrid<bool> tileArea, Vector2 tileSize, ref List<Vector2[]> outlines)
        {
            // Initialize the container we'll put our outlines into
            if (outlines == null)
                outlines = new List<Vector2[]>();
            else
                outlines.Clear();

            // Generate a data structure containing all visible edges
            TileEdgeMap edgeMap = new TileEdgeMap(tileArea.Width + 1, tileArea.Height + 1);
            for (int y = 0; y < edgeMap.Height; y++)
            {
                for (int x = 0; x < edgeMap.Width; x++)
                {
                    // Determine highlight state of the four tiles around this node
                    bool topLeft     = x > 0              && y > 0               && tileArea[x - 1, y - 1];
                    bool topRight    = x < tileArea.Width && y > 0               && tileArea[x    , y - 1];
                    bool bottomLeft  = x > 0              && y < tileArea.Height && tileArea[x - 1, y    ];
                    bool bottomRight = x < tileArea.Width && y < tileArea.Height && tileArea[x    , y    ];

                    // Determine which edges are visible
                    if (topLeft     != topRight   ) edgeMap.AddEdge(new Point2(x, y), new Point2(x    , y - 1));
                    if (topRight    != bottomRight) edgeMap.AddEdge(new Point2(x, y), new Point2(x + 1, y    ));
                    if (bottomRight != bottomLeft ) edgeMap.AddEdge(new Point2(x, y), new Point2(x    , y + 1));
                    if (bottomLeft  != topLeft    ) edgeMap.AddEdge(new Point2(x, y), new Point2(x - 1, y    ));
                }
            }

            // Traverse edges to form outlines until no more edges are left
            RawList<Vector2> outlineBuilder = new RawList<Vector2>();
            while (true)
            {
                // Find the beginning of an outline
                Point2 current = edgeMap.FindNonEmpty();
                if (current.X == -1 || current.Y == -1) break;

                // Traverse it until no more edges are left
                while (true)
                {
                    Point2 next = edgeMap.GetClockwiseNextFrom(current);
                    if (next.X == -1 || next.Y == -1) break;

                    outlineBuilder.Add(next * tileSize);
                    edgeMap.RemoveEdge(current, next);
                    current = next;
                }

                // Close the loop by adding the first element again
                if (outlineBuilder.Count > 0)
                    outlineBuilder.Add(outlineBuilder[0]);

                // If we have enough vertices, keep the outline for drawing
                Vector2[] outline = new Vector2[outlineBuilder.Count];
                outlineBuilder.CopyTo(outline, 0);
                outlines.Add(outline);

                // Reset the outline builder to an empty state
                outlineBuilder.Clear();
            }
        }
示例#9
0
 /// <summary>
 /// Returns a resource to the pool.
 /// </summary>
 /// <param name="list">List to return.</param>
 public static void GiveBack(RawList<CompoundChild> list)
 {
     list.Clear();
     SubPoolCompoundChildList.GiveBack(list);
 }
示例#10
0
 /// <summary>
 /// Returns a resource to the pool.
 /// </summary>
 /// <param name="list">List to return.</param>
 public static void GiveBack(RawList<float> list)
 {
     list.Clear();
     SubPoolFloatList.GiveBack(list);
 }
 /// <summary>
 /// Returns a resource to the pool.
 /// </summary>
 /// <param name="list">List to return.</param>
 public static void GiveBack(RawList<Collidable> list)
 {
     if (SubPoolCollidableList == null)
         SubPoolCollidableList = new UnsafeResourcePool<RawList<Collidable>>();
     list.Clear();
     SubPoolCollidableList.GiveBack(list);
 }
示例#12
0
        public bool LoadFromFile(
            GraphicsDevice gd,
            ResourceFactory factory,
            string filename,
            VertexLayoutDescription layout,
            ModelCreateInfo?createInfo,
            PostProcessSteps flags = DefaultPostProcessSteps)
        {
            // Load file
            AssimpContext assimpContext = new AssimpContext();
            Scene         pScene        = assimpContext.ImportFile(filename, flags);

            parts.Clear();
            parts.Count = (uint)pScene.Meshes.Count;

            Vector3 scale   = new Vector3(1.0f);
            Vector2 uvscale = new Vector2(1.0f);
            Vector3 center  = new Vector3(0.0f);

            if (createInfo != null)
            {
                scale   = createInfo.Value.Scale;
                uvscale = createInfo.Value.UVScale;
                center  = createInfo.Value.Center;
            }

            RawList <float> vertices = new RawList <float>();
            RawList <uint>  indices  = new RawList <uint>();

            vertexCount = 0;
            _indexCount = 0;

            // Load meshes
            for (int i = 0; i < pScene.Meshes.Count; i++)
            {
                var paiMesh = pScene.Meshes[i];

                parts[i]            = new ModelPart();
                parts[i].vertexBase = vertexCount;
                parts[i].indexBase  = _indexCount;

                vertexCount += (uint)paiMesh.VertexCount;

                var pColor = pScene.Materials[paiMesh.MaterialIndex].ColorDiffuse;

                Vector3D Zero3D = new Vector3D(0.0f, 0.0f, 0.0f);

                for (int j = 0; j < paiMesh.VertexCount; j++)
                {
                    Vector3D pPos       = paiMesh.Vertices[j];
                    Vector3D pNormal    = paiMesh.Normals[j];
                    Vector3D pTexCoord  = paiMesh.HasTextureCoords(0) ? paiMesh.TextureCoordinateChannels[0][j] : Zero3D;
                    Vector3D pTangent   = paiMesh.HasTangentBasis ? paiMesh.Tangents[j] : Zero3D;
                    Vector3D pBiTangent = paiMesh.HasTangentBasis ? paiMesh.BiTangents[j] : Zero3D;

                    foreach (var component in layout.Elements)
                    {
                        switch (component.Semantic)
                        {
                        case VertexElementSemantic.Position:
                            vertices.Add(pPos.X * scale.X + center.X);
                            vertices.Add(-pPos.Y * scale.Y + center.Y);
                            vertices.Add(pPos.Z * scale.Z + center.Z);
                            break;

                        case VertexElementSemantic.Normal:
                            vertices.Add(pNormal.X);
                            vertices.Add(-pNormal.Y);
                            vertices.Add(pNormal.Z);
                            break;

                        case VertexElementSemantic.TextureCoordinate:
                            vertices.Add(pTexCoord.X * uvscale.X);
                            vertices.Add(pTexCoord.Y * uvscale.Y);
                            break;

                        case VertexElementSemantic.Color:
                            vertices.Add(pColor.R);
                            vertices.Add(pColor.G);
                            vertices.Add(pColor.B);
                            break;

                        default: throw new System.NotImplementedException();
                        }
                        ;
                    }

                    dim.Max.X = Math.Max(pPos.X, dim.Max.X);
                    dim.Max.Y = Math.Max(pPos.Y, dim.Max.Y);
                    dim.Max.Z = Math.Max(pPos.Z, dim.Max.Z);

                    dim.Min.X = Math.Min(pPos.X, dim.Min.X);
                    dim.Min.Y = Math.Min(pPos.Y, dim.Min.Y);
                    dim.Min.Z = Math.Min(pPos.Z, dim.Min.Z);
                }

                dim.Size = dim.Max - dim.Min;

                parts[i].vertexCount = (uint)paiMesh.VertexCount;

                uint indexBase = indices.Count;
                for (uint j = 0; j < paiMesh.FaceCount; j++)
                {
                    Face Face = paiMesh.Faces[(int)j];
                    if (Face.IndexCount != 3)
                    {
                        continue;
                    }
                    indices.Add(indexBase + (uint)Face.Indices[0]);
                    indices.Add(indexBase + (uint)Face.Indices[1]);
                    indices.Add(indexBase + (uint)Face.Indices[2]);
                    parts[i].indexCount += 3;
                    _indexCount         += 3;
                }
            }


            uint vBufferSize = (vertices.Count) * sizeof(float);
            uint iBufferSize = (indices.Count) * sizeof(uint);

            _vertexBuffer = factory.CreateBuffer(new BufferDescription(vBufferSize, BufferUsage.VertexBuffer));
            _indexBuffer  = factory.CreateBuffer(new BufferDescription(iBufferSize, BufferUsage.IndexBuffer));

            gd.UpdateBuffer(_vertexBuffer, 0, ref vertices[0], vBufferSize);
            gd.UpdateBuffer(_indexBuffer, 0, ref indices[0], iBufferSize);

            return(true);
        }
示例#13
0
        /// <summary>
        /// Identifies the indices of points in a set which are on the outer convex hull of the set.
        /// </summary>
        /// <param name="points">List of points in the set.</param>
        /// <param name="outputTriangleIndices">List of indices into the input point set composing the triangulated surface of the convex hull.
        /// Each group of 3 indices represents a triangle on the surface of the hull.</param>
        public static void GetConvexHull(RawList <Vector3> points, RawList <int> outputTriangleIndices)
        {
            if (points.Count == 0)
            {
                throw new ArgumentException("Point set must have volume.");
            }

            RawList <int> outsidePoints = CommonResources.GetIntList();

            if (outsidePoints.Capacity < points.Count - 4)
            {
                outsidePoints.Capacity = points.Count - 4;
            }

            //Build the initial tetrahedron.
            //It will also give us the location of a point which is guaranteed to be within the
            //final convex hull.  We can use this point to calibrate the winding of triangles.
            //A set of outside point candidates (all points other than those composing the tetrahedron) will be returned in the outsidePoints list.
            //That list will then be further pruned by the RemoveInsidePoints call.
            Vector3 insidePoint;

            ComputeInitialTetrahedron(points, outsidePoints, outputTriangleIndices, out insidePoint);

            //Compute outside points.
            RemoveInsidePoints(points, outputTriangleIndices, outsidePoints);

            RawList <int> edges        = CommonResources.GetIntList();
            RawList <int> toRemove     = CommonResources.GetIntList();
            RawList <int> newTriangles = CommonResources.GetIntList();

            //We're now ready to begin the main loop.
            while (outsidePoints.Count > 0)
            //While the convex hull is incomplete...
            {
                for (int k = 0; k < outputTriangleIndices.Count; k += 3)
                {
                    //Find the normal of the triangle
                    Vector3 normal;
                    FindNormal(outputTriangleIndices, points, k, out normal);

                    //Get the furthest point in the direction of the normal.
                    int     maxIndexInOutsideList = GetExtremePoint(ref normal, points, outsidePoints);
                    int     maxIndex = outsidePoints.Elements[maxIndexInOutsideList];
                    Vector3 maximum  = points.Elements[maxIndex];

                    //If the point is beyond the current triangle, continue.
                    Vector3 offset;
                    Vector3.Subtract(ref maximum, ref points.Elements[outputTriangleIndices.Elements[k]], out offset);
                    float dot;
                    Vector3.Dot(ref normal, ref offset, out dot);
                    if (dot > 0)
                    {
                        //It's been picked! Remove the maximum point from the outside.
                        outsidePoints.FastRemoveAt(maxIndexInOutsideList);
                        //Remove any triangles that can see the point, including itself!
                        edges.Clear();
                        toRemove.Clear();
                        for (int n = outputTriangleIndices.Count - 3; n >= 0; n -= 3)
                        //Go through each triangle, if it can be seen, delete it and use maintainEdge on its edges.
                        {
                            if (IsTriangleVisibleFromPoint(outputTriangleIndices, points, n, ref maximum))
                            {
                                //This triangle can see it!
                                //TODO: CONSIDER CONSISTENT WINDING HAPPYTIMES
                                MaintainEdge(outputTriangleIndices[n], outputTriangleIndices[n + 1], edges);
                                MaintainEdge(outputTriangleIndices[n], outputTriangleIndices[n + 2], edges);
                                MaintainEdge(outputTriangleIndices[n + 1], outputTriangleIndices[n + 2], edges);
                                //Because fast removals are being used, the order is very important.
                                //It's pulling indices in from the end of the list in order, and also ensuring
                                //that we never issue a removal order beyond the end of the list.
                                outputTriangleIndices.FastRemoveAt(n + 2);
                                outputTriangleIndices.FastRemoveAt(n + 1);
                                outputTriangleIndices.FastRemoveAt(n);
                            }
                        }

                        //Create new triangles.
                        for (int n = 0; n < edges.Count; n += 2)
                        {
                            //For each edge, create a triangle with the extreme point.
                            newTriangles.Add(edges[n]);
                            newTriangles.Add(edges[n + 1]);
                            newTriangles.Add(maxIndex);
                        }

                        //Only verify the windings of the new triangles.
                        VerifyWindings(newTriangles, points, ref insidePoint);
                        outputTriangleIndices.AddRange(newTriangles);
                        newTriangles.Clear();

                        //Remove all points from the outsidePoints if they are inside the polyhedron
                        RemoveInsidePoints(points, outputTriangleIndices, outsidePoints);

                        //The list has been significantly messed with, so restart the loop.
                        break;
                    }
                }
            }


            CommonResources.GiveBack(outsidePoints);
            CommonResources.GiveBack(edges);
            CommonResources.GiveBack(toRemove);
            CommonResources.GiveBack(newTriangles);
        }
示例#14
0
        protected RawList <ImportInputAssignment> SelectImporter(AssetImportEnvironment env)
        {
            if (!env.IsPrepareStep)
            {
                throw new ArgumentException(
                          "The specified import environment must be configured as a preparation environment.",
                          "env");
            }

            // Find an importer to handle some or all of the unhandled input files
            RawList <ImportInputAssignment> candidateMapping = new RawList <ImportInputAssignment>();

            foreach (IAssetImporter importer in AssetManager.Importers)
            {
                env.ResetAcquiredData();

                try
                {
                    importer.PrepareImport(env);
                }
                catch (Exception ex)
                {
                    Log.Editor.WriteError("An error occurred in the preparation step of '{1}': {0}",
                                          Log.Exception(ex),
                                          Log.Type(importer.GetType()));
                    continue;
                }

                if (env.HandledInput.Any())
                {
                    candidateMapping.Add(new ImportInputAssignment
                    {
                        Importer       = importer,
                        HandledInput   = env.HandledInput.ToArray(),
                        ExpectedOutput = env.Output.ToArray()
                    });
                }
            }

            // Sort candidate mapping from most files to least files, so we can solve the biggest conflicts first
            candidateMapping.Sort((a, b) => b.HandledInput.Length - a.HandledInput.Length);

            // Determine if multiple importers intend to handle the same files and resolve conflicts
            List <int>    conflictingIndices = new List <int>();
            List <string> conflictingFiles   = new List <string>();

            for (int mainIndex = 0; mainIndex < candidateMapping.Count; mainIndex++)
            {
                ImportInputAssignment assignment = candidateMapping[mainIndex];

                // Find all conflicts related to this assignment
                conflictingIndices.Clear();
                conflictingFiles.Clear();
                for (int secondIndex = 0; secondIndex < candidateMapping.Count; secondIndex++)
                {
                    if (secondIndex == mainIndex)
                    {
                        continue;
                    }

                    ImportInputAssignment conflictAssignment = candidateMapping[secondIndex];
                    IEnumerable <string>  mainFiles          = assignment.HandledInput.Select(item => item.Path);
                    IEnumerable <string>  secondFiles        = conflictAssignment.HandledInput.Select(item => item.Path);
                    string[] conflicts = mainFiles.Intersect(secondFiles).ToArray();
                    if (conflicts.Length > 0)
                    {
                        if (conflictingIndices.Count == 0)
                        {
                            conflictingIndices.Add(mainIndex);
                        }
                        conflictingIndices.Add(secondIndex);
                        conflictingFiles.AddRange(conflicts);
                    }
                }

                // Resolve conflicts with this assignment
                if (conflictingIndices.Count > 0)
                {
                    // Determine which importer to prefer for this conflict
                    ImportInputAssignment[] conflictingAssignments = conflictingIndices.Select(i => candidateMapping[i]).ToArray();
                    int keepIndex = this.ResolveMappingConflict(conflictingAssignments);

                    // If we somehow decided that none of the options is viable, abort the operation
                    if (keepIndex == -1)
                    {
                        candidateMapping.Clear();
                        return(candidateMapping);
                    }

                    // Sort indices to remove in declining order and remove their mappings
                    conflictingIndices.Remove(keepIndex);
                    conflictingIndices.Sort((a, b) => b - a);
                    foreach (int index in conflictingIndices)
                    {
                        candidateMapping.RemoveAt(index);
                    }

                    // Start over with the conflict search
                    mainIndex = -1;
                    continue;
                }
            }

            return(candidateMapping);
        }
示例#15
0
        private static void GenerateCollisionShapes(TileEdgeMap edgeMap, Vector2 origin, Vector2 tileSize, bool roundedCorners, IList <ShapeInfo> shapeList)
        {
            // Traverse the edge map and gradually create chain / loop
            // shapes until all edges have been used.
            RawList <Point2>  currentChain = new RawList <Point2>();
            RawList <Vector2> vertexBuffer = new RawList <Vector2>();

            while (true)
            {
                // Begin a new continuous chain of nodes
                currentChain.Clear();

                // Find a starting node for our current chain.
                // If there is none, we found and handled all edges.
                Point2 start = edgeMap.FindNonEmpty();
                if (start == new Point2(-1, -1))
                {
                    break;
                }

                // Traverse the current chain node-by-node from the start we found
                Point2 current = start;
                while (true)
                {
                    // Add the current node to our continuous chain
                    currentChain.Add(current);

                    // Find the next node that connects to the current one.
                    // If there is none, our current chain is done.
                    Point2 next = edgeMap.GetClockwiseNextFrom(current);
                    if (next == new Point2(-1, -1))
                    {
                        break;
                    }

                    // Remove the edge we used to get to the next node
                    edgeMap.RemoveEdge(current, next);

                    // Use the next node as origin for traversing further
                    current = next;
                }

                // Generate a shape from the current chain
                bool isLoop = (start == currentChain[currentChain.Count - 1]);
                if (isLoop)
                {
                    currentChain.RemoveAt(currentChain.Count - 1);
                }
                vertexBuffer.Clear();

                // Rounded corners
                if (roundedCorners && currentChain.Count >= 3)
                {
                    vertexBuffer.Reserve(currentChain.Count * 2);
                    vertexBuffer.Count = 0;
                    for (int i = 0; i < currentChain.Count; i++)
                    {
                        int prevIndex;
                        int nextIndex;
                        if (isLoop)
                        {
                            prevIndex = (i - 1 + currentChain.Count) % currentChain.Count;
                            nextIndex = (i + 1) % currentChain.Count;
                        }
                        else
                        {
                            prevIndex = Math.Max(i - 1, 0);
                            nextIndex = Math.Min(i + 1, currentChain.Count - 1);
                        }

                        Vector2 currentVert = origin + tileSize * (Vector2)currentChain[i];
                        Vector2 prevVert    = origin + tileSize * (Vector2)currentChain[prevIndex];
                        Vector2 nextVert    = origin + tileSize * (Vector2)currentChain[nextIndex];

                        if (nextVert - currentVert != currentVert - prevVert)
                        {
                            if (!isLoop && (i == 0 || i == currentChain.Count - 1))
                            {
                                vertexBuffer.Add(currentVert);
                            }
                            else
                            {
                                vertexBuffer.Add(currentVert + (prevVert - currentVert).Normalized * tileSize * 0.2f);
                                vertexBuffer.Add(currentVert + (nextVert - currentVert).Normalized * tileSize * 0.2f);
                            }
                        }
                    }
                }
                // Sharp corners
                else
                {
                    vertexBuffer.Reserve(currentChain.Count);
                    vertexBuffer.Count = 0;
                    for (int i = 0; i < currentChain.Count; i++)
                    {
                        int prevIndex;
                        int nextIndex;
                        if (isLoop)
                        {
                            prevIndex = (i - 1 + currentChain.Count) % currentChain.Count;
                            nextIndex = (i + 1) % currentChain.Count;
                        }
                        else
                        {
                            prevIndex = Math.Max(i - 1, 0);
                            nextIndex = Math.Min(i + 1, currentChain.Count - 1);
                        }

                        Vector2 currentVert = origin + tileSize * (Vector2)currentChain[i];
                        Vector2 prevVert    = origin + tileSize * (Vector2)currentChain[prevIndex];
                        Vector2 nextVert    = origin + tileSize * (Vector2)currentChain[nextIndex];

                        if (nextVert - currentVert != currentVert - prevVert)
                        {
                            vertexBuffer.Add(currentVert);
                        }
                    }
                }

                Vector2[] vertices = new Vector2[vertexBuffer.Count];
                vertexBuffer.CopyTo(vertices, 0);
                shapeList.Add(isLoop ?
                              (ShapeInfo) new LoopShapeInfo(vertices) :
                              (ShapeInfo) new ChainShapeInfo(vertices));
            }
        }
示例#16
0
        /// <summary>
        /// Updates the collection of supporting contacts.
        /// </summary>
        public void UpdateSupports(ref Vector3 movementDirection)
        {
            bool hadTraction = HasTraction;

            //Reset traction/support.
            HasTraction = false;
            HasSupport  = false;

            Vector3 downDirection = characterBody.orientationMatrix.Down;
            Vector3 bodyPosition  = characterBody.position;

            //Compute the character's radius, minus a little margin. We want the rays to originate safely within the character's body.
            //Assume vertical rotational invariance. Spheres, cylinders, and capsules don't have varying horizontal radii.
            Vector3 extremePoint;
            var     convexShape = characterBody.CollisionInformation.Shape as ConvexShape;

            Debug.Assert(convexShape != null, "Character bodies must be convex.");

            //Find the lowest point on the collision shape.
            convexShape.GetLocalExtremePointWithoutMargin(ref Toolbox.DownVector, out extremePoint);
            BottomDistance = -extremePoint.Y + convexShape.collisionMargin;

            convexShape.GetLocalExtremePointWithoutMargin(ref Toolbox.RightVector, out extremePoint);
            float rayCastInnerRadius = Math.Max((extremePoint.X + convexShape.collisionMargin) * 0.8f, extremePoint.X);

            //Vertically, the rays will start at the same height as the character's center.
            //While they could be started lower on a cylinder, that wouldn't always work for a sphere or capsule: the origin might end up outside of the shape!

            tractionContacts.Clear();
            supportContacts.Clear();
            sideContacts.Clear();
            headContacts.Clear();

            foreach (var pair in characterBody.CollisionInformation.Pairs)
            {
                //Don't stand on things that aren't really colliding fully.
                if (pair.CollisionRule != CollisionRule.Normal)
                {
                    continue;
                }
                ContactCategorizer.CategorizeContacts(pair, characterBody.CollisionInformation, ref downDirection, ref tractionContacts, ref supportContacts, ref sideContacts, ref headContacts);
            }

            HasSupport  = supportContacts.Count > 0;
            HasTraction = tractionContacts.Count > 0;

            //Only perform ray casts if the character has fully left the surface, and only if the previous frame had traction.
            //(If ray casts are allowed when support contacts still exist, the door is opened for climbing surfaces which should not be climbable.
            //Consider a steep slope. If the character runs at it, the character will likely be wedged off of the ground, making it lose traction while still having a support contact with the slope.
            //If ray tests are allowed when support contacts exist, the character will maintain traction despite climbing the wall.
            //The VerticalMotionConstraint can stop the character from climbing in many cases, but it's nice not to have to rely on it.
            //Disallowing ray tests when supports exist does have a cost, though. For example, consider rounded steps.
            //If the character walks off a step such that it is still in contact with the step but is far enough down that the slope is too steep for traction,
            //the ray test won't recover traction. This situation just isn't very common.)
            if (!HasSupport && hadTraction)
            {
                float supportRayLength = maximumAssistedDownStepHeight + BottomDistance;
                SupportRayData = null;
                //If the contacts aren't available to support the character, raycast down to find the ground.
                if (!HasTraction)
                {
                    //TODO: could also require that the character has a nonzero movement direction in order to use a ray cast.  Questionable- would complicate the behavior on edges.
                    Ray ray = new Ray(bodyPosition, downDirection);

                    bool           hasTraction;
                    SupportRayData data;
                    if (TryDownCast(ref ray, supportRayLength, out hasTraction, out data))
                    {
                        SupportRayData = data;
                        HasTraction    = data.HasTraction;
                        HasSupport     = true;
                    }
                }

                //If contacts and the center ray cast failed, try a ray offset in the movement direction.
                bool tryingToMove = movementDirection.LengthSquared() > 0;
                if (!HasTraction && tryingToMove)
                {
                    Ray ray = new Ray(
                        characterBody.Position +
                        movementDirection * rayCastInnerRadius, downDirection);

                    //Have to test to make sure the ray doesn't get obstructed.  This could happen if the character is deeply embedded in a wall; we wouldn't want it detecting things inside the wall as a support!
                    Ray obstructionRay;
                    obstructionRay.Position  = characterBody.Position;
                    obstructionRay.Direction = ray.Position - obstructionRay.Position;
                    if (!QueryManager.RayCastHitAnything(obstructionRay, 1))
                    {
                        //The origin isn't obstructed, so now ray cast down.
                        bool           hasTraction;
                        SupportRayData data;
                        if (TryDownCast(ref ray, supportRayLength, out hasTraction, out data))
                        {
                            if (SupportRayData == null || data.HitData.T < SupportRayData.Value.HitData.T)
                            {
                                //Only replace the previous support ray if we now have traction or we didn't have a support ray at all before,
                                //or this hit is a better (sooner) hit.
                                if (hasTraction)
                                {
                                    SupportRayData = data;
                                    HasTraction    = true;
                                }
                                else if (SupportRayData == null)
                                {
                                    SupportRayData = data;
                                }
                                HasSupport = true;
                            }
                        }
                    }
                }

                //If contacts, center ray, AND forward ray failed to find traction, try a side ray created from down x forward.
                if (!HasTraction && tryingToMove)
                {
                    //Compute the horizontal offset direction.  Down direction and the movement direction are normalized and perpendicular, so the result is too.
                    Vector3 horizontalOffset;
                    Vector3.Cross(ref movementDirection, ref downDirection, out horizontalOffset);
                    Vector3.Multiply(ref horizontalOffset, rayCastInnerRadius, out horizontalOffset);
                    Ray ray = new Ray(bodyPosition + horizontalOffset, downDirection);

                    //Have to test to make sure the ray doesn't get obstructed.  This could happen if the character is deeply embedded in a wall; we wouldn't want it detecting things inside the wall as a support!
                    Ray obstructionRay;
                    obstructionRay.Position  = bodyPosition;
                    obstructionRay.Direction = ray.Position - obstructionRay.Position;
                    if (!QueryManager.RayCastHitAnything(obstructionRay, 1))
                    {
                        //The origin isn't obstructed, so now ray cast down.
                        bool           hasTraction;
                        SupportRayData data;
                        if (TryDownCast(ref ray, supportRayLength, out hasTraction, out data))
                        {
                            if (SupportRayData == null || data.HitData.T < SupportRayData.Value.HitData.T)
                            {
                                //Only replace the previous support ray if we now have traction or we didn't have a support ray at all before,
                                //or this hit is a better (sooner) hit.
                                if (hasTraction)
                                {
                                    SupportRayData = data;
                                    HasTraction    = true;
                                }
                                else if (SupportRayData == null)
                                {
                                    SupportRayData = data;
                                }
                                HasSupport = true;
                            }
                        }
                    }
                }

                //If contacts, center ray, forward ray, AND the first side ray failed to find traction, try a side ray created from forward x down.
                if (!HasTraction && tryingToMove)
                {
                    //Compute the horizontal offset direction.  Down direction and the movement direction are normalized and perpendicular, so the result is too.
                    Vector3 horizontalOffset;
                    Vector3.Cross(ref downDirection, ref movementDirection, out horizontalOffset);
                    Vector3.Multiply(ref horizontalOffset, rayCastInnerRadius, out horizontalOffset);
                    Ray ray = new Ray(bodyPosition + horizontalOffset, downDirection);

                    //Have to test to make sure the ray doesn't get obstructed.  This could happen if the character is deeply embedded in a wall; we wouldn't want it detecting things inside the wall as a support!
                    Ray obstructionRay;
                    obstructionRay.Position  = bodyPosition;
                    obstructionRay.Direction = ray.Position - obstructionRay.Position;
                    if (!QueryManager.RayCastHitAnything(obstructionRay, 1))
                    {
                        //The origin isn't obstructed, so now ray cast down.
                        bool           hasTraction;
                        SupportRayData data;
                        if (TryDownCast(ref ray, supportRayLength, out hasTraction, out data))
                        {
                            if (SupportRayData == null || data.HitData.T < SupportRayData.Value.HitData.T)
                            {
                                //Only replace the previous support ray if we now have traction or we didn't have a support ray at all before,
                                //or this hit is a better (sooner) hit.
                                if (hasTraction)
                                {
                                    SupportRayData = data;
                                    HasTraction    = true;
                                }
                                else if (SupportRayData == null)
                                {
                                    SupportRayData = data;
                                }
                                HasSupport = true;
                            }
                        }
                    }
                }
            }

            UpdateSupportData(ref downDirection);
            UpdateVerticalSupportData(ref downDirection, ref movementDirection);
        }
示例#17
0
        void ComputeShapeInformation(TransformableMeshData data, out ShapeDistributionInformation shapeInformation)
        {
            var indices = Resources.GetIntList();

            surfaceVertices.Clear();
            Toolbox.GetConvexHull(data.vertices, indices, surfaceVertices);
            for (int i = 0; i < surfaceVertices.count; i++)
            {
                AffineTransform.Transform(ref surfaceVertices.Elements[i], ref data.worldTransform, out surfaceVertices.Elements[i]);
            }
            shapeInformation.Center = new Vector3();

            if (solidity == MobileMeshSolidity.Solid)
            {
                //The following inertia tensor calculation assumes a closed mesh.

                shapeInformation.Volume = 0;
                for (int i = 0; i < data._indices.Length; i += 3)
                {
                    Vector3 v2, v3, v4;
                    data.GetTriangle(i, out v2, out v3, out v4);

                    //Determinant is 6 * volume.  It's signed, though; this is because the mesh isn't necessarily convex nor centered on the origin.
                    float tetrahedronVolume = v2.X * (v3.Y * v4.Z - v3.Z * v4.Y) -
                                              v3.X * (v2.Y * v4.Z - v2.Z * v4.Y) +
                                              v4.X * (v2.Y * v3.Z - v2.Z * v3.Y);

                    shapeInformation.Volume += tetrahedronVolume;
                    shapeInformation.Center += tetrahedronVolume * (v2 + v3 + v4);
                }
                shapeInformation.Center /= shapeInformation.Volume * 4;
                shapeInformation.Volume /= 6;
                shapeInformation.Volume  = Math.Abs(shapeInformation.Volume);

                data.worldTransform.Translation -= shapeInformation.Center;

                //Source: Explicit Exact Formulas for the 3-D Tetrahedron Inertia Tensor in Terms of its Vertex Coordinates
                //http://www.scipub.org/fulltext/jms2/jms2118-11.pdf
                //x1, x2, x3, x4 are origin, triangle1, triangle2, triangle3
                //Looking to find inertia tensor matrix of the form
                // [  a  -b' -c' ]
                // [ -b'  b  -a' ]
                // [ -c' -a'  c  ]
                float a = 0, b = 0, c = 0, ao = 0, bo = 0, co = 0;

                float totalWeight = 0;
                for (int i = 0; i < data._indices.Length; i += 3)
                {
                    Vector3 v2, v3, v4;
                    data.GetTriangle(i, out v2, out v3, out v4);

                    //Determinant is 6 * volume.  It's signed, though; this is because the mesh isn't necessarily convex nor centered on the origin.
                    float tetrahedronVolume = v2.X * (v3.Y * v4.Z - v3.Z * v4.Y) -
                                              v3.X * (v2.Y * v4.Z - v2.Z * v4.Y) +
                                              v4.X * (v2.Y * v3.Z - v2.Z * v3.Y);

                    totalWeight += tetrahedronVolume;

                    a += tetrahedronVolume * (v2.Y * v2.Y + v2.Y * v3.Y + v3.Y * v3.Y + v2.Y * v4.Y + v3.Y * v4.Y + v4.Y * v4.Y +
                                              v2.Z * v2.Z + v2.Z * v3.Z + v3.Z * v3.Z + v2.Z * v4.Z + v3.Z * v4.Z + v4.Z * v4.Z);
                    b += tetrahedronVolume * (v2.X * v2.X + v2.X * v3.X + v3.X * v3.X + v2.X * v4.X + v3.X * v4.X + v4.X * v4.X +
                                              v2.Z * v2.Z + v2.Z * v3.Z + v3.Z * v3.Z + v2.Z * v4.Z + v3.Z * v4.Z + v4.Z * v4.Z);
                    c += tetrahedronVolume * (v2.X * v2.X + v2.X * v3.X + v3.X * v3.X + v2.X * v4.X + v3.X * v4.X + v4.X * v4.X +
                                              v2.Y * v2.Y + v2.Y * v3.Y + v3.Y * v3.Y + v2.Y * v4.Y + v3.Y * v4.Y + v4.Y * v4.Y);
                    ao += tetrahedronVolume * (2 * v2.Y * v2.Z + v3.Y * v2.Z + v4.Y * v2.Z + v2.Y * v3.Z + 2 * v3.Y * v3.Z + v4.Y * v3.Z + v2.Y * v4.Z + v3.Y * v4.Z + 2 * v4.Y * v4.Z);
                    bo += tetrahedronVolume * (2 * v2.X * v2.Z + v3.X * v2.Z + v4.X * v2.Z + v2.X * v3.Z + 2 * v3.X * v3.Z + v4.X * v3.Z + v2.X * v4.Z + v3.X * v4.Z + 2 * v4.X * v4.Z);
                    co += tetrahedronVolume * (2 * v2.X * v2.Y + v3.X * v2.Y + v4.X * v2.Y + v2.X * v3.Y + 2 * v3.X * v3.Y + v4.X * v3.Y + v2.X * v4.Y + v3.X * v4.Y + 2 * v4.X * v4.Y);
                }
                float density        = 1 / totalWeight;
                float diagonalFactor = density / 10;
                float offFactor      = -density / 20;
                a  *= diagonalFactor;
                b  *= diagonalFactor;
                c  *= diagonalFactor;
                ao *= offFactor;
                bo *= offFactor;
                co *= offFactor;
                shapeInformation.VolumeDistribution = new Matrix3X3(a, bo, co,
                                                                    bo, b, ao,
                                                                    co, ao, c);
            }
            else
            {
                shapeInformation.Center = new Vector3();
                float totalWeight = 0;
                for (int i = 0; i < data._indices.Length; i += 3)
                { //Configure the inertia tensor to be local.
                    Vector3 vA, vB, vC;
                    data.GetTriangle(i, out vA, out vB, out vC);
                    Vector3 vAvB;
                    Vector3 vAvC;
                    Vector3.Subtract(ref vB, ref vA, out vAvB);
                    Vector3.Subtract(ref vC, ref vA, out vAvC);
                    Vector3 cross;
                    Vector3.Cross(ref vAvB, ref vAvC, out cross);
                    float weight = cross.Length();
                    totalWeight += weight;

                    shapeInformation.Center += weight * (vA + vB + vC) / 3;
                }
                shapeInformation.Center /= totalWeight;
                shapeInformation.Volume  = 0;


                data.worldTransform.Translation -= shapeInformation.Center;

                shapeInformation.VolumeDistribution = new Matrix3X3();
                for (int i = 0; i < data._indices.Length; i += 3)
                { //Configure the inertia tensor to be local.
                    Vector3 vA, vB, vC;
                    data.GetTriangle(i, out vA, out vB, out vC);
                    Vector3 vAvB;
                    Vector3 vAvC;
                    Vector3.Subtract(ref vB, ref vA, out vAvB);
                    Vector3.Subtract(ref vC, ref vA, out vAvC);
                    Vector3 cross;
                    Vector3.Cross(ref vAvB, ref vAvC, out cross);
                    float weight = cross.Length();
                    totalWeight += weight;

                    Matrix3X3 innerProduct;
                    Matrix3X3.CreateScale(vA.LengthSquared(), out innerProduct);
                    Matrix3X3 outerProduct;
                    Matrix3X3.CreateOuterProduct(ref vA, ref vA, out outerProduct);
                    Matrix3X3 contribution;
                    Matrix3X3.Subtract(ref innerProduct, ref outerProduct, out contribution);
                    Matrix3X3.Multiply(ref contribution, weight, out contribution);
                    Matrix3X3.Add(ref shapeInformation.VolumeDistribution, ref contribution, out shapeInformation.VolumeDistribution);

                    Matrix3X3.CreateScale(vB.LengthSquared(), out innerProduct);
                    Matrix3X3.CreateOuterProduct(ref vB, ref vB, out outerProduct);
                    Matrix3X3.Subtract(ref innerProduct, ref outerProduct, out outerProduct);
                    Matrix3X3.Multiply(ref contribution, weight, out contribution);
                    Matrix3X3.Add(ref shapeInformation.VolumeDistribution, ref contribution, out shapeInformation.VolumeDistribution);

                    Matrix3X3.CreateScale(vC.LengthSquared(), out innerProduct);
                    Matrix3X3.CreateOuterProduct(ref vC, ref vC, out outerProduct);
                    Matrix3X3.Subtract(ref innerProduct, ref outerProduct, out contribution);
                    Matrix3X3.Multiply(ref contribution, weight, out contribution);
                    Matrix3X3.Add(ref shapeInformation.VolumeDistribution, ref contribution, out shapeInformation.VolumeDistribution);
                }
                Matrix3X3.Multiply(ref shapeInformation.VolumeDistribution, 1 / (6 * totalWeight), out shapeInformation.VolumeDistribution);
            }

            ////Configure the inertia tensor to be local.
            //Vector3 finalOffset = shapeInformation.Center;
            //Matrix3X3 finalInnerProduct;
            //Matrix3X3.CreateScale(finalOffset.LengthSquared(), out finalInnerProduct);
            //Matrix3X3 finalOuterProduct;
            //Matrix3X3.CreateOuterProduct(ref finalOffset, ref finalOffset, out finalOuterProduct);

            //Matrix3X3 finalContribution;
            //Matrix3X3.Subtract(ref finalInnerProduct, ref finalOuterProduct, out finalContribution);

            //Matrix3X3.Subtract(ref shapeInformation.VolumeDistribution, ref finalContribution, out shapeInformation.VolumeDistribution);
        }
 /// <summary>
 /// Returns a resource to the pool.
 /// </summary>
 /// <param name="list">List to return.</param>
 public static void GiveBack(RawList<CompoundChild> list)
 {
     if (SubPoolCompoundChildList == null)
         SubPoolCompoundChildList = new UnsafeResourcePool<RawList<CompoundChild>>();
     list.Clear();
     SubPoolCompoundChildList.GiveBack(list);
 }
示例#19
0
 /// <summary>
 /// Returns a resource to the pool.
 /// </summary>
 /// <param name="list">List to return.</param>
 public static void GiveBack(RawList<RayHit> list)
 {
     list.Clear();
     SubPoolRayHitList.GiveBack(list);
 }
示例#20
0
 private void UpdateSurfaceVertices()
 {
     hullVertices.Clear();
     if (Volume > 0)
     {
         ConvexHullHelper.GetConvexHull(triangleMesh.Data.vertices, hullVertices);
         var transformableData = triangleMesh.Data as TransformableMeshData;
         if (transformableData != null)
         {
             var transform = transformableData.worldTransform;
             for (int i = 0; i < hullVertices.Count; i++)
             {
                 AffineTransform.Transform(ref hullVertices.Elements[i], ref transform, out hullVertices.Elements[i]);
             }
         }
     }
     else
     {
         hullVertices.Clear();
         //A mobile mesh is allowed to have zero volume, so long as it isn't solid.
         //In this case, compute the bounding box of all points.
         BoundingBox box = new BoundingBox();
         for (int i = 0; i < triangleMesh.Data.vertices.Length; i++)
         {
             Vector3 v;
             triangleMesh.Data.GetVertexPosition(i, out v);
             if (v.X > box.Max.X)
             {
                 box.Max.X = v.X;
             }
             if (v.X < box.Min.X)
             {
                 box.Min.X = v.X;
             }
             if (v.Y > box.Max.Y)
             {
                 box.Max.Y = v.Y;
             }
             if (v.Y < box.Min.Y)
             {
                 box.Min.Y = v.Y;
             }
             if (v.Z > box.Max.Z)
             {
                 box.Max.Z = v.Z;
             }
             if (v.Z < box.Min.Z)
             {
                 box.Min.Z = v.Z;
             }
         }
         //Add the corners.  This will overestimate the size of the surface a bit.
         hullVertices.Add(box.Min);
         hullVertices.Add(box.Max);
         hullVertices.Add(new Vector3(box.Min.X, box.Min.Y, box.Max.Z));
         hullVertices.Add(new Vector3(box.Min.X, box.Max.Y, box.Min.Z));
         hullVertices.Add(new Vector3(box.Max.X, box.Min.Y, box.Min.Z));
         hullVertices.Add(new Vector3(box.Min.X, box.Max.Y, box.Max.Z));
         hullVertices.Add(new Vector3(box.Max.X, box.Max.Y, box.Min.Z));
         hullVertices.Add(new Vector3(box.Max.X, box.Min.Y, box.Max.Z));
     }
 }
示例#21
0
 /// <summary>
 /// Returns a resource to the pool.
 /// </summary>
 /// <param name="list">List to return.</param>
 public static void GiveBack(RawList <int> list)
 {
     list.Clear();
     SubPoolIntList.GiveBack(list);
 }
示例#22
0
 /// <summary>
 /// Returns a resource to the pool.
 /// </summary>
 /// <param name="list">List to return.</param>
 public static void GiveBack(RawList <float> list)
 {
     list.Clear();
     SubPoolFloatList.GiveBack(list);
 }
        public override void UpdateCollision(float dt)
        {
            WasContaining = Containing;
            WasTouching   = Touching;

            //Gather current pairs.
            UpdateContainedPairs();

            //Eliminate old pairs.
            foreach (var other in subPairs.Keys)
            {
                if (!containedPairs.Contains(other))
                {
                    pairsToRemove.Add(other);
                }
            }
            for (int i = 0; i < pairsToRemove.Count; i++)
            {
                var toReturn = subPairs[pairsToRemove.Elements[i]];
                subPairs.Remove(pairsToRemove.Elements[i]);
                toReturn.CleanUp();
                toReturn.Factory.GiveBack(toReturn);
            }
            containedPairs.Clear();
            pairsToRemove.Clear();


            //Scan the pairs in sequence, updating the state as we go.
            //Touching can be set to true by a single touching subpair.
            Touching = false;
            //Containing can be set to false by a single noncontaining or nontouching subpair.
            Containing = subPairs.Count > 0;
            foreach (var pair in subPairs.Values)
            {
                //For child convex pairs, we don't need to always perform containment checks.
                //Only check if the containment state has not yet been invalidated or a touching state has not been identified.
                var convexPair = pair as DetectorVolumeConvexPairHandler;
                if (convexPair != null)
                {
                    convexPair.CheckContainment = Containing || !Touching;
                }

                pair.UpdateCollision(dt);

                if (pair.Touching)
                {
                    Touching = true; //If one child is touching, then we are touching too.
                }
                else
                {
                    Containing = false; //If one child isn't touching, then we aren't containing.
                }
                if (!pair.Containing)   //If one child isn't containing, then we aren't containing.
                {
                    Containing = false;
                }


                if (!Containing && Touching)
                {
                    //If it's touching but not containing, no further pairs will change the state.
                    //Containment has been invalidated by something that either didn't touch or wasn't contained.
                    //Touching has been ensured by at least one object touching.
                    break;
                }
            }

            NotifyDetectorVolumeOfChanges();
        }
示例#24
0
 /// <summary>
 /// Returns a resource to the pool.
 /// </summary>
 /// <param name="list">List to return.</param>
 public static void GiveBack(RawList<BroadPhaseEntry> list)
 {
     list.Clear();
     SubPoolCollisionEntryList.GiveBack(list);
 }
示例#25
0
        public override void UpdateCollision(float dt)
        {
            WasContaining = Containing;
            WasTouching   = Touching;

            mobileTriangle.collisionMargin = mesh.Shape.MeshCollisionMargin;

            //Scan the pairs in sequence, updating the state as we go.
            //Touching can be set to true by a single touching subpair.
            Touching = false;
            //Containing can be set to false by a single noncontaining or nontouching subpair.
            Containing = true;


            MeshBoundingBoxTreeData meshData = mesh.Shape.TriangleMesh.Data;
            RigidTransform          mobileTriangleTransform, detectorTriangleTransform;

            mobileTriangleTransform.Orientation   = Quaternion.Identity;
            detectorTriangleTransform.Orientation = Quaternion.Identity;
            for (int i = 0; i < meshData.Indices.Length; i += 3)
            {
                //Grab a triangle associated with the mobile mesh.
                meshData.GetTriangle(i, out mobileTriangle.vA, out mobileTriangle.vB, out mobileTriangle.vC);
                RigidTransform.Transform(ref mobileTriangle.vA, ref mesh.worldTransform, out mobileTriangle.vA);
                RigidTransform.Transform(ref mobileTriangle.vB, ref mesh.worldTransform, out mobileTriangle.vB);
                RigidTransform.Transform(ref mobileTriangle.vC, ref mesh.worldTransform, out mobileTriangle.vC);
                Vector3.Add(ref mobileTriangle.vA, ref mobileTriangle.vB, out mobileTriangleTransform.Position);
                Vector3.Add(ref mobileTriangle.vC, ref mobileTriangleTransform.Position,
                            out mobileTriangleTransform.Position);
                Vector3.Multiply(ref mobileTriangleTransform.Position, 1 / 3f, out mobileTriangleTransform.Position);
                Vector3.Subtract(ref mobileTriangle.vA, ref mobileTriangleTransform.Position, out mobileTriangle.vA);
                Vector3.Subtract(ref mobileTriangle.vB, ref mobileTriangleTransform.Position, out mobileTriangle.vB);
                Vector3.Subtract(ref mobileTriangle.vC, ref mobileTriangleTransform.Position, out mobileTriangle.vC);

                //Go through all the detector volume triangles which are near the mobile mesh triangle.
                bool        triangleTouching, triangleContaining;
                BoundingBox mobileBoundingBox;
                mobileTriangle.GetBoundingBox(ref mobileTriangleTransform, out mobileBoundingBox);
                DetectorVolume.TriangleMesh.Tree.GetOverlaps(mobileBoundingBox, overlaps);
                for (int j = 0; j < overlaps.Count; j++)
                {
                    DetectorVolume.TriangleMesh.Data.GetTriangle(overlaps.Elements[j], out detectorTriangle.vA,
                                                                 out detectorTriangle.vB, out detectorTriangle.vC);
                    Vector3.Add(ref detectorTriangle.vA, ref detectorTriangle.vB,
                                out detectorTriangleTransform.Position);
                    Vector3.Add(ref detectorTriangle.vC, ref detectorTriangleTransform.Position,
                                out detectorTriangleTransform.Position);
                    Vector3.Multiply(ref detectorTriangleTransform.Position, 1 / 3f,
                                     out detectorTriangleTransform.Position);
                    Vector3.Subtract(ref detectorTriangle.vA, ref detectorTriangleTransform.Position,
                                     out detectorTriangle.vA);
                    Vector3.Subtract(ref detectorTriangle.vB, ref detectorTriangleTransform.Position,
                                     out detectorTriangle.vB);
                    Vector3.Subtract(ref detectorTriangle.vC, ref detectorTriangleTransform.Position,
                                     out detectorTriangle.vC);

                    //If this triangle collides with the convex, we can stop immediately since we know we're touching and not containing.)))
                    //[MPR is used here in lieu of GJK because the MPR implementation tends to finish quicker than GJK when objects are overlapping.  The GJK implementation does better on separated objects.]
                    if (MPRToolbox.AreShapesOverlapping(detectorTriangle, mobileTriangle, ref detectorTriangleTransform,
                                                        ref mobileTriangleTransform))
                    {
                        triangleTouching = true;
                        //The convex can't be fully contained if it's still touching the surface.
                        triangleContaining = false;
                        overlaps.Clear();
                        goto finishTriangleTest;
                    }
                }

                overlaps.Clear();
                //If we get here, then there was no shell intersection.
                //If the convex's center point is contained by the mesh, then the convex is fully contained.
                //This test is only needed if containment hasn't yet been outlawed or a touching state hasn't been established.
                if ((!Touching || Containing) &&
                    DetectorVolume.IsPointContained(ref mobileTriangleTransform.Position, overlaps))
                {
                    triangleTouching   = true;
                    triangleContaining = true;
                    goto finishTriangleTest;
                }

                //If we get here, then there was no surface intersection and the convex's center is not contained- the volume and convex are separate!
                triangleTouching   = false;
                triangleContaining = false;

finishTriangleTest:
                //Analyze the results of the triangle test.

                if (triangleTouching)
                {
                    Touching = true; //If one child is touching, then we are touching too.
                }
                else
                {
                    Containing = false; //If one child isn't touching, then we aren't containing.
                }

                if (!triangleContaining) //If one child isn't containing, then we aren't containing.
                {
                    Containing = false;
                }

                if (!Containing && Touching)
                //If it's touching but not containing, no further pairs will change the state.
                //Containment has been invalidated by something that either didn't touch or wasn't contained.
                //Touching has been ensured by at least one object touching.
                {
                    break;
                }
            }

            //There is a possibility that the MobileMesh is solid and fully contains the DetectorVolume.
            //In this case, we should be Touching, but currently we are not.
            if (mesh.Shape.solidity == MobileMeshSolidity.Solid && !Containing && !Touching)
            {
                //To determine if the detector volume is fully contained, check if one of the detector mesh's vertices
                //are in the mobile mesh.

                //This *could* fail if the mobile mesh is actually multiple pieces, but that's not a common or really supported case for solids.
                Vector3 vertex;
                DetectorVolume.TriangleMesh.Data.GetVertexPosition(0, out vertex);
                Ray ray;
                ray.Direction = Vector3.Up;
                RayHit hit;
                RigidTransform.TransformByInverse(ref vertex, ref mesh.worldTransform, out ray.Position);
                if (mesh.Shape.IsLocalRayOriginInMesh(ref ray, out hit))
                {
                    Touching = true;
                }
            }

            NotifyDetectorVolumeOfChanges();
        }
示例#26
0
 /// <summary>
 /// Returns a resource to the pool.
 /// </summary>
 /// <param name="list">List to return.</param>
 public static void GiveBack(RawList<int> list)
 {
     list.Clear();
     SubPoolIntList.GiveBack(list);
 }
示例#27
0
 protected internal override void CleanUpOverlappingTriangles()
 {
     overlappedTriangles.Clear();
 }
示例#28
0
 /// <summary>
 /// Returns a resource to the pool.
 /// </summary>
 /// <param name="list">List to return.</param>
 public static void GiveBack(RawList<Vector3> list)
 {
     list.Clear();
     SubPoolVectorList.GiveBack(list);
 }
示例#29
0
        protected RawList<ImportInputAssignment> SelectImporter(AssetImportEnvironment env)
        {
            if (!env.IsPrepareStep) throw new ArgumentException(
                "The specified import environment must be configured as a preparation environment.",
                "env");

            // Find an importer to handle some or all of the unhandled input files
            RawList<ImportInputAssignment> candidateMapping = new RawList<ImportInputAssignment>();
            foreach (IAssetImporter importer in AssetManager.Importers)
            {
                env.ResetAcquiredData();

                try
                {
                    importer.PrepareImport(env);
                }
                catch (Exception ex)
                {
                    Log.Editor.WriteError("An error occurred in the preparation step of '{1}': {0}",
                        Log.Exception(ex),
                        Log.Type(importer.GetType()));
                    continue;
                }

                if (env.HandledInput.Any())
                {
                    candidateMapping.Add(new ImportInputAssignment
                    {
                        Importer = importer,
                        HandledInput = env.HandledInput.ToArray(),
                        ExpectedOutput = env.Output.ToArray()
                    });
                }
            }

            // Sort candidate mapping from most files to least files, so we can solve the biggest conflicts first
            candidateMapping.Sort((a, b) => b.HandledInput.Length - a.HandledInput.Length);

            // Determine if multiple importers intend to handle the same files and resolve conflicts
            List<int> conflictingIndices = new List<int>();
            List<string> conflictingFiles = new List<string>();
            for (int mainIndex = 0; mainIndex < candidateMapping.Count; mainIndex++)
            {
                ImportInputAssignment assignment = candidateMapping[mainIndex];

                // Find all conflicts related to this assignment
                conflictingIndices.Clear();
                conflictingFiles.Clear();
                for (int secondIndex = 0; secondIndex < candidateMapping.Count; secondIndex++)
                {
                    if (secondIndex == mainIndex) continue;

                    ImportInputAssignment conflictAssignment = candidateMapping[secondIndex];
                    IEnumerable<string> mainFiles = assignment.HandledInput.Select(item => item.Path);
                    IEnumerable<string> secondFiles = conflictAssignment.HandledInput.Select(item => item.Path);
                    string[] conflicts = mainFiles.Intersect(secondFiles).ToArray();
                    if (conflicts.Length > 0)
                    {
                        if (conflictingIndices.Count == 0) conflictingIndices.Add(mainIndex);
                        conflictingIndices.Add(secondIndex);
                        conflictingFiles.AddRange(conflicts);
                    }
                }

                // Resolve conflicts with this assignment
                if (conflictingIndices.Count > 0)
                {
                    // Determine which importer to prefer for this conflict
                    ImportInputAssignment[] conflictingAssignments = conflictingIndices.Select(i => candidateMapping[i]).ToArray();
                    int keepIndex = this.ResolveMappingConflict(conflictingAssignments);

                    // If we somehow decided that none of the options is viable, abort the operation
                    if (keepIndex == -1)
                    {
                        candidateMapping.Clear();
                        return candidateMapping;
                    }

                    // Sort indices to remove in declining order and remove their mappings
                    conflictingIndices.Remove(keepIndex);
                    conflictingIndices.Sort((a, b) => b - a);
                    foreach (int index in conflictingIndices)
                    {
                        candidateMapping.RemoveAt(index);
                    }

                    // Start over with the conflict search
                    mainIndex = -1;
                    continue;
                }
            }

            return candidateMapping;
        }
示例#30
0
 /// <summary>
 /// Returns a resource to the pool.
 /// </summary>
 /// <param name="triangleIndices">TriangleIndices list to return.</param>
 public static void GiveBack(RawList<BEPUphysics.CollisionTests.Manifolds.TriangleMeshConvexContactManifold.TriangleIndices> triangleIndices)
 {
     triangleIndices.Clear();
     SubPoolTriangleIndicesList.GiveBack(triangleIndices);
 }
示例#31
0
        public static void GetClosestPointOnTetrahedronToPoint(RawList<Vector3> tetrahedron, ref Vector3 p, RawList<int> subsimplex, RawList<float> baryCoords, out Vector3 closestPoint)
        {
            var subsimplexCandidate = CommonResources.GetIntList();
            var baryCoordsCandidate = CommonResources.GetFloatList();
            Vector3 a = tetrahedron[0];
            Vector3 b = tetrahedron[1];
            Vector3 c = tetrahedron[2];
            Vector3 d = tetrahedron[3];
            closestPoint = p;
            Vector3 pq;
            float bestSqDist = float.MaxValue;
            subsimplex.Clear();
            subsimplex.Add(0); //Provides a baseline; if the object is not outside of any planes, then it's inside and the subsimplex is the tetrahedron itself.
            subsimplex.Add(1);
            subsimplex.Add(2);
            subsimplex.Add(3);
            baryCoords.Clear();
            Vector3 q;
            bool baryCoordsFound = false;

            // If point outside face abc then compute closest point on abc
            if (ArePointsOnOppositeSidesOfPlane(ref p, ref d, ref a, ref b, ref c))
            {
                GetClosestPointOnTriangleToPoint(tetrahedron, 0, 1, 2, ref p, subsimplexCandidate, baryCoordsCandidate, out q);
                Vector3.Subtract(ref q, ref p, out pq);
                float sqDist = pq.LengthSquared();
                // Update best closest point if (squared) distance is less than current best
                if (sqDist < bestSqDist)
                {
                    bestSqDist = sqDist;
                    closestPoint = q;
                    subsimplex.Clear();
                    baryCoords.Clear();
                    for (int k = 0; k < subsimplexCandidate.Count; k++)
                    {
                        subsimplex.Add(subsimplexCandidate[k]);
                        baryCoords.Add(baryCoordsCandidate[k]);
                    }
                    //subsimplex.AddRange(subsimplexCandidate);
                    //baryCoords.AddRange(baryCoordsCandidate);
                    baryCoordsFound = true;
                }
            }
            // Repeat test for face acd
            if (ArePointsOnOppositeSidesOfPlane(ref p, ref b, ref a, ref c, ref d))
            {
                GetClosestPointOnTriangleToPoint(tetrahedron, 0, 2, 3, ref p, subsimplexCandidate, baryCoordsCandidate, out q);
                Vector3.Subtract(ref q, ref p, out pq);
                float sqDist = pq.LengthSquared();
                if (sqDist < bestSqDist)
                {
                    bestSqDist = sqDist;
                    closestPoint = q;
                    subsimplex.Clear();
                    baryCoords.Clear();
                    for (int k = 0; k < subsimplexCandidate.Count; k++)
                    {
                        subsimplex.Add(subsimplexCandidate[k]);
                        baryCoords.Add(baryCoordsCandidate[k]);
                    }
                    //subsimplex.AddRange(subsimplexCandidate);
                    //baryCoords.AddRange(baryCoordsCandidate);
                    baryCoordsFound = true;
                }
            }
            // Repeat test for face adb
            if (ArePointsOnOppositeSidesOfPlane(ref p, ref c, ref a, ref d, ref b))
            {
                GetClosestPointOnTriangleToPoint(tetrahedron, 0, 3, 1, ref p, subsimplexCandidate, baryCoordsCandidate, out q);
                Vector3.Subtract(ref q, ref p, out pq);
                float sqDist = pq.LengthSquared();
                if (sqDist < bestSqDist)
                {
                    bestSqDist = sqDist;
                    closestPoint = q;
                    subsimplex.Clear();
                    baryCoords.Clear();
                    for (int k = 0; k < subsimplexCandidate.Count; k++)
                    {
                        subsimplex.Add(subsimplexCandidate[k]);
                        baryCoords.Add(baryCoordsCandidate[k]);
                    }
                    //subsimplex.AddRange(subsimplexCandidate);
                    //baryCoords.AddRange(baryCoordsCandidate);
                    baryCoordsFound = true;
                }
            }
            // Repeat test for face bdc
            if (ArePointsOnOppositeSidesOfPlane(ref p, ref a, ref b, ref d, ref c))
            {
                GetClosestPointOnTriangleToPoint(tetrahedron, 1, 3, 2, ref p, subsimplexCandidate, baryCoordsCandidate, out q);
                Vector3.Subtract(ref q, ref p, out pq);
                float sqDist = pq.LengthSquared();
                if (sqDist < bestSqDist)
                {
                    closestPoint = q;
                    subsimplex.Clear();
                    baryCoords.Clear();
                    for (int k = 0; k < subsimplexCandidate.Count; k++)
                    {
                        subsimplex.Add(subsimplexCandidate[k]);
                        baryCoords.Add(baryCoordsCandidate[k]);
                    }
                    //subsimplex.AddRange(subsimplexCandidate);
                    //baryCoords.AddRange(baryCoordsCandidate);
                    baryCoordsFound = true;
                }
            }
            if (!baryCoordsFound)
            {
                //subsimplex is the entire tetrahedron, can only occur when objects intersect!  Determinants of each of the tetrahedrons based on triangles composing the sides and the point itself.
                //This is basically computing the volume of parallelepipeds (triple scalar product).
                //Could be quicker just to do it directly.
                float abcd = (new Matrix(tetrahedron[0].X, tetrahedron[0].Y, tetrahedron[0].Z, 1,
                                         tetrahedron[1].X, tetrahedron[1].Y, tetrahedron[1].Z, 1,
                                         tetrahedron[2].X, tetrahedron[2].Y, tetrahedron[2].Z, 1,
                                         tetrahedron[3].X, tetrahedron[3].Y, tetrahedron[3].Z, 1)).Determinant();
                float pbcd = (new Matrix(p.X, p.Y, p.Z, 1,
                                         tetrahedron[1].X, tetrahedron[1].Y, tetrahedron[1].Z, 1,
                                         tetrahedron[2].X, tetrahedron[2].Y, tetrahedron[2].Z, 1,
                                         tetrahedron[3].X, tetrahedron[3].Y, tetrahedron[3].Z, 1)).Determinant();
                float apcd = (new Matrix(tetrahedron[0].X, tetrahedron[0].Y, tetrahedron[0].Z, 1,
                                         p.X, p.Y, p.Z, 1,
                                         tetrahedron[2].X, tetrahedron[2].Y, tetrahedron[2].Z, 1,
                                         tetrahedron[3].X, tetrahedron[3].Y, tetrahedron[3].Z, 1)).Determinant();
                float abpd = (new Matrix(tetrahedron[0].X, tetrahedron[0].Y, tetrahedron[0].Z, 1,
                                         tetrahedron[1].X, tetrahedron[1].Y, tetrahedron[1].Z, 1,
                                         p.X, p.Y, p.Z, 1,
                                         tetrahedron[3].X, tetrahedron[3].Y, tetrahedron[3].Z, 1)).Determinant();
                abcd = 1 / abcd;
                baryCoords.Add(pbcd * abcd); //u
                baryCoords.Add(apcd * abcd); //v
                baryCoords.Add(abpd * abcd); //w
                baryCoords.Add(1 - baryCoords[0] - baryCoords[1] - baryCoords[2]); //x = 1-u-v-w
            }
            CommonResources.GiveBack(subsimplexCandidate);
            CommonResources.GiveBack(baryCoordsCandidate);
        }
        double RunTest(int splitOffset, IParallelLooper parallelLooper)
        {
            Entity toAdd;
            //BoundingBox box = new BoundingBox(new Vector3(-5, 1, 1), new Vector3(5, 7, 7));
            BoundingBox box = new BoundingBox(new Vector3(-500, -500, -500), new Vector3(500, 500, 500));

            int splitDepth = splitOffset + (int)Math.Ceiling(Math.Log(parallelLooper.ThreadCount, 2));

            DynamicHierarchy dh = new DynamicHierarchy(parallelLooper);

            Random rand = new Random(0);

            RawList<Entity> entities = new RawList<Entity>();
            for (int k = 0; k < 10000; k++)
            {
                Vector3 position = new Vector3((float)(rand.NextDouble() * (box.Max.X - box.Min.X) + box.Min.X),
                                               (float)(rand.NextDouble() * (box.Max.Y - box.Min.Y) + box.Min.Y),
                                               (float)(rand.NextDouble() * (box.Max.Z - box.Min.Z) + box.Min.Z));
                toAdd = new Box(position, 1, 1, 1, 1);
                toAdd.CollisionInformation.CollisionRules.Personal = CollisionRule.NoNarrowPhasePair;
                toAdd.CollisionInformation.UpdateBoundingBox(0);


                dh.Add(toAdd.CollisionInformation);
                entities.Add(toAdd);

            }


            Space.ForceUpdater.Gravity = new Vector3();

            int numRuns = 3000;
            //Prime the system.
            dh.Update();
            var testType = Test.Update;

            BroadPhaseOverlap[] overlapBasis = new BroadPhaseOverlap[dh.Overlaps.Count];
            dh.Overlaps.CopyTo(overlapBasis, 0);


            double time = 0;
            double startTime, endTime;


            switch (testType)
            {
                #region Update Timing
                case Test.Update:
                    for (int i = 0; i < numRuns; i++)
                    {
                        //DH4
                        startTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;
                        //dh.Update();
                        //lock (dh.Locker)
                        //{
                        //    dh.Overlaps.Clear();
                        //    if (dh.ROOTEXISTS)
                        //    {
                        //        dh.MultithreadedRefitPhase(splitDepth);

                        //        dh.MultithreadedOverlapPhase(splitDepth);
                        //    }
                        //}

                        //dh.Update();

                        //lock (dh.Locker)
                        //{
                        //    dh.Overlaps.Clear();
                        //    if (dh.ROOTEXISTS)
                        //    {
                        //        dh.SingleThreadedRefitPhase();
                        //        dh.SingleThreadedOverlapPhase();
                        //    }
                        //}

                        endTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;
                        time += endTime - startTime;

                        //if (dh.Overlaps.Count != overlapBasis.Length)
                        //    Debug.WriteLine("Failed Update.");
                        //for (int j = 0; j < overlapBasis.Length; j++)
                        //{
                        //    if (!dh.Overlaps.Contains(overlapBasis[j]))
                        //        Debug.WriteLine("Failed Update.");
                        //}


                        //MoveEntities(entities);
                    }
                    break;
                #endregion
                #region Refit Timing
                case Test.Refit:
                    for (int i = 0; i < numRuns; i++)
                    {

                        dh.Overlaps.Clear();

                        //DH4
                        startTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;
                        //dh.MultithreadedRefitPhase(splitDepth);
                        //dh.SingleThreadedRefitPhase();
                        endTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;
                        time += endTime - startTime;

                        //dh.SingleThreadedOverlapPhase();

                        //if (dh.Overlaps.Count != overlapBasis.Length)
                        //    Debug.WriteLine("Failed Refit.");
                        //for (int j = 0; j < overlapBasis.Length; j++)
                        //{
                        //    if (!dh.Overlaps.Contains(overlapBasis[j]))
                        //        Debug.WriteLine("Failed Refit.");
                        //}

                        //MoveEntities(entities);
                    }
                    break;
                #endregion
                #region Overlap Timing
                case Test.Overlap:
                    for (int i = 0; i < numRuns; i++)
                    {
                        dh.Overlaps.Clear();
                        //dh.MultithreadedRefitPhase(splitDepth);
                        //DH4
                        startTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;
                        //dh.MultithreadedOverlapPhase(splitDepth);
                        //dh.SingleThreadedOverlapPhase();
                        endTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;
                        time += endTime - startTime;


                        //if (dh.Overlaps.Count != overlapBasis.Length)
                        //    Debug.WriteLine("Failed Overlap.");
                        //for (int j = 0; j < overlapBasis.Length; j++)
                        //{
                        //    if (!dh.Overlaps.Contains(overlapBasis[j]))
                        //        Debug.WriteLine("Failed Overlap.");
                        //}

                        //MoveEntities(entities);
                    }
                    break;
                #endregion
                #region Ray cast timing
                case Test.RayCast:
                    float rayLength = 100;
                    RawList<Ray> rays = new RawList<Ray>();
                    for (int i = 0; i < numRuns; i++)
                    {
                        rays.Add(new Ray()
                        {
                            Position = new Vector3((float)(rand.NextDouble() * (box.Max.X - box.Min.X) + box.Min.X),
                                               (float)(rand.NextDouble() * (box.Max.Y - box.Min.Y) + box.Min.Y),
                                               (float)(rand.NextDouble() * (box.Max.Z - box.Min.Z) + box.Min.Z)),
                            Direction = Vector3.Normalize(new Vector3((float)(rand.NextDouble() - .5), (float)(rand.NextDouble() - .5), (float)(rand.NextDouble() - .5)))
                        });
                    }
                    RawList<BroadPhaseEntry> outputIntersections = new RawList<BroadPhaseEntry>();



                    //DH4
                    startTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;
                    for (int i = 0; i < numRuns; i++)
                    {
                        dh.QueryAccelerator.RayCast(rays.Elements[i], rayLength, outputIntersections);
                        outputIntersections.Clear();
                    }

                    endTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;
                    time = endTime - startTime;


                    break;
                #endregion
                #region Bounding box query timing
                case Test.BoundingBoxQuery:
                    float boundingBoxSize = 10;
                    var boundingBoxes = new RawList<BoundingBox>();
                    Vector3 offset = new Vector3(boundingBoxSize / 2, boundingBoxSize / 2, boundingBoxSize / 2);
                    for (int i = 0; i < numRuns; i++)
                    {
                        Vector3 center = new Vector3((float)(rand.NextDouble() * (box.Max.X - box.Min.X) + box.Min.X),
                                                     (float)(rand.NextDouble() * (box.Max.Y - box.Min.Y) + box.Min.Y),
                                                     (float)(rand.NextDouble() * (box.Max.Z - box.Min.Z) + box.Min.Z));
                        boundingBoxes.Add(new BoundingBox()
                        {
                            Min = center - offset,
                            Max = center + offset
                        });
                    }

                    outputIntersections = new RawList<BroadPhaseEntry>();


                    //DH4
                    startTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;
                    for (int i = 0; i < numRuns; i++)
                    {
                        dh.QueryAccelerator.GetEntries(boundingBoxes.Elements[i], outputIntersections);
                        outputIntersections.Clear();
                    }

                    endTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;
                    time = endTime - startTime;


                    break;
                #endregion
            }


            return time / numRuns;
        }
示例#33
0
 /// <summary>
 /// Returns a resource to the pool.
 /// </summary>
 /// <param name="list">List to return.</param>
 public static void GiveBack(RawList <Vector3> list)
 {
     list.Clear();
     SubPoolVectorList.GiveBack(list);
 }
示例#34
0
 public static void GetClosestPointOnTetrahedronToPoint(ref Vector3 a, ref Vector3 b, ref Vector3 c, ref Vector3 d, ref Vector3 p, RawList<Vector3> subsimplex, out Vector3 closestPoint)
 {
     // Start out assuming point inside all halfspaces, so closest to itself
     subsimplex.Clear();
     subsimplex.Add(a); //Provides a baseline; if the object is not outside of any planes, then it's inside and the subsimplex is the tetrahedron itself.
     subsimplex.Add(b);
     subsimplex.Add(c);
     subsimplex.Add(d);
     closestPoint = p;
     Vector3 pq;
     Vector3 q;
     float bestSqDist = float.MaxValue;
     // If point outside face abc then compute closest point on abc
     if (ArePointsOnOppositeSidesOfPlane(ref p, ref d, ref a, ref b, ref c))
     {
         GetClosestPointOnTriangleToPoint(ref a, ref b, ref c, ref p, subsimplex, out q);
         Vector3.Subtract(ref q, ref p, out pq);
         float sqDist = pq.X * pq.X + pq.Y * pq.Y + pq.Z * pq.Z;
         // Update best closest point if (squared) distance is less than current best
         if (sqDist < bestSqDist)
         {
             bestSqDist = sqDist;
             closestPoint = q;
         }
     }
     // Repeat test for face acd
     if (ArePointsOnOppositeSidesOfPlane(ref p, ref b, ref a, ref c, ref d))
     {
         GetClosestPointOnTriangleToPoint(ref a, ref c, ref d, ref p, subsimplex, out q);
         Vector3.Subtract(ref q, ref p, out pq);
         float sqDist = pq.X * pq.X + pq.Y * pq.Y + pq.Z * pq.Z;
         if (sqDist < bestSqDist)
         {
             bestSqDist = sqDist;
             closestPoint = q;
         }
     }
     // Repeat test for face adb
     if (ArePointsOnOppositeSidesOfPlane(ref p, ref c, ref a, ref d, ref b))
     {
         GetClosestPointOnTriangleToPoint(ref a, ref d, ref b, ref p, subsimplex, out q);
         Vector3.Subtract(ref q, ref p, out pq);
         float sqDist = pq.X * pq.X + pq.Y * pq.Y + pq.Z * pq.Z;
         if (sqDist < bestSqDist)
         {
             bestSqDist = sqDist;
             closestPoint = q;
         }
     }
     // Repeat test for face bdc
     if (ArePointsOnOppositeSidesOfPlane(ref p, ref a, ref b, ref d, ref c))
     {
         GetClosestPointOnTriangleToPoint(ref b, ref d, ref c, ref p, subsimplex, out q);
         Vector3.Subtract(ref q, ref p, out pq);
         float sqDist = pq.X * pq.X + pq.Y * pq.Y + pq.Z * pq.Z;
         if (sqDist < bestSqDist)
         {
             closestPoint = q;
         }
     }
 }
示例#35
0
        protected void UpdateLabel()
        {
            SetString(m_sInitialString, true);

            if (m_fWidth > 0)
            {
                // Step 1: Make multiline
                string str_whole = m_sString;
                int stringLength = m_sString.Length;
                var multiline_string = new StringBuilder(stringLength);
                var last_word = new StringBuilder(stringLength);

                int line = 1, i = 0;
                bool start_line = false, start_word = false;
                float startOfLine = -1, startOfWord = -1;
                int skip = 0;

                RawList<CCNode> children = m_pChildren;
                for (int j = 0; j < children.count; j++)
                {
                    CCSprite characterSprite;

                    while ((characterSprite = (CCSprite) GetChildByTag(j + skip)) == null)
                    {
                        skip++;
                    }

                    if (!characterSprite.Visible)
                    {
                        continue;
                    }

                    if (i >= stringLength)
                    {
                        break;
                    }

                    char character = str_whole[i];

                    if (!start_word)
                    {
                        startOfWord = GetLetterPosXLeft(characterSprite);
                        start_word = true;
                    }
                    if (!start_line)
                    {
                        startOfLine = startOfWord;
                        start_line = true;
                    }

                    // Newline.
                    if (character == '\n')
                    {
                        int len = last_word.Length;
                        while (len > 0 && Char.IsWhiteSpace(last_word[len - 1]))
                        {
                            len--;
                            last_word.Remove(len, 1);
                        }

                        multiline_string.Append(last_word);
                        multiline_string.Append('\n');

            #if XBOX || XBOX360
                        last_word.Length = 0;
            #else
                        last_word.Clear();
            #endif

                        start_word = false;
                        start_line = false;
                        startOfWord = -1;
                        startOfLine = -1;
                        i++;
                        line++;

                        if (i >= stringLength)
                            break;

                        character = str_whole[i];

                        if (startOfWord == 0)
                        {
                            startOfWord = GetLetterPosXLeft(characterSprite);
                            start_word = true;
                        }
                        if (startOfLine == 0)
                        {
                            startOfLine = startOfWord;
                            start_line = true;
                        }
                    }

                    // Whitespace.
                    if (Char.IsWhiteSpace(character))
                    {
                        last_word.Append(character);
                        multiline_string.Append(last_word);
            #if XBOX || XBOX360
                        last_word.Length = 0;
            #else
                        last_word.Clear();
            #endif
                        start_word = false;
                        startOfWord = -1;
                        i++;
                        continue;
                    }

                    // Out of bounds.
                    if (GetLetterPosXRight(characterSprite) - startOfLine > m_fWidth)
                    {
                        if (!m_bLineBreakWithoutSpaces)
                        {
                            last_word.Append(character);

                            int len = multiline_string.Length;
                            while (len > 0 && Char.IsWhiteSpace(multiline_string[len - 1]))
                            {
                                len--;
                                multiline_string.Remove(len, 1);
                            }

                            if (multiline_string.Length > 0)
                            {
                                multiline_string.Append('\n');
                            }

                            line++;
                            start_line = false;
                            startOfLine = -1;
                            i++;
                        }
                        else
                        {
                            int len = last_word.Length;
                            while (len > 0 && Char.IsWhiteSpace(last_word[len - 1]))
                            {
                                len--;
                                last_word.Remove(len, 1);
                            }

                            multiline_string.Append(last_word);
                            multiline_string.Append('\n');

            #if XBOX || XBOX360
                            last_word.Length = 0;
            #else
                        last_word.Clear();
            #endif

                            start_word = false;
                            start_line = false;
                            startOfWord = -1;
                            startOfLine = -1;
                            line++;

                            if (i >= stringLength)
                                break;

                            if (startOfWord == 0)
                            {
                                startOfWord = GetLetterPosXLeft(characterSprite);
                                start_word = true;
                            }
                            if (startOfLine == 0)
                            {
                                startOfLine = startOfWord;
                                start_line = true;
                            }

                            j--;
                        }

                        continue;
                    }
                    else
                    {
                        // Character is normal.
                        last_word.Append(character);
                        i++;
                        continue;
                    }
                }

                multiline_string.Append(last_word);

                m_sString = multiline_string.ToString();

                UpdateString(true);
            }

            // Step 2: Make alignment
            if (m_pAlignment != CCTextAlignment.CCTextAlignmentLeft)
            {
                int i = 0;

                int lineNumber = 0;
                int str_len = m_sString.Length;
                var last_line = new RawList<char>();
                for (int ctr = 0; ctr <= str_len; ++ctr)
                {
                    if (ctr == str_len || m_sString[ctr] == '\n')
                    {
                        float lineWidth = 0.0f;
                        int line_length = last_line.Count;
                        // if last line is empty we must just increase lineNumber and work with next line
                        if (line_length == 0)
                        {
                            lineNumber++;
                            continue;
                        }
                        int index = i + line_length - 1 + lineNumber;
                        if (index < 0) continue;

                        var lastChar = (CCSprite) GetChildByTag(index);
                        if (lastChar == null)
                            continue;

                        lineWidth = lastChar.Position.X + lastChar.ContentSize.Width / 2.0f;

                        float shift = 0;
                        switch (m_pAlignment)
                        {
                            case CCTextAlignment.CCTextAlignmentCenter:
                                shift = ContentSize.Width / 2.0f - lineWidth / 2.0f;
                                break;
                            case CCTextAlignment.CCTextAlignmentRight:
                                shift = ContentSize.Width - lineWidth;
                                break;
                            default:
                                break;
                        }

                        if (shift != 0)
                        {
                            for (int j = 0; j < line_length; j++)
                            {
                                index = i + j + lineNumber;
                                if (index < 0) continue;

                                var characterSprite = (CCSprite) GetChildByTag(index);
                                characterSprite.Position = characterSprite.Position + new CCPoint(shift, 0.0f);
                            }
                        }

                        i += line_length;
                        lineNumber++;

                        last_line.Clear();
                        continue;
                    }

                    last_line.Add(m_sString[ctr]);
                }
            }
        }
示例#36
0
 public static void GetClosestPointOnTriangleToPoint(ref Vector3 a, ref Vector3 b, ref Vector3 c, ref Vector3 p, RawList<Vector3> subsimplex, out Vector3 closestPoint)
 {
     subsimplex.Clear();
     float v, w;
     Vector3 ab;
     Vector3.Subtract(ref b, ref a, out ab);
     Vector3 ac;
     Vector3.Subtract(ref c, ref a, out ac);
     //Vertex region A?
     Vector3 ap;
     Vector3.Subtract(ref p, ref a, out ap);
     float d1;
     Vector3.Dot(ref ab, ref ap, out d1);
     float d2;
     Vector3.Dot(ref ac, ref ap, out d2);
     if (d1 <= 0 && d2 < 0)
     {
         subsimplex.Add(a);
         closestPoint = a;
         return;
     }
     //Vertex region B?
     Vector3 bp;
     Vector3.Subtract(ref p, ref b, out bp);
     float d3;
     Vector3.Dot(ref ab, ref bp, out d3);
     float d4;
     Vector3.Dot(ref ac, ref bp, out d4);
     if (d3 >= 0 && d4 <= d3)
     {
         subsimplex.Add(b);
         closestPoint = b;
         return;
     }
     //Edge region AB?
     float vc = d1 * d4 - d3 * d2;
     if (vc <= 0 && d1 >= 0 && d3 <= 0)
     {
         subsimplex.Add(a);
         subsimplex.Add(b);
         v = d1 / (d1 - d3);
         Vector3.Multiply(ref ab, v, out closestPoint);
         Vector3.Add(ref closestPoint, ref a, out closestPoint);
         return;
     }
     //Vertex region C?
     Vector3 cp;
     Vector3.Subtract(ref p, ref c, out cp);
     float d5;
     Vector3.Dot(ref ab, ref cp, out d5);
     float d6;
     Vector3.Dot(ref ac, ref cp, out d6);
     if (d6 >= 0 && d5 <= d6)
     {
         subsimplex.Add(c);
         closestPoint = c;
         return;
     }
     //Edge region AC?
     float vb = d5 * d2 - d1 * d6;
     if (vb <= 0 && d2 >= 0 && d6 <= 0)
     {
         subsimplex.Add(a);
         subsimplex.Add(c);
         w = d2 / (d2 - d6);
         Vector3.Multiply(ref ac, w, out closestPoint);
         Vector3.Add(ref closestPoint, ref a, out closestPoint);
         return;
     }
     //Edge region BC?
     float va = d3 * d6 - d5 * d4;
     if (va <= 0 && (d4 - d3) >= 0 && (d5 - d6) >= 0)
     {
         subsimplex.Add(b);
         subsimplex.Add(c);
         w = (d4 - d3) / ((d4 - d3) + (d5 - d6));
         Vector3.Subtract(ref c, ref b, out closestPoint);
         Vector3.Multiply(ref closestPoint, w, out closestPoint);
         Vector3.Add(ref closestPoint, ref b, out closestPoint);
         return;
     }
     //Inside triangle?
     subsimplex.Add(a);
     subsimplex.Add(b);
     subsimplex.Add(c);
     float denom = 1 / (va + vb + vc);
     v = vb * denom;
     w = vc * denom;
     Vector3 abv;
     Vector3.Multiply(ref ab, v, out abv);
     Vector3 acw;
     Vector3.Multiply(ref ac, w, out acw);
     Vector3.Add(ref a, ref abv, out closestPoint);
     Vector3.Add(ref closestPoint, ref acw, out closestPoint);
 }
示例#37
0
        /// <summary>
        /// Constructs a new demo.
        /// </summary>
        /// <param name="game">Game owning this demo.</param>
        public BroadPhasesTestDemo(DemosGame game)
            : base(game)
        {
            Space.Solver.IterationLimit = 0;
            Entity toAdd;
            //BoundingBox box = new BoundingBox(new Vector3(-5, 1, 1), new Vector3(5, 7, 7));
            BoundingBox box = new BoundingBox(new Vector3(-50, -50, -50), new Vector3(50, 50, 50));

            //DynamicHierarchyOld dhOld = new DynamicHierarchyOld(Space.ThreadManager);
            DynamicHierarchy dh = new DynamicHierarchy(Space.ParallelLooper);
            SortAndSweep1D sas1d = new SortAndSweep1D(Space.ParallelLooper);
            Grid2DSortAndSweep grid2DSAS = new Grid2DSortAndSweep(Space.ParallelLooper);
            //DynamicHierarchy dh = new DynamicHierarchy();
            //DynamicHierarchy4 dh4 = new DynamicHierarchy4();
            //SortAndSweep1D sas1d = new SortAndSweep1D();
            //Grid2DSortAndSweep grid2DSAS = new Grid2DSortAndSweep();

            //DynamicHierarchy2 dh2 = new DynamicHierarchy2();
            //DynamicHierarchy3 dh3 = new DynamicHierarchy3();
            //SortAndSweep3D sap3d = new SortAndSweep3D();

            RawList<Entity> entities = new RawList<Entity>();
            for (int k = 0; k < 100; k++)
            {
                Vector3 position = new Vector3((float)(rand.NextDouble() * (box.Max.X - box.Min.X) + box.Min.X),
                                               (float)(rand.NextDouble() * (box.Max.Y - box.Min.Y) + box.Min.Y),
                                               (float)(rand.NextDouble() * (box.Max.Z - box.Min.Z) + box.Min.Z));
                toAdd = new Box(position, 1, 1, 1, 1);
                toAdd.CollisionInformation.CollisionRules.Personal = CollisionRule.NoNarrowPhasePair;
                toAdd.CollisionInformation.UpdateBoundingBox(0);
                //Space.Add(toAdd);
                //dhOld.Add(toAdd.CollisionInformation);
                dh.Add(toAdd.CollisionInformation);
                sas1d.Add(toAdd.CollisionInformation);
                grid2DSAS.Add(toAdd.CollisionInformation);
                entities.Add(toAdd);

            }

            Space.ForceUpdater.Gravity = new Vector3();

            int numRuns = 10000;
            //Prime the system.
            grid2DSAS.Update();
            sas1d.Update();
            //dhOld.Update();
            dh.Update();
            var testType = Test.Update;

            double startTime, endTime;

            switch (testType)
            {
                #region Update Timing
                case Test.Update:
                    for (int i = 0; i < numRuns; i++)
                    {
                        ////DH
                        //startTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;
                        //dhOld.Update();
                        //endTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;
                        //DHOldTime += endTime - startTime;

                        //DH4
                        startTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;
                        dh.Update();
                        endTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;
                        DHtime += endTime - startTime;

                        //SAP1D
                        startTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;
                        sas1d.Update();
                        endTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;
                        SAS1Dtime += endTime - startTime;

                        //Grid2D SOS
                        startTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;
                        grid2DSAS.Update();
                        endTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;
                        grid2DSAStime += endTime - startTime;

                        //if (sap1d.Overlaps.Count != dh.Overlaps.Count)
                        //    Debug.WriteLine("SAP1D Failure");
                        //if (grid2DSOS.Overlaps.Count != dh.Overlaps.Count)
                        //    Debug.WriteLine("grid2DSOS Failure");

                        //for (int j = 0; j < dh2.Overlaps.Count; j++)
                        //{
                        //    if (!grid2DSOS.Overlaps.Contains(dh2.Overlaps[j]))
                        //        Debug.WriteLine("Break.");
                        //}
                        //for (int j = 0; j < grid2DSOS.Overlaps.Count; j++)
                        //{
                        //    if (!dh2.Overlaps.Contains(grid2DSOS.Overlaps[j]))
                        //        break;
                        //}

                        //for (int j = 0; j < grid2DSOS.Overlaps.Count; j++)
                        //{
                        //    if (!dh4.Overlaps.Contains(grid2DSOS.Overlaps[j]))
                        //        break;
                        //}

                        //for (int j = 0; j < dh.Overlaps.Count; j++)
                        //{
                        //    if (!dh.Overlaps[j].EntryA.BoundingBox.Intersects(dh.Overlaps[j].EntryB.BoundingBox))
                        //        Debug.WriteLine("Break.");
                        //}

                        //for (int j = 0; j < sap1d.Overlaps.Count; j++)
                        //{
                        //    if (!sap1d.Overlaps[j].EntryA.BoundingBox.Intersects(sap1d.Overlaps[j].EntryB.BoundingBox))
                        //        Debug.WriteLine("Break.");
                        //}

                        //for (int j = 0; j < grid2DSOS.Overlaps.Count; j++)
                        //{
                        //    if (!grid2DSOS.Overlaps[j].EntryA.BoundingBox.Intersects(grid2DSOS.Overlaps[j].EntryB.BoundingBox))
                        //        Debug.WriteLine("Break.");
                        //}

                        //MoveEntities(entities);
                    }
                    break;
                #endregion
                #region Ray cast timing
                case Test.RayCast:
                    float rayLength = 100;
                    RawList<Ray> rays = new RawList<Ray>();
                    for (int i = 0; i < numRuns; i++)
                    {
                        rays.Add(new Ray()
                        {
                            Position = new Vector3((float)(rand.NextDouble() * (box.Max.X - box.Min.X) + box.Min.X),
                                               (float)(rand.NextDouble() * (box.Max.Y - box.Min.Y) + box.Min.Y),
                                               (float)(rand.NextDouble() * (box.Max.Z - box.Min.Z) + box.Min.Z)),
                            Direction = Vector3.Normalize(new Vector3((float)(rand.NextDouble() - .5), (float)(rand.NextDouble() - .5), (float)(rand.NextDouble() - .5)))
                        });
                    }
                    RawList<BroadPhaseEntry> outputIntersections = new RawList<BroadPhaseEntry>();

                    ////DH
                    //startTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;
                    //for (int i = 0; i < numRuns; i++)
                    //{
                    //    dhOld.QueryAccelerator.RayCast(rays.Elements[i], rayLength, outputIntersections);
                    //    outputIntersections.Clear();

                    //}
                    //endTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;
                    //DHOldTime = endTime - startTime;

                    //DH4
                    startTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;
                    for (int i = 0; i < numRuns; i++)
                    {
                        dh.QueryAccelerator.RayCast(rays.Elements[i], rayLength, outputIntersections);
                        outputIntersections.Clear();
                    }

                    endTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;
                    DHtime = endTime - startTime;

                    //Grid2DSAS
                    startTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;
                    for (int i = 0; i < numRuns; i++)
                    {
                        grid2DSAS.QueryAccelerator.RayCast(rays.Elements[i], rayLength, outputIntersections);
                        outputIntersections.Clear();
                    }
                    endTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;
                    grid2DSAStime = endTime - startTime;
                    break;
                #endregion
                #region Bounding box query timing
                case Test.BoundingBoxQuery:
                    float boundingBoxSize = 10;
                    var boundingBoxes = new RawList<BoundingBox>();
                    Vector3 offset = new Vector3(boundingBoxSize / 2, boundingBoxSize / 2, boundingBoxSize / 2);
                    for (int i = 0; i < numRuns; i++)
                    {
                        Vector3 center = new Vector3((float)(rand.NextDouble() * (box.Max.X - box.Min.X) + box.Min.X),
                                                     (float)(rand.NextDouble() * (box.Max.Y - box.Min.Y) + box.Min.Y),
                                                     (float)(rand.NextDouble() * (box.Max.Z - box.Min.Z) + box.Min.Z));
                        boundingBoxes.Add(new BoundingBox()
                        {
                            Min = center - offset,
                            Max = center + offset
                        });
                    }

                    outputIntersections = new RawList<BroadPhaseEntry>();

                    ////DH
                    //startTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;
                    //for (int i = 0; i < numRuns; i++)
                    //{
                    //    dhOld.QueryAccelerator.GetEntries(boundingBoxes.Elements[i], outputIntersections);
                    //    outputIntersections.Clear();

                    //}
                    //endTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;
                    //DHOldTime = endTime - startTime;

                    //DH4
                    startTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;
                    for (int i = 0; i < numRuns; i++)
                    {
                        dh.QueryAccelerator.GetEntries(boundingBoxes.Elements[i], outputIntersections);
                        outputIntersections.Clear();
                    }

                    endTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;
                    DHtime = endTime - startTime;

                    //Grid2DSAS
                    startTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;
                    for (int i = 0; i < numRuns; i++)
                    {
                        grid2DSAS.QueryAccelerator.GetEntries(boundingBoxes.Elements[i], outputIntersections);
                        outputIntersections.Clear();
                    }
                    endTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;
                    grid2DSAStime = endTime - startTime;
                    break;
                #endregion
            }

            DHOldTime /= numRuns;
            DH2time /= numRuns;
            DH3time /= numRuns;
            DHtime /= numRuns;
            SAS1Dtime /= numRuns;
            grid2DSAStime /= numRuns;
        }
示例#38
0
 /// <summary>
 /// Returns a resource to the pool.
 /// </summary>
 /// <param name="triangleIndices">TriangleIndices list to return.</param>
 public static void GiveBack(RawList<TriangleMeshConvexContactManifold.TriangleIndices> triangleIndices)
 {
     if (SubPoolTriangleIndicesList == null)
         SubPoolTriangleIndicesList = new UnsafeResourcePool<RawList<TriangleMeshConvexContactManifold.TriangleIndices>>();
     triangleIndices.Clear();
     SubPoolTriangleIndicesList.GiveBack(triangleIndices);
 }
 /// <summary>
 /// Returns a resource to the pool.
 /// </summary>
 /// <param name="list">List to return.</param>
 public static void GiveBack(RawList<Collidable> list)
 {
     list.Clear();
     SubPoolCollidableList.GiveBack(list);
 }
 /// <summary>
 /// Returns a resource to the pool.
 /// </summary>
 /// <param name="list">List to return.</param>
 public static void GiveBack(RawList<Entity> list)
 {
     if (SubPoolEntityRawList == null)
         SubPoolEntityRawList = new UnsafeResourcePool<RawList<Entity>>();
     list.Clear();
     SubPoolEntityRawList.GiveBack(list);
 }
 /// <summary>
 /// Returns a resource to the pool.
 /// </summary>
 /// <param name="triangleIndices">TriangleIndices list to return.</param>
 public static void GiveBack(RawList<TriangleMeshConvexContactManifold.TriangleIndices> triangleIndices)
 {
     triangleIndices.Clear();
     SubPoolTriangleIndicesList.GiveBack(triangleIndices);
 }
示例#42
0
		[Test] public void RemoveResetsReferenceTypesToDefault()
		{
			RawList<string> list = new RawList<string>(Enumerable.Range(0, 10).Select(i => i.ToString()));

			// Is the internal array empty if not assigned otherwise?
			if (list.Capacity > list.Count)
				Assert.AreSame(null, list.Data[list.Count]);

			// Adjusting the count shouldn't affect the internal array, just as documented
			list.Count = 0;
			for (int i = 0; i < 10; i++)
			{
				Assert.AreNotSame(null, list.Data[i]);
			}
			list.Count = 10;

			// Check various types of removal and make sure the internal array is reset properly
			{
				// Remove an element
				list.Remove("1");
				Assert.AreSame(null, list.Data[list.Count]);
				list.RemoveAt(5);
				Assert.AreSame(null, list.Data[list.Count]);

				// Remove a range
				list.RemoveRange(0, 5);
				for (int i = list.Count; i < list.Data.Length; i++)
				{
					Assert.AreSame(null, list.Data[i]);
				}

				// Clear the list
				list.Clear();
				for (int i = list.Count; i < list.Data.Length; i++)
				{
					Assert.AreSame(null, list.Data[i]);
				}
			}
		}
示例#43
0
 /// <summary>
 /// Returns a resource to the pool.
 /// </summary>
 /// <param name="list">List to return.</param>
 public static void GiveBack(RawList<RayCastResult> list)
 {
     list.Clear();
     SubPoolRayCastResultList.GiveBack(list);
 }
示例#44
0
        internal bool IsPointContained(ref Vector3 point, RawList<int> triangles)
        {
            Vector3 rayDirection;
            //Point from the approximate center of the mesh outwards.
            //This is a cheap way to reduce the number of unnecessary checks when objects are external to the mesh.
            Vector3.Add(ref boundingBox.Max, ref boundingBox.Min, out rayDirection);
            Vector3.Multiply(ref rayDirection, .5f, out rayDirection);
            Vector3.Subtract(ref point, ref rayDirection, out rayDirection);
            //If the point is right in the middle, we'll need a backup.
            if (rayDirection.LengthSquared() < .01f)
                rayDirection = Vector3.Up;

            var ray = new Ray(point, rayDirection);
            triangleMesh.Tree.GetOverlaps(ray, triangles);

            float minimumT = float.MaxValue;
            bool minimumIsClockwise = false;

            for (int i = 0; i < triangles.Count; i++)
            {
                Vector3 a, b, c;
                triangleMesh.Data.GetTriangle(triangles.Elements[i], out a, out b, out c);

                RayHit hit;
                bool hitClockwise;
                if (Toolbox.FindRayTriangleIntersection(ref ray, float.MaxValue, ref a, ref b, ref c, out hitClockwise, out hit))
                {
                    if (hit.T < minimumT)
                    {
                        minimumT = hit.T;
                        minimumIsClockwise = hitClockwise;
                    }
                }
            }

            triangles.Clear();

            //If the first hit is on the inner surface, then the ray started inside the mesh.
            return minimumT < float.MaxValue && minimumIsClockwise == innerFacingIsClockwise;
        }
        /// <summary>
        /// Constructs a new demo.
        /// </summary>
        /// <param name="game">Game owning this demo.</param>
        public BroadPhasesTestDemo(DemosGame game)
            : base(game)
        {
            Space.Solver.IterationLimit = 0;
            Entity toAdd;
            //BoundingBox box = new BoundingBox(new Vector3(-5, 1, 1), new Vector3(5, 7, 7));
            BoundingBox box = new BoundingBox(new Vector3(-50, -50, -50), new Vector3(50, 50, 50));

            //DynamicHierarchyOld dhOld = new DynamicHierarchyOld(Space.ThreadManager);
            DynamicHierarchy   dh        = new DynamicHierarchy(Space.ParallelLooper);
            SortAndSweep1D     sas1d     = new SortAndSweep1D(Space.ParallelLooper);
            Grid2DSortAndSweep grid2DSAS = new Grid2DSortAndSweep(Space.ParallelLooper);
            //DynamicHierarchy dh = new DynamicHierarchy();
            //DynamicHierarchy4 dh4 = new DynamicHierarchy4();
            //SortAndSweep1D sas1d = new SortAndSweep1D();
            //Grid2DSortAndSweep grid2DSAS = new Grid2DSortAndSweep();

            //DynamicHierarchy2 dh2 = new DynamicHierarchy2();
            //DynamicHierarchy3 dh3 = new DynamicHierarchy3();
            //SortAndSweep3D sap3d = new SortAndSweep3D();

            RawList <Entity> entities = new RawList <Entity>();

            for (int k = 0; k < 100; k++)
            {
                Vector3 position = new Vector3((Fix64)rand.NextDouble() * (box.Max.X - box.Min.X) + box.Min.X,
                                               (Fix64)rand.NextDouble() * (box.Max.Y - box.Min.Y) + box.Min.Y,
                                               (Fix64)rand.NextDouble() * (box.Max.Z - box.Min.Z) + box.Min.Z);
                toAdd = new Box(position, 1, 1, 1, 1);
                toAdd.CollisionInformation.CollisionRules.Personal = CollisionRule.NoNarrowPhasePair;
                toAdd.CollisionInformation.UpdateBoundingBox(0);
                //Space.Add(toAdd);
                //dhOld.Add(toAdd.CollisionInformation);
                dh.Add(toAdd.CollisionInformation);
                sas1d.Add(toAdd.CollisionInformation);
                grid2DSAS.Add(toAdd.CollisionInformation);
                entities.Add(toAdd);
            }


            Space.ForceUpdater.Gravity = new Vector3();

            int numRuns = 10000;

            //Prime the system.
            grid2DSAS.Update();
            sas1d.Update();
            //dhOld.Update();
            dh.Update();
            var testType = Test.Update;

            double startTime, endTime;

            switch (testType)
            {
                #region Update Timing
            case Test.Update:
                for (int i = 0; i < numRuns; i++)
                {
                    ////DH
                    //startTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;
                    //dhOld.Update();
                    //endTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;
                    //DHOldTime += endTime - startTime;

                    //DH4
                    startTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;
                    dh.Update();
                    endTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;
                    DHtime += endTime - startTime;

                    //SAP1D
                    startTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;
                    sas1d.Update();
                    endTime    = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;
                    SAS1Dtime += endTime - startTime;

                    //Grid2D SOS
                    startTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;
                    grid2DSAS.Update();
                    endTime        = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;
                    grid2DSAStime += endTime - startTime;

                    //if (sap1d.Overlaps.Count != dh.Overlaps.Count)
                    //    Debug.WriteLine("SAP1D Failure");
                    //if (grid2DSOS.Overlaps.Count != dh.Overlaps.Count)
                    //    Debug.WriteLine("grid2DSOS Failure");

                    //for (int j = 0; j < dh2.Overlaps.Count; j++)
                    //{
                    //    if (!grid2DSOS.Overlaps.Contains(dh2.Overlaps[j]))
                    //        Debug.WriteLine("Break.");
                    //}
                    //for (int j = 0; j < grid2DSOS.Overlaps.Count; j++)
                    //{
                    //    if (!dh2.Overlaps.Contains(grid2DSOS.Overlaps[j]))
                    //        break;
                    //}

                    //for (int j = 0; j < grid2DSOS.Overlaps.Count; j++)
                    //{
                    //    if (!dh4.Overlaps.Contains(grid2DSOS.Overlaps[j]))
                    //        break;
                    //}

                    //for (int j = 0; j < dh.Overlaps.Count; j++)
                    //{
                    //    if (!dh.Overlaps[j].EntryA.BoundingBox.Intersects(dh.Overlaps[j].EntryB.BoundingBox))
                    //        Debug.WriteLine("Break.");
                    //}

                    //for (int j = 0; j < sap1d.Overlaps.Count; j++)
                    //{
                    //    if (!sap1d.Overlaps[j].EntryA.BoundingBox.Intersects(sap1d.Overlaps[j].EntryB.BoundingBox))
                    //        Debug.WriteLine("Break.");
                    //}

                    //for (int j = 0; j < grid2DSOS.Overlaps.Count; j++)
                    //{
                    //    if (!grid2DSOS.Overlaps[j].EntryA.BoundingBox.Intersects(grid2DSOS.Overlaps[j].EntryB.BoundingBox))
                    //        Debug.WriteLine("Break.");
                    //}

                    //MoveEntities(entities);
                }
                break;

                #endregion
                #region Ray cast timing
            case Test.RayCast:
                Fix64         rayLength = 100;
                RawList <Ray> rays      = new RawList <Ray>();
                for (int i = 0; i < numRuns; i++)
                {
                    rays.Add(new Ray()
                    {
                        Position = new Vector3((Fix64)rand.NextDouble() * (box.Max.X - box.Min.X) + box.Min.X,
                                               (Fix64)rand.NextDouble() * (box.Max.Y - box.Min.Y) + box.Min.Y,
                                               (Fix64)rand.NextDouble() * (box.Max.Z - box.Min.Z) + box.Min.Z),
                        Direction = Vector3.Normalize(new Vector3((Fix64)(rand.NextDouble() - .5), (Fix64)(rand.NextDouble() - .5), (Fix64)(rand.NextDouble() - .5)))
                    });
                }
                RawList <BroadPhaseEntry> outputIntersections = new RawList <BroadPhaseEntry>();


                ////DH
                //startTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;
                //for (int i = 0; i < numRuns; i++)
                //{
                //    dhOld.QueryAccelerator.RayCast(rays.Elements[i], rayLength, outputIntersections);
                //    outputIntersections.Clear();

                //}
                //endTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;
                //DHOldTime = endTime - startTime;

                //DH4
                startTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;
                for (int i = 0; i < numRuns; i++)
                {
                    dh.QueryAccelerator.RayCast(rays.Elements[i], rayLength, outputIntersections);
                    outputIntersections.Clear();
                }

                endTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;
                DHtime  = endTime - startTime;

                //Grid2DSAS
                startTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;
                for (int i = 0; i < numRuns; i++)
                {
                    grid2DSAS.QueryAccelerator.RayCast(rays.Elements[i], rayLength, outputIntersections);
                    outputIntersections.Clear();
                }
                endTime       = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;
                grid2DSAStime = endTime - startTime;
                break;

                #endregion
                #region Bounding box query timing
            case Test.BoundingBoxQuery:
                Fix64   boundingBoxSize = 10;
                var     boundingBoxes   = new RawList <BoundingBox>();
                Vector3 offset          = new Vector3(boundingBoxSize / 2, boundingBoxSize / 2, boundingBoxSize / 2);
                for (int i = 0; i < numRuns; i++)
                {
                    Vector3 center = new Vector3((Fix64)rand.NextDouble() * (box.Max.X - box.Min.X) + box.Min.X,
                                                 (Fix64)rand.NextDouble() * (box.Max.Y - box.Min.Y) + box.Min.Y,
                                                 (Fix64)rand.NextDouble() * (box.Max.Z - box.Min.Z) + box.Min.Z);
                    boundingBoxes.Add(new BoundingBox()
                    {
                        Min = center - offset,
                        Max = center + offset
                    });
                }

                outputIntersections = new RawList <BroadPhaseEntry>();

                ////DH
                //startTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;
                //for (int i = 0; i < numRuns; i++)
                //{
                //    dhOld.QueryAccelerator.GetEntries(boundingBoxes.Elements[i], outputIntersections);
                //    outputIntersections.Clear();

                //}
                //endTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;
                //DHOldTime = endTime - startTime;

                //DH4
                startTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;
                for (int i = 0; i < numRuns; i++)
                {
                    dh.QueryAccelerator.GetEntries(boundingBoxes.Elements[i], outputIntersections);
                    outputIntersections.Clear();
                }

                endTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;
                DHtime  = endTime - startTime;

                //Grid2DSAS
                startTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;
                for (int i = 0; i < numRuns; i++)
                {
                    grid2DSAS.QueryAccelerator.GetEntries(boundingBoxes.Elements[i], outputIntersections);
                    outputIntersections.Clear();
                }
                endTime       = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;
                grid2DSAStime = endTime - startTime;
                break;
                #endregion
            }


            DHOldTime     /= numRuns;
            DH2time       /= numRuns;
            DH3time       /= numRuns;
            DHtime        /= numRuns;
            SAS1Dtime     /= numRuns;
            grid2DSAStime /= numRuns;
        }