/// <summary> /// This method used to run forever because of the bug /// </summary> private bool Remove(string key) { int hc = key.GetHashCode(); Log("Making sure internal object contains hashcode key " + hc); if (!_internalObject.ContainsKey(hc)) { return false; } int keyIndex = _keysToIndexMapping[hc].Cast<int>(); Log("Key index is " + keyIndex); _keysToIndexMapping.RemoveKey(hc); Log("Key index removed from keys to index mapping. Rebuilding keys array"); NativeArray<string> newKeys = new NativeArray<string>(); int length = _keys.Length; int newLength = _keys.Length - 1; for (int i = 0; i < newLength; i++) { Log("At index: " + i); if (i == keyIndex) { continue; } newKeys.Push(_keys[i]); } _keys = newKeys; _internalObject.RemoveKey(hc); Log("Dictionary::Remove done!"); return true; }
internal static void Initialize() { _appDomains = new NativeArray<AppDomain>(); // create default appdomain _appDomains[0] = CreateAppDomain("Default AppDomain"); }
public virtual void GetAllIdsShouldIncludeArrayIndices() { NativeArray array = new NativeArray(new string[] { "a", "b" }); object[] expectedIds = new object[] { 0, 1, "length" }; object[] actualIds = array.GetAllIds(); Assert.AssertArrayEquals(expectedIds, actualIds); }
public Semaphore(int resources) { if (resources < 1) { throw new ArgumentException("Must have at least 1 resource for a semaphore"); } _totalResources = _resources = resources; _waitingTasks = new NativeArray<WaitingTask>(); }
public override void PerformTest() { _keys = new NativeArray<string>(); _keysToIndexMapping = new NativeObject(); _internalObject = new NativeObject(); Add("hello", "world"); Add("goodbye", "buddy"); Add("yester", "day"); // TODO: Do this in a separate thread and if the thread hasn't exited in 20 seconds, the test failed Remove("hello"); Remove("goodbye"); }
public static string GetStackTrace(Exception exception) { XaeiOSException xaeiosException = (XaeiOSException)exception; Continuation continuation = xaeiosException.ThrowContext; // TODO: Create StackWalker framework NativeArray<string> buffer = new NativeArray<string>(); while (continuation != null) { buffer.Push("at "); string methodName = RuntimeHelpers.GetMethodNameForStackTrace(continuation.Frame.Function); if (methodName == null) { methodName = "[External Code]"; // TODO: Provide something more descriptive. Maybe a code pointer? } buffer.Push(methodName); // TODO: Debug symbols should put C# line numbers here, rather than xaeios execution pointers // TODO: These execution pointers are wrong!!!, the execution pointer is set to the next execution pointer at the BEGINNING of the current execution block buffer.Push(":"); buffer.Push((continuation.ExecutionPointer).ToString()); buffer.Push("\n"); continuation = continuation.ParentContinuation; } return buffer.Join(""); }
internal void MoveChunksFrom( NativeArray <EntityRemapUtility.EntityRemapInfo> entityRemapping, EntityComponentStore *srcEntityComponentStore, ManagedComponentStore srcManagedComponentStore) { var moveChunksJob = new MoveAllChunksJob { srcEntityComponentStore = srcEntityComponentStore, dstEntityComponentStore = EntityComponentStore, entityRemapping = entityRemapping }.Schedule(); JobHandle.ScheduleBatchedJobs(); int chunkCount = 0; for (var i = 0; i < srcEntityComponentStore->m_Archetypes.Length; ++i) { var srcArchetype = srcEntityComponentStore->m_Archetypes.Ptr[i]; chunkCount += srcArchetype->Chunks.Count; } var remapChunks = new NativeArray <RemapChunk>(chunkCount, Allocator.TempJob); var remapArchetypes = new NativeArray <RemapArchetype>(srcEntityComponentStore->m_Archetypes.Length, Allocator.TempJob); var managedArrayChunks = new NativeList <IntPtr>(Allocator.Temp); int chunkIndex = 0; int archetypeIndex = 0; for (var i = 0; i < srcEntityComponentStore->m_Archetypes.Length; ++i) { var srcArchetype = srcEntityComponentStore->m_Archetypes.Ptr[i]; if (srcArchetype->Chunks.Count != 0) { var dstArchetype = EntityComponentStore->GetOrCreateArchetype(srcArchetype->Types, srcArchetype->TypesCount); remapArchetypes[archetypeIndex] = new RemapArchetype { srcArchetype = srcArchetype, dstArchetype = dstArchetype }; for (var j = 0; j < srcArchetype->Chunks.Count; ++j) { var srcChunk = srcArchetype->Chunks.p[j]; remapChunks[chunkIndex] = new RemapChunk { chunk = srcChunk, dstArchetype = dstArchetype }; chunkIndex++; } if (srcArchetype->NumManagedArrays > 0) { for (var j = 0; j < srcArchetype->Chunks.Count; ++j) { var chunk = srcArchetype->Chunks.p[j]; managedArrayChunks.Add((IntPtr)chunk); } } archetypeIndex++; EntityComponentStore->IncrementComponentTypeOrderVersion(dstArchetype); } } moveChunksJob.Complete(); var managedArrayDstIndices = new NativeArray <int>(managedArrayChunks.Length, Allocator.TempJob); var managedArraySrcIndices = new NativeArray <int>(managedArrayChunks.Length, Allocator.TempJob); EntityComponentStore->ReserveManagedObjectArrays(managedArrayDstIndices); var remapManaged = new RemapManagedArraysJob { chunks = managedArrayChunks, dstIndices = managedArrayDstIndices, srcIndices = managedArraySrcIndices, }.Schedule(managedArrayChunks.Length, 64); ManagedComponentStore.Playback(ref EntityComponentStore->ManagedChangesTracker); srcManagedComponentStore.Playback(ref srcEntityComponentStore->ManagedChangesTracker); k_ProfileMoveObjectComponents.Begin(); remapManaged.Complete(); m_ManagedComponentStore.MoveManagedObjectArrays(managedArraySrcIndices, managedArrayDstIndices, srcManagedComponentStore); k_ProfileMoveObjectComponents.End(); managedArrayDstIndices.Dispose(); managedArraySrcIndices.Dispose(); managedArrayChunks.Dispose(); k_ProfileMoveSharedComponents.Begin(); var remapShared = ManagedComponentStore.MoveAllSharedComponents(srcManagedComponentStore, Allocator.TempJob); k_ProfileMoveSharedComponents.End(); new ChunkPatchEntities { RemapChunks = remapChunks, EntityRemapping = entityRemapping, EntityComponentStore = EntityComponentStore }.Run(); var remapAllChunksJob = new RemapAllChunksJob { dstEntityComponentStore = EntityComponentStore, remapChunks = remapChunks, entityRemapping = entityRemapping }.Schedule(remapChunks.Length, 1); var remapArchetypesJob = new RemapArchetypesJob { remapArchetypes = remapArchetypes, remapShared = remapShared, dstEntityComponentStore = EntityComponentStore, chunkHeaderType = TypeManager.GetTypeIndex <ChunkHeader>() }.Schedule(archetypeIndex, 1, remapAllChunksJob); ManagedComponentStore.Playback(ref EntityComponentStore->ManagedChangesTracker); remapArchetypesJob.Complete(); remapShared.Dispose(); remapChunks.Dispose(); }
public static unsafe BlobAssetReference <Collider> Create(NativeArray <float3> vertices, NativeArray <int3> triangles, CollisionFilter filter, Material material) { SafetyChecks.CheckTriangleIndicesInRangeAndThrow(triangles, vertices.Length, nameof(triangles)); // Copy vertices var tempVertices = new NativeArray <float3>(vertices, Allocator.Temp); // Triangle indices - needed for WeldVertices var tempIndices = new NativeArray <int>(triangles.Reinterpret <int>(UnsafeUtility.SizeOf <int3>()), Allocator.Temp); // Build connectivity and primitives NativeList <float3> uniqueVertices = MeshConnectivityBuilder.WeldVertices(tempIndices, tempVertices); var tempTriangleIndices = new NativeArray <int3>(triangles.Length, Allocator.Temp); UnsafeUtility.MemCpy(tempTriangleIndices.GetUnsafePtr(), tempIndices.GetUnsafePtr(), tempIndices.Length * UnsafeUtility.SizeOf <int>()); var connectivity = new MeshConnectivityBuilder(tempTriangleIndices, uniqueVertices); NativeList <MeshConnectivityBuilder.Primitive> primitives = connectivity.EnumerateQuadDominantGeometry(tempTriangleIndices, uniqueVertices); // Build bounding volume hierarchy int nodeCount = math.max(primitives.Length * 2 + 1, 2); // We need at least two nodes - an "invalid" node and a root node. var nodes = new NativeArray <BoundingVolumeHierarchy.Node>(nodeCount, Allocator.Temp); int numNodes = 0; { // Prepare data for BVH var points = new NativeList <BoundingVolumeHierarchy.PointAndIndex>(primitives.Length, Allocator.Temp); var aabbs = new NativeArray <Aabb>(primitives.Length, Allocator.Temp); for (int i = 0; i < primitives.Length; i++) { MeshConnectivityBuilder.Primitive p = primitives[i]; // Skip degenerate triangles if (MeshConnectivityBuilder.IsTriangleDegenerate(p.Vertices[0], p.Vertices[1], p.Vertices[2])) { continue; } aabbs[i] = Aabb.CreateFromPoints(p.Vertices); points.Add(new BoundingVolumeHierarchy.PointAndIndex { Position = aabbs[i].Center, Index = i }); } var bvh = new BoundingVolumeHierarchy(nodes); bvh.Build(points.AsArray(), aabbs, out numNodes, useSah: true); } // Build mesh sections BoundingVolumeHierarchy.Node *nodesPtr = (BoundingVolumeHierarchy.Node *)nodes.GetUnsafePtr(); MeshBuilder.TempSection sections = MeshBuilder.BuildSections(nodesPtr, numNodes, primitives); // Allocate collider int meshDataSize = Mesh.CalculateMeshDataSize(numNodes, sections.Ranges); int totalColliderSize = Math.NextMultipleOf(sizeof(MeshCollider), 16) + meshDataSize; MeshCollider *meshCollider = (MeshCollider *)UnsafeUtility.Malloc(totalColliderSize, 16, Allocator.Temp); // Initialize it { UnsafeUtility.MemClear(meshCollider, totalColliderSize); meshCollider->MemorySize = totalColliderSize; meshCollider->m_Header.Type = ColliderType.Mesh; meshCollider->m_Header.CollisionType = CollisionType.Composite; meshCollider->m_Header.Version += 1; meshCollider->m_Header.Magic = 0xff; ref var mesh = ref meshCollider->Mesh; mesh.Init(nodesPtr, numNodes, sections, filter, material); // Calculate combined filter meshCollider->m_Header.Filter = mesh.Sections.Length > 0 ? mesh.Sections[0].Filters[0] : CollisionFilter.Default; for (int i = 0; i < mesh.Sections.Length; ++i) { for (var j = 0; j < mesh.Sections[i].Filters.Length; ++j) { var f = mesh.Sections[i].Filters[j]; meshCollider->m_Header.Filter = CollisionFilter.CreateUnion(meshCollider->m_Header.Filter, f); } } meshCollider->m_Aabb = meshCollider->Mesh.BoundingVolumeHierarchy.Domain; meshCollider->NumColliderKeyBits = meshCollider->Mesh.NumColliderKeyBits; }
public virtual IEnumerator LoadScenes([ValueSource(nameof(GetScenes))] string scenePath) { // Log scene name in case Unity crashes and test results aren't written out. Debug.Log("Loading " + scenePath); LogAssert.Expect(LogType.Log, "Loading " + scenePath); // Wait for next frame yield return(null); // Number of steps to simulate const int k_StopAfterStep = 100; // Number of worlds to simulate const int k_NumWorlds = 4; // Number of threads in each of the runs (3rd run is single threaded simulation) NativeArray <int> numThreadsPerRun = new NativeArray <int>(k_NumWorlds, Allocator.Persistent); numThreadsPerRun[0] = 8; numThreadsPerRun[1] = 4; numThreadsPerRun[2] = 0; numThreadsPerRun[3] = -1; // Load the scene and wait 2 frames SceneManager.LoadScene(scenePath); yield return(null); yield return(null); var sampler = DefaultWorld.GetOrCreateSystem <BuildPhysicsWorldSampler>(); sampler.BeginSampling(); while (!sampler.FinishedSampling) { yield return(new WaitForSeconds(0.05f)); } var buildPhysicsWorld = DefaultWorld.GetOrCreateSystem <BuildPhysicsWorld>(); var stepComponent = PhysicsStep.Default; if (buildPhysicsWorld.HasSingleton <PhysicsStep>()) { stepComponent = buildPhysicsWorld.GetSingleton <PhysicsStep>(); } // Extract original world and make copies List <PhysicsWorld> physicsWorlds = new List <PhysicsWorld>(k_NumWorlds); physicsWorlds.Add(sampler.PhysicsWorld.Clone()); physicsWorlds.Add(physicsWorlds[0].Clone()); physicsWorlds.Add(physicsWorlds[1].Clone()); physicsWorlds.Add(physicsWorlds[2].Clone()); NativeArray <int> buildStaticTree = new NativeArray <int>(1, Allocator.Persistent); buildStaticTree[0] = 1; // Simulation step input var stepInput = new SimulationStepInput() { Gravity = stepComponent.Gravity, NumSolverIterations = stepComponent.SolverIterationCount, SolverStabilizationHeuristicSettings = stepComponent.SolverStabilizationHeuristicSettings, SynchronizeCollisionWorld = true, TimeStep = DefaultWorld.Time.DeltaTime }; // Step the simulation on all worlds for (int i = 0; i < physicsWorlds.Count; i++) { int threadCountHint = numThreadsPerRun[i]; if (threadCountHint == -1) { stepInput.World = physicsWorlds[i]; stepInput.World.CollisionWorld.BuildBroadphase( ref stepInput.World, stepInput.TimeStep, stepInput.Gravity, true); #if HAVOK_PHYSICS_EXISTS if (SimulateHavok) { var simulationContext = new Havok.Physics.SimulationContext(Havok.Physics.HavokConfiguration.Default); for (int step = 0; step < k_StopAfterStep; step++) { simulationContext.Reset(ref stepInput.World); new StepHavokJob { Input = stepInput, SimulationContext = simulationContext }.Schedule().Complete(); } simulationContext.Dispose(); } else #endif { var simulationContext = new SimulationContext(); for (int step = 0; step < k_StopAfterStep; step++) { simulationContext.Reset(stepInput); new StepJob { Input = stepInput, SimulationContext = simulationContext }.Schedule().Complete(); } simulationContext.Dispose(); } } else { #if HAVOK_PHYSICS_EXISTS if (SimulateHavok) { var simulation = new Havok.Physics.HavokSimulation(Havok.Physics.HavokConfiguration.Default); stepInput.World = physicsWorlds[i]; stepInput.World.CollisionWorld.ScheduleBuildBroadphaseJobs( ref stepInput.World, stepInput.TimeStep, stepInput.Gravity, buildStaticTree, default, threadCountHint).Complete();
public void SendCommands(NativeArray <ArchetypeChunk> chunkArray, ComponentSystemBase system, CommandSystem commandSystem) { }
public static void Initialize() { _heap = new NativeArray<Task>(); _count = 0; }
public ManualResetEvent() { _waitingList = new NativeArray<TaskHandle>(); _set = false; }
protected override void OnUpdate() { if (HasSingleton <GameState>() == false) { return; } if (HasSingleton <BoardState>() == false) { return; } var G_State = GetSingleton <GameState>(); var B_State = GetSingleton <BoardState>(); if (G_State.IsActive == false) { return; } if (G_State.GameEnd == true) { return; } if (!(GridEntity.CalculateLength() > 0)) { return; } NativeArray <Entity> GridDatas = new NativeArray <Entity>(0, Allocator.Temp); GetGirdArray(ref GridDatas); if (B_State.InitBoard == false) { CheckCanPut_AllGrid(ref G_State, ref GridDatas); B_State.InitBoard = true; RefreshBoardColor(); PawnCounter(); SetSingleton <BoardState>(B_State); } Entities.With(GridEntity).ForEach((Entity EntityData, ref GridComp GridData) => { if (GridData.PutFlag == true) { SetGridData(GridData.GridNum, G_State.NowTurn, ref GridDatas); Reverse(GridData.GridNum, G_State.NowTurn, ref GridDatas); G_State.NowTurn = G_State.NowTurn == 1 ? 2 : 1; if (!CheckCanPut_AllGrid(ref G_State, ref GridDatas)) { G_State.NowTurn = G_State.NowTurn == 1 ? 2 : 1; CheckCanPut_AllGrid(ref G_State, ref GridDatas); } //処理終了後にフラグをFalseに変更します GridData.PutFlag = false; SetSingleton <GameState>(G_State); RefreshBoardColor(); PawnCounter(); } }); GridDatas.Dispose(); }
/// <summary>Create an array with a set of initial elements.</summary> /// <remarks>Create an array with a set of initial elements.</remarks> /// <param name="scope">the scope to create the object in.</param> /// <param name="elements"> /// the initial elements. Each object in this array /// must be an acceptable JavaScript type and type /// of array should be exactly Object[], not /// SomeObjectSubclass[]. /// </param> /// <returns>the new array object.</returns> public virtual Scriptable NewArray(Scriptable scope, object[] elements) { if (elements.GetType().GetElementType() != ScriptRuntime.ObjectClass) { throw new ArgumentException(); } NativeArray result = new NativeArray(elements); ScriptRuntime.SetBuiltinProtoAndParent(result, scope, TopLevel.Builtins.Array); return result; }
public virtual void Init(Context cx) { // Define some global functions particular to the shell. Note // that these functions are not part of ECMA. InitStandardObjects(cx, sealedStdLib); string[] names = new string[] { "defineClass", "deserialize", "doctest", "gc", "help", "load", "loadClass", "print", "quit", "readFile", "readUrl", "runCommand", "seal", "serialize", "spawn", "sync", "toint32", "version" }; DefineFunctionProperties(names, typeof(Rhino.Tools.Shell.Global), ScriptableObject.DONTENUM); // Set up "environment" in the global scope to provide access to the // System environment variables. Environment.DefineClass(this); Environment environment = new Environment(this); DefineProperty("environment", environment, ScriptableObject.DONTENUM); history = (NativeArray)cx.NewArray(this, 0); DefineProperty("history", history, ScriptableObject.DONTENUM); initialized = true; }
/// <summary>Create an array with a specified initial length.</summary> /// <remarks> /// Create an array with a specified initial length. /// <p> /// </remarks> /// <param name="scope">the scope to create the object in</param> /// <param name="length"> /// the initial length (JavaScript arrays may have /// additional properties added dynamically). /// </param> /// <returns>the new array object</returns> public virtual Scriptable NewArray(Scriptable scope, int length) { NativeArray result = new NativeArray(length); ScriptRuntime.SetBuiltinProtoAndParent(result, scope, TopLevel.Builtins.Array); return result; }
public MonitorLock() { _owner = null; _waitingOwners = new NativeArray<TaskHandle>(); _count = 0; }
internal static string NativeConcat(string[] objs) { NativeArray<string> sb = new NativeArray<string>(); for (int i = 0; i < objs.Length; i++) { sb.Push(objs[i]); } return sb.Join(""); }
public override void InitSystem() { m_entityCommandBuffer = World.GetOrCreateSystem <EndSimulationEntityCommandBufferSystem>(); m_boxBounds = new NativeArray <float3>(2, Allocator.Persistent); }
public Condition(Lock l) { _lock = l; _waitingList = new NativeArray<TaskHandle>(); }
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); } } } } }
public static void WriteArray <T>(this BinaryWriter writer, NativeArray <T> data) where T : struct { writer.WriteBytes(data.GetUnsafeReadOnlyPtr(), data.Length * UnsafeUtility.SizeOf <T>()); }
public static void CreateEntityAndAppend(this EntityManager manager, EntityArchetype archetype, NativeArray <Entity> entities) { for (int i = 0; i < entities.Length; i++) { entities[i] = manager.CreateEntityAndAppend(archetype); } }
public static void ReadArray <T>(this BinaryReader reader, NativeArray <T> elements, int count) where T : struct { reader.ReadBytes((byte *)elements.GetUnsafePtr(), count * UnsafeUtility.SizeOf <T>()); }
private static string Ja(NativeArray value, NativeJSON.StringifyState state) { if (state.stack.Search(value) != -1) { throw ScriptRuntime.TypeError0("msg.cyclic.value"); } state.stack.Push(value); string stepback = state.indent; state.indent = state.indent + state.gap; IList<object> partial = new List<object>(); long len = value.GetLength(); for (long index = 0; index < len; index++) { object strP; if (index > int.MaxValue) { strP = Str(System.Convert.ToString(index), value, state); } else { strP = Str((int)index, value, state); } if (strP == Undefined.instance) { partial.Add("null"); } else { partial.Add(strP); } } string finalValue; if (partial.IsEmpty()) { finalValue = "[]"; } else { if (state.gap.Length == 0) { finalValue = '[' + Join(partial, ",") + ']'; } else { string separator = ",\n" + state.indent; string properties = Join(partial, separator); finalValue = "[\n" + state.indent + properties + '\n' + stepback + ']'; } } state.stack.Pop(); state.indent = stepback; return finalValue; }
public static void Cleanup() { _count = 0; _heap = null; }
private static unsafe void CalculateAndStoreDeferredImpulses( CharacterControllerStepInput stepInput, float characterMass, float3 linearVelocity, int numConstraints, ref NativeArray <SurfaceConstraintInfo> constraints, ref BlockStream.Writer deferredImpulseWriter) { PhysicsWorld world = stepInput.World; for (int i = 0; i < numConstraints; i++) { SurfaceConstraintInfo constraint = constraints[i]; int rigidBodyIndex = constraint.RigidBodyIndex; if (rigidBodyIndex < 0 || rigidBodyIndex >= world.NumDynamicBodies) { // Invalid and static bodies should be skipped continue; } RigidBody body = world.Bodies[rigidBodyIndex]; float3 pointRelVel = world.GetLinearVelocity(rigidBodyIndex, constraint.HitPosition); pointRelVel -= linearVelocity; float projectedVelocity = math.dot(pointRelVel, constraint.Plane.Normal); // Required velocity change float deltaVelocity = -projectedVelocity * stepInput.Damping; float distance = constraint.Plane.Distance; if (distance < 0.0f) { deltaVelocity += (distance / stepInput.DeltaTime) * stepInput.Tau; } // Calculate impulse MotionVelocity mv = world.MotionVelocities[rigidBodyIndex]; float3 impulse = float3.zero; if (deltaVelocity < 0.0f) { // Impulse magnitude float impulseMagnitude = 0.0f; { float objectMassInv = GetInvMassAtPoint(constraint.HitPosition, constraint.Plane.Normal, body, mv); impulseMagnitude = deltaVelocity / objectMassInv; } impulse = impulseMagnitude * constraint.Plane.Normal; } // Add gravity { // Effect of gravity on character velocity in the normal direction float3 charVelDown = stepInput.Gravity * stepInput.DeltaTime; float relVelN = math.dot(charVelDown, constraint.Plane.Normal); // Subtract separation velocity if separating contact { bool isSeparatingContact = projectedVelocity < 0.0f; float newRelVelN = relVelN - projectedVelocity; relVelN = math.select(relVelN, newRelVelN, isSeparatingContact); } // If resulting velocity is negative, an impulse is applied to stop the character // from falling into the body { float3 newImpulse = impulse; newImpulse += relVelN * characterMass * constraint.Plane.Normal; impulse = math.select(impulse, newImpulse, relVelN < 0.0f); } } // Store impulse deferredImpulseWriter.Write( new DeferredCharacterControllerImpulse() { Entity = body.Entity, Impulse = impulse, Point = constraint.HitPosition }); } }
// TODO: This code is an infinite loop when compiled by XaeiO.Compiler2!!!! /* private static string SerializeArray(NativeArray<object> array) { StringBuilder buffer = new StringBuilder(); buffer.Append("["); if (array.Length > 0) { for (int i = 0; i < array.Length - 1; i++) { buffer.Append(Serialize(array[i])); buffer.Append(","); } buffer.Append(Serialize(array[array.Length - 1])); } buffer.Append("]"); return buffer.ToString(); } */ private static string SerializeArray(NativeArray<object> array) { StringBuilder buffer = new StringBuilder(); buffer.Append("["); for (int i = 0; i < array.Length; i++) { buffer.Append(Serialize(array[i])); if (i < array.Length - 1) { buffer.Append(","); } } buffer.Append("]"); return buffer.ToString(); }
public static void ReadBytes(this BinaryReader writer, NativeArray <byte> elements, int count, int offset = 0) { byte *destination = (byte *)elements.GetUnsafePtr() + offset; writer.ReadBytes(destination, count); }
public static void MoveChunks( NativeArray <ArchetypeChunk> chunks, NativeArray <EntityRemapUtility.EntityRemapInfo> entityRemapping, EntityComponentStore *srcEntityComponentStore, ManagedComponentStore srcManagedComponentStore, EntityGroupManager srcEntityGroupManager, EntityComponentStore *dstEntityComponentStore, ManagedComponentStore dstManagedComponentStore, EntityGroupManager dstEntityGroupManager) { new MoveChunksJob { srcEntityComponentStore = srcEntityComponentStore, dstEntityComponentStore = dstEntityComponentStore, entityRemapping = entityRemapping, chunks = chunks }.Run(); int chunkCount = chunks.Length; var remapChunks = new NativeArray <RemapChunk>(chunkCount, Allocator.TempJob); for (int i = 0; i < chunkCount; ++i) { var chunk = chunks[i].m_Chunk; var archetype = chunk->Archetype; //TODO: this should not be done more than once for each archetype var dstArchetype = EntityManagerCreateArchetypeUtility.GetOrCreateArchetype(archetype->Types, archetype->TypesCount, dstEntityComponentStore, dstEntityGroupManager); remapChunks[i] = new RemapChunk { chunk = chunk, dstArchetype = dstArchetype }; chunk->SequenceNumber = dstEntityComponentStore->AssignSequenceNumber(chunk); if (archetype->MetaChunkArchetype != null) { Entity srcEntity = chunk->metaChunkEntity; Entity dstEntity; EntityManagerCreateDestroyEntitiesUtility.CreateEntities(dstArchetype->MetaChunkArchetype, &dstEntity, 1, dstEntityComponentStore, dstManagedComponentStore, dstEntityGroupManager); srcEntityComponentStore->GetChunk(srcEntity, out var srcChunk, out var srcIndex); dstEntityComponentStore->GetChunk(dstEntity, out var dstChunk, out var dstIndex); ChunkDataUtility.SwapComponents(srcChunk, srcIndex, dstChunk, dstIndex, 1, srcEntityComponentStore->GlobalSystemVersion, dstEntityComponentStore->GlobalSystemVersion); EntityRemapUtility.AddEntityRemapping(ref entityRemapping, srcEntity, dstEntity); EntityManagerCreateDestroyEntitiesUtility.DestroyEntities(&srcEntity, 1, srcEntityComponentStore, srcManagedComponentStore, srcEntityGroupManager); } } k_ProfileMoveSharedComponents.Begin(); var remapShared = dstManagedComponentStore.MoveSharedComponents(srcManagedComponentStore, chunks, entityRemapping, Allocator.TempJob); k_ProfileMoveSharedComponents.End(); var remapChunksJob = new RemapChunksJob { dstEntityComponentStore = dstEntityComponentStore, remapChunks = remapChunks, entityRemapping = entityRemapping }.Schedule(remapChunks.Length, 1); var moveChunksBetweenArchetypeJob = new MoveChunksBetweenArchetypeJob { remapChunks = remapChunks, remapShared = remapShared, globalSystemVersion = dstEntityComponentStore->GlobalSystemVersion }.Schedule(remapChunksJob); moveChunksBetweenArchetypeJob.Complete(); remapShared.Dispose(); remapChunks.Dispose(); }
bool ExtractEntityRemapRefs(EntityManager srcManager, out NativeArray <EntityRemapUtility.EntityRemapInfo> entityRemapping) { // External entity references are "virtual" entities. If we don't have any, only real entities need remapping int remapTableSize = srcManager.EntityCapacity; using (var externalRefEntities = GetExternalRefEntities(srcManager, Allocator.TempJob)) { // We can potentially have several external entity reference arrays, each one pointing to a different scene var externalEntityRefInfos = new NativeArray <ExternalEntityRefInfo>(externalRefEntities.Length, Allocator.Temp); for (int i = 0; i < externalRefEntities.Length; ++i) { // External references point to indices beyond the range used by the entities in this scene // The highest index used by all those references defines how big the remap table has to be externalEntityRefInfos[i] = srcManager.GetComponentData <ExternalEntityRefInfo>(externalRefEntities[i]); var extRefs = srcManager.GetBuffer <ExternalEntityRef>(externalRefEntities[i]); remapTableSize = math.max(remapTableSize, externalEntityRefInfos[i].EntityIndexStart + extRefs.Length); } // Within a scene, external scenes are identified by some ID // In the destination world, scenes are identified by an entity // Every entity coming from a scene needs to have a SceneTag that references the scene entity using (var sceneTags = ExternalRefToSceneTag(externalEntityRefInfos, Allocator.TempJob)) { entityRemapping = new NativeArray <EntityRemapUtility.EntityRemapInfo>(remapTableSize, Allocator.TempJob); for (int i = 0; i < externalRefEntities.Length; ++i) { var extRefs = srcManager.GetBuffer <ExternalEntityRef>(externalRefEntities[i]); var extRefInfo = srcManager.GetComponentData <ExternalEntityRefInfo>(externalRefEntities[i]); // A scene that external references point to is expected to have a single public reference array m_PublicRefFilter.SetFilter(sceneTags[i]); using (var pubRefEntities = m_PublicRefFilter.ToEntityArray(Allocator.TempJob)) { if (pubRefEntities.Length == 0) { // If the array is missing, the external scene isn't loaded, we have to wait. entityRemapping.Dispose(); return(false); } var pubRefs = EntityManager.GetBuffer <PublicEntityRef>(pubRefEntities[0]); // Proper mapping from external reference in section to entity in main world for (int k = 0; k < extRefs.Length; ++k) { var srcIdx = extRefInfo.EntityIndexStart + k; var target = pubRefs[extRefs[k].entityIndex].targetEntity; // External references always have a version number of 1 entityRemapping[srcIdx] = new EntityRemapUtility.EntityRemapInfo { SourceVersion = 1, Target = target }; } } m_PublicRefFilter.ResetFilter(); } } } return(true); }
public bool AddSamples(NativeArray <float> interleavedSamples) { return(AddSamples(0, interleavedSamples)); }
public override void CleanComponents(NativeArray <ArchetypeChunk> chunkArray, ComponentSystemBase system, EntityCommandBuffer buffer) { var entityType = system.GetArchetypeChunkEntityType(); var componentAddedType = system.GetArchetypeChunkComponentType <ComponentAdded <Improbable.Gdk.Tests.ComponentsWithNoFields.ComponentWithNoFieldsWithEvents.Component> >(); var componentRemovedType = system.GetArchetypeChunkComponentType <ComponentRemoved <Improbable.Gdk.Tests.ComponentsWithNoFields.ComponentWithNoFieldsWithEvents.Component> >(); var receivedUpdateType = system.GetArchetypeChunkComponentType <Improbable.Gdk.Tests.ComponentsWithNoFields.ComponentWithNoFieldsWithEvents.ReceivedUpdates>(); var authorityChangeType = system.GetArchetypeChunkComponentType <AuthorityChanges <Improbable.Gdk.Tests.ComponentsWithNoFields.ComponentWithNoFieldsWithEvents.Component> >(); var evtEventType = system.GetArchetypeChunkComponentType <ReceivedEvents.Evt>(); foreach (var chunk in chunkArray) { var entities = chunk.GetNativeArray(entityType); // Updates if (chunk.Has(receivedUpdateType)) { var updateArray = chunk.GetNativeArray(receivedUpdateType); for (int i = 0; i < entities.Length; ++i) { buffer.RemoveComponent <Improbable.Gdk.Tests.ComponentsWithNoFields.ComponentWithNoFieldsWithEvents.ReceivedUpdates>(entities[i]); var updateList = updateArray[i].Updates; // Pool update lists to avoid excessive allocation updateList.Clear(); Improbable.Gdk.Tests.ComponentsWithNoFields.ComponentWithNoFieldsWithEvents.Update.Pool.Push(updateList); ReferenceTypeProviders.UpdatesProvider.Free(updateArray[i].handle); } } // Component Added if (chunk.Has(componentAddedType)) { for (int i = 0; i < entities.Length; ++i) { buffer.RemoveComponent <ComponentAdded <Improbable.Gdk.Tests.ComponentsWithNoFields.ComponentWithNoFieldsWithEvents.Component> >(entities[i]); } } // Component Removed if (chunk.Has(componentRemovedType)) { for (int i = 0; i < entities.Length; ++i) { buffer.RemoveComponent <ComponentRemoved <Improbable.Gdk.Tests.ComponentsWithNoFields.ComponentWithNoFieldsWithEvents.Component> >(entities[i]); } } // Authority if (chunk.Has(authorityChangeType)) { var authorityChangeArray = chunk.GetNativeArray(authorityChangeType); for (int i = 0; i < entities.Length; ++i) { buffer.RemoveComponent <AuthorityChanges <Improbable.Gdk.Tests.ComponentsWithNoFields.ComponentWithNoFieldsWithEvents.Component> >(entities[i]); AuthorityChangesProvider.Free(authorityChangeArray[i].Handle); } } // Evt Event if (chunk.Has(evtEventType)) { var evtEventArray = chunk.GetNativeArray(evtEventType); for (int i = 0; i < entities.Length; ++i) { buffer.RemoveComponent <ReceivedEvents.Evt>(entities[i]); ReferenceTypeProviders.EvtProvider.Free(evtEventArray[i].handle); } } } }
// Update is called once per frame protected override void OnUpdate() { // Make sure the world has finished building before querying it CreatePhysicsWorldSystem.FinalJobHandle.Complete(); PhysicsWorld world = CreatePhysicsWorldSystem.PhysicsWorld; Entities.ForEach((VehicleMechanics mechanics) => { if (mechanics.wheels.Count == 0) { return; } Entity ce = mechanics.chassisEntity; if (ce == Entity.Null) { return; } int ceIdx = world.GetRigidBodyIndex(ce); if (-1 == ceIdx || ceIdx >= world.NumDynamicBodies) { return; } //float ceMass = world.GetMass(ceIdx); float3 cePosition = EntityManager.GetComponentData <Translation>(ce).Value; quaternion ceRotation = EntityManager.GetComponentData <Rotation>(ce).Value; float3 ceCenterOfMass = world.GetCenterOfMass(ceIdx); float3 ceUp = math.mul(ceRotation, mechanics.chassisUp); float3 ceForward = math.mul(ceRotation, mechanics.chassisForward); float3 ceRight = math.mul(ceRotation, mechanics.chassisRight); var rayResults = new NativeArray <RaycastHit>(mechanics.wheels.Count, Allocator.TempJob); var rayVelocities = new NativeArray <float3>(mechanics.wheels.Count, Allocator.TempJob); // Collect the RayCast results var rayInputs = new NativeArray <RaycastInput>(mechanics.wheels.Count, Allocator.TempJob); CollisionFilter filter = world.GetCollisionFilter(ceIdx); for (int i = 0; i < mechanics.wheels.Count; i++) { GameObject weGO = mechanics.wheels[i]; float3 wheelCurrentPos = weGO.transform.position; float3 rayStart = weGO.transform.parent.position; float3 rayEnd = (-ceUp * (mechanics.suspensionLength + mechanics.wheelBase)) + rayStart; if (mechanics.drawDebugInformation) { Debug.DrawRay(rayStart, rayEnd - rayStart); } rayInputs[i] = new RaycastInput { Start = rayStart, End = rayEnd, Filter = filter }; } JobHandle rayJobHandle = ScheduleBatchRayCast(world.CollisionWorld, rayInputs, rayResults); rayJobHandle.Complete(); for (int i = 0; i < mechanics.wheels.Count; i++) { RaycastHit rayResult = rayResults[i]; rayVelocities[i] = float3.zero; if (rayResult.RigidBodyIndex != -1) { float3 wheelPos = rayResult.Position; wheelPos -= (cePosition - ceCenterOfMass); float3 velocityAtWheel = world.GetLinearVelocity(ceIdx, wheelPos); rayVelocities[i] = velocityAtWheel; } } rayInputs.Dispose(); // Calculate a simple slip factor based on chassis tilt. float slopeSlipFactor = math.pow(math.abs(math.dot(ceUp, math.up())), 4.0f); // Proportional apply velocity changes to each wheel float invWheelCount = 1.0f / mechanics.wheels.Count; for (int i = 0; i < mechanics.wheels.Count; i++) { GameObject weGO = mechanics.wheels[i]; float3 rayStart = weGO.transform.parent.position; float3 rayEnd = (-ceUp * (mechanics.suspensionLength + mechanics.wheelBase)) + rayStart; float3 rayDir = rayEnd - rayStart; RaycastHit rayResult = rayResults[i]; //float3 velocityAtWheel = rayVelocities[i]; float3 wheelPos = rayResult.Position; wheelPos -= (cePosition - ceCenterOfMass); float3 velocityAtWheel = world.GetLinearVelocity(ceIdx, wheelPos); float3 weUp = ceUp; float3 weRight = ceRight; float3 weForward = ceForward; #region handle wheel steering { bool bIsSteeringWheel = mechanics.steeringWheels.Contains(weGO); if (bIsSteeringWheel) { float steeringAngle = math.radians(mechanics.steeringAngle); //if((mechanics.steeringWheels.IndexOf(weGO)+1) > (0.5f * mechanics.steeringWheels.Count)) // steeringAngle = -steeringAngle; quaternion wRotation = quaternion.AxisAngle(ceUp, steeringAngle); weRight = math.rotate(wRotation, weRight); weForward = math.rotate(wRotation, weForward); weGO.transform.localRotation = quaternion.AxisAngle(mechanics.chassisUp, steeringAngle); } } #endregion float currentSpeedUp = math.dot(velocityAtWheel, weUp); float currentSpeedForward = math.dot(velocityAtWheel, weForward); float currentSpeedRight = math.dot(velocityAtWheel, weRight); #region handle wheel rotation { var rGO = weGO.transform.GetChild(0); if (rGO) { bool isDriven = (mechanics.driveEngaged && mechanics.driveWheels.Contains(weGO)); float weRotation = isDriven ? (mechanics.driveDesiredSpeed / mechanics.wheelBase) : (currentSpeedForward / mechanics.wheelBase); weRotation = math.radians(weRotation); rGO.transform.localRotation *= quaternion.AxisAngle(mechanics.chassisRight, weRotation); } } #endregion float3 wheelCurrentPos = weGO.transform.position; bool hit = !math.all(rayResult.SurfaceNormal == float3.zero); if (!hit) { float3 wheelDesiredPos = (-ceUp * mechanics.suspensionLength) + rayStart; weGO.transform.position = math.lerp(wheelCurrentPos, wheelDesiredPos, mechanics.suspensionDamping / mechanics.suspensionStrength); } else { // remove the wheelbase to get wheel position. float fraction = rayResult.Fraction - (mechanics.wheelBase) / (mechanics.suspensionLength + mechanics.wheelBase); float3 wheelDesiredPos = math.lerp(rayStart, rayEnd, fraction); weGO.transform.position = math.lerp(wheelCurrentPos, wheelDesiredPos, mechanics.suspensionDamping / mechanics.suspensionStrength); #region Suspension { // Calculate and apply the impulses var posA = rayEnd; var posB = rayResult.Position; var lvA = currentSpeedUp * weUp;// world.GetLinearVelocity(ceIdx, posA); var lvB = world.GetLinearVelocity(rayResult.RigidBodyIndex, posB); var impulse = mechanics.suspensionStrength * (posB - posA) + mechanics.suspensionDamping * (lvB - lvA); impulse = impulse * invWheelCount; float impulseUp = math.dot(impulse, weUp); // Suspension shouldn't necessarily pull the vehicle down! float downForceLimit = -0.25f; if (downForceLimit < impulseUp) { impulse = impulseUp * weUp; world.ApplyImpulse(ceIdx, impulse, posA); //world.ApplyImpulse(rayResult.RigidBodyIndex, -impulse, posB); if (mechanics.drawDebugInformation) { Debug.DrawRay(wheelDesiredPos, impulse, Color.green); } } } #endregion #region Sideways friction { float deltaSpeedRight = (0.0f - currentSpeedRight); deltaSpeedRight = math.clamp(deltaSpeedRight, -mechanics.wheelMaxImpulseRight, mechanics.wheelMaxImpulseRight); deltaSpeedRight *= mechanics.wheelFrictionRight; deltaSpeedRight *= slopeSlipFactor; float3 impulse = deltaSpeedRight * weRight; float effectiveMass = world.GetEffectiveMass(ceIdx, impulse, wheelPos); impulse = impulse * effectiveMass * invWheelCount; world.ApplyImpulse(ceIdx, impulse, wheelPos); world.ApplyImpulse(rayResult.RigidBodyIndex, -impulse, wheelPos); if (mechanics.drawDebugInformation) { Debug.DrawRay(wheelDesiredPos, impulse, Color.red); } } #endregion #region Drive { if (mechanics.driveEngaged && mechanics.driveWheels.Contains(weGO)) { float deltaSpeedForward = (mechanics.driveDesiredSpeed - currentSpeedForward); deltaSpeedForward = math.clamp(deltaSpeedForward, -mechanics.wheelMaxImpulseForward, mechanics.wheelMaxImpulseForward); deltaSpeedForward *= mechanics.wheelFrictionForward; deltaSpeedForward *= slopeSlipFactor; float3 impulse = deltaSpeedForward * weForward; float effectiveMass = world.GetEffectiveMass(ceIdx, impulse, wheelPos); impulse = impulse * effectiveMass * invWheelCount; world.ApplyImpulse(ceIdx, impulse, wheelPos); world.ApplyImpulse(rayResult.RigidBodyIndex, -impulse, wheelPos); if (mechanics.drawDebugInformation) { Debug.DrawRay(wheelDesiredPos, impulse, Color.blue); } } } #endregion } } rayResults.Dispose(); rayVelocities.Dispose(); }); }
public static BlobAssetReference <Collider> Create(NativeArray <float3> vertices, NativeArray <int3> triangles, CollisionFilter filter) => Create(vertices, triangles, filter, Material.Default);
public static JobHandle ScheduleBatchRayCast(CollisionWorld world, NativeArray <RaycastInput> inputs, NativeArray <RaycastHit> results) { JobHandle rcj = new RaycastJob { inputs = inputs, results = results, world = world }.Schedule(inputs.Length, 5); return(rcj); }
internal void MoveChunksFrom( NativeArray <ArchetypeChunk> chunks, NativeArray <EntityRemapUtility.EntityRemapInfo> entityRemapping, EntityComponentStore *srcEntityComponentStore, ManagedComponentStore srcManagedComponentStore) { new MoveChunksJob { srcEntityComponentStore = srcEntityComponentStore, dstEntityComponentStore = EntityComponentStore, entityRemapping = entityRemapping, chunks = chunks }.Run(); var managedArrayChunks = new NativeList <IntPtr>(Allocator.Temp); int chunkCount = chunks.Length; var remapChunks = new NativeArray <RemapChunk>(chunkCount, Allocator.TempJob); for (int i = 0; i < chunkCount; ++i) { var chunk = chunks[i].m_Chunk; var archetype = chunk->Archetype; //TODO: this should not be done more than once for each archetype var dstArchetype = EntityComponentStore->GetOrCreateArchetype(archetype->Types, archetype->TypesCount); remapChunks[i] = new RemapChunk { chunk = chunk, dstArchetype = dstArchetype }; if (archetype->NumManagedArrays > 0) { managedArrayChunks.Add((IntPtr)chunk); } if (archetype->MetaChunkArchetype != null) { Entity srcEntity = chunk->metaChunkEntity; Entity dstEntity; EntityComponentStore->CreateEntities(dstArchetype->MetaChunkArchetype, &dstEntity, 1); var srcEntityInChunk = srcEntityComponentStore->GetEntityInChunk(srcEntity); var dstEntityInChunk = EntityComponentStore->GetEntityInChunk(dstEntity); ChunkDataUtility.SwapComponents(srcEntityInChunk.Chunk, srcEntityInChunk.IndexInChunk, dstEntityInChunk.Chunk, dstEntityInChunk.IndexInChunk, 1, srcEntityComponentStore->GlobalSystemVersion, EntityComponentStore->GlobalSystemVersion); EntityRemapUtility.AddEntityRemapping(ref entityRemapping, srcEntity, dstEntity); srcEntityComponentStore->DestroyEntities(&srcEntity, 1); } } var managedArrayDstIndices = new NativeArray <int>(managedArrayChunks.Length, Allocator.TempJob); var managedArraySrcIndices = new NativeArray <int>(managedArrayChunks.Length, Allocator.TempJob); EntityComponentStore->ReserveManagedObjectArrays(managedArrayDstIndices); var remapManaged = new RemapManagedArraysJob { chunks = managedArrayChunks, dstIndices = managedArrayDstIndices, srcIndices = managedArraySrcIndices, }.Schedule(managedArrayChunks.Length, 64); ManagedComponentStore.Playback(ref EntityComponentStore->ManagedChangesTracker); srcManagedComponentStore.Playback(ref srcEntityComponentStore->ManagedChangesTracker); k_ProfileMoveObjectComponents.Begin(); remapManaged.Complete(); m_ManagedComponentStore.MoveManagedObjectArrays(managedArraySrcIndices, managedArrayDstIndices, srcManagedComponentStore); k_ProfileMoveObjectComponents.End(); managedArrayDstIndices.Dispose(); managedArraySrcIndices.Dispose(); managedArrayChunks.Dispose(); k_ProfileMoveSharedComponents.Begin(); var remapShared = ManagedComponentStore.MoveSharedComponents(srcManagedComponentStore, chunks, Allocator.TempJob); k_ProfileMoveSharedComponents.End(); new ChunkPatchEntities { RemapChunks = remapChunks, EntityRemapping = entityRemapping, EntityComponentStore = EntityComponentStore }.Run(); var remapChunksJob = new RemapChunksJob { dstEntityComponentStore = EntityComponentStore, remapChunks = remapChunks, entityRemapping = entityRemapping }.Schedule(remapChunks.Length, 1); var moveChunksBetweenArchetypeJob = new MoveChunksBetweenArchetypeJob { remapChunks = remapChunks, remapShared = remapShared, globalSystemVersion = EntityComponentStore->GlobalSystemVersion }.Schedule(remapChunksJob); moveChunksBetweenArchetypeJob.Complete(); ManagedComponentStore.Playback(ref EntityComponentStore->ManagedChangesTracker); remapShared.Dispose(); remapChunks.Dispose(); }
private void Render(ScriptableRenderContext context, Camera camera) { BeginCameraRendering(camera); ScriptableCullingParameters parameters; if (!camera.TryGetCullingParameters(out parameters)) { return; } CullingResults cullingResults = context.Cull(ref parameters); context.SetupCameraProperties(camera); cameraBuffer.Clear(); cameraBuffer.ClearRenderTarget((camera.clearFlags & CameraClearFlags.Depth) != 0, (camera.clearFlags & CameraClearFlags.Color) != 0, camera.backgroundColor); context.ExecuteCommandBuffer(cameraBuffer); //init FilteringSettings filteringSettings = new FilteringSettings(RenderQueueRange.all); SortingSettings sortingSettings = new SortingSettings(); DrawingSettings drawingSettings = new DrawingSettings(m_ShaderTagId, sortingSettings); RenderShawder(context); // cullingResults.ComputeDirectionalShadowMatricesAndCullingPrimitives(); //drawSkybox context.DrawSkybox(camera); #region light var lightcount = Mathf.Min(cullingResults.visibleLights.Length, MAX_VISABLE_COUNT); LightColors = new Vector4[MAX_VISABLE_COUNT]; LightDirections = new Vector4[MAX_VISABLE_COUNT]; LightAttenuations = new Vector4[MAX_VISABLE_COUNT]; LightSpotDirections = new Vector4[MAX_VISABLE_COUNT]; for (int i = 0; i < cullingResults.visibleLights.Length; i++) { if (i == MAX_VISABLE_COUNT) { break; } LightSpotDirections[i] = Vector4.zero; LightDirections[i] = Vector4.zero; LightAttenuations[i] = Vector4.zero; LightColors[i] = Vector4.zero; var light = cullingResults.visibleLights[i]; LightSpotDirections[i] = Vector4.zero; LightAttenuations[i].w = 1f; if (light.lightType == LightType.Directional) { var v = light.localToWorldMatrix.GetColumn(2); v.x = -v.x; v.y = -v.y; v.z = -v.z; v.w = 0;// LightDirections[i] = v; } else { LightDirections[i] = cullingResults.visibleLights[i].localToWorldMatrix.GetColumn(3); LightDirections[i].w = 1; //衰减 (1-(dir^2/range^2)^2)^2 LightAttenuations[i].x = 1f / Mathf.Max(Mathf.Sqrt(light.range), 0.000001f); //spot fade (lightPos*lightDir)-cos(r_out)/cos(r_in)-cos(r_out) if (light.lightType == LightType.Spot) { var dir = light.localToWorldMatrix.GetColumn(2); dir.x = -dir.x; dir.y = -dir.y; dir.z = -dir.z; LightSpotDirections[i] = dir; var outerRad = Mathf.Deg2Rad * 0.5f * light.spotAngle; var outerCos = Mathf.Cos(outerRad); //tan(r_in) = 46/64*tan(r_out) var outerTan = Mathf.Tan(outerRad); var innerCos = Mathf.Cos(Mathf.Atan(23 / 32 * outerTan)); LightAttenuations[i].z = 1 / Mathf.Max(innerCos - outerCos, 0.0001f); LightAttenuations[i].w = -outerCos * LightAttenuations[i].z; } } LightColors[i] = light.finalColor; } if (cullingResults.visibleLights.Length > MAX_VISABLE_COUNT) { NativeArray <int> lightMap = cullingResults.GetLightIndexMap(Allocator.Invalid); for (int i = MAX_VISABLE_COUNT; i < cullingResults.visibleLights.Length; i++) { lightMap[i] = -1; } cullingResults.SetLightIndexMap(lightMap); lightMap.Dispose(); } cameraBuffer.Clear(); cameraBuffer.SetGlobalVectorArray(_LightDirectionsID, LightDirections); cameraBuffer.SetGlobalVectorArray(_LightColorId, LightColors); cameraBuffer.SetGlobalVectorArray(_LightAttenuationID, LightAttenuations); cameraBuffer.SetGlobalVectorArray(_LightSpotDirectionID, LightSpotDirections); context.ExecuteCommandBuffer(cameraBuffer); #endregion //qaueue filteringSettings.renderQueueRange = RenderQueueRange.opaque; sortingSettings.criteria = SortingCriteria.CommonOpaque; context.DrawRenderers(cullingResults, ref drawingSettings, ref filteringSettings); context.Submit(); if (shadowMap) { RenderTexture.ReleaseTemporary(shadowMap); shadowMap = null; } }
/// <summary> /// Sample a bunch of points along a parabolic curve until you hit gnd. At that point, cut off the parabola /// </summary> /// /// <param name="p0">starting point of parabola</param> /// <param name="v0">initial parabola velocity</param> /// <param name="a">initial acceleration</param> /// <param name="dist">distance between sample points</param> /// <param name="points">number of sample points</param> /// <param name="tnm">Vive Nav Mesh used to teleport</param> /// <param name="outPts">List that will be populated by new points</param> /// <param name="normal">normal of hit point</param> /// /// <returns>true if the the parabole is at the end of the NavMesh</returns> private static bool CalculateParabolicCurve(float3 p0, Vector3 v0, Vector3 a, float dist, int points, TeleportNavMesh tnm, int excludedLayer, out NativeArray <Translation> outPts, out float3 normal, out int lastPointIndex) { // Init new list of points with p0 as the first point outPts = new NativeArray <Translation>(points, Allocator.TempJob); outPts[0] = new Translation { Value = p0 }; float3 last = p0; float t = 0; for (int i = 0; i < points; i++) { t += dist / ParabolicCurveDeriv(v0, a, t).magnitude; float3 next = ParabolicCurve(p0, v0, a, t); if (TeleportNavMeshHelper.Linecast(last, next, out bool endOnNavmesh, excludedLayer, out float3 castHit, out float3 norm, tnm)) { outPts[i] = new Translation { Value = castHit }; normal = norm; lastPointIndex = i; return(endOnNavmesh); }
public Queue() { _internalArray = new NativeArray<object>(); }
public override void UpdateSystem() { bool leftClickPressed = m_inputManagementSystem.InputData.mouseInput.leftClickPressed; bool leftClickReleased = m_inputManagementSystem.InputData.mouseInput.leftClickReleased; bool leftClickDown = m_inputManagementSystem.InputData.mouseInput.leftClickDown; if (leftClickDown || leftClickReleased) { Dependency = JobHandle.CombineDependencies(Dependency, m_raycastSystem.RaycastSystemDependency); NativeArray <float3> boxBounds = m_boxBounds; NativeArray <float3> boxBoundsSorted = new NativeArray <float3>(2, Allocator.TempJob); NativeArray <RaycastResult> selectionRaycastResult = m_raycastSystem.SelectionRaycastResult; NativeArray <RaycastResult> raycastResult = m_raycastSystem.RaycastResult; //Calculate box bounds Dependency = Job.WithReadOnly(selectionRaycastResult).WithCode(() => { if (leftClickPressed) { boxBounds[0] = selectionRaycastResult[0].hitPosition; } if (leftClickDown) { boxBounds[1] = selectionRaycastResult[0].hitPosition; } boxBoundsSorted[0] = math.min(boxBounds[0], boxBounds[1]); boxBoundsSorted[1] = math.max(boxBounds[0], boxBounds[1]); }).Schedule(Dependency); EntityCommandBuffer.ParallelWriter ecbConcurrent = m_entityCommandBuffer.CreateCommandBuffer().AsParallelWriter(); //Remove previous selections if (leftClickReleased) { //Deselect things outside of the box Dependency = Entities .WithReadOnly(boxBoundsSorted) .WithAll <SelectedTag>() .ForEach((Entity entity, int entityInQueryIndex, in Translation translation) => { if (((translation.Value.x < boxBoundsSorted[0].x) || (translation.Value.x > boxBoundsSorted[1].x) && (translation.Value.z < boxBoundsSorted[0].z) || (translation.Value.z > boxBoundsSorted[1].z)) && (raycastResult[0].raycastTargetEntity != entity)) { ecbConcurrent.RemoveComponent <SelectedTag>(entityInQueryIndex, entity); } }).ScheduleParallel(Dependency); //Select units inside the box if they aren't already selected Dependency = Entities .WithReadOnly(boxBoundsSorted) .WithAll <UnitTag>() .WithNone <SelectedTag>() .WithReadOnly(raycastResult) .ForEach((Entity entity, int entityInQueryIndex, in Translation translation) => { if (((translation.Value.x > boxBoundsSorted[0].x) && (translation.Value.x < boxBoundsSorted[1].x) && (translation.Value.z > boxBoundsSorted[0].z) && (translation.Value.z < boxBoundsSorted[1].z)) || (raycastResult[0].raycastTargetEntity == entity)) { ecbConcurrent.AddComponent(entityInQueryIndex, entity, new SelectedTag { }); } }).ScheduleParallel(Dependency); m_entityCommandBuffer.AddJobHandleForProducer(Dependency); redrawSelectedUnits = true; } boxBoundsSorted.Dispose(Dependency); } }
public virtual void Clear() { _internalArray = new NativeArray<object>(); }
//駒が挟めているかチェックして、挟めていたら反転させる public bool CheckReverseState(int2 CheckPos, int2 CheckVector, int BaseState, int Count, ref NativeArray <Entity> Entities) { if (CheckPos.x < 0 && CheckPos.y < 0) { return(false); } if (!(CheckPos.x < BoardSize && CheckPos.y < BoardSize)) { return(false); } if (GetGridData(CheckPos + CheckVector, ref Entities) == BaseState) { if (Count > 0) { SetGridData(CheckPos, BaseState, ref Entities); return(true); } return(false); } int TargetGridState = GetGridData(CheckPos + CheckVector, ref Entities); if (TargetGridState == 0 || TargetGridState == -1 || TargetGridState == 3) { return(false); } if (CheckReverseState(CheckPos + CheckVector, CheckVector, BaseState, ++Count, ref Entities)) { SetGridData(CheckPos, BaseState, ref Entities); return(true); } return(false); }
public unsafe void Utilities_CanSetBitsInBuffer() { using (var array = new NativeArray <byte>(6, Allocator.Temp)) { var arrayPtr = (byte *)array.GetUnsafePtr(); // Set bit #0. MemoryHelpers.SetBitsInBuffer(arrayPtr, 0, 0, 1, true); Assert.That(arrayPtr[0], Is.EqualTo(1)); Assert.That(arrayPtr[1], Is.Zero); // Reset bit #0. MemoryHelpers.SetBitsInBuffer(arrayPtr, 0, 0, 1, false); Assert.That(arrayPtr[0], Is.Zero); Assert.That(arrayPtr[1], Is.Zero); // Set bit #4. MemoryHelpers.SetBitsInBuffer(arrayPtr, 0, 4, 1, true); Assert.That(arrayPtr[0], Is.EqualTo(1 << 4)); Assert.That(arrayPtr[1], Is.Zero); // Reset bit #4. MemoryHelpers.SetBitsInBuffer(arrayPtr, 0, 4, 1, false); Assert.That(arrayPtr[0], Is.Zero); Assert.That(arrayPtr[1], Is.Zero); // Set bits #1-#5. MemoryHelpers.SetBitsInBuffer(arrayPtr, 0, 1, 5, true); Assert.That(arrayPtr[0], Is.EqualTo(0x3E)); Assert.That(arrayPtr[1], Is.Zero); // Unset bits #1-#5. MemoryHelpers.SetBitsInBuffer(arrayPtr, 0, 1, 5, false); Assert.That(arrayPtr[0], Is.Zero); Assert.That(arrayPtr[1], Is.Zero); // Set bits #4-#10. MemoryHelpers.SetBitsInBuffer(arrayPtr, 0, 4, 7, true); Assert.That(arrayPtr[0], Is.EqualTo(0xF0)); Assert.That(arrayPtr[1], Is.EqualTo(0x07)); Assert.That(arrayPtr[2], Is.Zero); // Unset bits #4-#10. MemoryHelpers.SetBitsInBuffer(arrayPtr, 0, 4, 7, false); Assert.That(arrayPtr[0], Is.Zero); Assert.That(arrayPtr[1], Is.Zero); Assert.That(arrayPtr[2], Is.Zero); // Set bits #9-#28. MemoryHelpers.SetBitsInBuffer(arrayPtr, 0, 9, 20, true); Assert.That(arrayPtr[0], Is.Zero); Assert.That(arrayPtr[1], Is.EqualTo(0xFE)); Assert.That(arrayPtr[2], Is.EqualTo(0xFF)); Assert.That(arrayPtr[3], Is.EqualTo(0x1F)); Assert.That(arrayPtr[4], Is.Zero); // Unset bits #4-#10. MemoryHelpers.SetBitsInBuffer(arrayPtr, 0, 9, 20, false); Assert.That(arrayPtr[0], Is.Zero); Assert.That(arrayPtr[1], Is.Zero); Assert.That(arrayPtr[2], Is.Zero); Assert.That(arrayPtr[3], Is.Zero); Assert.That(arrayPtr[4], Is.Zero); } }
// internal TransformSceneHandle targetEffector; public void SetUp() { initialized = 0; int length = joints.Length; edges = new NativeArray <Edge>(length, Allocator.Persistent); positions = new NativeArray <float3>(length, Allocator.Persistent); velocities = new NativeArray <float3>(length, Allocator.Persistent); forces = new NativeArray <float3>(length, Allocator.Persistent); masses = new NativeArray <float>(length, Allocator.Persistent); flags = new NativeArray <int>(length, Allocator.Persistent); constraints = new NativeArray <Constraint>(2, Allocator.Persistent); sphereCollisions = new NativeArray <SphereCollision>(1, Allocator.Persistent); for (int i = 0; i < sphereCollisions.Length; i++) { sphereCollisions[i] = new SphereCollision() { enabled = 0, centerPosition = float3.zero, radious = 0.0f }; } for (int i = 0; i < flags.Length; i++) { flags[i] = 0; } flags[0] = 0x8000; constraints[0] = new Constraint() { pointIndex = 0, fixedPosition = rootOffset, fixedVelocity = float3.zero }; constraints[1] = new Constraint() { pointIndex = -1, fixedPosition = rootOffset, fixedVelocity = float3.zero }; vectorData = new NativeArray <float3>(3, Allocator.Persistent); gravity = new float3(0.0f, -9.8f, 0.0f); #if false stiffness = 500.0f; // // restLength = 1.0f; dampingCoefficient = 1.0f; dragCoefficient = 0.1f; restitutionCoefficient = 0.3f; #else stiffness = 1300.0f; // // restLength = 1.0f; dampingCoefficient = 7.0f; dragCoefficient = 2.1f; restitutionCoefficient = 0.3f; #endif UnitVector = new float3(baseAxis == BaseAxis.X ? 1.0f : 0.0f, baseAxis == BaseAxis.Y ? 1.0f : 0.0f, baseAxis == BaseAxis.Z ? 1.0f : 0.0f); MakeChain(length); baseAxis = AnimationJob.BaseAxis.Y; timeIntervalInSeconds = 1 / 30.0f; // Time.fixedDeltaTime; resolution = 0.5f; timeIntervalInSeconds *= resolution; elapsed = 0.0f; }
public static unsafe void CheckSupport(CharacterControllerStepInput stepInput, RigidTransform transform, float maxSlope, MaxHitsCollector <DistanceHit> distanceHitsCollector, ref NativeArray <SurfaceConstraintInfo> constraints, out int numConstraints, out CharacterSupportState characterState, out float3 surfaceNormal, out float3 surfaceVelocity) { surfaceNormal = float3.zero; surfaceVelocity = float3.zero; // If no hits, proclaim unsupported state if (distanceHitsCollector.NumHits == 0) { characterState = CharacterSupportState.Unsupported; numConstraints = 0; return; } // Downwards direction must be normalized float3 downwardsDirection = -stepInput.Up; Assert.IsTrue(Unity.Physics.Math.IsNormalized(downwardsDirection)); float maxSlopeCos = math.cos(maxSlope); // Iterate over distance hits and create constraints from them numConstraints = 0; for (int i = 0; i < distanceHitsCollector.NumHits; i++) { DistanceHit hit = distanceHitsCollector.AllHits[i]; CreateConstraint(stepInput.World, stepInput.Up, hit.RigidBodyIndex, hit.ColliderKey, hit.Position, hit.SurfaceNormal, hit.Distance, stepInput.SkinWidth, maxSlopeCos, ref constraints, ref numConstraints); } float3 initialVelocity; { float velAlongDownwardsDir = math.dot(stepInput.CurrentVelocity, downwardsDirection); bool velocityIsAlongDownwardsDirection = velAlongDownwardsDir > 0.0f; if (velocityIsAlongDownwardsDirection) { float3 downwardsVelocity = velAlongDownwardsDir * downwardsDirection; initialVelocity = math.select(downwardsVelocity, downwardsDirection, math.abs(velAlongDownwardsDir) > 1.0f) + stepInput.Gravity * stepInput.DeltaTime; } else { initialVelocity = downwardsDirection; } } // Solve downwards (don't use min delta time, try to solve full step) float3 outVelocity = initialVelocity; float3 outPosition = transform.pos; SimplexSolver.Solve(stepInput.World, stepInput.DeltaTime, stepInput.DeltaTime, stepInput.Up, numConstraints, ref constraints, ref outPosition, ref outVelocity, out float integratedTime, false); // Reset touched state of constraints and get info on surface { int numSupportingPlanes = 0; for (int j = 0; j < numConstraints; j++) { var constraint = constraints[j]; if (constraint.Touched) { numSupportingPlanes++; surfaceNormal += constraint.Plane.Normal; surfaceVelocity += constraint.Velocity; constraint.Touched = false; constraints[j] = constraint; } } if (numSupportingPlanes > 0) { float invNumSupportingPlanes = 1.0f / numSupportingPlanes; surfaceNormal *= invNumSupportingPlanes; surfaceVelocity *= invNumSupportingPlanes; surfaceNormal = math.normalize(surfaceNormal); } } // Check support state { if (math.lengthsq(initialVelocity - outVelocity) < k_SimplexSolverEpsilonSq) { // If velocity hasn't changed significantly, declare unsupported state characterState = CharacterSupportState.Unsupported; } else if (math.lengthsq(outVelocity) < k_SimplexSolverEpsilonSq) { // If velocity is very small, declare supported state characterState = CharacterSupportState.Supported; } else { // Check if sliding or supported outVelocity = math.normalize(outVelocity); float slopeAngleSin = math.max(0.0f, math.dot(outVelocity, downwardsDirection) - k_SimplexSolverEpsilon); float slopeAngleCosSq = 1 - slopeAngleSin * slopeAngleSin; if (slopeAngleCosSq < maxSlopeCos * maxSlopeCos) { characterState = CharacterSupportState.Sliding; } else { characterState = CharacterSupportState.Supported; } } } }
public virtual void Init() { array = new NativeArray(1); }
public static unsafe void CollideAndIntegrate( CharacterControllerStepInput stepInput, float characterMass, bool affectBodies, Collider *collider, MaxHitsCollector <DistanceHit> distanceHitsCollector, ref NativeArray <ColliderCastHit> castHits, ref NativeArray <SurfaceConstraintInfo> constraints, ref RigidTransform transform, ref float3 linearVelocity, ref BlockStream.Writer deferredImpulseWriter) { CollideAndIntegrate(stepInput, characterMass, affectBodies, collider, ref castHits, ref constraints, distanceHitsCollector.NumHits, ref transform, ref linearVelocity, ref deferredImpulseWriter); }
public StringBuilder() { _internalArray = new NativeArray<string>(); }
public static unsafe void CollideAndIntegrate( CharacterControllerStepInput stepInput, float characterMass, bool affectBodies, Collider *collider, ref NativeArray <ColliderCastHit> castHits, ref NativeArray <SurfaceConstraintInfo> constraints, int numConstraints, ref RigidTransform transform, ref float3 linearVelocity, ref BlockStream.Writer deferredImpulseWriter) { // Copy parameters float deltaTime = stepInput.DeltaTime; float3 gravity = stepInput.Gravity; float3 up = stepInput.Up; PhysicsWorld world = stepInput.World; float remainingTime = deltaTime; float3 lastDisplacement = linearVelocity * remainingTime; float3 newPosition = transform.pos; quaternion orientation = transform.rot; float3 newVelocity = linearVelocity; float maxSlopeCos = math.cos(stepInput.MaxSlope); const float timeEpsilon = 0.000001f; for (int i = 0; i < stepInput.MaxIterations && remainingTime > timeEpsilon; i++) { float3 gravityMovement = gravity * remainingTime * remainingTime * 0.5f; // Then do a collider cast (but not in first iteration) if (i > 0) { int numCastConstraints = 0; float3 displacement = lastDisplacement + gravityMovement; MaxHitsCollector <ColliderCastHit> collector = new MaxHitsCollector <ColliderCastHit>(stepInput.RigidBodyIndex, 1.0f, ref castHits); ColliderCastInput input = new ColliderCastInput() { Collider = collider, Orientation = orientation, Start = newPosition, End = newPosition + displacement * (1.0f + stepInput.ContactTolerance), }; world.CastCollider(input, ref collector); // Iterate over hits and create constraints from them for (int hitIndex = 0; hitIndex < collector.NumHits; hitIndex++) { ColliderCastHit hit = collector.AllHits[hitIndex]; CreateConstraint(stepInput.World, stepInput.Up, hit.RigidBodyIndex, hit.ColliderKey, hit.Position, hit.SurfaceNormal, hit.Fraction * math.length(lastDisplacement), stepInput.SkinWidth, maxSlopeCos, ref constraints, ref numCastConstraints); } numConstraints = numCastConstraints; } // Min delta time for solver to break float minDeltaTime = 0.0f; if (math.lengthsq(newVelocity) > k_SimplexSolverEpsilonSq) { // Min delta time to travel at least 1cm minDeltaTime = 0.01f / math.length(newVelocity); } // Solve float3 prevVelocity = newVelocity; float3 prevPosition = newPosition; SimplexSolver.Solve(world, remainingTime, minDeltaTime, up, numConstraints, ref constraints, ref newPosition, ref newVelocity, out float integratedTime); // Apply impulses to hit bodies if (affectBodies) { CalculateAndStoreDeferredImpulses(stepInput, characterMass, prevVelocity, numConstraints, ref constraints, ref deferredImpulseWriter); } float3 newDisplacement = newPosition - prevPosition; // Check if we can walk to the position simplex solver has suggested MaxHitsCollector <ColliderCastHit> newCollector = new MaxHitsCollector <ColliderCastHit>(stepInput.RigidBodyIndex, 1.0f, ref castHits); int newContactIndex = -1; // If simplex solver moved the character we need to re-cast to make sure it can move to new position if (math.lengthsq(newDisplacement) > k_SimplexSolverEpsilon) { float3 displacement = newDisplacement + gravityMovement; ColliderCastInput input = new ColliderCastInput() { Collider = collider, Orientation = orientation, Start = prevPosition, End = prevPosition + displacement * (1.0f + stepInput.ContactTolerance) }; world.CastCollider(input, ref newCollector); float minFraction = float.MaxValue; for (int hitIndex = 0; hitIndex < newCollector.NumHits; hitIndex++) { ColliderCastHit hit = newCollector.AllHits[hitIndex]; if (hit.Fraction < minFraction) { bool found = false; for (int constraintIndex = 0; constraintIndex < numConstraints; constraintIndex++) { SurfaceConstraintInfo constraint = constraints[constraintIndex]; if (constraint.RigidBodyIndex == hit.RigidBodyIndex && constraint.ColliderKey.Equals(hit.ColliderKey)) { found = true; break; } } if (!found) { minFraction = hit.Fraction; newContactIndex = hitIndex; } } } } // Move character along the newDisplacement direction until it reaches this new contact if (newContactIndex >= 0) { ColliderCastHit newContact = newCollector.AllHits[newContactIndex]; Assert.IsTrue(newContact.Fraction >= 0.0f && newContact.Fraction <= 1.0f); integratedTime *= newContact.Fraction; newPosition = prevPosition + newDisplacement * newContact.Fraction; } remainingTime -= integratedTime; // Remember last displacement for next iteration lastDisplacement = newVelocity * remainingTime; } // Write back position and velocity transform.pos = newPosition; linearVelocity = newVelocity; }
public Lock() { _owner = null; _waitingOwners = new NativeArray<TaskHandle>(); }
private static void AddMaxSlopeConstraint(float3 up, ref SurfaceConstraintInfo constraint, ref NativeArray <SurfaceConstraintInfo> constraints, ref int numConstraints) { float verticalComponent = math.dot(constraint.Plane.Normal, up); SurfaceConstraintInfo newConstraint = constraint; newConstraint.Plane.Normal = math.normalize(newConstraint.Plane.Normal - verticalComponent * up); float distance = newConstraint.Plane.Distance; // Calculate distance to the original plane along the new normal. // Clamp the new distance to 2x the old distance to avoid penetration recovery explosions. newConstraint.Plane.Distance = distance / math.max(math.dot(newConstraint.Plane.Normal, constraint.Plane.Normal), 0.5f); if (newConstraint.Plane.Distance < 0.0f) { // Disable penetration recovery for the original plane constraint.Plane.Distance = 0.0f; // Set the new constraint velocity float3 newVel = newConstraint.Velocity - newConstraint.Plane.Normal * newConstraint.Plane.Distance; newConstraint.Velocity = newVel; } // Prepare velocity to resolve penetration ResolveConstraintPenetration(ref newConstraint); // Add max slope constraint to the list constraints[numConstraints++] = newConstraint; }