public void UpdateBoundary(FluidBoundary newBoundary)
        {
            Boundary = newBoundary;
            float cellSize = Body.ParticleRadius * 4.0f;
            int   total    = Body.NumParticles + Boundary.NumParticles;

            Hash.Dispose();
            Hash = new GridHash(Boundary.Bounds, total, cellSize);
        }
        //private void CreateArgBuffer(uint indexCount)
        //{
        //    uint[] args = new uint[5] { 0, 0, 0, 0, 0 };
        //    args[0] = indexCount;
        //    args[1] = (uint)NumParticles;

        //    m_argsBuffer = new ComputeBuffer(1, args.Length * sizeof(uint), ComputeBufferType.IndirectArguments);
        //    m_argsBuffer.SetData(args);
        //}

        private void CreateBoundryPsi()
        {
            float           cellSize = ParticleRadius * 4.0f;
            SmoothingKernel K        = new SmoothingKernel(cellSize);

            GridHash grid = new GridHash(Bounds, NumParticles, cellSize);

            grid.Process(PositionsBuffer);

            ComputeShader createBoundaryShader = Resources.Load("FluidBoundary") as ComputeShader;

            int psiKernelID = createBoundaryShader.FindKernel("ComputePsi");

            createBoundaryShader.SetFloat("Density", DensityCoeff);
            createBoundaryShader.SetFloat("KernelRadiuse", K.Radius);
            createBoundaryShader.SetFloat("KernelRadius2", K.Radius2);
            createBoundaryShader.SetFloat("Poly6", K.POLY6);
            createBoundaryShader.SetFloat("Poly6Zero", K.Poly6(Vector3.zero));
            createBoundaryShader.SetInt("NumParticles", NumParticles);

            createBoundaryShader.SetFloat("HashScale", grid.InvCellSize);
            createBoundaryShader.SetVector("HashSize", grid.Bounds.size);
            createBoundaryShader.SetVector("HashTranslate", grid.Bounds.min);
            createBoundaryShader.SetBuffer(psiKernelID, "IndexMap", grid.IndexMap);
            createBoundaryShader.SetBuffer(psiKernelID, "Table", grid.Table);

            createBoundaryShader.SetBuffer(psiKernelID, "Boundary", PositionsBuffer);

            int groups = NumParticles / THREADS;

            if (NumParticles % THREADS != 0)
            {
                groups++;
            }

            //Fills the boundarys psi array so the fluid can
            //collide against it smoothly. The original computes
            //the phi for each boundary particle based on the
            //density of the boundary but I find the fluid
            //leaks out so Im just using a const value.

            createBoundaryShader.Dispatch(psiKernelID, groups, 1, 1);

            grid.Dispose();
        }
        public FluidSolver(FluidBody body, FluidBoundary boundary, int densityComputeIteration, int constraintComputeIteration)
        {
            DensityComputeIterations    = densityComputeIteration;
            ConstraintComputeIterations = constraintComputeIteration;

            Body     = body;
            Boundary = boundary;

            float cellSize = Body.ParticleRadius * 4.0f;
            int   total    = Body.NumParticles + Boundary.NumParticles;

            Hash   = new GridHash(Boundary.Bounds, total, cellSize);
            Kernel = new SmoothingKernel(cellSize);

            int numParticles = Body.NumParticles;

            Groups = numParticles / THREADS;
            if (numParticles % THREADS != 0)
            {
                Groups++;
            }

            fluidSolverShader = Resources.Load("FluidSolver") as ComputeShader;
        }