public void Execute(int i) { int simplexStart = simplexCounts.GetSimplexStartAndSize(i, out int simplexSize); var bounds = new BurstAabb(float.MaxValue, float.MinValue); for (int j = 0; j < simplexSize; ++j) { int p = simplices[simplexStart + j]; // Find this particle's stick distance: int m = particleMaterialIndices[p]; float stickDistance = m >= 0 ? collisionMaterials[m].stickDistance : 0; // Expand simplex bounds, using both the particle's original position and its velocity: bounds.EncapsulateParticle(positions[p], positions[p] + velocities[p] * continuousCollisionDetection * dt, math.max(radii[p].x + stickDistance, fluidRadii[p] * 0.5f) + collisionMargin); } simplexBounds[i] = bounds; }
public void Execute(int i) { var cell = particleGrid.usedCells[i]; BurstAabb cellBounds = new BurstAabb(float.MaxValue, float.MinValue); // here we calculate cell bounds that enclose both the predicted position and the original position of all its particles, // for accurate continuous collision detection. for (int p = 0; p < cell.Length; ++p) { int pIndex = cell[p]; // get collision material stick distance: float stickDistance = 0; int materialIndex = particleMaterialIndices[pIndex]; if (materialIndex >= 0) { stickDistance = collisionMaterials[materialIndex].stickDistance; } cellBounds.EncapsulateParticle(positions[pIndex], positions[pIndex] + velocities[pIndex] * deltaTime, radii[pIndex].x + stickDistance); } // transform the cell bounds to world space: cellBounds.Transform(solverToWorld); // get all colliders overlapped by the cell bounds, in all grid levels: NativeList <int> candidates = new NativeList <int>(Allocator.Temp); for (int l = 0; l < gridLevels.Length; ++l) { GetCandidatesForBoundsAtLevel(candidates, cellBounds, gridLevels[l], is2D); } if (candidates.Length > 0) { // make sure each candidate collider only shows up once in the array: NativeArray <int> uniqueCandidates = candidates.AsArray(); uniqueCandidates.Sort(); int uniqueCount = uniqueCandidates.Unique(); // iterate over candidate colliders, generating contacts for each one for (int c = 0; c < uniqueCount; ++c) { int colliderIndex = uniqueCandidates[c]; BurstColliderShape shape = shapes[colliderIndex]; BurstAabb colliderBounds = bounds[colliderIndex]; BurstAffineTransform colliderToSolver = worldToSolver * transforms[colliderIndex]; // transform collider bounds to solver space: colliderBounds.Transform(worldToSolver); // iterate over all particles in the cell: for (int p = 0; p < cell.Length; ++p) { int particleIndex = cell[p]; // skip this pair if particle and collider have the same phase: if (shape.phase == (phases[particleIndex] & (int)Oni.ParticleFlags.GroupMask)) { continue; } // get collision material stick distance: float stickDistance = 0; int materialIndex = particleMaterialIndices[particleIndex]; if (materialIndex >= 0) { stickDistance = collisionMaterials[materialIndex].stickDistance; } // inflate collider bounds by particle's bounds: BurstAabb inflatedColliderBounds = colliderBounds; inflatedColliderBounds.Expand(radii[particleIndex].x * 1.2f + stickDistance); float4 invDir = math.rcp(velocities[particleIndex] * deltaTime); // We check particle trajectory ray vs inflated collider aabb // instead of checking particle vs collider aabbs directly, as this reduces // the amount of contacts generated for fast moving particles. if (inflatedColliderBounds.IntersectsRay(positions[particleIndex], invDir, shape.is2D != 0)) { // generate contacts for the collider: GenerateContacts(shape.type, particleIndex, colliderIndex, positions[particleIndex], orientations[particleIndex], velocities[particleIndex], radii[particleIndex], colliderToSolver, shape, contactsQueue, deltaTime); } } } } }