/// <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(); }
public void BuildWorld() { MainThread = Thread.CurrentThread; MainThreadID = MainThread.ManagedThreadId; ParallelLooper pl = new ParallelLooper(); for (int i = 0; i < Environment.ProcessorCount; i++) { pl.AddThread(); } CollisionDetectionSettings.AllowedPenetration = 0.01f; PhysicsWorld = new Space(pl); PhysicsWorld.TimeStepSettings.MaximumTimeStepsPerFrame = 10; PhysicsWorld.ForceUpdater.Gravity = new Vector3(0, 0, -9.8f * 3f / 2f); PhysicsWorld.DuringForcesUpdateables.Add(new LiquidVolume(this)); PhysicsWorld.TimeStepSettings.TimeStepDuration = 1f / TheServer.CVars.g_fps.ValueF; Collision = new CollisionUtil(PhysicsWorld); EntityConstructors.Add(EntityType.ITEM, new ItemEntityConstructor()); EntityConstructors.Add(EntityType.BLOCK_ITEM, new BlockItemEntityConstructor()); EntityConstructors.Add(EntityType.GLOWSTICK, new GlowstickEntityConstructor()); EntityConstructors.Add(EntityType.MODEL, new ModelEntityConstructor()); EntityConstructors.Add(EntityType.SMOKE_GRENADE, new SmokeGrenadeEntityConstructor()); EntityConstructors.Add(EntityType.MUSIC_BLOCK, new MusicBlockEntityConstructor()); ChunkManager = new ChunkDataManager(); ChunkManager.Init(this); //LoadRegion(new Location(-MaxViewRadiusInChunks * 30), new Location(MaxViewRadiusInChunks * 30), true); //TheServer.Schedule.RunAllSyncTasks(0.016); // TODO: Separate per-region scheduler // Also don't freeze the entire server/region just because we're waiting on chunks >.> //SysConsole.Output(OutputType.INIT, "Finished building chunks! Now have " + LoadedChunks.Count + " chunks!"); }
public Physics() { _Main = this; var 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 (Environment.ProcessorCount > 1) { for (int i = 0; i < Environment.ProcessorCount; i++) { parallelLooper.AddThread(); } } space = new Space(parallelLooper); space.ForceUpdater.Gravity = new BEPUutilities.Vector3(0, -9.81f, 0); /*_BufferPool = new BufferPool(); * * var targetThreadCount = Math.Max(1, Environment.ProcessorCount > 4 ? Environment.ProcessorCount - 2 : Environment.ProcessorCount - 1); * _ThreadDispatcher = new SimpleThreadDispatcher(targetThreadCount); * * _Simulation = Simulation.Create(_BufferPool, new NarrowPhaseCallbacks(), new PoseIntegratorCallbacks(new System.Numerics.Vector3(GravityX, GravityY, GravityZ)), new PositionLastTimestepper());*/ }
internal PhysicsManager() { instance = this; 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 BEPUphysics.Space(parallelLooper); Space.ForceUpdater.Gravity = new Vector3(0, -9.81f, 0f); Space.TimeStepSettings.MaximumTimeStepsPerFrame = 100; //Set up two stacks which go through each other firstStackGroup = new CollisionGroup(); secondStackGroup = new CollisionGroup(); //Adding this rule to the space's collision group rules will prevent entities belong to these two groups from generating collision pairs with each other. var groupPair = new CollisionGroupPair(firstStackGroup, secondStackGroup); //CollisionRules.CollisionGroupRules.Add(groupPair, CollisionRule.NoBroadPhase); }
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 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); }
public ShapesExtractor(ParallelLooper looper, int initialCapacityPerShapeType = 1024) { var initialSpheresSpan = new Array <SphereInstance>(new SphereInstance[initialCapacityPerShapeType]); spheres = new QuickList <SphereInstance, Array <SphereInstance> >(ref initialSpheresSpan); this.looper = looper; }
/// <summary> /// Sets up data for the region to work with, including the physics environment and the chunk data management. /// </summary> public void BuildRegion() { // TODO: generator registry if (TheWorld.Generator == "sphere") { Generator = new SphereGeneratorCore(); } else { Generator = new SimpleGeneratorCore(); } ParallelLooper pl = new ParallelLooper(); for (int i = 0; i < Environment.ProcessorCount; i++) { pl.AddThread(); } CollisionDetectionSettings.AllowedPenetration = 0.01f; // TODO: This is a global setting - handle it elsewhere, or make it non-global? PhysicsWorld = new Space(pl); PhysicsWorld.TimeStepSettings.MaximumTimeStepsPerFrame = 10; PhysicsWorld.ForceUpdater.Gravity = (GravityNormal * GravityStrength).ToBVector(); PhysicsWorld.DuringForcesUpdateables.Add(new LiquidVolume(this)); PhysicsWorld.TimeStepSettings.TimeStepDuration = 1f / TheServer.CVars.g_fps.ValueF; Collision = new CollisionUtil(PhysicsWorld); // TODO: Perhaps these should be on the server level, not region? EntityConstructors.Add(EntityType.ITEM, new ItemEntityConstructor()); EntityConstructors.Add(EntityType.BLOCK_ITEM, new BlockItemEntityConstructor()); EntityConstructors.Add(EntityType.GLOWSTICK, new GlowstickEntityConstructor()); EntityConstructors.Add(EntityType.MODEL, new ModelEntityConstructor()); EntityConstructors.Add(EntityType.SMOKE_GRENADE, new SmokeGrenadeEntityConstructor()); EntityConstructors.Add(EntityType.MUSIC_BLOCK, new MusicBlockEntityConstructor()); EntityConstructors.Add(EntityType.HOVER_MESSAGE, new HoverMessageEntityConstructor()); ChunkManager = new ChunkDataManager(); ChunkManager.Init(this); }
public LineExtractor(BufferPool pool, ParallelLooper looper, int initialLineCapacity = 8192) { lines = new QuickList <LineInstance>(initialLineCapacity, pool); constraints = new ConstraintLineExtractor(pool); boundingBoxes = new BoundingBoxLineExtractor(pool); this.pool = pool; this.looper = looper; }
public LineExtractor(ParallelLooper looper, int initialLineCapacity = 8192) { QuickList <LineInstance, Array <LineInstance> > .Create(new PassthroughArrayPool <LineInstance>(), initialLineCapacity, out lines); constraints = new ConstraintLineExtractor(); boundingBoxes = new BoundingBoxLineExtractor(); this.looper = looper; }
protected override void UpdateMultithreaded() { FlushSplits(); ParallelLooper.ForLoop(0, simulationIslandMembers.Count, multithreadedCandidacyLoopDelegate); DeactivateObjects(); }
protected override void UpdateMultithreaded() { if (backbuffer.Count != entries.Count) { backbuffer.Capacity = entries.Capacity; backbuffer.Count = entries.Count; } Overlaps.Clear(); //Sort along x axis using insertion sort; the list will be nearly sorted, so very few swaps are necessary. for (int i = 1; i < entries.Count; i++) { BroadPhaseEntry entry = entries.Elements[i]; for (int j = i - 1; j >= 0; j--) { if (entry.boundingBox.Min.X < entries.Elements[j].boundingBox.Min.X) { entries.Elements[j + 1] = entries.Elements[j]; entries.Elements[j] = entry; } else { break; } } } //TODO: Multithreaded sorting could help in some large cases. //The overhead involved in this implementation is way too high for reasonable object counts. //for (int i = 0; i < sortSegmentCount; i++) // SortSection(i); ////MergeSections(0, 1); ////MergeSections(2, 3); ////MergeSections(0, 2); ////MergeSections(1, 3); //MergeSections(0, 1); //MergeSections(2, 3); //MergeSections(4, 5); //MergeSections(6, 7); //MergeSections(0, 2); //MergeSections(1, 3); //MergeSections(4, 6); //MergeSections(5, 7); //MergeSections(0, 4); //MergeSections(1, 5); //MergeSections(2, 6); //MergeSections(3, 7); //var temp = backbuffer; //backbuffer = entries; //entries = temp; ParallelLooper.ForLoop(0, sweepSegmentCount, sweepSegment); }
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); }
public ShapesExtractor(ParallelLooper looper, int initialCapacityPerShapeType = 1024) { QuickList <SphereInstance, Array <SphereInstance> > .Create(new PassthroughArrayPool <SphereInstance>(), initialCapacityPerShapeType, out spheres); QuickList <CapsuleInstance, Array <CapsuleInstance> > .Create(new PassthroughArrayPool <CapsuleInstance>(), initialCapacityPerShapeType, out capsules); QuickList <BoxInstance, Array <BoxInstance> > .Create(new PassthroughArrayPool <BoxInstance>(), initialCapacityPerShapeType, out boxes); this.looper = looper; }
/// <summary> /// LoadContent will be called once per game and is the place to load /// all of your content. /// </summary> protected override void LoadContent() { //Set up drawers ModelDrawer = new InstancedModelDrawer(this); //Create the space itself Space = new Space(); var 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 (Environment.ProcessorCount > 1) { for (int i = 0; i < Environment.ProcessorCount; i++) { parallelLooper.AddThread(); } } Space = new Space(parallelLooper); Space.ForceUpdater.Gravity = new Vector3(0, -9.81f, 0); Space.Add(new Box(Vector3.Zero, 30, 1, 30)); //Create a bunch of boxes randomly. Random random = new Random(); int boxCount = 100; BoundingBox spawnVolume = new BoundingBox(new Vector3(-10, 10, -10), new Vector3(10, 30, 10)); for (int i = 0; i < boxCount; i++) { Vector3 position = new Vector3((float)(random.NextDouble() - 0.5f) * (spawnVolume.Max.X - spawnVolume.Min.X), (float)(random.NextDouble() - 0.5f) * (spawnVolume.Max.Y - spawnVolume.Min.Y), (float)(random.NextDouble() - 0.5f) * (spawnVolume.Max.Z - spawnVolume.Min.Z)) + (spawnVolume.Min + spawnVolume.Max) / 2; Space.Add(new Box(position, 1, 1, 1, 1)); } #region DisplayObject creation foreach (Entity e in Space.Entities) { if ((string)e.Tag != "noDisplayObject") { ModelDrawer.Add(e); } else//Remove the now unnecessary tag. { e.Tag = null; } } #endregion }
/// <summary> /// Construct the physics space. /// </summary> public PhysicsSpace() { ParallelLooper pl = new ParallelLooper(); for (int i = 0; i < Environment.ProcessorCount * 2; i++) { pl.AddThread(); } Internal = new Space(pl); Internal.ForceUpdater.Gravity = new Vector3(0, 0, -9.8); }
protected override void UpdateMultithreaded() { lock (Locker) { Overlaps.Clear(); //Update the entries! ParallelLooper.ForLoop(0, entries.Count, updateEntry); //Update the cells! ParallelLooper.ForLoop(0, cellSet.count, updateCell); } }
public ShapesExtractor(Device device, ParallelLooper looper, BufferPool pool, int initialCapacityPerShapeType = 1024) { spheres = new QuickList <SphereInstance>(initialCapacityPerShapeType, pool); capsules = new QuickList <CapsuleInstance>(initialCapacityPerShapeType, pool); boxes = new QuickList <BoxInstance>(initialCapacityPerShapeType, pool); triangles = new QuickList <TriangleInstance>(initialCapacityPerShapeType, pool); meshes = new QuickList <MeshInstance>(initialCapacityPerShapeType, pool); this.MeshCache = new MeshCache(device, pool); this.pool = pool; this.looper = looper; }
public PhysicsSystem(PhysicsLayersDescription layers) { _collisionGroups = new PhysicsCollisionGroups(layers); CollisionRules.CollisionRuleCalculator = CustomCollisionRuleCalculator; _looper = new ParallelLooper(); for (int g = 0; g < Environment.ProcessorCount - 1; g++) { _looper.AddThread(); } Space = new Space(_looper); Space.ForceUpdater.Gravity = s_defaultGravity; Space.BufferedStates.Enabled = true; Space.BufferedStates.InterpolatedStates.Enabled = true; }
/// <summary> /// Construct the physics space. /// </summary> /// <param name="construct">Set false to disable constructing the internal space.</param> public PhysicsSpace(bool construct = true) { if (!construct) { return; } ParallelLooper pl = new ParallelLooper(); for (int i = 0; i < Environment.ProcessorCount * 2; i++) { pl.AddThread(); } Internal = new Space(pl); Internal.ForceUpdater.Gravity = new Vector3(0, 0, -9.8); }
public ShapesExtractor(Device device, ParallelLooper looper, BufferPool pool, int initialCapacityPerShapeType = 1024) { QuickList <SphereInstance, Array <SphereInstance> > .Create(new PassthroughArrayPool <SphereInstance>(), initialCapacityPerShapeType, out spheres); QuickList <CapsuleInstance, Array <CapsuleInstance> > .Create(new PassthroughArrayPool <CapsuleInstance>(), initialCapacityPerShapeType, out capsules); QuickList <BoxInstance, Array <BoxInstance> > .Create(new PassthroughArrayPool <BoxInstance>(), initialCapacityPerShapeType, out boxes); QuickList <TriangleInstance, Array <TriangleInstance> > .Create(new PassthroughArrayPool <TriangleInstance>(), initialCapacityPerShapeType, out triangles); QuickList <MeshInstance, Array <MeshInstance> > .Create(new PassthroughArrayPool <MeshInstance>(), initialCapacityPerShapeType, out meshes); this.MeshCache = new MeshCache(device, pool); this.looper = looper; }
/// <summary> /// Initialize physics. /// </summary> private void _setupPhysics() { _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 (Environment.ProcessorCount > 1) { for (int i = 0; i < Environment.ProcessorCount; i++) { _parallelLooper.AddThread(); } } _space = new Space(_parallelLooper); _space.ForceUpdater.Gravity = VectorHelper.Down * 9.81f; }
/// <summary> /// Builds the physics world. /// </summary> public void BuildWorld() { ParallelLooper pl = new ParallelLooper(); for (int i = 0; i < Environment.ProcessorCount; i++) { pl.AddThread(); } CollisionDetectionSettings.AllowedPenetration = 0.01f; PhysicsWorld = new Space(pl); PhysicsWorld.TimeStepSettings.MaximumTimeStepsPerFrame = 10; // Set the world's general default gravity PhysicsWorld.ForceUpdater.Gravity = new BEPUutilities.Vector3(0, 0, -9.8f * 3f / 2f); PhysicsWorld.DuringForcesUpdateables.Add(new LiquidVolume(this)); // Load a CollisionUtil instance Collision = new CollisionUtil(PhysicsWorld); }
public void MultithreadedRefitPhase(int splitDepth) { if (splitDepth > 0) { root.CollectMultithreadingNodes(splitDepth, 1, multithreadingSourceNodes); //Go through every node and refit it. ParallelLooper.ForLoop(0, multithreadingSourceNodes.Count, multithreadedRefit); multithreadingSourceNodes.Clear(); //Now that the subtrees belonging to the source nodes are refit, refit the top nodes. //Sometimes, this will go deeper than necessary because the refit process may require an extremely high level (nonmultithreaded) revalidation. //The waste cost is a matter of nanoseconds due to the simplicity of the operations involved. root.PostRefit(splitDepth, 1); } else { SingleThreadedRefitPhase(); } }
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. }
public void MultithreadedOverlapPhase(int splitDepth) { if (splitDepth > 0) { //The trees are now fully refit (and revalidated, if the refit process found it to be necessary). //The overlap traversal is conceptually similar to the multithreaded refit, but is a bit easier since there's no need to go back up the stack. if (!root.IsLeaf ) //If the root is a leaf, it's alone- nothing to collide against! This test is required by the assumptions of the leaf-leaf test. { root.GetMultithreadedOverlaps(root, splitDepth, 1, this, multithreadingSourceOverlaps); ParallelLooper.ForLoop(0, multithreadingSourceOverlaps.Count, multithreadedOverlap); multithreadingSourceOverlaps.Clear(); } } else { SingleThreadedOverlapPhase(); } }
/// <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); } } }
public BEPUPhysicsWorld(Karen90MmoFramework.Quantum.Bounds bounds, Karen90MmoFramework.Quantum.Vector3 gravity, bool createBoundary = false) { var parallelLooper = new ParallelLooper(); if (Environment.ProcessorCount > 1) { for (var i = 0; i < Environment.ProcessorCount; i++) { parallelLooper.AddThread(); } } this.space = new Space(parallelLooper) { ForceUpdater = { Gravity = new Vector3(gravity.X, gravity.Y, gravity.Z) } }; this.bounds = bounds; this.frictionlessMaterial = new Material(0f, 0f, 0f); this.staticGroup = new CollisionGroup(); this.kinematicGroup = new CollisionGroup(); this.dynamicGroup = new CollisionGroup(); this.avatarGroup = new CollisionGroup(); CollisionGroup.DefineCollisionRule(this.staticGroup, this.staticGroup, CollisionRule.NoBroadPhase); CollisionGroup.DefineCollisionRule(this.staticGroup, this.kinematicGroup, CollisionRule.NoBroadPhase); CollisionGroup.DefineCollisionRule(this.staticGroup, this.dynamicGroup, CollisionRule.NoBroadPhase); CollisionGroup.DefineCollisionRule(this.staticGroup, this.avatarGroup, CollisionRule.Defer); CollisionGroup.DefineCollisionRule(this.kinematicGroup, this.kinematicGroup, CollisionRule.NoBroadPhase); CollisionGroup.DefineCollisionRule(this.kinematicGroup, this.dynamicGroup, CollisionRule.NoBroadPhase); CollisionGroup.DefineCollisionRule(this.kinematicGroup, this.avatarGroup, CollisionRule.Defer); CollisionGroup.DefineCollisionRule(this.dynamicGroup, this.dynamicGroup, CollisionRule.NoBroadPhase); CollisionGroup.DefineCollisionRule(this.dynamicGroup, this.avatarGroup, CollisionRule.Defer); CollisionGroup.DefineCollisionRule(this.avatarGroup, this.avatarGroup, CollisionRule.NoBroadPhase); if (createBoundary) { this.CreateWorldBoundary(); } }
public override void InitialiseLevel() { base.InitialiseLevel(); BEPUDebugDrawer = new ModelDrawer(vxEngine.Game); //Starts BEPU with multiple Cores BEPUParallelLooper = new ParallelLooper(); if (Environment.ProcessorCount > 1) { for (int i = 0; i < Environment.ProcessorCount; i++) { BEPUParallelLooper.AddThread(); } } BEPUPhyicsSpace = new Space(BEPUParallelLooper); BEPUPhyicsSpace.ForceUpdater.Gravity = new Vector3(0, -9.81f, 0); vxConsole.WriteLine("Starting Physics vxEngine using " + BEPUPhyicsSpace.ParallelLooper.ThreadCount + " Processors"); }
/// <summary> /// Constructs a new demo. /// </summary> /// <param name="game">Game owning this demo.</param> public MultithreadedScalingTestDemo(DemosGame game) : base(game) { simulationBuilders = new Func<Space, int>[] { BuildPileSimulation, BuildWallSimulation, BuildPlanetSimulation }; #if WINDOWS int coreCountMax = Environment.ProcessorCount; testResults = new double[coreCountMax, simulationBuilders.Length]; int reruns = 1; for (int i = 0; i < reruns; i++) { GC.Collect(); var looper = new ParallelLooper(); //Try different thread counts. for (int j = 0; j < coreCountMax; j++) { looper.AddThread(); for (int k = 0; k < simulationBuilders.Length; k++) testResults[j, k] = RunTest(looper, simulationBuilders[k]); GC.Collect(); } } #else testResults = new double[4, simulationBuilders.Length]; int reruns = 10; for (int i = 0; i < reruns; i++) { GC.Collect(); var threadManager = new SpecializedThreadManager(); threadManager.AddThread(delegate { Thread.CurrentThread.SetProcessorAffinity(new[] { 1 }); }, null); for (int k = 0; k < simulationBuilders.Length; k++) testResults[0, k] += RunTest(threadManager, simulationBuilders[k]); GC.Collect(); threadManager.AddThread(delegate { Thread.CurrentThread.SetProcessorAffinity(new[] { 3 }); }, null); for (int k = 0; k < simulationBuilders.Length; k++) testResults[1, k] += RunTest(threadManager, simulationBuilders[k]); GC.Collect(); threadManager.AddThread(delegate { Thread.CurrentThread.SetProcessorAffinity(new[] { 5 }); }, null); for (int k = 0; k < simulationBuilders.Length; k++) testResults[2, k] += RunTest(threadManager, simulationBuilders[k]); GC.Collect(); threadManager.AddThread(delegate { Thread.CurrentThread.SetProcessorAffinity(new[] { 4 }); }, null); for (int k = 0; k < simulationBuilders.Length; k++) testResults[3, k] += RunTest(threadManager, simulationBuilders[k]); GC.Collect(); } #endif }