/// <summary> /// Applies buoyancy forces to appropriate objects. /// Called automatically when needed by the owning Space. /// </summary> /// <param name="dt">Time since last frame in physical logic.</param> void IDuringForcesUpdateable.Update(float dt) { QueryAccelerator.GetEntries(boundingBox, broadPhaseEntries); //TODO: Could integrate the entire thing into the collision detection pipeline. Applying forces //in the collision detection pipeline isn't allowed, so there'd still need to be an Updateable involved. //However, the broadphase query would be eliminated and the raycasting work would be automatically multithreaded. this.dt = dt; //Don't always multithread. For small numbers of objects, the overhead of using multithreading isn't worth it. //Could tune this value depending on platform for better performance. if (broadPhaseEntries.Count > 30 && ParallelLooper != null && ParallelLooper.ThreadCount > 1) { ParallelLooper.ForLoop(0, broadPhaseEntries.Count, analyzeCollisionEntryDelegate); } else { for (int i = 0; i < broadPhaseEntries.Count; i++) { AnalyzeEntry(i); } } broadPhaseEntries.Clear(); }
protected override void UpdateMultithreaded() { #if PROFILE startPairs = Stopwatch.GetTimestamp(); #endif ParallelLooper.ForLoop(0, broadPhaseOverlaps.Count, updateBroadPhaseOverlapDelegate); #if PROFILE endPairs = Stopwatch.GetTimestamp(); #endif //Remove stale objects BEFORE adding new objects. This ensures that simulation islands which will be activated //by new narrow phase pairs will not be momentarily considered stale. //(The RemoveStale only considers islands that are active to be potentially stale.) //If that happened, all the pairs would be remove and immediately recreated. Very wasteful! RemoveStaleOverlaps(); #if PROFILE endStale = Stopwatch.GetTimestamp(); #endif //This sets NeedsUpdate to true for all new objects, ensuring that they are considered for staleness next time. AddNewNarrowPhaseObjects(); #if PROFILE endFlushNew = Stopwatch.GetTimestamp(); #endif }
protected override void UpdateMultithreaded() { FlushSplits(); ParallelLooper.ForLoop(0, simulationIslandMembers.Count, multithreadedCandidacyLoopDelegate); DeactivateObjects(); }
protected override void UpdateMultithreaded() { ParallelLooper.ForLoop(0, solverUpdateables.Count, multithreadedPrestepDelegate); //By performing all velocity modifications after the prestep, the prestep is free to read velocities consistently. //If the exclusive update was performed in the same call as the prestep, the velocities would enter inconsistent states based on update order. ParallelLooper.ForLoop(0, solverUpdateables.Count, multithreadedExclusiveUpdateDelegate); ++PermutationMapper.PermutationIndex; ParallelLooper.ForLoop(0, iterationLimit * solverUpdateables.Count, multithreadedIterationDelegate); }
protected override void UpdateMultithreaded() { //Go through the list of all updateables which do not permit motion clamping. //Since these do not care about CCD, just update them as if they were discrete. //In addition, go through the remaining non-discrete objects and perform their prestep. //This usually involves updating their angular motion, but not their linear motion. int count = discreteUpdateables.Count + passiveUpdateables.Count + continuousUpdateables.Count; ParallelLooper.ForLoop(0, count, preUpdate); //Now go through the list of all full CCD objects. These are responsible //for determining the TOI of collision pairs, if existent. if (continuousUpdateables.Count > MultithreadingThreshold) { ParallelLooper.ForLoop(0, continuousUpdateables.Count, updateTimeOfImpact); } else { for (int i = 0; i < continuousUpdateables.Count; i++) { UpdateTimeOfImpact(i); } } //The TOI's are now computed, so we can integrate all of the CCD or allow-motionclampers //to their new positions. count = passiveUpdateables.Count + continuousUpdateables.Count; if (count > MultithreadingThreshold) { ParallelLooper.ForLoop(0, count, updateContinuous); } else { for (int i = 0; i < count; i++) { UpdateContinuousItem(i); } } //The above process is the same as the UpdateSingleThreaded version, but //it doesn't always use multithreading. Sometimes, a simulation can have //very few continuous objects. In this case, there's no point in having the //multithreaded overhead. }
/// <summary> /// Applies forces specified by the given calculation delegate to bodies in the volume. /// Called automatically when needed by the owning Space. /// </summary> /// <param name="dt">Time since the last frame in simulation seconds.</param> void IDuringForcesUpdateable.Update(float dt) { PreUpdate(); affectedEntities = Shape.GetPossiblyAffectedEntities(); if (AllowMultithreading && ParallelLooper != null && ParallelLooper.ThreadCount > 1) { currentTimestep = dt; ParallelLooper.ForLoop(0, affectedEntities.Count, subfunction); } else { currentTimestep = dt; //No multithreading, so do it directly. int count = affectedEntities.Count; for (int i = 0; i < count; i++) { CalculateImpulsesSubfunction(i); } } }
protected override void UpdateMultithreaded() { Vector3.Multiply(ref gravity, timeStepSettings.TimeStepDuration, out gravityDt); ParallelLooper.ForLoop(0, dynamicObjects.Count, multithreadedLoopBodyDelegate); }
protected override void UpdateMultithreaded() { ParallelLooper.ForLoop(0, manager.entities.Count, multithreadedWithReadBuffersDelegate); FlipBuffers(); }
protected override void UpdateMultithreaded() { ParallelLooper.ForLoop(0, entries.Count, multithreadedLoopBodyDelegate); }