protected override void OnUpdate() { Entities .WithName("ChangeSphereColliderRadius") .WithBurst() .ForEach((ref PhysicsCollider collider, ref ChangeSphereColliderRadius radius, ref Scale scale) => { // make sure we are dealing with spheres if (collider.Value.Value.Type != ColliderType.Sphere) { return; } // tweak the physical representation of the sphere // NOTE: this approach affects all instances using the same BlobAsset // so you cannot simply use this approach for instantiated prefabs // if you want to modify prefab instances independently, you need to create // unique BlobAssets at run-time and dispose them when you are done float oldRadius = 1.0f; float newRadius = 1.0f; unsafe { // grab the sphere pointer SphereCollider *scPtr = (SphereCollider *)collider.ColliderPtr; oldRadius = scPtr->Radius; newRadius = math.lerp(oldRadius, radius.Target, 0.05f); // if we have reached the target radius get a new target if (math.abs(newRadius - radius.Target) < 0.01f) { radius.Target = radius.Target == radius.Min ? radius.Max : radius.Min; } // update the collider geometry var sphereGeometry = scPtr->Geometry; sphereGeometry.Radius = newRadius; scPtr->Geometry = sphereGeometry; } // now tweak the graphical representation of the sphere float oldScale = scale.Value; float newScale = oldScale; if (oldRadius == 0.0f) { // avoid the divide by zero errors. newScale = newRadius; } else { newScale *= newRadius / oldRadius; } scale = new Scale { Value = newScale }; }).Schedule(); }
public static unsafe Result BoxSphere(BoxCollider *boxA, SphereCollider *sphereB, MTransform aFromB) { MTransform aFromBoxA = new MTransform(boxA->Orientation, boxA->Center); float3 posBinA = Mul(aFromB, sphereB->Center); float3 posBinBoxA = Mul(Inverse(aFromBoxA), posBinA); float3 innerHalfExtents = boxA->Size * 0.5f - boxA->ConvexRadius; float3 normalInBoxA; float distance; { // from hkAabb::signedDistanceToPoint(), can optimize a lot float3 projection = math.min(posBinBoxA, innerHalfExtents); projection = math.max(projection, -innerHalfExtents); float3 difference = projection - posBinBoxA; float distanceSquared = math.lengthsq(difference); // Check if the sphere center is inside the box if (distanceSquared < 1e-6f) { float3 projectionLocal = projection; float3 absProjectionLocal = math.abs(projectionLocal); float3 del = absProjectionLocal - innerHalfExtents; int axis = IndexOfMaxComponent(new float4(del, -float.MaxValue)); switch (axis) { case 0: normalInBoxA = new float3(projectionLocal.x < 0.0f ? 1.0f : -1.0f, 0.0f, 0.0f); break; case 1: normalInBoxA = new float3(0.0f, projectionLocal.y < 0.0f ? 1.0f : -1.0f, 0.0f); break; case 2: normalInBoxA = new float3(0.0f, 0.0f, projectionLocal.z < 0.0f ? 1.0f : -1.0f); break; default: normalInBoxA = new float3(1, 0, 0); Assert.IsTrue(false); break; } distance = math.max(del.x, math.max(del.y, del.z)); } else { float invDistance = math.rsqrt(distanceSquared); normalInBoxA = difference * invDistance; distance = distanceSquared * invDistance; } } float3 normalInA = math.mul(aFromBoxA.Rotation, normalInBoxA); return(new Result { NormalInA = normalInA, PositionOnAinA = posBinA + normalInA * (distance - boxA->ConvexRadius), Distance = distance - (sphereB->Radius + boxA->ConvexRadius) }); }
public static void AppendSphere(SphereCollider *sphere, RigidTransform worldFromCollider, ref List <DisplayResult> results) { float r = sphere->Radius; results.Add(new DisplayResult { Mesh = ReferenceSphere, Scale = new Vector4(r * 2.0f, r * 2.0f, r * 2.0f), Position = math.transform(worldFromCollider, sphere->Center), Orientation = worldFromCollider.rot, }); }
// Create a contact point for a pair of spheres in world space. public static unsafe void SphereSphere( SphereCollider *sphereA, SphereCollider *sphereB, MTransform worldFromA, MTransform aFromB, float maxDistance, out Manifold manifold) { DistanceQueries.Result convexDistance = DistanceQueries.SphereSphere(sphereA, sphereB, aFromB); if (convexDistance.Distance < maxDistance) { manifold = new Manifold(convexDistance, worldFromA); } else { manifold = new Manifold(); } }
// Create a single point manifold between a capsule and a sphere in world space. public static unsafe void CapsuleSphere( CapsuleCollider *capsuleA, SphereCollider *sphereB, MTransform worldFromA, MTransform aFromB, float maxDistance, out Manifold manifold) { DistanceQueries.Result convexDistance = DistanceQueries.CapsuleSphere( capsuleA->Vertex0, capsuleA->Vertex1, capsuleA->Radius, sphereB->Center, sphereB->Radius, aFromB); if (convexDistance.Distance < maxDistance) { manifold = new Manifold(convexDistance, worldFromA); } else { manifold = new Manifold(); } }
public unsafe void Execute(ref PhysicsCollider collider, ref ChangeSphereColliderRadius radius, ref Scale scale) { // make sure we are dealing with spheres if (collider.ColliderPtr->Type != ColliderType.Sphere) { return; } // // tweak the physical representation of the sphere // grab the sphere pointer SphereCollider *scPtr = (SphereCollider *)collider.ColliderPtr; float oldRadius = scPtr->Radius; float newRadius = math.lerp(oldRadius, radius.Target, 0.05f); // if we have reached the target radius get a new target if (math.abs(newRadius - radius.Target) < 0.01f) { radius.Target = radius.Target == radius.Min ? radius.Max : radius.Min; } // update the collider geometry var sphereGeometry = scPtr->Geometry; sphereGeometry.Radius = newRadius; scPtr->Geometry = sphereGeometry; // // now tweak the graphical representation of the sphere float oldScale = scale.Value; float newScale = oldScale; if (oldRadius == 0.0f) { // avoid the divide by zero errors. newScale = newRadius; } else { newScale *= newRadius / oldRadius; } scale = new Scale() { Value = newScale }; }
// Create a single point manifold between a triangle and sphere in world space. public static unsafe void TriangleSphere( PolygonCollider *triangleA, SphereCollider *sphereB, MTransform worldFromA, MTransform aFromB, float maxDistance, out Manifold manifold) { Assert.IsTrue(triangleA->Vertices.Length == 3); DistanceQueries.Result convexDistance = DistanceQueries.TriangleSphere( triangleA->Vertices[0], triangleA->Vertices[1], triangleA->Vertices[2], triangleA->Planes[0].Normal, sphereB->Center, sphereB->Radius, aFromB); if (convexDistance.Distance < maxDistance) { manifold = new Manifold(convexDistance, worldFromA); } else { manifold = new Manifold(); } }
// Create a contact point for a pair of spheres in world space. public static unsafe void SphereSphere( SphereCollider *sphereA, SphereCollider *sphereB, [NoAlias] in MTransform worldFromA, [NoAlias] in MTransform aFromB, float maxDistance,
// Dispatch any pair of convex colliders public static unsafe Result ConvexConvex(Collider *convexA, Collider *convexB, MTransform aFromB) { Result result; bool flip = false; switch (convexA->Type) { case ColliderType.Sphere: SphereCollider *sphereA = (SphereCollider *)convexA; switch (convexB->Type) { case ColliderType.Sphere: result = SphereSphere(sphereA, (SphereCollider *)convexB, aFromB); break; case ColliderType.Capsule: CapsuleCollider *capsuleB = (CapsuleCollider *)convexB; result = CapsuleSphere(capsuleB->Vertex0, capsuleB->Vertex1, capsuleB->Radius, sphereA->Center, sphereA->Radius, Inverse(aFromB)); flip = true; break; case ColliderType.Triangle: PolygonCollider *triangleB = (PolygonCollider *)convexB; result = TriangleSphere( triangleB->Vertices[0], triangleB->Vertices[1], triangleB->Vertices[2], triangleB->Planes[0].Normal, sphereA->Center, sphereA->Radius, Inverse(aFromB)); flip = true; break; case ColliderType.Quad: PolygonCollider *quadB = (PolygonCollider *)convexB; result = QuadSphere( quadB->Vertices[0], quadB->Vertices[1], quadB->Vertices[2], quadB->Vertices[3], quadB->Planes[0].Normal, sphereA->Center, sphereA->Radius, Inverse(aFromB)); flip = true; break; case ColliderType.Box: result = BoxSphere((BoxCollider *)convexB, sphereA, Inverse(aFromB)); flip = true; break; case ColliderType.Cylinder: case ColliderType.Convex: result = ConvexConvex(ref sphereA->ConvexHull, ref ((ConvexCollider *)convexB)->ConvexHull, aFromB); break; default: throw new NotImplementedException(); } break; case ColliderType.Capsule: CapsuleCollider *capsuleA = (CapsuleCollider *)convexA; switch (convexB->Type) { case ColliderType.Sphere: SphereCollider *sphereB = (SphereCollider *)convexB; result = CapsuleSphere(capsuleA->Vertex0, capsuleA->Vertex1, capsuleA->Radius, sphereB->Center, sphereB->Radius, aFromB); break; case ColliderType.Capsule: result = CapsuleCapsule(capsuleA, (CapsuleCollider *)convexB, aFromB); break; case ColliderType.Triangle: result = CapsuleTriangle(capsuleA, (PolygonCollider *)convexB, aFromB); break; case ColliderType.Box: case ColliderType.Quad: case ColliderType.Cylinder: case ColliderType.Convex: result = ConvexConvex(ref capsuleA->ConvexHull, ref ((ConvexCollider *)convexB)->ConvexHull, aFromB); break; default: throw new NotImplementedException(); } break; case ColliderType.Triangle: PolygonCollider *triangleA = (PolygonCollider *)convexA; switch (convexB->Type) { case ColliderType.Sphere: SphereCollider *sphereB = (SphereCollider *)convexB; result = TriangleSphere( triangleA->Vertices[0], triangleA->Vertices[1], triangleA->Vertices[2], triangleA->Planes[0].Normal, sphereB->Center, sphereB->Radius, aFromB); break; case ColliderType.Capsule: result = CapsuleTriangle((CapsuleCollider *)convexB, triangleA, Inverse(aFromB)); flip = true; break; case ColliderType.Box: case ColliderType.Triangle: case ColliderType.Quad: case ColliderType.Cylinder: case ColliderType.Convex: result = ConvexConvex(ref triangleA->ConvexHull, ref ((ConvexCollider *)convexB)->ConvexHull, aFromB); break; default: throw new NotImplementedException(); } break; case ColliderType.Box: BoxCollider *boxA = (BoxCollider *)convexA; switch (convexB->Type) { case ColliderType.Sphere: result = BoxSphere(boxA, (SphereCollider *)convexB, aFromB); break; case ColliderType.Capsule: case ColliderType.Box: case ColliderType.Triangle: case ColliderType.Quad: case ColliderType.Cylinder: case ColliderType.Convex: result = ConvexConvex(ref boxA->ConvexHull, ref ((ConvexCollider *)convexB)->ConvexHull, aFromB); break; default: throw new NotImplementedException(); } break; case ColliderType.Quad: case ColliderType.Cylinder: case ColliderType.Convex: result = ConvexConvex(ref ((ConvexCollider *)convexA)->ConvexHull, ref ((ConvexCollider *)convexB)->ConvexHull, aFromB); break; default: throw new NotImplementedException(); } if (flip) { result.PositionOnAinA = Mul(aFromB, result.PositionOnBinA); result.NormalInA = math.mul(aFromB.Rotation, -result.NormalInA); } return(result); }
public static unsafe Result SphereSphere(SphereCollider *sphereA, SphereCollider *sphereB, MTransform aFromB) { float3 posBinA = Mul(aFromB, sphereB->Center); return(PointPoint(sphereA->Center, posBinA, sphereA->Radius, sphereA->Radius + sphereB->Radius)); }