unsafe static void SolveSingleJoint(JointData *jointData, int numIterations, float timestep, ref MotionVelocity velocityA, ref MotionVelocity velocityB, ref MotionData motionA, ref MotionData motionB, out NativeStream jacobiansOut) { var stepInput = new Solver.StepInput { IsLastIteration = false, InvNumSolverIterations = 1.0f / numIterations, Timestep = timestep, InvTimestep = timestep > 0.0f ? 1.0f / timestep : 0.0f }; // Build jacobians jacobiansOut = new NativeStream(1, Allocator.Temp); { NativeStream.Writer jacobianWriter = jacobiansOut.AsWriter(); jacobianWriter.BeginForEachIndex(0); Solver.BuildJointJacobian(jointData, new BodyIndexPair(), velocityA, velocityB, motionA, motionB, timestep, numIterations, ref jacobianWriter); jacobianWriter.EndForEachIndex(); } var eventWriter = new NativeStream.Writer(); // no events expected // Solve the joint for (int iIteration = 0; iIteration < numIterations; iIteration++) { stepInput.IsLastIteration = (iIteration == numIterations - 1); NativeStream.Reader jacobianReader = jacobiansOut.AsReader(); var jacIterator = new JacobianIterator(jacobianReader, 0); while (jacIterator.HasJacobiansLeft()) { ref JacobianHeader header = ref jacIterator.ReadJacobianHeader(); header.Solve(ref velocityA, ref velocityB, stepInput, ref eventWriter, ref eventWriter); } }
protected override JobHandle OnUpdate(JobHandle inputDeps) { if (m_CharacterControllersGroup.CalculateEntityCount() == 0) { return(inputDeps); } var chunks = m_CharacterControllersGroup.CreateArchetypeChunkArray(Allocator.TempJob); var characterMoveType = GetArchetypeChunkComponentType <CharacterMoveSetting>(); var userCommandType = GetArchetypeChunkComponentType <UserCommand>(); var movePredictedType = GetArchetypeChunkComponentType <CharacterMovePredictedState>(); var transformType = GetArchetypeChunkComponentType <TransformPredictedState>(); var velocityType = GetArchetypeChunkComponentType <VelocityPredictedState>(); var physicsColliderType = GetArchetypeChunkComponentType <PhysicsCollider>(); var entityType = GetArchetypeChunkEntityType(); var deferredImpulses = new NativeStream(chunks.Length, Allocator.TempJob); var tickDuration = GetSingleton <WorldTime>().TickDuration; var ccJob = new CharacterControllerJob { EntityType = entityType, // Archetypes CharacterMoveType = characterMoveType, UserCommandComponentType = userCommandType, CharacterMovePredictedType = movePredictedType, PhysicsColliderType = physicsColliderType, TransformType = transformType, VelocityType = velocityType, // Input DeltaTime = tickDuration, PhysicsWorld = m_BuildPhysicsWorldSystem.PhysicsWorld, DeferredImpulseWriter = deferredImpulses.AsWriter() }; inputDeps = JobHandle.CombineDependencies(inputDeps, m_ExportPhysicsWorldSystem.FinalJobHandle); inputDeps = ccJob.Schedule(m_CharacterControllersGroup, inputDeps); var applyJob = new ApplyDefferedPhysicsUpdatesJob { Chunks = chunks, DeferredImpulseReader = deferredImpulses.AsReader(), PhysicsMassData = GetComponentDataFromEntity <PhysicsMass>(), TransformPredictedData = GetComponentDataFromEntity <TransformPredictedState>(), VelocityPredictedData = GetComponentDataFromEntity <VelocityPredictedState>(), CharacterMovePredictedData = GetComponentDataFromEntity <CharacterMovePredictedState>() }; inputDeps = applyJob.Schedule(inputDeps); var disposeHandle = deferredImpulses.Dispose(inputDeps); disposeHandle.Complete(); // Must finish all jobs before physics step end // m_EndFramePhysicsSystem.HandlesToWaitFor.Add(disposeHandle); return(inputDeps); }
// Schedule jobs to build Jacobians from the contacts stored in the simulation context internal static SimulationJobHandles ScheduleBuildJacobiansJobs(ref PhysicsWorld world, float timeStep, float3 gravity, int numSolverIterations, JobHandle inputDeps, ref NativeList <DispatchPairSequencer.DispatchPair> dispatchPairs, ref DispatchPairSequencer.SolverSchedulerInfo solverSchedulerInfo, ref NativeStream contacts, ref NativeStream jacobians, int threadCountHint = 0) { SimulationJobHandles returnHandles = default; if (threadCountHint <= 0) { returnHandles.FinalExecutionHandle = new BuildJacobiansJob { ContactsReader = contacts.AsReader(), JacobiansWriter = jacobians.AsWriter(), TimeStep = timeStep, Gravity = gravity, NumSolverIterations = numSolverIterations, World = world, DispatchPairs = dispatchPairs.AsDeferredJobArray(), SolverSchedulerInfo = solverSchedulerInfo }.Schedule(inputDeps); } else { var buildJob = new BuildJacobiansJob { ContactsReader = contacts.AsReader(), JacobiansWriter = jacobians.AsWriter(), TimeStep = timeStep, InvTimeStep = timeStep > 0.0f ? 1.0f / timeStep : 0.0f, GravityAcceleration = math.length(gravity), NumSolverIterations = numSolverIterations, World = world, DispatchPairs = dispatchPairs.AsDeferredJobArray(), SolverSchedulerInfo = solverSchedulerInfo }; JobHandle handle = buildJob.ScheduleUnsafeIndex0(solverSchedulerInfo.NumWorkItems, 1, inputDeps); returnHandles.FinalDisposeHandle = JobHandle.CombineDependencies( dispatchPairs.Dispose(handle), contacts.Dispose(handle)); returnHandles.FinalExecutionHandle = handle; } return(returnHandles); }
internal Enumerator(NativeStream stream) { m_Reader = stream.IsCreated ? stream.AsReader() : new NativeStream.Reader(); m_CurrentWorkItem = 0; m_NumWorkItems = stream.IsCreated ? stream.ForEachCount : 0; Current = default; AdvanceReader(); }
protected override void OnUpdate() { if (m_CharacterControllersGroup.CalculateEntityCount() == 0) { return; } var chunks = m_CharacterControllersGroup.CreateArchetypeChunkArray(Allocator.TempJob); var ccComponentType = GetComponentTypeHandle <CharacterControllerComponentData>(); var ccInternalType = GetComponentTypeHandle <CharacterControllerInternalData>(); var physicsColliderType = GetComponentTypeHandle <PhysicsCollider>(); var translationType = GetComponentTypeHandle <Translation>(); var rotationType = GetComponentTypeHandle <Rotation>(); var collisionEventBufferType = GetBufferTypeHandle <StatefulCollisionEvent>(); var triggerEventBufferType = GetBufferTypeHandle <StatefulTriggerEvent>(); var deferredImpulses = new NativeStream(chunks.Length, Allocator.TempJob); var ccJob = new CharacterControllerJob { // Archetypes CharacterControllerComponentType = ccComponentType, CharacterControllerInternalType = ccInternalType, PhysicsColliderType = physicsColliderType, TranslationType = translationType, RotationType = rotationType, CollisionEventBufferType = collisionEventBufferType, TriggerEventBufferType = triggerEventBufferType, // Input DeltaTime = UnityEngine.Time.fixedDeltaTime, PhysicsWorld = m_BuildPhysicsWorldSystem.PhysicsWorld, DeferredImpulseWriter = deferredImpulses.AsWriter() }; Dependency = JobHandle.CombineDependencies(Dependency, m_ExportPhysicsWorldSystem.GetOutputDependency()); Dependency = ccJob.Schedule(m_CharacterControllersGroup, Dependency); var applyJob = new ApplyDefferedPhysicsUpdatesJob() { Chunks = chunks, DeferredImpulseReader = deferredImpulses.AsReader(), PhysicsVelocityData = GetComponentDataFromEntity <PhysicsVelocity>(), PhysicsMassData = GetComponentDataFromEntity <PhysicsMass>(), TranslationData = GetComponentDataFromEntity <Translation>(), RotationData = GetComponentDataFromEntity <Rotation>() }; Dependency = applyJob.Schedule(Dependency); var disposeHandle = deferredImpulses.Dispose(Dependency); // Must finish all jobs before physics step end m_EndFramePhysicsSystem.AddInputDependency(disposeHandle); }
internal Enumerator(NativeStream stream, NativeSlice <RigidBody> bodies) { m_Reader = stream.IsCreated ? stream.AsReader() : new NativeStream.Reader(); m_CurrentWorkItem = 0; m_NumWorkItems = stream.IsCreated ? stream.ForEachCount : 0; Current = default; m_Bodies = bodies; AdvanceReader(); }
public void JacobianIteratorHasJacobiansLeftTest() { var jacobianStream = new NativeStream(1, Allocator.Temp); NativeStream.Reader jacobianStreamReader = jacobianStream.AsReader(); int workItemIndex = 0; var jacIterator = new JacobianIterator(jacobianStreamReader, workItemIndex); Assert.IsFalse(jacIterator.HasJacobiansLeft()); jacobianStream.Dispose(); }
protected override JobHandle OnUpdate(JobHandle inputDeps) { if (m_CharacterControllersGroup.CalculateEntityCount() == 0) { return(inputDeps); } var chunks = m_CharacterControllersGroup.CreateArchetypeChunkArray(Allocator.TempJob); var ccComponentType = GetArchetypeChunkComponentType <CharacterControllerComponentData>(); var ccInternalType = GetArchetypeChunkComponentType <CharacterControllerInternalData>(); var physicsColliderType = GetArchetypeChunkComponentType <PhysicsCollider>(); var translationType = GetArchetypeChunkComponentType <Translation>(); var rotationType = GetArchetypeChunkComponentType <Rotation>(); var deferredImpulses = new NativeStream(chunks.Length, Allocator.TempJob); var ccJob = new CharacterControllerJob { // Archetypes CharacterControllerComponentType = ccComponentType, CharacterControllerInternalType = ccInternalType, PhysicsColliderType = physicsColliderType, TranslationType = translationType, RotationType = rotationType, // Input DeltaTime = UnityEngine.Time.fixedDeltaTime, cameraWorldPoint = mainCamera.ScreenToWorldPoint(Input.mousePosition), PhysicsWorld = m_BuildPhysicsWorldSystem.PhysicsWorld, DeferredImpulseWriter = deferredImpulses.AsWriter() }; inputDeps = JobHandle.CombineDependencies(inputDeps, m_ExportPhysicsWorldSystem.FinalJobHandle); inputDeps = ccJob.Schedule(m_CharacterControllersGroup, inputDeps); var applyJob = new ApplyDefferedPhysicsUpdatesJob() { Chunks = chunks, DeferredImpulseReader = deferredImpulses.AsReader(), PhysicsVelocityData = GetComponentDataFromEntity <PhysicsVelocity>(), PhysicsMassData = GetComponentDataFromEntity <PhysicsMass>(), TranslationData = GetComponentDataFromEntity <Translation>(), RotationData = GetComponentDataFromEntity <Rotation>() }; inputDeps = applyJob.Schedule(inputDeps); var disposeHandle = deferredImpulses.Dispose(inputDeps); // Must finish all jobs before physics step end m_EndFramePhysicsSystem.HandlesToWaitFor.Add(disposeHandle); return(inputDeps); }
internal Enumerator(NativeStream stream, NativeArray <Velocity> inputVelocities, float timeStep) { m_Reader = stream.IsCreated ? stream.AsReader() : new NativeStream.Reader(); m_CurrentWorkItem = 0; m_NumWorkItems = stream.IsCreated ? stream.ForEachCount : 0; m_InputVelocities = inputVelocities; m_TimeStep = timeStep; unsafe { m_Current = default; } AdvanceReader(); }
public void PopulateInts([Values(1, 100, 200)] int count, [Values(1, 3, 10)] int batchSize) { var stream = new NativeStream(count, Allocator.TempJob); var fillInts = new WriteInts { Writer = stream.AsWriter() }; var jobHandle = fillInts.Schedule(count, batchSize); var compareInts = new ReadInts { Reader = stream.AsReader() }; var res0 = compareInts.Schedule(count, batchSize, jobHandle); var res1 = compareInts.Schedule(count, batchSize, jobHandle); res0.Complete(); res1.Complete(); stream.Dispose(); }
public void NativeStreamBasic() { var stream = new NativeStream(1, Allocator.Persistent); var writer = stream.AsWriter(); var reader = stream.AsReader(); writer.BeginForEachIndex(0); for (var i = 0; i < 100; i++) { if (i % 2 == 0) { //unsafe{ // var pInt = (int*)writer.Allocate(sizeof(int)); // *pInt = i; //} ref int x = ref writer.Allocate <int>(); x = i; }
protected sealed override void OnUpdate() { Dependency = JobHandle.CombineDependencies(Dependency, TriggerJobHandle); // If the producer did not actually write anything to the stream, the native stream will not be flaged as created. // In that case we don't need to do anything. // Not doing this checks actually result in a non authrorized access to the memory and crashes Unity. if (!_effectStream.IsCreated) { return; } NativeStream.Reader effectReader = _effectStream.AsReader(); SetupEffectMap AllocateJob = new SetupEffectMap() { EffectReader = effectReader, Effects = _effects }; Dependency = AllocateJob.Schedule(Dependency); NativeMultiHashMap <Entity, EFFECT_CTX> .ParallelWriter effectsWriter = _effects.AsParallelWriter(); RemapEffects RemapEffectsJob = new RemapEffects() { EffectReader = effectReader, EffectsWriter = _effects.AsParallelWriter() }; Dependency = RemapEffectsJob.Schedule(_forEachCount, 1, Dependency); // Call the effect consumption logic defined in hte derived class. Consume(); Dependency = _effectStream.Dispose(Dependency); }
/// <summary> /// Voxelizes the mesh into the specified grid. The mesh is scaled to fit the grid (minus padding). /// Returns the voxelization job containing its job handle. The voxelization job must be disposed once the job has completed. /// </summary> /// <param name="vertices"></param> /// <param name="normals"></param> /// <param name="grid"></param> /// <param name="material"></param> /// <param name="properties"></param> /// <returns>The voxelization job containing its job handle. The voxelization job must be disposed once the job has completed.</returns> public static VoxelizationJob Voxelize <TIndexer>(NativeArray <float3> vertices, NativeArray <float3> normals, NativeArray3D <Voxel, TIndexer> grid, int material, VoxelizationProperties properties) where TIndexer : struct, IIndexer { var triangles = vertices.Length / 3; var width = grid.Length(0); var height = grid.Length(1); var depth = grid.Length(2); var scaledVertices = new NativeArray <float3>(vertices.Length, Allocator.TempJob); var scaleJobHandle = new VoxelizerMeshScaleJob { inVertices = vertices, outVertices = scaledVertices, width = grid.Length(0), height = grid.Length(1), depth = grid.Length(2), padding = properties.padding }.Schedule(); var binsStream = new NativeStream(triangles, Allocator.TempJob); //Bin triangles var binJobHandle = new VoxelizerBinJob { vertices = scaledVertices, width = width, height = height, depth = depth, stream = binsStream.AsWriter() }.Schedule(triangles, properties.parallelForBatchCount, scaleJobHandle); var binColsX = new NativeList <VoxelizerCollectBinsJob.Column>(Allocator.TempJob); var binColsY = new NativeList <VoxelizerCollectBinsJob.Column>(Allocator.TempJob); var binColsZ = new NativeList <VoxelizerCollectBinsJob.Column>(Allocator.TempJob); var binsX = new NativeList <int>(Allocator.TempJob); var binsY = new NativeList <int>(Allocator.TempJob); var binsZ = new NativeList <int>(Allocator.TempJob); //Collect bins and reorder var collectBinsJobHandle = new VoxelizerCollectBinsJob { stream = binsStream.AsReader(), streams = triangles, width = width, height = height, depth = depth, binColumnsX = binColsX, binsX = binsX, binColumnsY = binColsY, binsY = binsY, binColumnsZ = binColsZ, binsZ = binsZ }.Schedule(binJobHandle); var intersectionsStreamX = new NativeStream(height * depth, Allocator.TempJob); var intersectionsStreamY = new NativeStream(width * depth, Allocator.TempJob); var intersectionsStreamZ = new NativeStream(width * height, Allocator.TempJob); //Intersect X axis var intersectXJobHandle = new VoxelizerMeshIntersectionJob { vertices = scaledVertices, normals = normals, columns = binColsX.AsDeferredJobArray(), bins = binsX, width = width, height = height, depth = depth, axis = 0, stream = intersectionsStreamX.AsWriter(), smoothNormals = properties.smoothNormals }.Schedule(binColsX, properties.parallelForBatchCount, collectBinsJobHandle); //Intersect Y axis var intersectYJobHandle = new VoxelizerMeshIntersectionJob { vertices = scaledVertices, normals = normals, columns = binColsY.AsDeferredJobArray(), bins = binsY, width = width, height = height, depth = depth, axis = 1, stream = intersectionsStreamY.AsWriter(), smoothNormals = properties.smoothNormals }.Schedule(binColsY, properties.parallelForBatchCount, collectBinsJobHandle); //Intersect Z axis var intersectZJobHandle = new VoxelizerMeshIntersectionJob { vertices = scaledVertices, normals = normals, columns = binColsZ.AsDeferredJobArray(), bins = binsZ, width = width, height = height, depth = depth, axis = 2, stream = intersectionsStreamZ.AsWriter(), smoothNormals = properties.smoothNormals }.Schedule(binColsZ, properties.parallelForBatchCount, collectBinsJobHandle); var intersectionColsX = new NativeList <VoxelizerCollectBinsJob.Column>(height * depth, Allocator.TempJob); var intersectionColsY = new NativeList <VoxelizerCollectBinsJob.Column>(width * depth, Allocator.TempJob); var intersectionColsZ = new NativeList <VoxelizerCollectBinsJob.Column>(width * height, Allocator.TempJob); var intersectionsX = new NativeList <float4>(Allocator.TempJob); var intersectionsY = new NativeList <float4>(Allocator.TempJob); var intersectionsZ = new NativeList <float4>(Allocator.TempJob); //Collect X axis var collectXJobHandle = new VoxelizerCollectIntersectionsJob { stream = intersectionsStreamX.AsReader(), binColumns = binColsX, columns = intersectionColsX, intersections = intersectionsX }.Schedule(intersectXJobHandle); //Collect Y axis var collectYJobHandle = new VoxelizerCollectIntersectionsJob { stream = intersectionsStreamY.AsReader(), binColumns = binColsY, columns = intersectionColsY, intersections = intersectionsY }.Schedule(intersectYJobHandle); //Collect Z axis var collectZJobHandle = new VoxelizerCollectIntersectionsJob { stream = intersectionsStreamZ.AsReader(), binColumns = binColsZ, columns = intersectionColsZ, intersections = intersectionsZ }.Schedule(intersectZJobHandle); //Voxelizing using only the axis intersections can result in holes. //The voxelizer job will detect those holes and put them in this list //so they can be fixed later var holes = new NativeList <VoxelizerFillJob <TIndexer> .Hole>(Allocator.TempJob); //Fill in materials and normals where possible var voxelizerFillJobHandle = new VoxelizerFillJob <TIndexer> { colsX = intersectionColsX, colsY = intersectionColsY, colsZ = intersectionColsZ, intersectionsX = intersectionsX, intersectionsY = intersectionsY, intersectionsZ = intersectionsZ, material = material, grid = grid, holes = holes, angleThreshold = properties.angleThreshold, snapThreshold = properties.snapThreshold }.Schedule(JobHandle.CombineDependencies(collectXJobHandle, collectYJobHandle, collectZJobHandle)); //If there are holes in the voxel data, i.e. missing intersections and normals, //then they are patched up in a second pass var patchesQueue = new NativeQueue <VoxelizerFindPatchesJob <TIndexer> .PatchedHole>(Allocator.TempJob); //Find all hole patches in parallel var findPatchesJobHandle = new VoxelizerFindPatchesJob <TIndexer> { vertices = scaledVertices, normals = normals, holes = holes.AsDeferredJobArray(), angleThreshold = properties.angleThreshold, smoothNormals = properties.smoothNormals, queue = patchesQueue.AsParallelWriter() }.Schedule(holes, properties.parallelForBatchCount, voxelizerFillJobHandle); //Apply the hole patches to the grid var applyPatchesJobHandle = new VoxelizerApplyPatchesJob <TIndexer> { queue = patchesQueue, grid = grid }.Schedule(findPatchesJobHandle); return(new VoxelizationJob(applyPatchesJobHandle, scaledVertices, binsStream, binColsX, binColsY, binColsZ, binsX, binsY, binsZ, intersectionsStreamX, intersectionsStreamY, intersectionsStreamZ, intersectionColsX, intersectionColsY, intersectionColsZ, intersectionsX, intersectionsY, intersectionsZ, holes, patchesQueue)); }
public unsafe void OverlapTaskFilteringTest([Values(2, 10, 33, 100)] int elementCount) { elementCount *= 2; int numNodes = elementCount + Constants.MaxNumTreeBranches; var points = new NativeArray <PointAndIndex>(elementCount, Allocator.Temp, NativeArrayOptions.UninitializedMemory); var aabbs = new NativeArray <Aabb>(elementCount, Allocator.Temp, NativeArrayOptions.UninitializedMemory); var bodyFilters = new NativeArray <CollisionFilter>(elementCount, Allocator.Temp, NativeArrayOptions.UninitializedMemory); InitInputWithCopyArrays(points, aabbs, bodyFilters); var nodes = new NativeArray <Node>(numNodes, Allocator.Temp, NativeArrayOptions.UninitializedMemory); Node *nodesPtr = (Node *)nodes.GetUnsafePtr(); var seenUnfiltered = new HashSet <BodyIndexPair>(); { var bvhUnfiltered = new BoundingVolumeHierarchy(nodes); bvhUnfiltered.Build(points, aabbs, out int numNodesOut); bvhUnfiltered.CheckIntegrity(); EverythingWriter pairWriter = new EverythingWriter { SeenPairs = seenUnfiltered }; BoundingVolumeHierarchy.TreeOverlap(ref pairWriter, nodesPtr, nodesPtr); } var nodeFilters = new NativeArray <CollisionFilter>(numNodes, Allocator.Temp, NativeArrayOptions.UninitializedMemory); var bvhFiltered = new BoundingVolumeHierarchy(nodes, nodeFilters); int numNodesFilteredTree; bvhFiltered.Build(points, aabbs, out numNodesFilteredTree); bvhFiltered.BuildCombinedCollisionFilter(bodyFilters, 0, numNodesFilteredTree - 1); var filteredCollisionPairs = new NativeStream(1, Allocator.TempJob); NativeStream.Writer filteredPairWriter = filteredCollisionPairs.AsWriter(); filteredPairWriter.BeginForEachIndex(0); CollisionFilter *bodyFiltersPtr = (CollisionFilter *)bodyFilters.GetUnsafePtr(); var bufferedPairs = new Broadphase.BodyPairWriter(&filteredPairWriter, bodyFiltersPtr, bodyFiltersPtr, 0, 0); CollisionFilter *nodeFiltersPtr = (CollisionFilter *)nodeFilters.GetUnsafePtr(); BoundingVolumeHierarchy.TreeOverlap(ref bufferedPairs, nodesPtr, nodesPtr, nodeFiltersPtr, nodeFiltersPtr); bufferedPairs.Close(); filteredPairWriter.EndForEachIndex(); NativeStream.Reader filteredPairReader = filteredCollisionPairs.AsReader(); filteredPairReader.BeginForEachIndex(0); // Check that every pair in our filtered set also appears in the unfiltered set while (filteredPairReader.RemainingItemCount > 0) { var pair = filteredPairReader.Read <BodyIndexPair>(); Assert.IsTrue(seenUnfiltered.Contains(pair)); seenUnfiltered.Remove(pair); // Remove the pair } // Pairs were removed, so the only remaining ones should be filtered foreach (BodyIndexPair pair in seenUnfiltered) { bool shouldCollide = CollisionFilter.IsCollisionEnabled(bodyFilters[pair.BodyIndexA], bodyFilters[pair.BodyIndexB]); Assert.IsFalse(shouldCollide); } nodeFilters.Dispose(); nodes.Dispose(); bodyFilters.Dispose(); aabbs.Dispose(); points.Dispose(); filteredCollisionPairs.Dispose(); }
protected unsafe override JobHandle OnUpdate(JobHandle inputDeps) { var entityCount = m_CharacterControllerGroup.CalculateEntityCount(); if (entityCount == 0) { return(inputDeps); } var defferredImpulses = new NativeStream(entityCount, Allocator.TempJob); var time = m_TimeSingletonQuery.GetSingleton <GlobalGameTime>().gameTime; var physicWorld = m_BuildPhysicsWorld.PhysicsWorld; var writer = defferredImpulses.AsWriter(); var constraints = new NativeList <SurfaceConstraintInfo>(Allocator.Temp); var castHits = new NativeList <ColliderCastHit>(Allocator.Temp); var distanceHits = new NativeList <DistanceHit>(Allocator.Temp); var input = new ColliderCastInput(); var hit = new ColliderCastHit(); var hasHit = false; var deltaTime = Time.DeltaTime; Entities .WithName("CharacterControllerStepSystem") .ForEach(( ref CharacterControllerComponentData ccData, ref CharacterControllerCollider ccCollider, ref CharacterControllerMoveQuery moveQuery, ref CharacterControllerMoveResult moveResult, ref CharacterControllerVelocity velocity ) => { var collider = (Collider *)ccCollider.Collider.GetUnsafePtr(); var stepInput = new CharacterControllerUtilities.CharacterControllerStepInput { World = physicWorld, //DeltaTime = time.tickDuration, DeltaTime = deltaTime, Gravity = new float3(0.0f, -9.8f, 0.0f), MaxIterations = ccData.MaxIterations, Tau = CharacterControllerUtilities.k_DefaultTau, Damping = CharacterControllerUtilities.k_DefaultDamping, SkinWidth = ccData.SkinWidth, ContactTolerance = ccData.ContactTolearance, MaxSlope = ccData.MaxSlope, RigidBodyIndex = -1, CurrentVelocity = velocity.WorldVelocity, MaxMovementSpeed = ccData.MaxMovementSpeed, FollowGroud = moveQuery.FollowGroud }; var transform = new RigidTransform { pos = moveQuery.StartPosition, rot = quaternion.identity }; CharacterControllerUtilities.CollideAndIntegrate( stepInput, ccData.CharacterMass, ccData.AffectsPhysicsBodies > 0, collider, ref transform, ref velocity.WorldVelocity, ref writer, ref constraints, ref castHits, ref distanceHits, out input, out hit); moveResult.MoveResult = transform.pos; }) .Run(); var applyJob = new ApplyDefferedImpulses() { DeferredImpulseReader = defferredImpulses.AsReader(), PhysicsVelocityData = GetComponentDataFromEntity <PhysicsVelocity>(), PhysicsMassData = GetComponentDataFromEntity <PhysicsMass>(), TranslationData = GetComponentDataFromEntity <Translation>(), RotationData = GetComponentDataFromEntity <Rotation>() }; applyJob.Run(); CharacterControllerDebug.input = input; CharacterControllerDebug.hit = hit; defferredImpulses.Dispose(); constraints.Dispose(); castHits.Dispose(); distanceHits.Dispose(); return(inputDeps); }
protected override void OnUpdate() { var ecsJH = Dependency; //Query arrays var aliveListenerEntities = m_aliveListenersQuery.ToEntityArrayAsync(Allocator.TempJob, out JobHandle aliveListenerEntitiesJH); var deadListenerEntities = m_deadListenersQuery.ToEntityArrayAsync(Allocator.TempJob, out JobHandle deadListenerEntitiesJH); var listenerEntitiesJH = JobHandle.CombineDependencies(aliveListenerEntitiesJH, deadListenerEntitiesJH); //Type handles var entityHandle = GetEntityTypeHandle(); var listenerHandle = GetComponentTypeHandle <AudioListener>(true); var oneshotHandle = GetComponentTypeHandle <AudioSourceOneShot>(false); var loopedHandle = GetComponentTypeHandle <AudioSourceLooped>(false); var coneHandle = GetComponentTypeHandle <AudioSourceEmitterCone>(true); var translationHandle = GetComponentTypeHandle <Translation>(true); var rotationHandle = GetComponentTypeHandle <Rotation>(true); var ltwHandle = GetComponentTypeHandle <LocalToWorld>(true); var parentHandle = GetComponentTypeHandle <Parent>(true); var audioSettingsCdfe = GetComponentDataFromEntity <AudioSettings>(true); var listenerCdfe = GetComponentDataFromEntity <AudioListener>(true); var listenerGraphStateCdfe = GetComponentDataFromEntity <ListenerGraphState>(false); var entityOutputGraphStateCdfe = GetComponentDataFromEntity <EntityOutputGraphState>(false); //Buffer m_currentBufferId++; var ildBuffer = new ManagedIldBuffer { buffer = new NativeList <float>(Allocator.Persistent), channels = new NativeList <IldBufferChannel>(Allocator.Persistent), bufferId = m_currentBufferId }; //Containers var destroyCommandBuffer = latiosWorld.syncPoint.CreateDestroyCommandBuffer().AsParallelWriter(); var entityCommandBuffer = latiosWorld.syncPoint.CreateEntityCommandBuffer(); var dspCommandBlock = m_graph.CreateCommandBlock(); var listenersWithTransforms = new NativeList <ListenerWithTransform>(aliveListenerEntities.Length, Allocator.TempJob); var listenerBufferParameters = new NativeArray <ListenerBufferParameters>(aliveListenerEntities.Length, Allocator.TempJob, NativeArrayOptions.UninitializedMemory); var forIndexToListenerAndChannelIndices = new NativeList <int2>(Allocator.TempJob); var oneshotEmitters = new NativeArray <OneshotEmitter>(m_oneshotsQuery.CalculateEntityCount(), Allocator.TempJob, NativeArrayOptions.UninitializedMemory); var loopedEmitters = new NativeArray <LoopedEmitter>(m_loopedQuery.CalculateEntityCount(), Allocator.TempJob, NativeArrayOptions.UninitializedMemory); var oneshotWeightsStream = new NativeStream(oneshotEmitters.Length / CullingAndWeighting.BATCH_SIZE + 1, Allocator.TempJob); var loopedWeightsStream = new NativeStream(loopedEmitters.Length / CullingAndWeighting.BATCH_SIZE + 1, Allocator.TempJob); var oneshotListenerEmitterPairsStream = new NativeStream(oneshotEmitters.Length / CullingAndWeighting.BATCH_SIZE + 1, Allocator.TempJob); var loopedListenerEmitterPairsStream = new NativeStream(loopedEmitters.Length / CullingAndWeighting.BATCH_SIZE + 1, Allocator.TempJob); var oneshotClipFrameLookups = new NativeList <ClipFrameLookup>(Allocator.TempJob); var loopedClipFrameLookups = new NativeList <ClipFrameLookup>(Allocator.TempJob); var oneshotBatchedWeights = new NativeList <Weights>(Allocator.TempJob); var loopedBatchedWeights = new NativeList <Weights>(Allocator.TempJob); var oneshotTargetListenerIndices = new NativeList <int>(Allocator.TempJob); var loopedTargetListenerIndices = new NativeList <int>(Allocator.TempJob); //Jobs m_lastUpdateJobHandle.Complete(); //This may lag behind what the job threads will see. //That's fine, as this is only used for disposing memory. int lastReadIldBufferFromMainThread = m_lastReadBufferId.Value; var captureListenersJH = new InitUpdateDestroy.UpdateListenersJob { listenerHandle = listenerHandle, translationHandle = translationHandle, rotationHandle = rotationHandle, ltwHandle = ltwHandle, listenersWithTransforms = listenersWithTransforms }.Schedule(m_aliveListenersQuery, ecsJH); var captureFrameJH = new GraphHandling.CaptureIldFrameJob { packedFrameCounterBufferId = m_packedFrameCounterBufferId, audioFrame = m_audioFrame, lastReadBufferId = m_lastReadBufferId }.Schedule(); var ecsCaptureFrameJH = JobHandle.CombineDependencies(ecsJH, captureFrameJH); var updateListenersGraphJH = new GraphHandling.UpdateListenersGraphJob { listenerEntities = aliveListenerEntities, destroyedListenerEntities = deadListenerEntities, listenerCdfe = listenerCdfe, listenerGraphStateCdfe = listenerGraphStateCdfe, listenerOutputGraphStateCdfe = entityOutputGraphStateCdfe, ecb = entityCommandBuffer, audioSettingsCdfe = audioSettingsCdfe, worldBlackboardEntity = worldBlackboardEntity, audioFrame = m_audioFrame, systemMixNodePortFreelist = m_mixNodePortFreelist, systemMixNodePortCount = m_mixNodePortCount, systemMixNode = m_mixNode, systemIldNodePortCount = m_ildNodePortCount, systemIldNode = m_ildNode, commandBlock = dspCommandBlock, listenerBufferParameters = listenerBufferParameters, forIndexToListenerAndChannelIndices = forIndexToListenerAndChannelIndices, outputSamplesMegaBuffer = ildBuffer.buffer, outputSamplesMegaBufferChannels = ildBuffer.channels, bufferId = m_currentBufferId, samplesPerSubframe = m_samplesPerSubframe }.Schedule(JobHandle.CombineDependencies(captureListenersJH, captureFrameJH, listenerEntitiesJH)); var destroyOneshotsJH = new InitUpdateDestroy.DestroyOneshotsWhenFinishedJob { dcb = destroyCommandBuffer, entityHandle = entityHandle, oneshotHandle = oneshotHandle, audioFrame = m_audioFrame, sampleRate = m_sampleRate, settingsCdfe = audioSettingsCdfe, samplesPerSubframe = m_samplesPerSubframe, worldBlackboardEntity = worldBlackboardEntity }.ScheduleParallel(m_oneshotsToDestroyWhenFinishedQuery, 1, ecsCaptureFrameJH); var updateOneshotsJH = new InitUpdateDestroy.UpdateOneshotsJob { oneshotHandle = oneshotHandle, ltwHandle = ltwHandle, translationHandle = translationHandle, rotationHandle = rotationHandle, parentHandle = parentHandle, coneHandle = coneHandle, audioFrame = m_audioFrame, lastConsumedBufferId = m_lastReadBufferId, bufferId = m_currentBufferId, emitters = oneshotEmitters }.ScheduleParallel(m_oneshotsQuery, 1, destroyOneshotsJH); var updateLoopedJH = new InitUpdateDestroy.UpdateLoopedsJob { loopedHandle = loopedHandle, ltwHandle = ltwHandle, translationHandle = translationHandle, rotationHandle = rotationHandle, parentHandle = parentHandle, coneHandle = coneHandle, audioFrame = m_audioFrame, lastConsumedBufferId = m_lastReadBufferId, bufferId = m_currentBufferId, emitters = loopedEmitters }.ScheduleParallel(m_loopedQuery, 1, ecsCaptureFrameJH); //No more ECS var oneshotsCullingWeightingJH = new CullingAndWeighting.OneshotsJob { emitters = oneshotEmitters, listenersWithTransforms = listenersWithTransforms, weights = oneshotWeightsStream.AsWriter(), listenerEmitterPairs = oneshotListenerEmitterPairsStream.AsWriter() }.ScheduleBatch(oneshotEmitters.Length, CullingAndWeighting.BATCH_SIZE, JobHandle.CombineDependencies(captureListenersJH, updateOneshotsJH)); var loopedCullingWeightingJH = new CullingAndWeighting.LoopedJob { emitters = loopedEmitters, listenersWithTransforms = listenersWithTransforms, weights = loopedWeightsStream.AsWriter(), listenerEmitterPairs = loopedListenerEmitterPairsStream.AsWriter() }.ScheduleBatch(loopedEmitters.Length, CullingAndWeighting.BATCH_SIZE, JobHandle.CombineDependencies(captureListenersJH, updateLoopedJH)); var oneshotsBatchingJH = new Batching.BatchOneshotsJob { emitters = oneshotEmitters, pairWeights = oneshotWeightsStream.AsReader(), listenerEmitterPairs = oneshotListenerEmitterPairsStream.AsReader(), clipFrameLookups = oneshotClipFrameLookups, batchedWeights = oneshotBatchedWeights, targetListenerIndices = oneshotTargetListenerIndices }.Schedule(oneshotsCullingWeightingJH); var loopedBatchingJH = new Batching.BatchLoopedJob { emitters = loopedEmitters, pairWeights = loopedWeightsStream.AsReader(), listenerEmitterPairs = loopedListenerEmitterPairsStream.AsReader(), clipFrameLookups = loopedClipFrameLookups, batchedWeights = loopedBatchedWeights, targetListenerIndices = loopedTargetListenerIndices }.Schedule(loopedCullingWeightingJH); var oneshotSamplingJH = new Sampling.SampleOneshotClipsJob { clipFrameLookups = oneshotClipFrameLookups.AsDeferredJobArray(), weights = oneshotBatchedWeights.AsDeferredJobArray(), targetListenerIndices = oneshotTargetListenerIndices.AsDeferredJobArray(), listenerBufferParameters = listenerBufferParameters, forIndexToListenerAndChannelIndices = forIndexToListenerAndChannelIndices.AsDeferredJobArray(), outputSamplesMegaBuffer = ildBuffer.buffer.AsDeferredJobArray(), sampleRate = m_sampleRate, samplesPerSubframe = m_samplesPerSubframe, audioFrame = m_audioFrame }.Schedule(forIndexToListenerAndChannelIndices, 1, JobHandle.CombineDependencies(updateListenersGraphJH, oneshotsBatchingJH)); var loopedSamplingJH = new Sampling.SampleLoopedClipsJob { clipFrameLookups = loopedClipFrameLookups.AsDeferredJobArray(), weights = loopedBatchedWeights.AsDeferredJobArray(), targetListenerIndices = loopedTargetListenerIndices.AsDeferredJobArray(), listenerBufferParameters = listenerBufferParameters, forIndexToListenerAndChannelIndices = forIndexToListenerAndChannelIndices.AsDeferredJobArray(), outputSamplesMegaBuffer = ildBuffer.buffer.AsDeferredJobArray(), sampleRate = m_sampleRate, samplesPerSubframe = m_samplesPerSubframe, audioFrame = m_audioFrame }.Schedule(forIndexToListenerAndChannelIndices, 1, JobHandle.CombineDependencies(oneshotSamplingJH, loopedBatchingJH)); var shipItJH = new GraphHandling.SubmitToDspGraphJob { commandBlock = dspCommandBlock }.Schedule(loopedSamplingJH); Dependency = JobHandle.CombineDependencies(updateListenersGraphJH, //handles captureListener and captureFrame updateOneshotsJH, //handles destroyOneshots updateLoopedJH ); var disposeJobHandles = new NativeList <JobHandle>(Allocator.TempJob); disposeJobHandles.Add(aliveListenerEntities.Dispose(updateListenersGraphJH)); disposeJobHandles.Add(deadListenerEntities.Dispose(updateListenersGraphJH)); disposeJobHandles.Add(listenersWithTransforms.Dispose(JobHandle.CombineDependencies(oneshotsCullingWeightingJH, loopedCullingWeightingJH))); disposeJobHandles.Add(listenerBufferParameters.Dispose(loopedSamplingJH)); disposeJobHandles.Add(forIndexToListenerAndChannelIndices.Dispose(loopedSamplingJH)); disposeJobHandles.Add(oneshotEmitters.Dispose(oneshotsBatchingJH)); disposeJobHandles.Add(loopedEmitters.Dispose(loopedBatchingJH)); disposeJobHandles.Add(oneshotWeightsStream.Dispose(oneshotsBatchingJH)); disposeJobHandles.Add(loopedWeightsStream.Dispose(loopedBatchingJH)); disposeJobHandles.Add(oneshotListenerEmitterPairsStream.Dispose(oneshotsBatchingJH)); disposeJobHandles.Add(loopedListenerEmitterPairsStream.Dispose(loopedBatchingJH)); disposeJobHandles.Add(oneshotClipFrameLookups.Dispose(oneshotSamplingJH)); disposeJobHandles.Add(loopedClipFrameLookups.Dispose(loopedSamplingJH)); disposeJobHandles.Add(oneshotBatchedWeights.Dispose(oneshotSamplingJH)); disposeJobHandles.Add(loopedBatchedWeights.Dispose(loopedSamplingJH)); disposeJobHandles.Add(oneshotTargetListenerIndices.Dispose(oneshotSamplingJH)); disposeJobHandles.Add(loopedTargetListenerIndices.Dispose(loopedSamplingJH)); disposeJobHandles.Add(shipItJH); for (int i = 0; i < m_buffersInFlight.Count; i++) { var buffer = m_buffersInFlight[i]; if (buffer.bufferId - lastReadIldBufferFromMainThread < 0) { disposeJobHandles.Add(buffer.buffer.Dispose(ecsJH)); disposeJobHandles.Add(buffer.channels.Dispose(ecsJH)); m_buffersInFlight.RemoveAtSwapBack(i); i--; } } m_lastUpdateJobHandle = JobHandle.CombineDependencies(disposeJobHandles); disposeJobHandles.Dispose(); m_buffersInFlight.Add(ildBuffer); }
// Schedule jobs to solve the Jacobians stored in the simulation context internal static unsafe SimulationJobHandles ScheduleSolveJacobiansJobs(ref DynamicsWorld dynamicsWorld, float timestep, int numIterations, ref NativeStream jacobians, ref NativeStream collisionEvents, ref NativeStream triggerEvents, ref DispatchPairSequencer.SolverSchedulerInfo solverSchedulerInfo, JobHandle inputDeps, int threadCountHint = 0) { SimulationJobHandles returnHandles = default; if (threadCountHint <= 0) { collisionEvents = new NativeStream(1, Allocator.Persistent); triggerEvents = new NativeStream(1, Allocator.Persistent); returnHandles.FinalExecutionHandle = new SolverJob { CollisionEventsWriter = collisionEvents.AsWriter(), JacobiansReader = jacobians.AsReader(), NumIterations = numIterations, Timestep = timestep, TriggerEventsWriter = triggerEvents.AsWriter(), MotionVelocities = dynamicsWorld.MotionVelocities, Phases = solverSchedulerInfo.PhaseInfo }.Schedule(inputDeps); return(returnHandles); } JobHandle handle; int numPhases = solverSchedulerInfo.NumPhases; // Use persistent allocator to allow these to live until the start of next step { NativeArray <int> workItemList = solverSchedulerInfo.NumWorkItems; //TODO: Change this to Allocator.TempJob when https://github.com/Unity-Technologies/Unity.Physics/issues/7 is resolved JobHandle collisionEventStreamHandle = NativeStream.ScheduleConstruct(out collisionEvents, workItemList, inputDeps, Allocator.Persistent); JobHandle triggerEventStreamHandle = NativeStream.ScheduleConstruct(out triggerEvents, workItemList, inputDeps, Allocator.Persistent); handle = JobHandle.CombineDependencies(collisionEventStreamHandle, triggerEventStreamHandle); float invNumIterations = math.rcp(numIterations); var phaseInfoPtrs = (DispatchPairSequencer.SolverSchedulerInfo.SolvePhaseInfo *)NativeArrayUnsafeUtility.GetUnsafeBufferPointerWithoutChecks(solverSchedulerInfo.PhaseInfo); for (int solverIterationId = 0; solverIterationId < numIterations; solverIterationId++) { bool lastIteration = solverIterationId == numIterations - 1; for (int phaseId = 0; phaseId < numPhases; phaseId++) { var job = new SolverJob { JacobiansReader = jacobians.AsReader(), PhaseIndex = phaseId, Phases = solverSchedulerInfo.PhaseInfo, MotionVelocities = dynamicsWorld.MotionVelocities, StepInput = new StepInput { InvNumSolverIterations = invNumIterations, IsLastIteration = lastIteration, Timestep = timestep, InvTimestep = timestep > 0.0f ? 1.0f / timestep : 0.0f } }; // Only initialize event writers for last solver iteration jobs if (lastIteration) { job.CollisionEventsWriter = collisionEvents.AsWriter(); job.TriggerEventsWriter = triggerEvents.AsWriter(); } // NOTE: The last phase must be executed on a single job since it // int.MaxValue can't be used as batchSize since 19.1 overflows in that case... bool isLastPhase = phaseId == numPhases - 1; int batchSize = isLastPhase ? (int.MaxValue / 2) : 1; int *numWorkItems = &(phaseInfoPtrs[phaseId].NumWorkItems); handle = job.Schedule(numWorkItems, batchSize, handle); } } } // Dispose processed data returnHandles.FinalDisposeHandle = JobHandle.CombineDependencies( jacobians.Dispose(handle), solverSchedulerInfo.ScheduleDisposeJob(handle)); returnHandles.FinalExecutionHandle = handle; return(returnHandles); }
public NativeStream.Reader AsReader() { return(NativeStream.AsReader()); }
public NativeStream.Reader GetEffectReader() { return(_effectStream.AsReader()); }
// Steps the simulation immediately on a single thread without spawning any jobs. public static void StepImmediate(SimulationStepInput input, ref SimulationContext simulationContext) { if (input.TimeStep < 0) { throw new ArgumentOutOfRangeException(); } if (input.NumSolverIterations <= 0) { throw new ArgumentOutOfRangeException(); } if (input.World.NumDynamicBodies == 0) { // No need to do anything, since nothing can move return; } // Inform the context of the timeStep simulationContext.TimeStep = input.TimeStep; // Find all body pairs that overlap in the broadphase var dynamicVsDynamicBodyPairs = new NativeStream(1, Allocator.Temp); var dynamicVsStaticBodyPairs = new NativeStream(1, Allocator.Temp); { var dynamicVsDynamicBodyPairsWriter = dynamicVsDynamicBodyPairs.AsWriter(); var dynamicVsStaticBodyPairsWriter = dynamicVsStaticBodyPairs.AsWriter(); input.World.CollisionWorld.FindOverlaps(ref dynamicVsDynamicBodyPairsWriter, ref dynamicVsStaticBodyPairsWriter); } // Create dispatch pairs var dispatchPairs = new NativeList <DispatchPairSequencer.DispatchPair>(Allocator.Temp); DispatchPairSequencer.CreateDispatchPairs(ref dynamicVsDynamicBodyPairs, ref dynamicVsStaticBodyPairs, input.World.NumDynamicBodies, input.World.Joints, ref dispatchPairs); // Apply gravity and copy input velocities Solver.ApplyGravityAndCopyInputVelocities(input.World.DynamicsWorld.MotionDatas, input.World.DynamicsWorld.MotionVelocities, simulationContext.InputVelocities, input.TimeStep * input.Gravity); // Narrow phase var contacts = new NativeStream(1, Allocator.Temp); { var contactsWriter = contacts.AsWriter(); NarrowPhase.CreateContacts(ref input.World, dispatchPairs.AsArray(), input.TimeStep, ref contactsWriter); } // Build Jacobians var jacobians = new NativeStream(1, Allocator.Temp); { var contactsReader = contacts.AsReader(); var jacobiansWriter = jacobians.AsWriter(); Solver.BuildJacobians(ref input.World, input.TimeStep, input.Gravity, input.NumSolverIterations, dispatchPairs.AsArray(), ref contactsReader, ref jacobiansWriter); } // Solve Jacobians { var jacobiansReader = jacobians.AsReader(); var collisionEventsWriter = simulationContext.CollisionEventDataStream.AsWriter(); var triggerEventsWriter = simulationContext.TriggerEventDataStream.AsWriter(); Solver.SolveJacobians(ref jacobiansReader, input.World.DynamicsWorld.MotionVelocities, input.TimeStep, input.NumSolverIterations, ref collisionEventsWriter, ref triggerEventsWriter); } // Integrate motions Integrator.Integrate(input.World.DynamicsWorld.MotionDatas, input.World.DynamicsWorld.MotionVelocities, input.TimeStep); // Synchronize the collision world if asked for if (input.SynchronizeCollisionWorld) { input.World.CollisionWorld.UpdateDynamicTree(ref input.World, input.TimeStep, input.Gravity); } }