//----------------------------------------------------------------------- //----------------------------------------------------------------------- // file="PlainInstancingBuffer.cs" // Project: StgSharp // AuthorGroup: Nitload Space // Copyright (c) Nitload Space. All rights reserved. // // 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 StgSharp.Math; using System; using System.Collections; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics.Contracts; using System.Linq; using System.Numerics; using System.Reflection; using System.Text; using System.Threading; using System.Threading.Tasks; namespace StgSharp.Geometries { public class PlainInstancingBuffer : IDisposable,IEnumerable, IInstancingBuffer where T : IInstancing { private CoordinatePlain globalCorrdinnate; private List coordList; private List instanceList; private List scalingList; private Mutex mutex; private bool disposedValue; #region field of mem opt vec4d[] coordArray; float[] scaleArray; #endregion public PlainInstancingBuffer() { coordList = new List(capacity: 100); instanceList = new List(capacity:100); scalingList = new List(capacity: 100); coordArray = Array.Empty(); scaleArray = Array.Empty(); mutex = new Mutex(); } public List InstanceList { get => instanceList; } public List CoordAndRotationList { get => coordList; } public List ScalingList { get => scalingList; } public Span CoordAndRotationSpan { get { if (coordArray.Length != coordList.Capacity) { FieldInfo fieldInfo = typeof(List). GetField("_items", BindingFlags.NonPublic | BindingFlags.Instance); if (fieldInfo == null) { #pragma warning disable CA1065 #pragma warning disable CA2201 throw new NullReferenceException(); #pragma warning restore CA2201 #pragma warning restore CA1065 } coordArray = (vec4d[])fieldInfo.GetValue(coordList); } return new Span(coordArray, 0, coordList.Count); } } public Span ScalingSpan { get { if (scaleArray.Length != coordList.Capacity) { FieldInfo fieldInfo = typeof(List). GetField("_items", BindingFlags.NonPublic | BindingFlags.Instance); if (fieldInfo == null) { #pragma warning disable CA1065 #pragma warning disable CA2201 throw new NullReferenceException(); #pragma warning restore CA2201 #pragma warning restore CA1065 } scaleArray = (float[])fieldInfo.GetValue(scalingList); } return new Span(scaleArray, 0, coordList.Count); } } IGeometry IInstancingBuffer.TypicalShape => throw new NotImplementedException(); public int CreateInstanceID() { mutex.WaitOne(); int ret = instanceList.Count; coordList.Add(new vec4d()); scalingList.Add(0); mutex.ReleaseMutex(); return ret; } public void Remove(T instance) { mutex.WaitOne(); if (instance.GlobalBuffer != this) { throw new ArgumentException( message:"instance does not belong to current Particle Buffer", paramName: nameof(instance)); } int index = instance.BufferId; IInstancing temp = instanceList[instanceList.Count - 1]; instanceList[instance.BufferId] = temp; temp.BufferId = instance.BufferId; coordList[instance.BufferId] = coordList[coordList.Count - 1]; scalingList[instance.BufferId] = scalingList[scalingList.Count - 1]; instanceList.RemoveAt(instanceList.Count - 1); coordList.RemoveAt(coordList.Count - 1); scalingList.RemoveAt(scalingList.Count - 1); mutex.ReleaseMutex(); } public void UpdateAllParticles() { foreach (var particle in instanceList) { particle.Move(); } } protected virtual void Dispose(bool disposing) { if (!disposedValue) { if (disposing) { mutex.Dispose(); } coordList.Clear(); instanceList.Clear(); scalingList.Clear(); disposedValue = true; } } // ~PlainInstancingBuffer() // { // Dispose(disposing: false); // } public void Dispose() { Dispose(disposing: true); GC.SuppressFinalize(this); } public IEnumerator GetEnumerator() { foreach (var item in instanceList) { yield return (T)item; } } IEnumerator IEnumerable.GetEnumerator() { foreach (var item in instanceList) { yield return (T)item; } } } }