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); }
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); }
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); } }
public ViewType this[uint index] { get { DebugHelper.AssertThrow <ArgumentOutOfRangeException>(index < Count); return(Unsafe.Read <ViewType>(_parent._dataPtr + index * s_elementByteSize)); } }
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); } }
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; } }
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); }
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); } } }
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); } }
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); }
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); }
public static JobGroup StartNewGroup() { DebugHelper.AssertThrow <ThreadAccessException>(ECSWorld.CheckThreadIsMainThread()); return(JobManager.StartJobGroup()); }
public static void CompleteAllJobs() { DebugHelper.AssertThrow <ThreadAccessException>(ECSWorld.CheckThreadIsMainThread()); JobManager.CompleteAll(); }
public static JobHandle QueueJob <T>(T job, JobGroup group) where T : struct, IJob { DebugHelper.AssertThrow <ThreadAccessException>(ECSWorld.CheckThreadIsMainThread()); return(JobManager.QueueJob(job, group)); }
public static JobGroup StartNewGroup(ComponentQuery dependencies) { DebugHelper.AssertThrow <ThreadAccessException>(ECSWorld.CheckThreadIsMainThread()); return(JobManager.StartJobGroup(dependencies)); }
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); }
public void RemoveAt(uint index) { ThrowIfDisposed(); DebugHelper.AssertThrow <ArgumentOutOfRangeException>(index < _count); CoreRemoveAt(index); }
public IntPtr GetAddress(uint index) { ThrowIfDisposed(); DebugHelper.AssertThrow <ArgumentOutOfRangeException>(index < _count); return(new IntPtr(_dataPtr + (index * s_elementByteSize))); }
public bool IsComplete() { DebugHelper.AssertThrow <ThreadAccessException>(ECSWorld.CheckThreadIsMainThread()); return(JobManager.IsGroupComplete(this)); }