Ejemplo n.º 1
0
        protected JobHandle GenerateContacts(JobHandle inputDeps, float deltaTime)
        {
            // Dispose of previous fluid interactions.
            // We need fluid data during interpolation, for anisotropic fluid particles. For this reason,
            // we can't dispose of these arrays in ResetForces() at the end of each full step. They must use persistent allocation.

            if (fluidInteractions.IsCreated)
            {
                fluidInteractions.Dispose();
            }
            if (fluidBatchData.IsCreated)
            {
                fluidBatchData.Dispose();
            }

            // get constraint parameters for constraint types that depend on broadphases:
            var collisionParameters         = m_Solver.GetConstraintParameters(Oni.ConstraintType.Collision);
            var particleCollisionParameters = m_Solver.GetConstraintParameters(Oni.ConstraintType.ParticleCollision);
            var densityParameters           = m_Solver.GetConstraintParameters(Oni.ConstraintType.Density);

            // if no enabled constraints that require broadphase info, skip it entirely.
            if (collisionParameters.enabled ||
                particleCollisionParameters.enabled ||
                densityParameters.enabled)
            {
                // update the bounding box of each simplex:
                inputDeps = UpdateSimplexBounds(inputDeps, deltaTime);


                // generate particle-particle and particle-collider interactions in parallel:
                JobHandle generateParticleInteractionsHandle = inputDeps, generateContactsHandle = inputDeps;

                // particle-particle interactions (contacts, fluids)
                if (particleCollisionParameters.enabled || densityParameters.enabled)
                {
                    particleGrid.Update(this, deltaTime, inputDeps);
                    generateParticleInteractionsHandle = particleGrid.GenerateContacts(this, deltaTime);
                }

                // particle-collider interactions (contacts)
                if (collisionParameters.enabled)
                {
                    generateContactsHandle = colliderGrid.GenerateContacts(this, deltaTime);
                }

                JobHandle.CombineDependencies(generateParticleInteractionsHandle, generateContactsHandle).Complete();

                // allocate arrays for interactions and batch data:
                particleContacts  = new NativeArray <BurstContact>(particleGrid.particleContactQueue.Count, Allocator.TempJob, NativeArrayOptions.UninitializedMemory);
                particleBatchData = new NativeArray <BatchData>(maxBatches, Allocator.TempJob, NativeArrayOptions.UninitializedMemory);

                fluidInteractions = new NativeArray <FluidInteraction>(particleGrid.fluidInteractionQueue.Count, Allocator.Persistent, NativeArrayOptions.UninitializedMemory);
                fluidBatchData    = new NativeArray <BatchData>(maxBatches, Allocator.Persistent, NativeArrayOptions.UninitializedMemory);

                colliderContacts = new NativeArray <BurstContact>(colliderGrid.colliderContactQueue.Count, Allocator.TempJob, NativeArrayOptions.UninitializedMemory);

                // dequeue contacts/interactions into temporary arrays:
                var rawParticleContacts         = new NativeArray <BurstContact>(particleGrid.particleContactQueue.Count, Allocator.TempJob, NativeArrayOptions.UninitializedMemory);
                var sortedParticleContacts      = new NativeArray <BurstContact>(particleGrid.particleContactQueue.Count, Allocator.TempJob, NativeArrayOptions.UninitializedMemory);
                var rawFluidInteractions        = new NativeArray <FluidInteraction>(particleGrid.fluidInteractionQueue.Count, Allocator.TempJob, NativeArrayOptions.UninitializedMemory);

                DequeueIntoArrayJob <BurstContact> dequeueParticleContacts      = new DequeueIntoArrayJob <BurstContact>()
                {
                    InputQueue  = particleGrid.particleContactQueue,
                    OutputArray = rawParticleContacts
                };

                DequeueIntoArrayJob <FluidInteraction> dequeueFluidInteractions = new DequeueIntoArrayJob <FluidInteraction>()
                {
                    InputQueue  = particleGrid.fluidInteractionQueue,
                    OutputArray = rawFluidInteractions
                };

                DequeueIntoArrayJob <BurstContact> dequeueColliderContacts      = new DequeueIntoArrayJob <BurstContact>()
                {
                    InputQueue  = colliderGrid.colliderContactQueue,
                    OutputArray = colliderContacts
                };

                var dequeueHandle               = JobHandle.CombineDependencies(dequeueParticleContacts.Schedule(), dequeueFluidInteractions.Schedule(), dequeueColliderContacts.Schedule());

                // Sort contacts for jitter-free gauss-seidel (sequential) solving:
                dequeueHandle = ConstraintSorter.SortConstraints <BurstContact>(simplexCounts.simplexCount, rawParticleContacts, ref sortedParticleContacts, dequeueHandle);

                ContactProvider contactProvider = new ContactProvider()
                {
                    contacts       = sortedParticleContacts,
                    sortedContacts = particleContacts,
                    simplices      = simplices,
                    simplexCounts  = simplexCounts
                };

                FluidInteractionProvider fluidProvider = new FluidInteractionProvider()
                {
                    interactions       = rawFluidInteractions,
                    sortedInteractions = fluidInteractions,
                };

                // batch particle contacts:
                var activeParticleBatchCount = new NativeArray <int>(1, Allocator.TempJob);
                var particleBatchHandle      = constraintBatcher.BatchConstraints(ref contactProvider, particleCount, ref particleBatchData, ref activeParticleBatchCount, dequeueHandle);

                // batch fluid interactions:
                var activeFluidBatchCount = new NativeArray <int>(1, Allocator.TempJob);
                var fluidBatchHandle      = constraintBatcher.BatchConstraints(ref fluidProvider, particleCount, ref fluidBatchData, ref activeFluidBatchCount, dequeueHandle);

                JobHandle.CombineDependencies(particleBatchHandle, fluidBatchHandle).Complete();

                // Generate particle contact/friction batches:
                var pc = constraints[(int)Oni.ConstraintType.ParticleCollision] as BurstParticleCollisionConstraints;
                pc.batches.Clear();
                var pf = constraints[(int)Oni.ConstraintType.ParticleFriction] as BurstParticleFrictionConstraints;
                pf.batches.Clear();
                for (int i = 0; i < activeParticleBatchCount[0]; ++i)
                {
                    var cbatch = pc.CreateConstraintsBatch() as BurstParticleCollisionConstraintsBatch;
                    cbatch.batchData = particleBatchData[i];

                    var fbatch = pf.CreateConstraintsBatch() as BurstParticleFrictionConstraintsBatch;
                    fbatch.batchData = particleBatchData[i];
                }

                // Generate fluid interaction batches:
                var dc = constraints[(int)Oni.ConstraintType.Density] as BurstDensityConstraints;
                dc.batches.Clear();
                for (int i = 0; i < activeFluidBatchCount[0]; ++i)
                {
                    var batch = dc.CreateConstraintsBatch() as BurstDensityConstraintsBatch;
                    batch.batchData = fluidBatchData[i];
                }

                // dispose of temporary buffers:
                rawParticleContacts.Dispose();
                rawFluidInteractions.Dispose();
                sortedParticleContacts.Dispose();
                activeParticleBatchCount.Dispose();
                activeFluidBatchCount.Dispose();
            }

            return(inputDeps);
        }