OldBlueWater/BlueWater/Assets/NWH/Dynamic Water Physics 2/Scripts/Lib/MIConvexHull/ConvexHull/ObjectManager.cs
2023-12-19 11:31:29 +09:00

248 lines
7.8 KiB
C#

/******************************************************************************
*
* The MIT License (MIT)
*
* MIConvexHull, Copyright (c) 2015 David Sehnal, Matthew Campbell
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*****************************************************************************/
using System;
namespace NWH.DWP2.MiConvexHull
{
/// <summary>
/// A helper class for object allocation/storage.
/// This helps the GC a lot as it prevents the creation of about 75% of
/// new face objects (in the case of ConvexFaceInternal). In the case of
/// FaceConnectors and DefferedFaces, the difference is even higher (in most
/// cases O(1) vs O(number of created faces)).
/// </summary>
internal class ObjectManager
{
/// <summary>
/// The dimension
/// </summary>
private readonly int Dimension;
/// <summary>
/// The deferred face stack
/// </summary>
private readonly SimpleList<DeferredFace> DeferredFaceStack;
/// <summary>
/// The empty buffer stack
/// </summary>
private readonly SimpleList<IndexBuffer> EmptyBufferStack;
/// <summary>
/// The free face indices
/// </summary>
private readonly IndexBuffer FreeFaceIndices;
/// <summary>
/// The hull
/// </summary>
private readonly ConvexHullAlgorithm Hull;
/// <summary>
/// The connector stack
/// </summary>
private FaceConnector ConnectorStack;
/// <summary>
/// The face pool
/// </summary>
private ConvexFaceInternal[] FacePool;
/// <summary>
/// The face pool size
/// </summary>
private int FacePoolSize;
/// <summary>
/// The face pool capacity
/// </summary>
private int FacePoolCapacity;
/// <summary>
/// Create the manager.
/// </summary>
/// <param name="hull">The hull.</param>
public ObjectManager(ConvexHullAlgorithm hull)
{
Dimension = hull.NumOfDimensions;
Hull = hull;
FacePool = hull.FacePool;
FacePoolSize = 0;
FacePoolCapacity = hull.FacePool.Length;
FreeFaceIndices = new IndexBuffer();
EmptyBufferStack = new SimpleList<IndexBuffer>();
DeferredFaceStack = new SimpleList<DeferredFace>();
}
/// <summary>
/// Return the face to the pool for later use.
/// </summary>
/// <param name="faceIndex">Index of the face.</param>
public void DepositFace(int faceIndex)
{
ConvexFaceInternal face = FacePool[faceIndex];
int[] af = face.AdjacentFaces;
for (int i = 0; i < af.Length; i++)
{
af[i] = -1;
}
FreeFaceIndices.Push(faceIndex);
}
/// <summary>
/// Reallocate the face pool, including the AffectedFaceFlags
/// </summary>
private void ReallocateFacePool()
{
ConvexFaceInternal[] newPool = new ConvexFaceInternal[2 * FacePoolCapacity];
bool[] newTags = new bool[2 * FacePoolCapacity];
Array.Copy(FacePool, newPool, FacePoolCapacity);
Buffer.BlockCopy(Hull.AffectedFaceFlags, 0, newTags, 0, FacePoolCapacity * sizeof(bool));
FacePoolCapacity = 2 * FacePoolCapacity;
Hull.FacePool = newPool;
FacePool = newPool;
Hull.AffectedFaceFlags = newTags;
}
/// <summary>
/// Create a new face and put it in the pool.
/// </summary>
/// <returns>System.Int32.</returns>
private int CreateFace()
{
int index = FacePoolSize;
ConvexFaceInternal face = new ConvexFaceInternal(Dimension, index, GetVertexBuffer());
FacePoolSize++;
if (FacePoolSize > FacePoolCapacity)
{
ReallocateFacePool();
}
FacePool[index] = face;
return index;
}
/// <summary>
/// Return index of an unused face or creates a new one.
/// </summary>
/// <returns>System.Int32.</returns>
public int GetFace()
{
if (FreeFaceIndices.Count > 0)
{
return FreeFaceIndices.Pop();
}
return CreateFace();
}
/// <summary>
/// Store a face connector in the "embedded" linked list.
/// </summary>
/// <param name="connector">The connector.</param>
public void DepositConnector(FaceConnector connector)
{
if (ConnectorStack == null)
{
connector.Next = null;
ConnectorStack = connector;
}
else
{
connector.Next = ConnectorStack;
ConnectorStack = connector;
}
}
/// <summary>
/// Get an unused face connector. If none is available, create it.
/// </summary>
/// <returns>FaceConnector.</returns>
public FaceConnector GetConnector()
{
if (ConnectorStack == null)
{
return new FaceConnector(Dimension);
}
FaceConnector ret = ConnectorStack;
ConnectorStack = ConnectorStack.Next;
ret.Next = null;
return ret;
}
/// <summary>
/// Deposit the index buffer.
/// </summary>
/// <param name="buffer">The buffer.</param>
public void DepositVertexBuffer(IndexBuffer buffer)
{
buffer.Clear();
EmptyBufferStack.Push(buffer);
}
/// <summary>
/// Get a store index buffer or create a new instance.
/// </summary>
/// <returns>IndexBuffer.</returns>
public IndexBuffer GetVertexBuffer()
{
return EmptyBufferStack.Count != 0 ? EmptyBufferStack.Pop() : new IndexBuffer();
}
/// <summary>
/// Deposit the deferred face.
/// </summary>
/// <param name="face">The face.</param>
public void DepositDeferredFace(DeferredFace face)
{
DeferredFaceStack.Push(face);
}
/// <summary>
/// Get the deferred face.
/// </summary>
/// <returns>DeferredFace.</returns>
public DeferredFace GetDeferredFace()
{
return DeferredFaceStack.Count != 0 ? DeferredFaceStack.Pop() : new DeferredFace();
}
}
}