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); }