예제 #1
0
        public void Unset(int pos)
        {
            int arrIndex = pos >> 6;

            DebugHelper.AssertThrow(arrIndex < 4, () => new IndexOutOfRangeException($"Position {pos} is out of range for this BitSet."));
            bits[arrIndex] &= ~(1L << pos);
        }
예제 #2
0
        public readonly bool Get(int pos)
        {
            int arrIndex = pos >> 6;

            DebugHelper.AssertThrow(arrIndex < 4, () => new IndexOutOfRangeException($"Position {pos} is out of range for this BitSet."));
            return((bits[arrIndex] & (1L << pos)) != 0);
        }
예제 #3
0
 public T this[int index]
 {
     get {
         DebugHelper.AssertThrow <ArgumentOutOfRangeException>(index >= 0 && index < Count);
         return(_list[(uint)index + _start]);
     }
 }
        void VerifyFaces(List <vec3> points)
        {
            foreach (var kvp in faces)
            {
                var fi   = kvp.Key;
                var face = kvp.Value;

                DebugHelper.AssertThrow <InvalidOperationException>(faces.ContainsKey(face.Opposite0));
                DebugHelper.AssertThrow <InvalidOperationException>(faces.ContainsKey(face.Opposite1));
                DebugHelper.AssertThrow <InvalidOperationException>(faces.ContainsKey(face.Opposite2));

                DebugHelper.AssertThrow <InvalidOperationException>(face.Opposite0 != fi);
                DebugHelper.AssertThrow <InvalidOperationException>(face.Opposite1 != fi);
                DebugHelper.AssertThrow <InvalidOperationException>(face.Opposite2 != fi);

                DebugHelper.AssertThrow <InvalidOperationException>(face.Vertex0 != face.Vertex1);
                DebugHelper.AssertThrow <InvalidOperationException>(face.Vertex0 != face.Vertex2);
                DebugHelper.AssertThrow <InvalidOperationException>(face.Vertex1 != face.Vertex2);

                DebugHelper.AssertThrow <InvalidOperationException>(HasEdge(faces[face.Opposite0], face.Vertex2, face.Vertex1));
                DebugHelper.AssertThrow <InvalidOperationException>(HasEdge(faces[face.Opposite1], face.Vertex0, face.Vertex2));
                DebugHelper.AssertThrow <InvalidOperationException>(HasEdge(faces[face.Opposite2], face.Vertex1, face.Vertex0));

                DebugHelper.AssertThrow <InvalidOperationException>((face.Normal - CalculateNormal(
                                                                         points[face.Vertex0],
                                                                         points[face.Vertex1],
                                                                         points[face.Vertex2])).Length < EPSILON);
            }
        }
예제 #5
0
 public ViewType this[uint index]
 {
     get {
         DebugHelper.AssertThrow <ArgumentOutOfRangeException>(index < Count);
         return(Unsafe.Read <ViewType>(_parent._dataPtr + index * s_elementByteSize));
     }
 }
예제 #6
0
        private static VkShaderModule loadShader(AssetReference <ShaderAsset> asset, VkDevice device, VkShaderStageFlags stage)
        {
            if (!asset.IsLoaded)
            {
                asset.LoadNow();
            }

            var shader = asset.Get();

            if ((stage & VkShaderStageFlags.Fragment) != 0)
            {
                DebugHelper.AssertThrow <InvalidOperationException>(shader.Type == ShaderAsset.ShaderType.Frag);
            }
            else if ((stage & VkShaderStageFlags.Vertex) != 0)
            {
                DebugHelper.AssertThrow <InvalidOperationException>(shader.Type == ShaderAsset.ShaderType.Vertex);
            }

            byte[] shaderCode = shader.GetBytes();
            ulong  shaderSize = (ulong)shaderCode.Length;

            fixed(byte *scPtr = shaderCode)
            {
                // Create a new shader module that will be used for Pipeline creation
                VkShaderModuleCreateInfo moduleCreateInfo = VkShaderModuleCreateInfo.New();

                moduleCreateInfo.codeSize = new UIntPtr(shaderSize);
                moduleCreateInfo.pCode    = (uint *)scPtr;

                Util.CheckResult(vkCreateShaderModule(device, ref moduleCreateInfo, null, out VkShaderModule shaderModule));

                return(shaderModule);
            }
        }
예제 #7
0
 public ref T this[int index]
 {
     get
     {
         ThrowIfDisposed();
         DebugHelper.AssertThrow <ArgumentOutOfRangeException>(index >= 0 && index < _count);
         return(ref Unsafe.AsRef <T>(_dataPtr + index * s_elementByteSize));
     }
 }
        void VerifyHorizon()
        {
            for (int i = 0; i < horizon.Count; i++)
            {
                var prev = i == 0 ? horizon.Count - 1 : i - 1;

                DebugHelper.AssertThrow <InvalidOperationException>(horizon[prev].Edge1 == horizon[i].Edge0);
                DebugHelper.AssertThrow <InvalidOperationException>(HasEdge(faces[horizon[i].Face], horizon[i].Edge1, horizon[i].Edge0));
            }
        }
        /// <summary>
        ///   Remove all lit faces and construct new faces from the
        ///   horizon in a "cone-like" fashion.
        ///
        ///   This is a relatively straight-forward procedure, given
        ///   that the horizon is handed to it in already sorted
        ///   counter-clockwise. The neighbors of the new faces are
        ///   easy to find: they're the previous and next faces to be
        ///   constructed in the cone, as well as the face on the
        ///   other side of the horizon. We also have to update the
        ///   face on the other side of the horizon to reflect it's
        ///   new neighbor from the cone.
        /// </summary>
        void ConstructCone(List <vec3> points, int farthestPoint)
        {
            foreach (var fi in litFaces)
            {
                DebugHelper.AssertThrow <InvalidOperationException>(faces.ContainsKey(fi));
                faces.Remove(fi);
            }

            var firstNewFace = faceCount;

            for (int i = 0; i < horizon.Count; i++)
            {
                // Vertices of the new face, the farthest point as
                // well as the edge on the horizon. Horizon edge is
                // CCW, so the triangle should be as well.
                var v0 = farthestPoint;
                var v1 = horizon[i].Edge0;
                var v2 = horizon[i].Edge1;

                // Opposite faces of the triangle. First, the edge on
                // the other side of the horizon, then the next/prev
                // faces on the new cone
                var o0 = horizon[i].Face;
                var o1 = (i == horizon.Count - 1) ? firstNewFace : firstNewFace + i + 1;
                var o2 = (i == 0) ? (firstNewFace + horizon.Count - 1) : firstNewFace + i - 1;

                var fi = faceCount++;

                faces[fi] = new Face(
                    v0, v1, v2,
                    o0, o1, o2,
                    CalculateNormal(points[v0], points[v1], points[v2]));

                var horizonFace = faces[horizon[i].Face];

                if (horizonFace.Vertex0 == v1)
                {
                    DebugHelper.AssertThrow <InvalidOperationException>(v2 == horizonFace.Vertex2);
                    horizonFace.Opposite1 = fi;
                }
                else if (horizonFace.Vertex1 == v1)
                {
                    DebugHelper.AssertThrow <InvalidOperationException>(v2 == horizonFace.Vertex0);
                    horizonFace.Opposite2 = fi;
                }
                else
                {
                    DebugHelper.AssertThrow <InvalidOperationException>(v1 == horizonFace.Vertex2);
                    DebugHelper.AssertThrow <InvalidOperationException>(v2 == horizonFace.Vertex1);
                    horizonFace.Opposite0 = fi;
                }

                faces[horizon[i].Face] = horizonFace;
            }
        }
예제 #10
0
        public void UpdateBuffer <T>(T value, DeviceBuffer dstBuffer, ulong dstOffset) where T : unmanaged
        {
            if (vkCmd.Handle == NullHandle)
            {
                return;
            }
            ulong size = (ulong)Unsafe.SizeOf <T>();

            DebugHelper.AssertThrow <InvalidOperationException>(size <= 65536);
            CheckBegun();
            CheckNotInRenderPass();

            vkCmdUpdateBuffer(vkCmd, dstBuffer.vkBuffer, dstOffset, size, &value);
        }
예제 #11
0
        public void SetData <T>(T data, UInt64 dstOffsetInBytes = 0) where T : unmanaged
        {
            DebugHelper.AssertThrow <IndexOutOfRangeException>(size - dstOffsetInBytes >= (ulong)Unsafe.SizeOf <T>());
            uint len = (uint)Math.Min(size - dstOffsetInBytes, (ulong)Unsafe.SizeOf <T>());

            if (memory.hostVisible)
            {
                Unsafe.Copy((byte *)memory.Mapped + dstOffsetInBytes, ref data);
                //Flush(dstOffsetInBytes, len);
            }
            else
            {
                StagingTransfer(dstOffsetInBytes, (UInt64)(len), &data);
            }
        }
        void VerifyMesh(List <vec3> points, ref List <vec3> verts, ref List <uint> tris)
        {
            DebugHelper.AssertThrow <InvalidOperationException>(tris.Count % 3 == 0);

            for (int i = 0; i < points.Count; i++)
            {
                for (int j = 0; j < tris.Count; j += 3)
                {
                    var t0 = verts[(int)tris[j]];
                    var t1 = verts[(int)tris[j + 1]];
                    var t2 = verts[(int)tris[j + 2]];

                    DebugHelper.AssertThrow <InvalidOperationException>(vec3.Dot(points[i] - t0, vec3.Cross(t1 - t0, t2 - t0)) <= EPSILON);
                }
            }
        }
예제 #13
0
        public void UpdateBuffer <T>(ReadOnlySpan <T> values, DeviceBuffer dstBuffer, ulong dstOffset) where T : unmanaged
        {
            if (vkCmd.Handle == NullHandle)
            {
                return;
            }
            ulong size = (ulong)Unsafe.SizeOf <T>() * (ulong)values.Length;

            DebugHelper.AssertThrow <InvalidOperationException>(size <= 65536);
            CheckBegun();
            CheckNotInRenderPass();

            fixed(T *ptr = values)
            {
                vkCmdUpdateBuffer(vkCmd, dstBuffer.vkBuffer, dstOffset, size, &ptr);
            }
        }
예제 #14
0
        public void QueueEvent <T>(T _event) where T : struct, IEvent
        {
            DebugHelper.AssertThrow <ThreadAccessException>(ECSWorld.CheckThreadIsMainThread());
            int hash = TypeHelper <T> .hashCode;

            if (!eventManagers.TryGetValue(hash, out IEventManager manager))
            {
                manager = new EventManager <T>();
                if (systems != null)
                {
                    manager.UpdateSubscribers(systems);
                }
                eventManagers.Add(hash, manager);
                allEventManagers.Add(manager);
            }
            ((EventManager <T>)manager).QueueEvent(_event);
        }
예제 #15
0
        public void SetData <T>(ReadOnlySpan <T> data, UInt64 dstOffsetInBytes = 0) where T : unmanaged
        {
            DebugHelper.AssertThrow <IndexOutOfRangeException>(size - dstOffsetInBytes >= (ulong)(data.Length * Unsafe.SizeOf <T>()));
            fixed(T *ptr = data)
            {
                uint len = (uint)Math.Min(size - dstOffsetInBytes, (ulong)(data.Length * Unsafe.SizeOf <T>()));

                if (memory.hostVisible)
                {
                    Unsafe.CopyBlock((byte *)memory.Mapped + dstOffsetInBytes, ptr, len);
                    //Flush(dstOffsetInBytes, len);
                }
                else
                {
                    StagingTransfer(dstOffsetInBytes, len, ptr);
                }
            }
        }
        void VerifyOpenSet(List <vec3> points)
        {
            for (int i = 0; i < openSet.Count; i++)
            {
                if (i > openSetTail)
                {
                    DebugHelper.AssertThrow <InvalidOperationException>(openSet[i].Face == INSIDE);
                }
                else
                {
                    DebugHelper.AssertThrow <InvalidOperationException>(openSet[i].Face != INSIDE);
                    DebugHelper.AssertThrow <InvalidOperationException>(openSet[i].Face != UNASSIGNED);

                    DebugHelper.AssertThrow <InvalidOperationException>(PointFaceDistance(
                                                                            points[openSet[i].Point],
                                                                            points[faces[openSet[i].Face].Vertex0],
                                                                            faces[openSet[i].Face]) > 0.0f);
                }
            }
        }
        internal void Return(VulkanMemorySlice returnSlice)
        {
            DebugHelper.AssertThrow <InvalidOperationException>(returnSlice.vkDeviceMemory.Handle == vkDeviceMemory.Handle);

            //First try to merge with existing free slices
            for (int i = 0; i < freeSlices.Count; i++)
            {
                var   slice         = freeSlices[i];
                ulong sizeWithAlign = returnSlice.size + returnSlice.alignOffset;

                if (slice.startIndex == returnSlice.offset + sizeWithAlign)
                {
                    slice.length     += sizeWithAlign;
                    slice.startIndex -= sizeWithAlign;
                    freeSlices[i]     = slice;
                    return;
                }
            }
            //If not possible insert to the list
            FreeSlice newSlice = new FreeSlice()
            {
                length = returnSlice.size + returnSlice.alignOffset, startIndex = returnSlice.offset - returnSlice.alignOffset
            };

            //freeSlices.Add(newSlice);

            //Add and sort in ascending order by length
            for (int i = 0; i < freeSlices.Count; i++)
            {
                if (freeSlices[i].length > newSlice.length)
                {
                    freeSlices.Insert(i, newSlice);
                    return;
                }
            }
            //If largest, add to the end
            freeSlices.Add(newSlice);
        }
        /// <summary>
        ///   Grow the hull. This method takes the current hull, and
        ///   expands it to encompass the point in openSet with the
        ///   point furthest away from it's face.
        /// </summary>
        void GrowHull(List <vec3> points)
        {
            DebugHelper.AssertThrow <InvalidOperationException>(openSetTail >= 0);
            DebugHelper.AssertThrow <InvalidOperationException>(openSet[0].Face != INSIDE);

            // Find farthest point and first lit face.
            var farthestPoint = 0;
            var dist          = openSet[0].Distance;

            for (int i = 1; i <= openSetTail; i++)
            {
                if (openSet[i].Distance > dist)
                {
                    farthestPoint = i;
                    dist          = openSet[i].Distance;
                }
            }

            // Use lit face to find horizon and the rest of the lit
            // faces.
            FindHorizon(
                points,
                points[openSet[farthestPoint].Point],
                openSet[farthestPoint].Face,
                faces[openSet[farthestPoint].Face]);

            VerifyHorizon();

            // Construct new cone from horizon
            ConstructCone(points, openSet[farthestPoint].Point);

            VerifyFaces(points);

            // Reassign points
            ReassignPoints(points);
        }
예제 #19
0
 public static JobGroup StartNewGroup()
 {
     DebugHelper.AssertThrow <ThreadAccessException>(ECSWorld.CheckThreadIsMainThread());
     return(JobManager.StartJobGroup());
 }
예제 #20
0
 public static void CompleteAllJobs()
 {
     DebugHelper.AssertThrow <ThreadAccessException>(ECSWorld.CheckThreadIsMainThread());
     JobManager.CompleteAll();
 }
예제 #21
0
 public static JobHandle QueueJob <T>(T job, JobGroup group) where T : struct, IJob
 {
     DebugHelper.AssertThrow <ThreadAccessException>(ECSWorld.CheckThreadIsMainThread());
     return(JobManager.QueueJob(job, group));
 }
예제 #22
0
 public static JobGroup StartNewGroup(ComponentQuery dependencies)
 {
     DebugHelper.AssertThrow <ThreadAccessException>(ECSWorld.CheckThreadIsMainThread());
     return(JobManager.StartJobGroup(dependencies));
 }
예제 #23
0
 public ReadOnlyNativeListView <T> GetReadOnlyView(uint start, uint count)
 {
     ThrowIfDisposed();
     DebugHelper.AssertThrow <ArgumentOutOfRangeException>(start + count <= _count);
     return(new ReadOnlyNativeListView <T>(this, start, count));
 }
        /// <summary>
        ///   Recursively search to find the horizon or lit set.
        /// </summary>
        void SearchHorizon(List <vec3> points, vec3 point, int prevFaceIndex, int faceCount, Face face)
        {
            DebugHelper.AssertThrow <InvalidOperationException>(prevFaceIndex >= 0);
            DebugHelper.AssertThrow <InvalidOperationException>(litFaces.Contains(prevFaceIndex));
            DebugHelper.AssertThrow <InvalidOperationException>(!litFaces.Contains(faceCount));
            DebugHelper.AssertThrow <InvalidOperationException>(faces[faceCount].Equals(face));

            litFaces.Add(faceCount);

            // Use prevFaceIndex to determine what the next face to
            // search will be, and what edges we need to cross to get
            // there. It's important that the search proceeds in
            // counter-clockwise order from the previous face.
            int nextFaceIndex0;
            int nextFaceIndex1;
            int edge0;
            int edge1;
            int edge2;

            if (prevFaceIndex == face.Opposite0)
            {
                nextFaceIndex0 = face.Opposite1;
                nextFaceIndex1 = face.Opposite2;

                edge0 = face.Vertex2;
                edge1 = face.Vertex0;
                edge2 = face.Vertex1;
            }
            else if (prevFaceIndex == face.Opposite1)
            {
                nextFaceIndex0 = face.Opposite2;
                nextFaceIndex1 = face.Opposite0;

                edge0 = face.Vertex0;
                edge1 = face.Vertex1;
                edge2 = face.Vertex2;
            }
            else
            {
                DebugHelper.AssertThrow <InvalidOperationException>(prevFaceIndex == face.Opposite2);

                nextFaceIndex0 = face.Opposite0;
                nextFaceIndex1 = face.Opposite1;

                edge0 = face.Vertex1;
                edge1 = face.Vertex2;
                edge2 = face.Vertex0;
            }

            if (!litFaces.Contains(nextFaceIndex0))
            {
                var oppositeFace = faces[nextFaceIndex0];

                var dist = PointFaceDistance(
                    point,
                    points[oppositeFace.Vertex0],
                    oppositeFace);

                if (dist <= 0.0f)
                {
                    horizon.Add(new HorizonEdge {
                        Face  = nextFaceIndex0,
                        Edge0 = edge0,
                        Edge1 = edge1,
                    });
                }
                else
                {
                    SearchHorizon(points, point, faceCount, nextFaceIndex0, oppositeFace);
                }
            }

            if (!litFaces.Contains(nextFaceIndex1))
            {
                var oppositeFace = faces[nextFaceIndex1];

                var dist = PointFaceDistance(
                    point,
                    points[oppositeFace.Vertex0],
                    oppositeFace);

                if (dist <= 0.0f)
                {
                    horizon.Add(new HorizonEdge {
                        Face  = nextFaceIndex1,
                        Edge0 = edge1,
                        Edge1 = edge2,
                    });
                }
                else
                {
                    SearchHorizon(points, point, faceCount, nextFaceIndex1, oppositeFace);
                }
            }
        }
        /// <summary>
        ///   Start the search for the horizon.
        ///
        ///   The search is a DFS search that searches neighboring
        ///   triangles in a counter-clockwise fashion. When it find a
        ///   neighbor which is not lit, that edge will be a line on
        ///   the horizon. If the search always proceeds
        ///   counter-clockwise, the edges of the horizon will be
        ///   found in counter-clockwise order.
        ///
        ///   The heart of the search can be found in the recursive
        ///   SearchHorizon() method, but the the first iteration of
        ///   the search is special, because it has to visit three
        ///   neighbors (all the neighbors of the initial triangle),
        ///   while the rest of the search only has to visit two
        ///   (because one of them has already been visited, the one
        ///   you came from).
        /// </summary>
        void FindHorizon(List <vec3> points, vec3 point, int fi, Face face)
        {
            // TODO should I use epsilon in the PointFaceDistance comparisons?

            litFaces.Clear();
            horizon.Clear();

            litFaces.Add(fi);

            DebugHelper.AssertThrow <InvalidOperationException>(PointFaceDistance(point, points[face.Vertex0], face) > 0.0f);

            // For the rest of the recursive search calls, we first
            // check if the triangle has already been visited and is
            // part of litFaces. However, in this first call we can
            // skip that because we know it can't possibly have been
            // visited yet, since the only thing in litFaces is the
            // current triangle.
            {
                var oppositeFace = faces[face.Opposite0];

                var dist = PointFaceDistance(
                    point,
                    points[oppositeFace.Vertex0],
                    oppositeFace);

                if (dist <= 0.0f)
                {
                    horizon.Add(new HorizonEdge {
                        Face  = face.Opposite0,
                        Edge0 = face.Vertex1,
                        Edge1 = face.Vertex2,
                    });
                }
                else
                {
                    SearchHorizon(points, point, fi, face.Opposite0, oppositeFace);
                }
            }

            if (!litFaces.Contains(face.Opposite1))
            {
                var oppositeFace = faces[face.Opposite1];

                var dist = PointFaceDistance(
                    point,
                    points[oppositeFace.Vertex0],
                    oppositeFace);

                if (dist <= 0.0f)
                {
                    horizon.Add(new HorizonEdge {
                        Face  = face.Opposite1,
                        Edge0 = face.Vertex2,
                        Edge1 = face.Vertex0,
                    });
                }
                else
                {
                    SearchHorizon(points, point, fi, face.Opposite1, oppositeFace);
                }
            }

            if (!litFaces.Contains(face.Opposite2))
            {
                var oppositeFace = faces[face.Opposite2];

                var dist = PointFaceDistance(
                    point,
                    points[oppositeFace.Vertex0],
                    oppositeFace);

                if (dist <= 0.0f)
                {
                    horizon.Add(new HorizonEdge {
                        Face  = face.Opposite2,
                        Edge0 = face.Vertex0,
                        Edge1 = face.Vertex1,
                    });
                }
                else
                {
                    SearchHorizon(points, point, fi, face.Opposite2, oppositeFace);
                }
            }
        }
        /// <summary>
        ///   Create initial seed hull.
        /// </summary>
        void GenerateInitialHull(List <vec3> points)
        {
            // Find points suitable for use as the seed hull. Some
            // varieties of this algorithm pick extreme points here,
            // but I'm not convinced you gain all that much from that.
            // Currently what it does is just find the first four
            // points that are not coplanar.
            int b0, b1, b2, b3;

            FindInitialHullIndices(points, out b0, out b1, out b2, out b3);

            var v0 = points[b0];
            var v1 = points[b1];
            var v2 = points[b2];
            var v3 = points[b3];

            var above = vec3.Dot(v3 - v1, vec3.Cross(v1 - v0, v2 - v0)) > 0.0f;

            // Create the faces of the seed hull. You need to draw a
            // diagram here, otherwise it's impossible to know what's
            // going on :)

            // Basically: there are two different possible
            // start-tetrahedrons, depending on whether the fourth
            // point is above or below the base triangle. If you draw
            // a tetrahedron with these coordinates (in a right-handed
            // coordinate-system):

            //   b0 = (0,0,0)
            //   b1 = (1,0,0)
            //   b2 = (0,1,0)
            //   b3 = (0,0,1)

            // you can see the first case (set b3 = (0,0,-1) for the
            // second case). The faces are added with the proper
            // references to the faces opposite each vertex

            faceCount = 0;
            if (above)
            {
                faces[faceCount++] = new Face(b0, b2, b1, 3, 1, 2, CalculateNormal(points[b0], points[b2], points[b1]));
                faces[faceCount++] = new Face(b0, b1, b3, 3, 2, 0, CalculateNormal(points[b0], points[b1], points[b3]));
                faces[faceCount++] = new Face(b0, b3, b2, 3, 0, 1, CalculateNormal(points[b0], points[b3], points[b2]));
                faces[faceCount++] = new Face(b1, b2, b3, 2, 1, 0, CalculateNormal(points[b1], points[b2], points[b3]));
            }
            else
            {
                faces[faceCount++] = new Face(b0, b1, b2, 3, 2, 1, CalculateNormal(points[b0], points[b1], points[b2]));
                faces[faceCount++] = new Face(b0, b3, b1, 3, 0, 2, CalculateNormal(points[b0], points[b3], points[b1]));
                faces[faceCount++] = new Face(b0, b2, b3, 3, 1, 0, CalculateNormal(points[b0], points[b2], points[b3]));
                faces[faceCount++] = new Face(b1, b3, b2, 2, 0, 1, CalculateNormal(points[b1], points[b3], points[b2]));
            }

            VerifyFaces(points);

            // Create the openSet. Add all points except the points of
            // the seed hull.
            for (int i = 0; i < points.Count; i++)
            {
                if (i == b0 || i == b1 || i == b2 || i == b3)
                {
                    continue;
                }

                openSet.Add(new PointFace(i, UNASSIGNED, 0.0f));
            }

            // Add the seed hull verts to the tail of the list.
            openSet.Add(new PointFace(b0, INSIDE, float.NaN));
            openSet.Add(new PointFace(b1, INSIDE, float.NaN));
            openSet.Add(new PointFace(b2, INSIDE, float.NaN));
            openSet.Add(new PointFace(b3, INSIDE, float.NaN));

            // Set the openSetTail value. Last item in the array is
            // openSet.Count - 1, but four of the points (the verts of
            // the seed hull) are part of the closed set, so move
            // openSetTail to just before those.
            openSetTail = openSet.Count - 5;

            DebugHelper.AssertThrow <InvalidOperationException>(openSet.Count == points.Count);

            // Assign all points of the open set. This does basically
            // the same thing as ReassignPoints()
            for (int i = 0; i <= openSetTail; i++)
            {
                DebugHelper.AssertThrow <InvalidOperationException>(openSet[i].Face == UNASSIGNED);
                DebugHelper.AssertThrow <InvalidOperationException>(openSet[openSetTail].Face == UNASSIGNED);
                DebugHelper.AssertThrow <InvalidOperationException>(openSet[openSetTail + 1].Face == INSIDE);

                var assigned = false;
                var fp       = openSet[i];

                DebugHelper.AssertThrow <InvalidOperationException>(faces.Count == 4);
                DebugHelper.AssertThrow <InvalidOperationException>(faces.Count == faceCount);
                for (int j = 0; j < 4; j++)
                {
                    DebugHelper.AssertThrow <InvalidOperationException>(faces.ContainsKey(j));

                    var face = faces[j];

                    var dist = PointFaceDistance(points[fp.Point], points[face.Vertex0], face);

                    if (dist > 0)
                    {
                        fp.Face     = j;
                        fp.Distance = dist;
                        openSet[i]  = fp;

                        assigned = true;
                        break;
                    }
                }

                if (!assigned)
                {
                    // Point is inside
                    fp.Face     = INSIDE;
                    fp.Distance = float.NaN;

                    // Point is inside seed hull: swap point with
                    // tail, and move openSetTail back. We also have
                    // to decrement i, because there's a new item at
                    // openSet[i], and we need to process it next iteration
                    openSet[i]           = openSet[openSetTail];
                    openSet[openSetTail] = fp;

                    openSetTail -= 1;
                    i           -= 1;
                }
            }

            VerifyOpenSet(points);
        }
예제 #27
0
 public void RemoveAt(uint index)
 {
     ThrowIfDisposed();
     DebugHelper.AssertThrow <ArgumentOutOfRangeException>(index < _count);
     CoreRemoveAt(index);
 }
예제 #28
0
 public IntPtr GetAddress(uint index)
 {
     ThrowIfDisposed();
     DebugHelper.AssertThrow <ArgumentOutOfRangeException>(index < _count);
     return(new IntPtr(_dataPtr + (index * s_elementByteSize)));
 }
예제 #29
0
 public bool IsComplete()
 {
     DebugHelper.AssertThrow <ThreadAccessException>(ECSWorld.CheckThreadIsMainThread());
     return(JobManager.IsGroupComplete(this));
 }