/// <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 Demo(DemosGame game) { Game = game; parallelLooper = new ParallelLooper(); //This section lets the engine know that it can make use of multithreaded systems //by adding threads to its thread pool. #if XBOX360 parallelLooper.AddThread(delegate { Thread.CurrentThread.SetProcessorAffinity(new[] { 1 }); }); parallelLooper.AddThread(delegate { Thread.CurrentThread.SetProcessorAffinity(new[] { 3 }); }); parallelLooper.AddThread(delegate { Thread.CurrentThread.SetProcessorAffinity(new[] { 4 }); }); parallelLooper.AddThread(delegate { Thread.CurrentThread.SetProcessorAffinity(new[] { 5 }); }); #else if (Environment.ProcessorCount > 1) { for (int i = 0; i < Environment.ProcessorCount; i++) { parallelLooper.AddThread(); } } #endif Space = new Space(parallelLooper); game.Camera.LockedUp = Vector3.Up; game.Camera.ViewDirection = new Vector3(0, 0, -1); }
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); }
internal ParallelLoopWorker(ParallelLooper manager, Action threadStart) { this.manager = manager; this.threadStart = threadStart; getToWork = new AutoResetEvent(false); thread = new Thread(Work) { IsBackground = true }; thread.Start(); }
//Default Constructor public ServerPhysics() { //Run extra threads if they are available ParallelLooper = new ParallelLooper(); if (Environment.ProcessorCount > 1) { for (int i = 0; i < Environment.ProcessorCount; i++) { ParallelLooper.AddThread(); } } Globals.space = new Space(ParallelLooper); //Set the gravity force in the physics simulation Globals.space.ForceUpdater.Gravity = new Vector3(0, -9.81f, 0); //Load in the terrain mesh collsion data to use as the base of the game simulation }
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); }
//public ServerEntity WaypointTest; public WorldSimulator(WorldRenderer game) { Game = game; parallelLooper = new ParallelLooper(); if (Environment.ProcessorCount > 1) { for (int i = 0; i < Environment.ProcessorCount; i++) { parallelLooper.AddThread(); } } Globals.space = new Space(parallelLooper); game.Camera.LockedUp = Vector3.Up; game.Camera.ViewDirection = new Vector3(0, -1.5f, 1); game.Camera.Position = new Vector3(-19.55f, 39.25f, -10.35f); ServerCamera = new FreeCamera(100, game.Camera, game); //Add some force of gravity to the simulation Globals.space.ForceUpdater.Gravity = new Vector3(0, -9.81f, 0); //Load the world terrain mesh data Vector3[] TerrainVertices; int[] TerrainIndices; Model TerrainCollision = Globals.game.Content.Load <Model>("LowDetailTerrain"); ModelDataExtractor.GetVerticesAndIndicesFromModel(TerrainCollision, out TerrainVertices, out TerrainIndices); StaticMesh TerrainMesh = new StaticMesh(TerrainVertices, TerrainIndices, new AffineTransform(new Vector3(0, 0, 0))); Globals.TerrainVerts = TerrainVertices; Globals.TerrainInds = TerrainIndices; Globals.space.Add(TerrainMesh); Globals.game.ModelDrawer.Add(TerrainMesh); //Create a new mesh node object for each unique location in the navigation mesh for (int i = 0; i < Globals.TerrainVerts.Length; i++) { //Dont create mesh nodes at locations already been used if (!NavMeshNodes.IsLocationAvailable(Globals.TerrainVerts[i])) { continue; } //Add a new mesh node object to every other space in the terrain verts that we find to be available NavMeshNodes.AddNode(new NavMeshNode(Globals.TerrainVerts[i])); } //Now sort all of the mesh nodes into a dictionary sorted by their index in the level //Start with the first column of mesh nodes for (int i = 1; i < 10; i++) { Vector2 MeshIndex = new Vector2(i, 1); int MeshNodeIndex = (i - 1) * 2; NavMeshNode MeshNode = NavMeshNodes.MeshNodes[MeshNodeIndex]; NavMeshDictionary.AddNode(MeshNode, MeshIndex); } //Then the second column of mesh nodes int CurrentNodeIndex = 1; for (int i = 1; i < 10; i++) { Vector2 MeshIndex = new Vector2(i, 2); int NodeIndex = CurrentNodeIndex; CurrentNodeIndex += 2; NavMeshNode MeshNode = NavMeshNodes.MeshNodes[NodeIndex]; MeshNode.NodeIndex = MeshIndex; NavMeshDictionary.AddNode(MeshNode, MeshIndex); } //Add the other remaining columns int ListIndex = 18; for (int Column = 3; Column < 10; Column++) { for (int j = 1; j < 10; j++) { Vector2 MeshIndex = new Vector2(j, Column); NavMeshNode MeshNode = NavMeshNodes.MeshNodes[ListIndex]; MeshNode.NodeIndex = MeshIndex; ListIndex++; NavMeshDictionary.AddNode(MeshNode, MeshIndex); } } //Add two game entities into the scene, the first entity will pathfind its way to the 2nd entity PrincessFox = new GameEntity(new Vector3(-17.74f, 2.15f, 10.54f)); PrincessTarget = new GameEntity(new Vector3(-41.17f, 0.89f, 24.15f)); //Figure out which node each of these entities is closest two, these will be the ends of the pathway NavMeshNode StartNode = NavMeshDictionary.MeshDictionary[new Vector2(3, 4)]; NavMeshNode EndNode = NavMeshDictionary.MeshDictionary[new Vector2(7, 8)]; //Find our pathway between the two entities List <NavMeshNode> NodePath = AStarSearch.FindPath(StartNode, EndNode, new Vector2(9, 9)); //Now assign this path to the princess fox entity and have her navigate along to reach her target }