private Bounds GetBoundsFromParticlePositions(int instanceID, SGenericParticleArray particles)
        {
            long key = vBugMathHelper.CombineInts(currentFrameNumber, instanceID);
            if (boundsPerFrame.ContainsKey(key)) {
                return boundsPerFrame[key];
            } else {

                Vector3 min = new Vector3(float.MaxValue, float.MaxValue, float.MaxValue);
                Vector3 max = new Vector3(float.MinValue, float.MinValue, float.MinValue);

                for (int i = 0; i < particles.positions.Length; i += 3) {

                    float halfSize = particles.sizes[i / 3]/ 2f;
                    Vector3 pos = new Vector3(particles.positions[i], particles.positions[i + 1], particles.positions[i + 2]);
                    min.x = Math.Min(min.x, pos.x - halfSize);
                    min.y = Math.Min(min.y, pos.y - halfSize);
                    min.z = Math.Min(min.z, pos.z - halfSize);

                    max.x = Mathf.Max(max.x, pos.x + halfSize);
                    max.y = Mathf.Max(max.y, pos.y + halfSize);
                    max.z = Mathf.Max(max.z, pos.z + halfSize);
                }

                Bounds bounds = new Bounds((min + max) / 2f, max - min);
                boundsPerFrame.Add(key, bounds);
                return bounds;
            }
        }
        public SGenericParticleSystem(ParticleSystem system, ParticleSystemRenderer renderer, ParticleSystem.Particle[] particles, int particleCount)
        {
            if (system == null || renderer == null)
                return;

            instanceID = system.GetInstanceID();
            goInstanceID = system.gameObject.GetInstanceID();
            isLegacy = false;
            isWorldSpace = system.simulationSpace == ParticleSystemSimulationSpace.World;
            emit = system.enableEmission;
            enabled = renderer.enabled;
            position = system.transform.position;
            name = system.gameObject.name;
            SetParticleRenderer(renderer);

            this.particles = new SGenericParticleArray(particles, particleCount);
        }
        public override void Dispose()
        {
            base.Dispose();

            if (particles != null)
                particles.Dispose();

            renderer = null;
            particles = null;
        }
        public SGenericParticleSystem(ParticleEmitter emitter, ParticleRenderer renderer, Particle[] particles)
        {
            if (emitter == null || renderer == null)
                return;

            instanceID = emitter.GetInstanceID();
            goInstanceID = emitter.gameObject.GetInstanceID();
            isLegacy = true;
            isWorldSpace = emitter.useWorldSpace;
            emit = emitter.emit;
            enabled = emitter.enabled;
            position = emitter.transform.position;
            name = emitter.gameObject.name;
            SetParticleRenderer(renderer);

            this.particles = new SGenericParticleArray(particles);
        }
        //--------------- Serialize / Deserialize --------------------
        public static byte[] Serialize(SGenericParticleArray input)
        {
            if (input == null)
                return null;

            ComposedByteStream stream = ComposedByteStream.FetchStream(8);
            stream.AddStream(input.colors);
            stream.AddStream(input.positions);
            //stream.AddStream(input.rotations);
            stream.AddStream(input.sizes);
            stream.AddStream(input.velocities);
            return stream.Compose();
        }
        public static SGenericParticleArray Deserialize(byte[] input)
        {
            if (input == null || input.Length == 0)
                return null;

            ComposedByteStream stream = ComposedByteStream.FromByteArray(input);
            SGenericParticleArray result = new SGenericParticleArray();

            result.colors = stream.ReadNextStream<byte>();
            result.positions = stream.ReadNextStream<float>();
            //result.rotations = stream.ReadNextStream<float>();
            result.sizes = stream.ReadNextStream<float>();
            result.velocities = stream.ReadNextStream<float>();

            stream.Dispose();
            return result;
        }
        public void SetParticles(int frameNumber, SParticleRenderer particleRenderer, SGenericParticleArray particleData)
        {
            this.particleRenderer = particleRenderer;
            this.particleData = particleData;

            if (frameNumber != currentFrameNumber){
                SetMaterial(particleRenderer, frameNumber);
                Render();
                currentFrameNumber = frameNumber;
            }
        }
        private void OnDestroy()
        {
            if (this.mesh != null)
                UnityEngine.Object.DestroyImmediate(this.mesh);

            if (mat != null)
                UnityEngine.Object.DestroyImmediate(mat);

            mat = null;
            mesh = null;
            meshFilter = null;
            meshRenderer = null;
            particleData = null;
        }