public void TestConvexColliderCalculateAabbLocal() { var points = new NativeArray <float3>(6, Allocator.Temp) { [0] = new float3(1.45f, 8.67f, 3.45f), [1] = new float3(8.75f, 1.23f, 6.44f), [2] = new float3(100.34f, 5.33f, -2.55f), [3] = new float3(8.76f, 4.56f, -4.54f), [4] = new float3(9.75f, -0.45f, -8.99f), [5] = new float3(7.66f, 3.44f, 0.0f) }; float convexRadius = 1.25f; Aabb expectedAabb = Aabb.CreateFromPoints(new float3x4(points[0], points[1], points[2], points[3])); expectedAabb.Include(points[4]); expectedAabb.Include(points[5]); // Currently the convex hull is not shrunk, so we have to expand by the convex radius expectedAabb.Expand(convexRadius); var collider = ConvexCollider.Create(points, convexRadius); points.Dispose(); Aabb actualAabb = collider.Value.CalculateAabb(); TestUtils.AreEqual(expectedAabb.Min, actualAabb.Min, 1e-3f); TestUtils.AreEqual(expectedAabb.Max, actualAabb.Max, 1e-3f); }
public void TestConvexColliderMassProperties() { var points = new NativeArray <float3>(8, Allocator.Temp) { [0] = new float3(-1.56f, 8.89f, -10.76f), [1] = new float3(-4.74f, 80.11f, 10.56f), [2] = new float3(-100.60f, -4.93f, -10.76f), [3] = new float3(1.44f, 3.56f, 73.4f), [4] = new float3(17.66f, 18.43f, 0.0f), [5] = new float3(-1.32f, 9.99f, 80.4f), [6] = new float3(-17.45f, 3.22f, -3.22f), [7] = new float3(0.0f, 0.0f, 0.03f) }; var collider = ConvexCollider.Create(points, convexRadius: 0.15f); points.Dispose(); float3 expectedInertiaTensor = new float3(434.014862f, 824.963989f, 684.776672f); float3 inertiaTensor = collider.Value.MassProperties.MassDistribution.InertiaTensor; // Given the number of FP operations, we do a percentage comparison in this case Assert.IsTrue(math.abs(expectedInertiaTensor.x - inertiaTensor.x) / expectedInertiaTensor.x < 0.01f); Assert.IsTrue(math.abs(expectedInertiaTensor.y - inertiaTensor.y) / expectedInertiaTensor.y < 0.01f); Assert.IsTrue(math.abs(expectedInertiaTensor.z - inertiaTensor.z) / expectedInertiaTensor.z < 0.01f); }
protected override BlobAssetReference <Collider> ProduceColliderBlob(LegacyMesh shape) { if (shape.sharedMesh == null) { throw new InvalidOperationException( $"No {nameof(LegacyMesh.sharedMesh)} assigned to {typeof(MeshCollider)} on {shape.name}." ); } var filter = ProduceCollisionFilter(shape); var material = ProduceMaterial(shape); using (var pointCloud = new NativeList <float3>(shape.sharedMesh.vertexCount, Allocator.Temp)) { // transform points into world space and back into shape space shape.sharedMesh.GetVertices(m_Vertices); var shapeFromWorld = math.inverse( new float4x4(new RigidTransform(shape.transform.rotation, shape.transform.position)) ); for (int i = 0, count = m_Vertices.Count; i < count; ++i) { var worldPt = math.mul(shape.transform.localToWorldMatrix, new float4(m_Vertices[i], 1f)); pointCloud.Add(math.mul(shapeFromWorld, worldPt).xyz); } return(shape.convex ? ConvexCollider.Create(pointCloud, PhysicsShape.k_DefaultConvexRadius, new float3(1f), filter, material) : MeshCollider.Create(pointCloud.ToArray(), shape.sharedMesh.triangles, filter, material)); } }
public void Execute(int index) { var inputParameters = InputParameters[index]; var points = new NativeArray <float3>( inputParameters.PointCount, Allocator.Temp, NativeArrayOptions.UninitializedMemory ); UnsafeUtility.MemCpy( points.GetUnsafePtr(), (float3 *)AllPoints.GetUnsafeReadOnlyPtr() + inputParameters.PointsStart, UnsafeUtility.SizeOf <float3>() * inputParameters.PointCount ); Output[index] = new KeyValuePair <Entity, LeafShapeData>( inputParameters.BodyEntity, new LeafShapeData { LeafEntity = inputParameters.LeafEntity, ColliderBlobInstance = new CompoundCollider.ColliderBlobInstance { CompoundFromChild = inputParameters.CompoundFromChild, Collider = ConvexCollider.Create( points, inputParameters.GenerationParameters, inputParameters.Filter, inputParameters.Material ) } } ); }
public unsafe void TestConvexColliderCalculateAabbLocal([Values(0, 0.01f, 1.25f)] float maxShrinkMovement) { var points = new NativeArray <float3>(6, Allocator.TempJob) { [0] = new float3(1.45f, 8.67f, 3.45f), [1] = new float3(8.75f, 1.23f, 6.44f), [2] = new float3(100.34f, 5.33f, -2.55f), [3] = new float3(8.76f, 4.56f, -4.54f), [4] = new float3(9.75f, -0.45f, -8.99f), [5] = new float3(7.66f, 3.44f, 0.0f) }; Aabb expectedAabb = Aabb.CreateFromPoints(new float3x4(points[0], points[1], points[2], points[3])); expectedAabb.Include(points[4]); expectedAabb.Include(points[5]); var collider = ConvexCollider.Create( points, new ConvexHullGenerationParameters { BevelRadius = maxShrinkMovement }, CollisionFilter.Default ); points.Dispose(); Aabb actualAabb = collider.Value.CalculateAabb(); float convexRadius = ((ConvexCollider *)collider.GetUnsafePtr())->ConvexHull.ConvexRadius; float maxError = 1e-3f + maxShrinkMovement - convexRadius; TestUtils.AreEqual(expectedAabb.Min, actualAabb.Min, maxError); TestUtils.AreEqual(expectedAabb.Max, actualAabb.Max, maxError); }
public void Execute() { var points = new NativeArray <float3>(1024, Allocator.Temp); var random = new Random(1234); for (var i = 0; i < points.Length; ++i) { points[i] = random.NextFloat3(new float3(-1f), new float3(1f)); } ConvexCollider.Create(points, ConvexHullGenerationParameters.Default).Release(); }
public void TestConvexColliderCreate() { var points = new NativeArray <float3>(k_TestPoints, Allocator.Temp); var collider = ConvexCollider.Create( points, new ConvexHullGenerationParameters { BevelRadius = 0.15f }, CollisionFilter.Default ); Assert.AreEqual(ColliderType.Convex, collider.Value.Type); Assert.AreEqual(CollisionType.Convex, collider.Value.CollisionType); }
public void Execute(int index) { var inputParameters = InputValues[index]; Output[index] = new KeyValuePair <Hash128, BlobAssetReference <Collider> >( InputKeys[index], ConvexCollider.Create( AllPoints.GetSubArray(inputParameters.PointsStart, inputParameters.PointCount), inputParameters.GenerationParameters, inputParameters.Filter, inputParameters.Material ) ); }
public void ConvexCollider_Create_WhenGenerationParametersBevelRadiusInvalid_Throws( [Values(float.PositiveInfinity, float.NegativeInfinity, float.NaN, -1f)] float errantValue ) { var points = new NativeArray <float3>(k_TestPoints, Allocator.Temp); var generationParameters = ConvexHullGenerationParameters.Default; generationParameters.BevelRadius = errantValue; var ex = Assert.Throws <ArgumentException>(() => ConvexCollider.Create(points, generationParameters)); Assert.That(ex.ParamName, Is.EqualTo("generationParameters")); }
public void ConvexCollider_Create_WhenPointsInvalid_Throws( [Values(float.PositiveInfinity, float.NegativeInfinity, float.NaN)] float errantValue ) { var points = new NativeArray <float3>(k_TestPoints, Allocator.Temp) { [2] = new float3(errantValue) }; var ex = Assert.Throws <ArgumentException>(() => ConvexCollider.Create(points, ConvexHullGenerationParameters.Default)); Assert.That(ex.ParamName, Is.EqualTo("points")); }
private static PhysicsCollider CreateMeshCollider(Resource.Mesh mesh, float3 scale, CollisionFilter filter, PhysicsMaterial physicsMaterial) { UnityEngine.Vector3[] v3Verts = Resource.GetMesh(mesh).vertices; float3[] float3Verts = new float3[v3Verts.Length]; for (int i = 0; i < v3Verts.Length; i++) { float3Verts[i] = v3Verts[i] * scale; } NativeArray <float3> nativeVerts = new NativeArray <float3>(float3Verts, Allocator.Temp); return(new PhysicsCollider { Value = ConvexCollider.Create(nativeVerts, ConvexHullGenerationParameters.Default, filter, physicsMaterial) }); }
private void SelectMultipleUnits() { _isDragging = false; var topLeft = math.min(_mouseStartPos, Input.mousePosition); var botRight = math.max(_mouseStartPos, Input.mousePosition); var rect = Rect.MinMaxRect(topLeft.x, topLeft.y, botRight.x, botRight.y); var cornerRays = new[] { _mainCamera.ScreenPointToRay(rect.min), _mainCamera.ScreenPointToRay(rect.max), _mainCamera.ScreenPointToRay(new Vector2(rect.xMin, rect.yMax)), _mainCamera.ScreenPointToRay(new Vector2(rect.xMax, rect.yMin)) }; var vertices = new NativeArray <float3>(5, Allocator.Temp); for (var i = 0; i < cornerRays.Length; i++) { vertices[i] = cornerRays[i].GetPoint(50f); } vertices[4] = _mainCamera.transform.position; var collisionFilter = new CollisionFilter { BelongsTo = (uint)CollisionLayers.Selection, CollidesWith = (uint)CollisionLayers.Units }; var physicsMaterial = Unity.Physics.Material.Default; physicsMaterial.CollisionResponse = CollisionResponsePolicy.RaiseTriggerEvents; var selectionCollider = ConvexCollider.Create(vertices, ConvexHullGenerationParameters.Default, collisionFilter, physicsMaterial); var newSelectionEntity = EntityManager.CreateEntity(_selectionArchetype); EntityManager.SetComponentData(newSelectionEntity, new PhysicsCollider { Value = selectionCollider }); }
public void TestConvexColliderCreate() { var points = new NativeArray <float3>(8, Allocator.Temp) { [0] = new float3(1.45f, 8.67f, 3.45f), [1] = new float3(8.75f, 1.23f, 6.44f), [2] = new float3(100.34f, 5.33f, -2.55f), [3] = new float3(8.76f, 4.56f, -4.54f), [4] = new float3(9.75f, -0.45f, -8.99f), [5] = new float3(7.66f, 3.44f, 0.0f) }; var collider = ConvexCollider.Create(points, convexRadius: 0.15f); points.Dispose(); Assert.AreEqual(ColliderType.Convex, collider.Value.Type); Assert.AreEqual(CollisionType.Convex, collider.Value.CollisionType); }
public void Execute(int index) { var inputParameters = InputValues[index]; var points = new NativeArray <float3>( inputParameters.PointCount, Allocator.Temp, NativeArrayOptions.UninitializedMemory ); UnsafeUtility.MemCpy( points.GetUnsafePtr(), (float3 *)AllPoints.GetUnsafeReadOnlyPtr() + inputParameters.PointsStart, UnsafeUtility.SizeOf <float3>() * inputParameters.PointCount ); Output[index] = new KeyValuePair <Hash128, BlobAssetReference <Collider> >( InputKeys[index], ConvexCollider.Create(points, inputParameters.GenerationParameters, inputParameters.Filter, inputParameters.Material) ); }
public unsafe void TestConvexColliderCalculateAabbTransformed([Values(0, 0.01f, 1.25f)] float maxShrinkMovement) { var points = new NativeArray <float3>(6, Allocator.TempJob) { [0] = new float3(1.45f, 8.67f, 3.45f), [1] = new float3(8.75f, 1.23f, 6.44f), [2] = new float3(100.34f, 5.33f, -2.55f), [3] = new float3(8.76f, 4.56f, -4.54f), [4] = new float3(9.75f, -0.45f, -8.99f), [5] = new float3(7.66f, 3.44f, 0.0f) }; float3 translation = new float3(43.56f, -87.32f, -0.02f); quaternion rotation = quaternion.AxisAngle(math.normalize(new float3(8.45f, -2.34f, 0.82f)), 43.21f); float3[] transformedPoints = new float3[points.Length]; for (int i = 0; i < points.Length; ++i) { transformedPoints[i] = translation + math.mul(rotation, points[i]); } Aabb expectedAabb = Aabb.CreateFromPoints(new float3x4(transformedPoints[0], transformedPoints[1], transformedPoints[2], transformedPoints[3])); expectedAabb.Include(transformedPoints[4]); expectedAabb.Include(transformedPoints[5]); var collider = ConvexCollider.Create( points, new ConvexHullGenerationParameters { BevelRadius = maxShrinkMovement }, CollisionFilter.Default ); points.Dispose(); Aabb actualAabb = collider.Value.CalculateAabb(new RigidTransform(rotation, translation)); float convexRadius = ((ConvexCollider *)collider.GetUnsafePtr())->ConvexHull.ConvexRadius; float maxError = 1e-3f + maxShrinkMovement - convexRadius; TestUtils.AreEqual(expectedAabb.Min, actualAabb.Min, maxError); TestUtils.AreEqual(expectedAabb.Max, actualAabb.Max, maxError); }
public void TestConvexColliderCalculateAabbTransformed() { var points = new NativeArray <float3>(6, Allocator.Temp) { [0] = new float3(1.45f, 8.67f, 3.45f), [1] = new float3(8.75f, 1.23f, 6.44f), [2] = new float3(100.34f, 5.33f, -2.55f), [3] = new float3(8.76f, 4.56f, -4.54f), [4] = new float3(9.75f, -0.45f, -8.99f), [5] = new float3(7.66f, 3.44f, 0.0f) }; float convexRadius = 1.25f; float3 translation = new float3(43.56f, -87.32f, -0.02f); quaternion rotation = quaternion.AxisAngle(math.normalize(new float3(8.45f, -2.34f, 0.82f)), 43.21f); float3[] transformedPoints = new float3[points.Length]; for (int i = 0; i < points.Length; ++i) { transformedPoints[i] = translation + math.mul(rotation, points[i]); } Aabb expectedAabb = Aabb.CreateFromPoints(new float3x4(transformedPoints[0], transformedPoints[1], transformedPoints[2], transformedPoints[3])); expectedAabb.Include(transformedPoints[4]); expectedAabb.Include(transformedPoints[5]); // Currently the convex hull is not shrunk, so we have to expand by the convex radius expectedAabb.Expand(convexRadius); var collider = ConvexCollider.Create(points, convexRadius); points.Dispose(); Aabb actualAabb = collider.Value.CalculateAabb(new RigidTransform(rotation, translation)); TestUtils.AreEqual(expectedAabb.Min, actualAabb.Min, 1e-3f); TestUtils.AreEqual(expectedAabb.Max, actualAabb.Max, 1e-3f); }
public void TestConvexColliderCreate() { var points = new NativeArray <float3>(8, Allocator.TempJob) { [0] = new float3(1.45f, 8.67f, 3.45f), [1] = new float3(8.75f, 1.23f, 6.44f), [2] = new float3(100.34f, 5.33f, -2.55f), [3] = new float3(8.76f, 4.56f, -4.54f), [4] = new float3(9.75f, -0.45f, -8.99f), [5] = new float3(7.66f, 3.44f, 0.0f) }; var collider = ConvexCollider.Create( points, new ConvexHullGenerationParameters { BevelRadius = 0.15f }, CollisionFilter.Default ); points.Dispose(); Assert.AreEqual(ColliderType.Convex, collider.Value.Type); Assert.AreEqual(CollisionType.Convex, collider.Value.CollisionType); }
public static unsafe BlobAssetReference <Collider> GenerateRandomConvex(ref Random rnd) { ColliderType colliderType = (ColliderType)rnd.NextInt((int)ColliderType.Box); float radius = (rnd.NextInt(4) > 0) ? rnd.NextFloat(0.5f) : 0.0f; switch (colliderType) { case ColliderType.Convex: { int numPoints = rnd.NextInt(1, 16); if (numPoints == 3) // TODO - hull builder doesn't build faces for flat shapes, work around it for now to run the test { numPoints++; } var points = new NativeArray <float3>(numPoints, Allocator.Temp); for (int i = 0; i < numPoints; i++) { points[i] = rnd.NextFloat3(-1.0f, 1.0f); } var collider = ConvexCollider.Create(points, radius); points.Dispose(); return(collider); } case ColliderType.Sphere: { float3 center = (rnd.NextInt(4) > 0) ? float3.zero : rnd.NextFloat3(-0.5f, 0.5f); return(SphereCollider.Create(center, rnd.NextFloat(0.01f, 0.5f))); } case ColliderType.Capsule: { float3 point0 = rnd.NextFloat3(0.0f, 1.0f); float3 point1 = (rnd.NextInt(4) > 0) ? -point0 : rnd.NextFloat3(-1.0f, 1.0f); return(CapsuleCollider.Create(point0, point1, rnd.NextFloat(0.01f, 0.5f))); } case ColliderType.Triangle: { return(PolygonCollider.CreateTriangle(rnd.NextFloat3(-1.0f, 1.0f), rnd.NextFloat3(-1.0f, 1.0f), rnd.NextFloat3(-1.0f, 1.0f))); } case ColliderType.Quad: { // Pick 3 totally random points, then choose a fourth that makes a flat and convex quad float3 point0 = rnd.NextFloat3(-1.0f, 1.0f); float3 point1 = rnd.NextFloat3(-1.0f, 1.0f); float3 point3 = rnd.NextFloat3(-1.0f, 1.0f); float t0 = rnd.NextFloat(0.0f, 1.0f); float t1 = rnd.NextFloat(0.0f, 1.0f); float3 e = point1 + point1 - point0; float3 a = math.lerp(point1, e, t0); float3 b = math.lerp(point3, point3 + point3 - point0, t0); float3 point2 = math.lerp(a, b, t1); return(PolygonCollider.CreateQuad(point0, point1, point2, point3)); } case ColliderType.Box: { float3 center = (rnd.NextInt(4) > 0) ? float3.zero : rnd.NextFloat3(-0.5f, 0.5f); quaternion orientation = (rnd.NextInt(4) > 0) ? quaternion.identity : rnd.NextQuaternionRotation(); return(BoxCollider.Create(center, orientation, rnd.NextFloat3(0.01f, 1.0f), radius)); } default: throw new System.NotImplementedException(); } }
protected override BlobAssetReference <Collider> ProduceColliderBlob(PhysicsShape shape) { var material = ProduceMaterial(shape); var collisionFilter = ProduceCollisionFilter(shape); var blob = new BlobAssetReference <Collider>(); shape.GetBakeTransformation(out var linearScalar, out var radiusScalar); switch (shape.ShapeType) { case ShapeType.Box: shape.GetBoxProperties(out var center, out var size, out quaternion orientation); blob = BoxCollider.Create( center * linearScalar, orientation, math.abs(size * linearScalar), shape.ConvexRadius * radiusScalar, collisionFilter, material); break; case ShapeType.Capsule: shape.GetCapsuleProperties(out var v0, out var v1, out var radius); blob = CapsuleCollider.Create( v0 * linearScalar, v1 * linearScalar, radius * radiusScalar, collisionFilter, material); break; case ShapeType.Sphere: shape.GetSphereProperties(out center, out radius, out orientation); blob = SphereCollider.Create( center * linearScalar, radius * radiusScalar, collisionFilter, material); break; case ShapeType.Cylinder: shape.GetCylinderProperties(out center, out var height, out radius, out orientation); var s = math.abs(math.mul(math.inverse(orientation), linearScalar)); blob = CylinderCollider.Create( center * linearScalar, height * s.z, radius * math.cmax(s.xy), orientation, shape.ConvexRadius * radiusScalar, collisionFilter, material); break; case ShapeType.Plane: shape.GetPlaneProperties(out v0, out v1, out var v2, out var v3); blob = PolygonCollider.CreateQuad( v0 * linearScalar, v1 * linearScalar, v2 * linearScalar, v3 * linearScalar, collisionFilter, material); break; case ShapeType.ConvexHull: var pointCloud = new NativeList <float3>(65535, Allocator.Temp); shape.GetConvexHullProperties(pointCloud); if (pointCloud.Length == 0) { pointCloud.Dispose(); throw new InvalidOperationException( $"No vertices associated with {shape.name}. Add a {typeof(MeshFilter)} component or assign {nameof(PhysicsShape.CustomMesh)}." ); } blob = ConvexCollider.Create( pointCloud, shape.ConvexRadius * radiusScalar, linearScalar, collisionFilter, material); pointCloud.Dispose(); break; case ShapeType.Mesh: // TODO: no convex radius? var mesh = shape.GetMesh(); if (mesh == null) { throw new InvalidOperationException( $"No mesh associated with {shape.name}. Add a {typeof(MeshFilter)} component or assign {nameof(PhysicsShape.CustomMesh)}." ); } else { blob = MeshCollider.Create(mesh.GetScaledVertices(linearScalar), mesh.triangles, collisionFilter, material); } break; default: throw new UnimplementedShapeException(shape.ShapeType); } return(blob); }
private BlobAssetReference <Collider> CreateCollider(UnityEngine.Mesh mesh, ColliderType type) { switch (type) { case ColliderType.Sphere: { Bounds bounds = mesh.bounds; return(SphereCollider.Create(bounds.center, math.cmax(bounds.extents))); } case ColliderType.Triangle: { return(PolygonCollider.CreateTriangle(mesh.vertices[0], mesh.vertices[1], mesh.vertices[2])); } case ColliderType.Quad: { // We assume the first 2 triangles of the mesh are a quad with a shared edge // Work out a correct ordering for the triangle int[] orderedIndices = new int[4]; // Find the vertex in first triangle that is not on the shared edge for (int i = 0; i < 3; i++) { if ((mesh.triangles[i] != mesh.triangles[3]) && (mesh.triangles[i] != mesh.triangles[4]) && (mesh.triangles[i] != mesh.triangles[5])) { // Push in order or prev, unique, next orderedIndices[0] = mesh.triangles[(i - 1 + 3) % 3]; orderedIndices[1] = mesh.triangles[i]; orderedIndices[2] = mesh.triangles[(i + 1) % 3]; break; } } // Find the vertex in second triangle that is not on a shared edge for (int i = 3; i < 6; i++) { if ((mesh.triangles[i] != orderedIndices[0]) && (mesh.triangles[i] != orderedIndices[1]) && (mesh.triangles[i] != orderedIndices[2])) { orderedIndices[3] = mesh.triangles[i]; break; } } return(PolygonCollider.CreateQuad( mesh.vertices[orderedIndices[0]], mesh.vertices[orderedIndices[1]], mesh.vertices[orderedIndices[2]], mesh.vertices[orderedIndices[3]])); } case ColliderType.Box: { Bounds bounds = mesh.bounds; return(BoxCollider.Create(bounds.center, quaternion.identity, 2.0f * bounds.extents, 0.0f)); } case ColliderType.Capsule: { Bounds bounds = mesh.bounds; float min = math.cmin(bounds.extents); float max = math.cmax(bounds.extents); int x = math.select(math.select(2, 1, min == bounds.extents.y), 0, min == bounds.extents.x); int z = math.select(math.select(2, 1, max == bounds.extents.y), 0, max == bounds.extents.x); int y = math.select(math.select(2, 1, (1 != x) && (1 != z)), 0, (0 != x) && (0 != z)); float radius = bounds.extents[y]; float3 vertex0 = bounds.center; vertex0[z] = -(max - radius); float3 vertex1 = bounds.center; vertex1[z] = (max - radius); return(CapsuleCollider.Create(vertex0, vertex1, radius)); } case ColliderType.Cylinder: // TODO: need someone to add throw new NotImplementedException(); case ColliderType.Convex: { NativeArray <float3> points = new NativeArray <float3>(mesh.vertices.Length, Allocator.Temp); for (int i = 0; i < mesh.vertices.Length; i++) { points[i] = mesh.vertices[i]; } return(ConvexCollider.Create(points, 0.0f)); } default: throw new System.NotImplementedException(); } }
private void CreateRagdoll(Mesh torsoMesh, Mesh renderMesh, float3 positionOffset, quaternion rotationOffset, float3 initialVelocity, int ragdollIndex = 1, bool internalCollisions = false, float rangeGain = 1.0f) { var entities = new NativeList <Entity>(Allocator.Temp); var rangeModifier = new float2(math.max(0, math.min(rangeGain, 1))); // Head float headRadius = 0.1f; float3 headPosition = new float3(0, 1.8f, headRadius); Entity head; { CollisionFilter filter = internalCollisions ? layerFilter(layer.Head, layer.Torso) : groupFilter(-ragdollIndex); BlobAssetReference <Collider> headCollider = Unity.Physics.CapsuleCollider.Create(new CapsuleGeometry { Vertex0 = new float3(0, 0, 0), Vertex1 = new float3(0, 0, headRadius / 4), Radius = headRadius }, filter); CreatedColliders.Add(headCollider); head = CreateDynamicBody(headPosition, quaternion.identity, headCollider, float3.zero, float3.zero, 5.0f); } entities.Add(head); // Torso float3 torsoSize; float3 torsoPosition; Entity torso; { //UnityEngine.Mesh torsoMesh = (UnityEngine.Mesh)Resources.Load("torso", typeof(UnityEngine.Mesh)); torsoSize = torsoMesh.bounds.size; torsoPosition = headPosition - new float3(0, headRadius * 3.0f / 4.0f + torsoSize.y, 0); CollisionFilter filter = internalCollisions ? layerFilter(layer.Torso, layer.Thigh | layer.Head | layer.UpperArm | layer.Pelvis) : groupFilter(-ragdollIndex); NativeArray <float3> points = new NativeArray <float3>(torsoMesh.vertices.Length, Allocator.TempJob); for (int i = 0; i < torsoMesh.vertices.Length; i++) { points[i] = torsoMesh.vertices[i]; } BlobAssetReference <Collider> collider = ConvexCollider.Create( points, ConvexHullGenerationParameters.Default, CollisionFilter.Default ); CreatedColliders.Add(collider); points.Dispose(); collider.Value.Filter = filter; torso = CreateDynamicBody(torsoPosition, quaternion.identity, collider, float3.zero, float3.zero, 20.0f); } entities.Add(torso); // Neck { float3 pivotHead = new float3(0, -headRadius, 0); float3 pivotTorso = math.transform(math.inverse(GetBodyTransform(torso)), math.transform(GetBodyTransform(head), pivotHead)); float3 axisHead = new float3(0, 0, 1); float3 perpendicular = new float3(1, 0, 0); FloatRange coneAngle = new FloatRange(math.radians(0), math.radians(45)) * rangeModifier; FloatRange perpendicularAngle = new FloatRange(math.radians(-30), math.radians(+30)) * rangeModifier; FloatRange twistAngle = new FloatRange(math.radians(-5), math.radians(5)) * rangeModifier; var axisTorso = math.rotate(math.inverse(GetBodyTransform(torso).rot), math.rotate(GetBodyTransform(head).rot, axisHead)); axisTorso = math.rotate(quaternion.AxisAngle(perpendicular, math.radians(10)), axisTorso); var headFrame = new BodyFrame { Axis = axisHead, PerpendicularAxis = perpendicular, Position = pivotHead }; var torsoFrame = new BodyFrame { Axis = axisTorso, PerpendicularAxis = perpendicular, Position = pivotTorso }; PhysicsJoint.CreateRagdoll(headFrame, torsoFrame, coneAngle.Max, perpendicularAngle, twistAngle, out var ragdoll0, out var ragdoll1); CreateJoint(ragdoll0, head, torso); CreateJoint(ragdoll1, head, torso); } // Arms { float armLength = 0.25f; float armRadius = 0.05f; CollisionFilter armUpperFilter = internalCollisions ? layerFilter(layer.UpperArm, layer.Torso | layer.Forearm) : groupFilter(-ragdollIndex); CollisionFilter armLowerFilter = internalCollisions ? layerFilter(layer.Forearm, layer.UpperArm | layer.Hand) : groupFilter(-ragdollIndex); BlobAssetReference <Collider> upperArmCollider = Unity.Physics.CapsuleCollider.Create(new CapsuleGeometry { Vertex0 = new float3(-armLength / 2, 0, 0), Vertex1 = new float3(armLength / 2, 0, 0), Radius = armRadius }, armUpperFilter); BlobAssetReference <Collider> foreArmCollider = Unity.Physics.CapsuleCollider.Create(new CapsuleGeometry { Vertex0 = new float3(-armLength / 2, 0, 0), Vertex1 = new float3(armLength / 2, 0, 0), Radius = armRadius }, armLowerFilter); float handLength = 0.025f; float handRadius = 0.055f; CollisionFilter handFilter = internalCollisions ? layerFilter(layer.Hand, layer.Forearm) : groupFilter(-ragdollIndex); BlobAssetReference <Collider> handCollider = Unity.Physics.CapsuleCollider.Create(new CapsuleGeometry { Vertex0 = new float3(-handLength / 2, 0, 0), Vertex1 = new float3(handLength / 2, 0, 0), Radius = handRadius }, handFilter); CreatedColliders.Add(upperArmCollider); CreatedColliders.Add(foreArmCollider); CreatedColliders.Add(handCollider); for (int i = 0; i < 2; i++) { float s = i * 2 - 1.0f; float3 upperArmPosition = torsoPosition + new float3(s * (torsoSize.x + armLength) / 2.0f, 0.9f * torsoSize.y - armRadius, 0.0f); Entity upperArm = CreateDynamicBody(upperArmPosition, quaternion.identity, upperArmCollider, float3.zero, float3.zero, 10.0f); float3 foreArmPosition = upperArmPosition + new float3(armLength * s, 0, 0); Entity foreArm = CreateDynamicBody(foreArmPosition, quaternion.identity, foreArmCollider, float3.zero, float3.zero, 5.0f); float3 handPosition = foreArmPosition + new float3((armLength + handLength) / 2.0f * s, 0, 0); Entity hand = CreateDynamicBody(handPosition, quaternion.identity, handCollider, float3.zero, float3.zero, 2.0f); entities.Add(upperArm); entities.Add(foreArm); entities.Add(hand); // shoulder { float3 pivotArm = new float3(-s * armLength / 2.0f, 0, 0); float3 pivotTorso = math.transform(math.inverse(GetBodyTransform(torso)), math.transform(GetBodyTransform(upperArm), pivotArm)); float3 axisArm = new float3(-s, 0, 0); float3 perpendicularArm = new float3(0, 1, 0); FloatRange coneAngle = new FloatRange(math.radians(0), math.radians(80)) * rangeModifier; FloatRange perpendicularAngle = new FloatRange(math.radians(-70), math.radians(20)) * rangeModifier; FloatRange twistAngle = new FloatRange(math.radians(-5), math.radians(5)) * rangeModifier; var axisTorso = math.rotate(math.inverse(GetBodyTransform(torso).rot), math.rotate(GetBodyTransform(upperArm).rot, axisArm)); axisTorso = math.rotate(quaternion.AxisAngle(perpendicularArm, math.radians(-s * 45.0f)), axisTorso); var armFrame = new BodyFrame { Axis = axisArm, PerpendicularAxis = perpendicularArm, Position = pivotArm }; var bodyFrame = new BodyFrame { Axis = axisTorso, PerpendicularAxis = perpendicularArm, Position = pivotTorso }; PhysicsJoint.CreateRagdoll(armFrame, bodyFrame, coneAngle.Max, perpendicularAngle, twistAngle, out var ragdoll0, out var ragdoll1); CreateJoint(ragdoll0, upperArm, torso); CreateJoint(ragdoll1, upperArm, torso); } // elbow { float3 pivotUpper = new float3(s * armLength / 2.0f, 0, 0); float3 pivotFore = -pivotUpper; float3 axis = new float3(0, -s, 0); float3 perpendicular = new float3(-s, 0, 0); var lowerArmFrame = new BodyFrame { Axis = axis, PerpendicularAxis = perpendicular, Position = pivotFore }; var upperArmFrame = new BodyFrame { Axis = axis, PerpendicularAxis = perpendicular, Position = pivotUpper }; var hingeRange = new FloatRange(math.radians(0), math.radians(100)); hingeRange = (hingeRange - new float2(hingeRange.Mid)) * rangeModifier + hingeRange.Mid; PhysicsJoint hinge = PhysicsJoint.CreateLimitedHinge(lowerArmFrame, upperArmFrame, hingeRange); CreateJoint(hinge, foreArm, upperArm); } // wrist { float3 pivotFore = new float3(s * armLength / 2.0f, 0, 0); float3 pivotHand = new float3(-s * handLength / 2.0f, 0, 0); float3 axis = new float3(0, 0, -s); float3 perpendicular = new float3(0, 0, 1); var handFrame = new BodyFrame { Axis = axis, PerpendicularAxis = perpendicular, Position = pivotHand }; var forearmFrame = new BodyFrame { Axis = axis, PerpendicularAxis = perpendicular, Position = pivotFore }; var hingeRange = new FloatRange(math.radians(0), math.radians(135)) * rangeModifier; PhysicsJoint hinge = PhysicsJoint.CreateLimitedHinge(handFrame, forearmFrame, hingeRange); CreateJoint(hinge, hand, foreArm); } } } // Pelvis float pelvisRadius = 0.08f; float pelvisLength = 0.22f; float3 pelvisPosition = torsoPosition - new float3(0, pelvisRadius * 0.75f, 0.0f); Entity pelvis; { CollisionFilter filter = internalCollisions ? layerFilter(layer.Pelvis, layer.Torso | layer.Thigh) : groupFilter(-ragdollIndex); BlobAssetReference <Collider> collider = Unity.Physics.CapsuleCollider.Create(new CapsuleGeometry { Vertex0 = new float3(-pelvisLength / 2, 0, 0), Vertex1 = new float3(pelvisLength / 2, 0, 0), Radius = pelvisRadius }, filter); pelvis = CreateDynamicBody(pelvisPosition, quaternion.identity, collider, float3.zero, float3.zero, 15.0f); CreatedColliders.Add(collider); } entities.Add(pelvis); // Waist { float3 pivotTorso = float3.zero; float3 pivotPelvis = math.transform(math.inverse(GetBodyTransform(pelvis)), math.transform(GetBodyTransform(torso), pivotTorso)); float3 axis = new float3(0, 1, 0); float3 perpendicular = new float3(0, 0, 1); FloatRange coneAngle = new FloatRange(math.radians(0), math.radians(5)) * rangeModifier; FloatRange perpendicularAngle = new FloatRange(math.radians(-5), math.radians(90)) * rangeModifier; FloatRange twistAngle = new FloatRange(-math.radians(-5), math.radians(5)) * rangeModifier; var pelvisFrame = new BodyFrame { Axis = axis, PerpendicularAxis = perpendicular, Position = pivotPelvis }; var torsoFrame = new BodyFrame { Axis = axis, PerpendicularAxis = perpendicular, Position = pivotTorso }; PhysicsJoint.CreateRagdoll(pelvisFrame, torsoFrame, coneAngle.Max, perpendicularAngle, twistAngle, out var ragdoll0, out var ragdoll1); CreateJoint(ragdoll0, pelvis, torso); CreateJoint(ragdoll1, pelvis, torso); } // Legs { float thighLength = 0.32f; float thighRadius = 0.08f; CollisionFilter thighFilter = internalCollisions ? layerFilter(layer.Thigh, layer.Pelvis | layer.Calf) : groupFilter(-ragdollIndex); BlobAssetReference <Collider> thighCollider = Unity.Physics.CapsuleCollider.Create(new CapsuleGeometry { Vertex0 = new float3(0, -thighLength / 2, 0), Vertex1 = new float3(0, thighLength / 2, 0), Radius = thighRadius }, thighFilter); float calfLength = 0.32f; float calfRadius = 0.06f; CollisionFilter calfFilter = internalCollisions ? layerFilter(layer.Calf, layer.Thigh | layer.Foot) : groupFilter(-ragdollIndex); BlobAssetReference <Collider> calfCollider = Unity.Physics.CapsuleCollider.Create(new CapsuleGeometry { Vertex0 = new float3(0, -calfLength / 2, 0), Vertex1 = new float3(0, calfLength / 2, 0), Radius = calfRadius }, calfFilter); float footLength = 0.08f; float footRadius = 0.06f; CollisionFilter footFilter = internalCollisions ? layerFilter(layer.Foot, layer.Calf) : groupFilter(-ragdollIndex); BlobAssetReference <Collider> footCollider = Unity.Physics.CapsuleCollider.Create(new CapsuleGeometry { Vertex0 = new float3(0), Vertex1 = new float3(0, 0, footLength), Radius = footRadius }, footFilter); CreatedColliders.Add(thighCollider); CreatedColliders.Add(calfCollider); CreatedColliders.Add(footCollider); for (int i = 0; i < 2; i++) { float s = i * 2 - 1.0f; float3 thighPosition = pelvisPosition + new float3(s * pelvisLength / 2.0f, -thighLength / 2.0f, 0.0f); Entity thigh = CreateDynamicBody(thighPosition, quaternion.identity, thighCollider, float3.zero, float3.zero, 10.0f); float3 calfPosition = thighPosition + new float3(0, -(thighLength + calfLength) / 2.0f, 0); Entity calf = CreateDynamicBody(calfPosition, quaternion.identity, calfCollider, float3.zero, float3.zero, 5.0f); float3 footPosition = calfPosition + new float3(0, -calfLength / 2.0f, 0); Entity foot = CreateDynamicBody(footPosition, quaternion.identity, footCollider, float3.zero, float3.zero, 2.0f); entities.Add(thigh); entities.Add(calf); entities.Add(foot); // hip { float3 pivotThigh = new float3(0, thighLength / 2.0f, 0); float3 pivotPelvis = math.transform(math.inverse(GetBodyTransform(pelvis)), math.transform(GetBodyTransform(thigh), pivotThigh)); float3 axisLeg = new float3(0, -1, 0); float3 perpendicularLeg = new float3(-s, 0, 0); FloatRange coneAngle = new FloatRange(math.radians(0), math.radians(60)) * rangeModifier; FloatRange perpendicularAngle = new FloatRange(math.radians(-10), math.radians(40)) * rangeModifier; FloatRange twistAngle = new FloatRange(-math.radians(5), math.radians(5)) * rangeModifier; var axisPelvis = math.rotate(math.inverse(GetBodyTransform(pelvis).rot), math.rotate(GetBodyTransform(thigh).rot, axisLeg)); axisPelvis = math.rotate(quaternion.AxisAngle(perpendicularLeg, math.radians(s * 45.0f)), axisPelvis); var upperLegFrame = new BodyFrame { Axis = axisLeg, PerpendicularAxis = perpendicularLeg, Position = pivotThigh }; var pelvisFrame = new BodyFrame { Axis = axisPelvis, PerpendicularAxis = perpendicularLeg, Position = pivotPelvis }; PhysicsJoint.CreateRagdoll(upperLegFrame, pelvisFrame, coneAngle.Max, perpendicularAngle, twistAngle, out var ragdoll0, out var ragdoll1); CreateJoint(ragdoll0, thigh, pelvis); CreateJoint(ragdoll1, thigh, pelvis); } // knee { float3 pivotThigh = new float3(0, -thighLength / 2.0f, 0); float3 pivotCalf = math.transform(math.inverse(GetBodyTransform(calf)), math.transform(GetBodyTransform(thigh), pivotThigh)); float3 axis = new float3(-1, 0, 0); float3 perpendicular = new float3(0, 0, 1); var lowerLegFrame = new BodyFrame { Axis = axis, PerpendicularAxis = perpendicular, Position = pivotCalf }; var upperLegFrame = new BodyFrame { Axis = axis, PerpendicularAxis = perpendicular, Position = pivotThigh }; var hingeRange = new FloatRange(math.radians(-90), math.radians(0)); hingeRange = (hingeRange - new float2(hingeRange.Mid)) * rangeModifier + hingeRange.Mid; PhysicsJoint hinge = PhysicsJoint.CreateLimitedHinge(lowerLegFrame, upperLegFrame, hingeRange); CreateJoint(hinge, calf, thigh); } // ankle { float3 pivotCalf = new float3(0, -calfLength / 2.0f, 0); float3 pivotFoot = float3.zero; float3 axis = new float3(-1, 0, 0); float3 perpendicular = new float3(0, 0, 1); var footFrame = new BodyFrame { Axis = axis, PerpendicularAxis = perpendicular, Position = pivotFoot }; var lowerLegFrame = new BodyFrame { Axis = axis, PerpendicularAxis = perpendicular, Position = pivotCalf }; var hingeRange = new FloatRange(math.radians(-5), math.radians(5)) * rangeModifier; PhysicsJoint hinge = PhysicsJoint.CreateLimitedHinge(footFrame, lowerLegFrame, hingeRange); CreateJoint(hinge, foot, calf); } } } // reposition with offset information if (entities.Length > 0) { for (int i = 0; i < entities.Length; i++) { var e = entities[i]; bool isTorso = (i == 1); SwapRenderMesh(e, isTorso, torsoMesh, renderMesh); Translation positionComponent = EntityManager.GetComponentData <Translation>(e); Rotation rotationComponent = EntityManager.GetComponentData <Rotation>(e); PhysicsVelocity velocityComponent = EntityManager.GetComponentData <PhysicsVelocity>(e); float3 position = positionComponent.Value; quaternion rotation = rotationComponent.Value; float3 localPosition = position - pelvisPosition; localPosition = math.rotate(rotationOffset, localPosition); position = localPosition + pelvisPosition + positionOffset; rotation = math.mul(rotation, rotationOffset); positionComponent.Value = position; rotationComponent.Value = rotation; velocityComponent.Linear = initialVelocity; EntityManager.SetComponentData <PhysicsVelocity>(e, velocityComponent); EntityManager.SetComponentData <Translation>(e, positionComponent); EntityManager.SetComponentData <Rotation>(e, rotationComponent); } } }
public static unsafe BlobAssetReference <Collider> GenerateRandomConvex(ref Random rnd) { ColliderType colliderType = (ColliderType)rnd.NextInt((int)ColliderType.Cylinder + 1); float convexRadius = (rnd.NextInt(4) > 0) ? rnd.NextFloat(0.5f) : 0.0f; switch (colliderType) { case ColliderType.Convex: { int numPoints = rnd.NextInt(1, 16); if (numPoints == 3) // TODO - hull builder doesn't build faces for flat shapes, work around it for now to run the test { numPoints++; } var points = new NativeArray <float3>(numPoints, Allocator.TempJob); for (int i = 0; i < numPoints; i++) { points[i] = rnd.NextFloat3(-1.0f, 1.0f); } var generationParameters = ConvexHullGenerationParameters.Default; generationParameters.BevelRadius = convexRadius; var collider = ConvexCollider.Create(points, generationParameters, CollisionFilter.Default); points.Dispose(); return(collider); } case ColliderType.Sphere: { return(SphereCollider.Create(new SphereGeometry { Center = (rnd.NextInt(4) > 0) ? float3.zero : rnd.NextFloat3(-0.5f, 0.5f), Radius = rnd.NextFloat(0.01f, 0.5f) })); } case ColliderType.Capsule: { float3 point0 = rnd.NextFloat3(0.0f, 1.0f); float3 point1 = (rnd.NextInt(4) > 0) ? -point0 : rnd.NextFloat3(-1.0f, 1.0f); return(CapsuleCollider.Create(new CapsuleGeometry { Vertex0 = point0, Vertex1 = point1, Radius = rnd.NextFloat(0.01f, 0.5f) })); } case ColliderType.Triangle: { return(PolygonCollider.CreateTriangle(rnd.NextFloat3(-1.0f, 1.0f), rnd.NextFloat3(-1.0f, 1.0f), rnd.NextFloat3(-1.0f, 1.0f))); } case ColliderType.Quad: { // Pick 3 totally random points, then choose a fourth that makes a flat and convex quad float3 point0 = rnd.NextFloat3(-1.0f, 1.0f); float3 point1 = rnd.NextFloat3(-1.0f, 1.0f); float3 point3 = rnd.NextFloat3(-1.0f, 1.0f); float t0 = rnd.NextFloat(0.0f, 1.0f); float t1 = rnd.NextFloat(0.0f, 1.0f); float3 e = point1 + point1 - point0; float3 a = math.lerp(point1, e, t0); float3 b = math.lerp(point3, point3 + point3 - point0, t0); float3 point2 = math.lerp(a, b, t1); return(PolygonCollider.CreateQuad(point0, point1, point2, point3)); } case ColliderType.Box: { float minSize = 0.05f; // TODO - work around hull builder problems with small faces, sometimes doesn't extend 1D->2D based on face area var boxGeometry = new BoxGeometry { Center = (rnd.NextInt(4) > 0) ? float3.zero : rnd.NextFloat3(-0.5f, 0.5f), Orientation = (rnd.NextInt(4) > 0) ? quaternion.identity : rnd.NextQuaternionRotation(), Size = rnd.NextFloat3(minSize, 1.0f) }; float maxBevelRadius = math.max(math.cmin((boxGeometry.Size - minSize) / (2.0f * (1.0f + float.Epsilon))), 0.0f); boxGeometry.BevelRadius = math.min(maxBevelRadius, convexRadius); return(BoxCollider.Create(boxGeometry)); } case ColliderType.Cylinder: { float minSize = 0.01f; // TODO - cylinder gets degenerate faces if radius-convexRadius=0 or height/2-convexRadius=0, decide how to handle this in CylinderCollider var cylinderGeometry = new CylinderGeometry { Center = (rnd.NextInt(4) > 0) ? float3.zero : rnd.NextFloat3(-0.5f, 0.5f), Orientation = (rnd.NextInt(4) > 0) ? quaternion.identity : rnd.NextQuaternionRotation(), Height = rnd.NextFloat(2.0f * minSize, 1f), Radius = rnd.NextFloat(minSize, 1.0f), SideCount = 20 }; var maxBevelRadius = math.max(math.min(cylinderGeometry.Height / 2, cylinderGeometry.Radius) - minSize, 0.0f); cylinderGeometry.BevelRadius = math.min(maxBevelRadius, convexRadius); return(CylinderCollider.Create(cylinderGeometry)); } default: throw new NotImplementedException(); } }
public void Execute() => Output[0] = ConvexCollider.Create(Points, GenerationParameters, CollisionFilter.Default);
public void TestConvexColliderCreateInvalid() { // Invalid points { var validBevelRadius = new ConvexHullGenerationParameters { BevelRadius = 0.15f }; // invalid point, +inf { var invalidPoints = new NativeArray <float3>(6, Allocator.TempJob) { [0] = new float3(1.45f, 8.67f, 3.45f), [1] = new float3(8.75f, 1.23f, 6.44f), [2] = new float3(float.PositiveInfinity, 5.33f, -2.55f), [3] = new float3(8.76f, 4.56f, -4.54f), [4] = new float3(9.75f, -0.45f, -8.99f), [5] = new float3(7.66f, 3.44f, 0.0f) }; TestUtils.ThrowsException <ArgumentException>( () => ConvexCollider.Create(invalidPoints, validBevelRadius, CollisionFilter.Default) ); invalidPoints.Dispose(); } // invalid point, -inf { var invalidPoints = new NativeArray <float3>(6, Allocator.TempJob) { [0] = new float3(1.45f, 8.67f, 3.45f), [1] = new float3(8.75f, 1.23f, 6.44f), [2] = new float3(float.NegativeInfinity, 5.33f, -2.55f), [3] = new float3(8.76f, 4.56f, -4.54f), [4] = new float3(9.75f, -0.45f, -8.99f), [5] = new float3(7.66f, 3.44f, 0.0f) }; TestUtils.ThrowsException <ArgumentException>( () => ConvexCollider.Create(invalidPoints, validBevelRadius, CollisionFilter.Default) ); invalidPoints.Dispose(); } // invalid point, NaN { var invalidPoints = new NativeArray <float3>(6, Allocator.TempJob) { [0] = new float3(1.45f, 8.67f, 3.45f), [1] = new float3(8.75f, 1.23f, 6.44f), [2] = new float3(float.NaN, 5.33f, -2.55f), [3] = new float3(8.76f, 4.56f, -4.54f), [4] = new float3(9.75f, -0.45f, -8.99f), [5] = new float3(7.66f, 3.44f, 0.0f) }; TestUtils.ThrowsException <ArgumentException>( () => ConvexCollider.Create(invalidPoints, validBevelRadius, CollisionFilter.Default) ); invalidPoints.Dispose(); } } // invalid convex radius { var points = new NativeArray <float3>(6, Allocator.TempJob) { [0] = new float3(1.45f, 8.67f, 3.45f), [1] = new float3(8.75f, 1.23f, 6.44f), [2] = new float3(7.54f, 5.33f, -2.55f), [3] = new float3(8.76f, 4.56f, -4.54f), [4] = new float3(9.75f, -0.45f, -8.99f), [5] = new float3(7.66f, 3.44f, 0.0f) }; float3 scale = new float3(1.0f, 1.0f, 1.0f); var invalidBevelRadius = new ConvexHullGenerationParameters(); // negative convex radius { invalidBevelRadius.BevelRadius = -0.30f; TestUtils.ThrowsException <ArgumentException>( () => ConvexCollider.Create(points, invalidBevelRadius, CollisionFilter.Default) ); } // +inf convex radius { invalidBevelRadius.BevelRadius = float.PositiveInfinity; TestUtils.ThrowsException <ArgumentException>( () => ConvexCollider.Create(points, invalidBevelRadius, CollisionFilter.Default) ); } // -inf convex radius { invalidBevelRadius.BevelRadius = float.NegativeInfinity; TestUtils.ThrowsException <ArgumentException>( () => ConvexCollider.Create(points, invalidBevelRadius, CollisionFilter.Default) ); } // nan convex radius { invalidBevelRadius.BevelRadius = float.NaN; TestUtils.ThrowsException <ArgumentException>( () => ConvexCollider.Create(points, invalidBevelRadius, CollisionFilter.Default) ); } points.Dispose(); } }
private BlobAssetReference <Collider> CreateCollider(ColliderType type) { int numMeshes = type == ColliderType.Compound ? 2 : 1; ColliderMeshes = new Mesh[numMeshes]; BlobAssetReference <Collider> collider = default; switch (type) { case ColliderType.Sphere: collider = SphereCollider.Create(new SphereGeometry { Center = float3.zero, Radius = 0.5f }); break; case ColliderType.Triangle: collider = PolygonCollider.CreateTriangle(k_TriangleVertices[0], k_TriangleVertices[1], k_TriangleVertices[2]); break; case ColliderType.Quad: collider = PolygonCollider.CreateQuad(k_QuadVertices[0], k_QuadVertices[1], k_QuadVertices[2], k_QuadVertices[3]); break; case ColliderType.Box: collider = BoxCollider.Create(new BoxGeometry { Center = float3.zero, Orientation = quaternion.identity, Size = new float3(1.0f), BevelRadius = 0.0f }); break; case ColliderType.Capsule: collider = CapsuleCollider.Create(new CapsuleGeometry { Vertex0 = new float3(0, -0.5f, 0), Vertex1 = new float3(0, 0.5f, 0), Radius = 0.5f }); break; case ColliderType.Cylinder: // TODO: need someone to add throw new NotImplementedException(); case ColliderType.Convex: // Tetrahedron NativeArray <float3> points = new NativeArray <float3>(k_TetraherdonVertices, Allocator.TempJob); collider = ConvexCollider.Create(points, ConvexHullGenerationParameters.Default, CollisionFilter.Default); points.Dispose(); break; case ColliderType.Compound: var child1 = SphereCollider.Create(new SphereGeometry { Center = float3.zero, Radius = 0.5f }); ChildrenColliders.Add(child1); var child2 = BoxCollider.Create(new BoxGeometry { Center = float3.zero, Orientation = quaternion.identity, Size = new float3(1.0f), BevelRadius = 0.0f }); ChildrenColliders.Add(child2); NativeArray <ColliderBlobInstance> childrenBlobs = new NativeArray <ColliderBlobInstance>(2, Allocator.TempJob); childrenBlobs[0] = new ColliderBlobInstance { Collider = child1, CompoundFromChild = new RigidTransform { pos = new float3(0.5f, 0, 0), rot = quaternion.identity } }; childrenBlobs[1] = new ColliderBlobInstance { Collider = child2, CompoundFromChild = new RigidTransform { pos = new float3(-0.5f, 0, 0), rot = quaternion.identity } }; ColliderMeshes[0] = SceneCreationUtilities.CreateMeshFromCollider(child1); ColliderMeshes[1] = SceneCreationUtilities.CreateMeshFromCollider(child2); collider = CompoundCollider.Create(childrenBlobs); childrenBlobs.Dispose(); break; case ColliderType.Mesh: // Tetrahedron mesh NativeArray <float3> meshVertices = new NativeArray <float3>(k_TetraherdonVertices, Allocator.TempJob); NativeArray <int3> meshTriangles = new NativeArray <int3>(k_TetrahedronMeshTriangles, Allocator.TempJob); collider = MeshCollider.Create(meshVertices, meshTriangles); meshVertices.Dispose(); meshTriangles.Dispose(); break; case ColliderType.Terrain: int2 size = 2; float3 scale = 1; Random rand = new Random(0x9739); int numSamples = size.x * size.y; var heights = new NativeArray <float>(numSamples, Allocator.TempJob, NativeArrayOptions.UninitializedMemory); for (int i = 0; i < numSamples; i++) { heights[i] = rand.NextFloat(0, 1); } collider = TerrainCollider.Create(heights, size, scale, TerrainCollider.CollisionMethod.VertexSamples); heights.Dispose(); break; default: throw new System.NotImplementedException(); } if (ColliderType != ColliderType.Compound) { ColliderMeshes[0] = SceneCreationUtilities.CreateMeshFromCollider(collider); } return(collider); }
private void CreateRagdoll(float3 positionOffset, quaternion rotationOffset, int ragdollIndex = 1, bool internalCollisions = false) { var entities = new NativeList <Entity>(Allocator.Temp); // Head float headRadius = 0.1f; float3 headPosition = new float3(0, 1.8f, 0); Entity head; { CollisionFilter filter = internalCollisions ? layerFilter(layer.Head, layer.Torso) : groupFilter(-ragdollIndex); BlobAssetReference <Unity.Physics.Collider> collider = Unity.Physics.SphereCollider.Create(new SphereGeometry { Center = float3.zero, Radius = headRadius }, filter); head = CreateDynamicBody(headPosition, quaternion.identity, collider, float3.zero, float3.zero, 5.0f); } entities.Add(head); // Torso float3 torsoSize; float3 torsoPosition; Entity torso; { //UnityEngine.Mesh torsoMesh = (UnityEngine.Mesh)Resources.Load("torso", typeof(UnityEngine.Mesh)); torsoSize = torsoMesh.bounds.size; torsoPosition = headPosition - new float3(0, headRadius * 3.0f / 4.0f + torsoSize.y, 0); CollisionFilter filter = internalCollisions ? layerFilter(layer.Torso, layer.Thigh | layer.Head | layer.UpperArm | layer.Pelvis) : groupFilter(-ragdollIndex); NativeArray <float3> points = new NativeArray <float3>(torsoMesh.vertices.Length, Allocator.TempJob); for (int i = 0; i < torsoMesh.vertices.Length; i++) { points[i] = torsoMesh.vertices[i]; } BlobAssetReference <Unity.Physics.Collider> collider = ConvexCollider.Create( points, ConvexHullGenerationParameters.Default, CollisionFilter.Default ); points.Dispose(); collider.Value.Filter = filter; torso = CreateDynamicBody(torsoPosition, quaternion.identity, collider, float3.zero, float3.zero, 20.0f); } entities.Add(torso); // Neck { float3 pivotHead = new float3(0, -headRadius, 0); float3 pivotBody = math.transform(math.inverse(GetBodyTransform(torso)), math.transform(GetBodyTransform(head), pivotHead)); float3 axis = new float3(0, 1, 0); float3 perpendicular = new float3(0, 0, 1); float coneAngle = (float)math.PI / 5.0f; var perpendicularAngle = new FloatRange { Max = math.PI }; // unlimited var twistAngle = new FloatRange(-math.PI / 3f, math.PI / 3f); var headFrame = new BodyFrame { Axis = axis, PerpendicularAxis = perpendicular, Position = pivotHead }; var bodyFrame = new BodyFrame { Axis = axis, PerpendicularAxis = perpendicular, Position = pivotBody }; PhysicsJoint.CreateRagdoll(headFrame, bodyFrame, coneAngle, perpendicularAngle, twistAngle, out var ragdoll0, out var ragdoll1); CreateJoint(ragdoll0, head, torso); CreateJoint(ragdoll1, head, torso); } // Arms { float armLength = 0.25f; float armRadius = 0.05f; CollisionFilter armUpperFilter = internalCollisions ? layerFilter(layer.UpperArm, layer.Torso | layer.Forearm) : groupFilter(-ragdollIndex); CollisionFilter armLowerFilter = internalCollisions ? layerFilter(layer.Forearm, layer.UpperArm | layer.Hand) : groupFilter(-ragdollIndex); BlobAssetReference <Unity.Physics.Collider> upperArmCollider = Unity.Physics.CapsuleCollider.Create(new CapsuleGeometry { Vertex0 = new float3(-armLength / 2, 0, 0), Vertex1 = new float3(armLength / 2, 0, 0), Radius = armRadius }, armUpperFilter); BlobAssetReference <Unity.Physics.Collider> foreArmCollider = Unity.Physics.CapsuleCollider.Create(new CapsuleGeometry { Vertex0 = new float3(-armLength / 2, 0, 0), Vertex1 = new float3(armLength / 2, 0, 0), Radius = armRadius }, armLowerFilter); float handLength = 0.025f; float handRadius = 0.055f; CollisionFilter handFilter = internalCollisions ? layerFilter(layer.Hand, layer.Forearm) : groupFilter(-ragdollIndex); BlobAssetReference <Unity.Physics.Collider> handCollider = Unity.Physics.CapsuleCollider.Create(new CapsuleGeometry { Vertex0 = new float3(-handLength / 2, 0, 0), Vertex1 = new float3(handLength / 2, 0, 0), Radius = handRadius }, handFilter); for (int i = 0; i < 2; i++) { float s = i * 2 - 1.0f; float3 upperArmPosition = torsoPosition + new float3(s * (torsoSize.x + armLength) / 2.0f, 0.9f * torsoSize.y - armRadius, 0.0f); Entity upperArm = CreateDynamicBody(upperArmPosition, quaternion.identity, upperArmCollider, float3.zero, float3.zero, 10.0f); float3 foreArmPosition = upperArmPosition + new float3(armLength * s, 0, 0); Entity foreArm = CreateDynamicBody(foreArmPosition, quaternion.identity, foreArmCollider, float3.zero, float3.zero, 5.0f); float3 handPosition = foreArmPosition + new float3((armLength + handLength) / 2.0f * s, 0, 0); Entity hand = CreateDynamicBody(handPosition, quaternion.identity, handCollider, float3.zero, float3.zero, 2.0f); entities.Add(upperArm); entities.Add(foreArm); entities.Add(hand); // shoulder { float3 pivotArm = new float3(-s * armLength / 2.0f, 0, 0); float3 pivotBody = math.transform(math.inverse(GetBodyTransform(torso)), math.transform(GetBodyTransform(upperArm), pivotArm)); float3 axis = new float3(s, 0, 0); float3 perpendicular = new float3(0, 0, 1); float coneAngle = (float)math.PI / 2.0f; var perpendicularAngle = new FloatRange { Max = math.PI / 2f }; var twistAngle = new FloatRange(-math.PI / 4f, math.PI / 4f); var armFrame = new BodyFrame { Axis = axis, PerpendicularAxis = perpendicular, Position = pivotArm }; var bodyFrame = new BodyFrame { Axis = axis, PerpendicularAxis = perpendicular, Position = pivotBody }; PhysicsJoint.CreateRagdoll(armFrame, bodyFrame, coneAngle, perpendicularAngle, twistAngle, out var ragdoll0, out var ragdoll1); CreateJoint(ragdoll0, upperArm, torso); CreateJoint(ragdoll1, upperArm, torso); } // elbow { float3 pivotUpper = new float3(s * armLength / 2.0f, 0, 0); float3 pivotFore = -pivotUpper; float3 axis = new float3(0, -s, 0); float3 perpendicular = new float3(s, 0, 0); var lowerArmFrame = new BodyFrame { Axis = axis, PerpendicularAxis = perpendicular, Position = pivotFore }; var upperArmFrame = new BodyFrame { Axis = axis, PerpendicularAxis = perpendicular, Position = pivotUpper }; PhysicsJoint hinge = PhysicsJoint.CreateLimitedHinge(lowerArmFrame, upperArmFrame, new FloatRange { Max = 3f }); CreateJoint(hinge, foreArm, upperArm); } // wrist { float3 pivotFore = new float3(s * armLength / 2.0f, 0, 0); float3 pivotHand = new float3(-s * handLength / 2.0f, 0, 0); float3 axis = new float3(0, -s, 0); float3 perpendicular = new float3(s, 0, 0); var handFrame = new BodyFrame { Axis = axis, PerpendicularAxis = perpendicular, Position = pivotHand }; var forearmFrame = new BodyFrame { Axis = axis, PerpendicularAxis = perpendicular, Position = pivotFore }; PhysicsJoint hinge = PhysicsJoint.CreateLimitedHinge(handFrame, forearmFrame, new FloatRange(-0.3f, 0.6f)); CreateJoint(hinge, hand, foreArm); } } } // Pelvis float pelvisRadius = 0.08f; float pelvisLength = 0.22f; float3 pelvisPosition = torsoPosition - new float3(0, pelvisRadius * 0.75f, 0.0f); Entity pelvis; { CollisionFilter filter = internalCollisions ? layerFilter(layer.Pelvis, layer.Torso | layer.Thigh) : groupFilter(-ragdollIndex); BlobAssetReference <Unity.Physics.Collider> collider = Unity.Physics.CapsuleCollider.Create(new CapsuleGeometry { Vertex0 = new float3(-pelvisLength / 2, 0, 0), Vertex1 = new float3(pelvisLength / 2, 0, 0), Radius = pelvisRadius }, filter); pelvis = CreateDynamicBody(pelvisPosition, quaternion.identity, collider, float3.zero, float3.zero, 15.0f); } entities.Add(pelvis); // Waist { float3 pivotTorso = float3.zero; float3 pivotPelvis = math.transform(math.inverse(GetBodyTransform(pelvis)), math.transform(GetBodyTransform(torso), pivotTorso)); float3 axis = new float3(0, -1, 0); float3 perpendicular = new float3(0, 0, 1); float coneAngle = 0.1f; var perpendicularAngle = new FloatRange(-0.1f, math.PI); var twistAngle = new FloatRange(-0.1f, 0.1f); var pelvisFrame = new BodyFrame { Axis = axis, PerpendicularAxis = perpendicular, Position = pivotPelvis }; var torsoFrame = new BodyFrame { Axis = axis, PerpendicularAxis = perpendicular, Position = pivotTorso }; PhysicsJoint.CreateRagdoll(pelvisFrame, torsoFrame, coneAngle, perpendicularAngle, twistAngle, out var ragdoll0, out var ragdoll1); CreateJoint(ragdoll0, pelvis, torso); CreateJoint(ragdoll1, pelvis, torso); } // Legs { float thighLength = 0.32f; float thighRadius = 0.08f; CollisionFilter thighFilter = internalCollisions ? layerFilter(layer.Thigh, layer.Pelvis | layer.Calf) : groupFilter(-ragdollIndex); BlobAssetReference <Unity.Physics.Collider> thighCollider = Unity.Physics.CapsuleCollider.Create(new CapsuleGeometry { Vertex0 = new float3(0, -thighLength / 2, 0), Vertex1 = new float3(0, thighLength / 2, 0), Radius = thighRadius }, thighFilter); float calfLength = 0.32f; float calfRadius = 0.06f; CollisionFilter calfFilter = internalCollisions ? layerFilter(layer.Calf, layer.Thigh | layer.Foot) : groupFilter(-ragdollIndex); BlobAssetReference <Unity.Physics.Collider> calfCollider = Unity.Physics.CapsuleCollider.Create(new CapsuleGeometry { Vertex0 = new float3(0, -calfLength / 2, 0), Vertex1 = new float3(0, calfLength / 2, 0), Radius = calfRadius }, calfFilter); float footLength = 0.08f; float footRadius = 0.06f; CollisionFilter footFilter = internalCollisions ? layerFilter(layer.Foot, layer.Calf) : groupFilter(-ragdollIndex); BlobAssetReference <Unity.Physics.Collider> footCollider = Unity.Physics.CapsuleCollider.Create(new CapsuleGeometry { Vertex0 = new float3(0), Vertex1 = new float3(0, 0, footLength), Radius = footRadius }, footFilter); for (int i = 0; i < 2; i++) { float s = i * 2 - 1.0f; float3 thighPosition = pelvisPosition + new float3(s * pelvisLength / 2.0f, -thighLength / 2.0f, 0.0f); Entity thigh = CreateDynamicBody(thighPosition, quaternion.identity, thighCollider, float3.zero, float3.zero, 10.0f); float3 calfPosition = thighPosition + new float3(0, -(thighLength + calfLength) / 2.0f, 0); Entity calf = CreateDynamicBody(calfPosition, quaternion.identity, calfCollider, float3.zero, float3.zero, 5.0f); float3 footPosition = calfPosition + new float3(0, -calfLength / 2.0f, 0); Entity foot = CreateDynamicBody(footPosition, quaternion.identity, footCollider, float3.zero, float3.zero, 2.0f); entities.Add(thigh); entities.Add(calf); entities.Add(foot); // hip { float3 pivotThigh = new float3(0, thighLength / 2.0f, 0); float3 pivotBody = math.transform(math.inverse(GetBodyTransform(torso)), math.transform(GetBodyTransform(thigh), pivotThigh)); float3 axis = new float3(0, -1, 0); float3 perpendicular = new float3(s, 0, 0); float coneAngle = (float)math.PI / 4.0f; var perpendicularAngle = new FloatRange { Max = 0.2f + math.PI / 2.0f }; var twistAngle = new FloatRange(-0.2f, 0.2f); var upperLegFrame = new BodyFrame { Axis = axis, PerpendicularAxis = perpendicular, Position = pivotThigh }; var bodyFrame = new BodyFrame { Axis = axis, PerpendicularAxis = perpendicular, Position = pivotBody }; PhysicsJoint.CreateRagdoll(upperLegFrame, bodyFrame, coneAngle, perpendicularAngle, twistAngle, out var ragdoll0, out var ragdoll1); CreateJoint(ragdoll0, thigh, torso); CreateJoint(ragdoll1, thigh, torso); } // knee { float3 pivotThigh = new float3(0, -thighLength / 2.0f, 0); float3 pivotCalf = math.transform(math.inverse(GetBodyTransform(calf)), math.transform(GetBodyTransform(thigh), pivotThigh)); float3 axis = new float3(-1, 0, 0); float3 perpendicular = new float3(0, 0, 1); var lowerLegFrame = new BodyFrame { Axis = axis, PerpendicularAxis = perpendicular, Position = pivotCalf }; var upperLegFrame = new BodyFrame { Axis = axis, PerpendicularAxis = perpendicular, Position = pivotThigh }; PhysicsJoint hinge = PhysicsJoint.CreateLimitedHinge(lowerLegFrame, upperLegFrame, new FloatRange { Min = -1.2f }); CreateJoint(hinge, calf, thigh); } // ankle { float3 pivotCalf = new float3(0, -calfLength / 2.0f, 0); float3 pivotFoot = float3.zero; float3 axis = new float3(-1, 0, 0); float3 perpendicular = new float3(0, 0, 1); var footFrame = new BodyFrame { Axis = axis, PerpendicularAxis = perpendicular, Position = pivotFoot }; var lowerLegFrame = new BodyFrame { Axis = axis, PerpendicularAxis = perpendicular, Position = pivotCalf }; PhysicsJoint hinge = PhysicsJoint.CreateLimitedHinge(footFrame, lowerLegFrame, new FloatRange(-0.4f, 0.1f)); CreateJoint(hinge, foot, calf); } } } var entityManager = BasePhysicsDemo.DefaultWorld.EntityManager; // reposition with offset information if (entities.Length > 0) { float3 center = float3.zero; for (int i = 0; i < entities.Length; i++) { var e = entities[i]; center += entityManager.GetComponentData <Translation>(e).Value; } center /= entities.Length; for (int i = 0; i < entities.Length; i++) { var e = entities[i]; Translation positionComponent = entityManager.GetComponentData <Translation>(e); Rotation rotationComponent = entityManager.GetComponentData <Rotation>(e); float3 position = positionComponent.Value; quaternion rotation = rotationComponent.Value; float3 localPosition = position - center; localPosition = math.rotate(rotationOffset, localPosition); position = localPosition + center + positionOffset; rotation = math.mul(rotation, rotationOffset); positionComponent.Value = position; rotationComponent.Value = rotation; entityManager.SetComponentData <Translation>(e, positionComponent); entityManager.SetComponentData <Rotation>(e, rotationComponent); } } }
public void TestConvexColliderCreateInvalid() { // Invalid points { float convexRadius = 0.15f; // invalid point, +inf { var invalidPoints = new NativeArray <float3>(6, Allocator.Temp) { [0] = new float3(1.45f, 8.67f, 3.45f), [1] = new float3(8.75f, 1.23f, 6.44f), [2] = new float3(float.PositiveInfinity, 5.33f, -2.55f), [3] = new float3(8.76f, 4.56f, -4.54f), [4] = new float3(9.75f, -0.45f, -8.99f), [5] = new float3(7.66f, 3.44f, 0.0f) }; TestUtils.ThrowsException <System.ArgumentException>( () => ConvexCollider.Create(invalidPoints, convexRadius) ); invalidPoints.Dispose(); } // invalid point, -inf { var invalidPoints = new NativeArray <float3>(6, Allocator.Temp) { [0] = new float3(1.45f, 8.67f, 3.45f), [1] = new float3(8.75f, 1.23f, 6.44f), [2] = new float3(float.NegativeInfinity, 5.33f, -2.55f), [3] = new float3(8.76f, 4.56f, -4.54f), [4] = new float3(9.75f, -0.45f, -8.99f), [5] = new float3(7.66f, 3.44f, 0.0f), }; TestUtils.ThrowsException <System.ArgumentException>( () => ConvexCollider.Create(invalidPoints, convexRadius) ); invalidPoints.Dispose(); } // invalid point, NaN { var invalidPoints = new NativeArray <float3>(6, Allocator.Temp) { [0] = new float3(1.45f, 8.67f, 3.45f), [1] = new float3(8.75f, 1.23f, 6.44f), [2] = new float3(float.NaN, 5.33f, -2.55f), [3] = new float3(8.76f, 4.56f, -4.54f), [4] = new float3(9.75f, -0.45f, -8.99f), [5] = new float3(7.66f, 3.44f, 0.0f) }; TestUtils.ThrowsException <System.ArgumentException>( () => ConvexCollider.Create(invalidPoints, convexRadius) ); invalidPoints.Dispose(); } } // invalid convex radius { var points = new NativeArray <float3>(6, Allocator.Temp) { [0] = new float3(1.45f, 8.67f, 3.45f), [1] = new float3(8.75f, 1.23f, 6.44f), [2] = new float3(7.54f, 5.33f, -2.55f), [3] = new float3(8.76f, 4.56f, -4.54f), [4] = new float3(9.75f, -0.45f, -8.99f), [5] = new float3(7.66f, 3.44f, 0.0f) }; float3 scale = new float3(1.0f, 1.0f, 1.0f); // negative convex radius { float invalidConvexRadius = -0.30f; TestUtils.ThrowsException <System.ArgumentException>( () => ConvexCollider.Create(points, invalidConvexRadius) ); } // +inf convex radius { float invalidConvexRadius = float.PositiveInfinity; TestUtils.ThrowsException <System.ArgumentException>( () => ConvexCollider.Create(points, invalidConvexRadius) ); } // -inf convex radius { float invalidConvexRadius = float.NegativeInfinity; TestUtils.ThrowsException <System.ArgumentException>( () => ConvexCollider.Create(points, invalidConvexRadius) ); } // nan convex radius { float invalidConvexRadius = float.NaN; TestUtils.ThrowsException <System.ArgumentException>( () => ConvexCollider.Create(points, invalidConvexRadius) ); } points.Dispose(); } }
private void CreateRagdoll(float3 positionOffset, quaternion rotationOffset, int ragdollIndex = 1, bool internalCollisions = false) { NativeList <Entity> entities = new NativeList <Entity>(Allocator.Temp); // Head float headRadius = 0.1f; float3 headPosition = new float3(0, 1.8f, 0); Entity head; { CollisionFilter filter = internalCollisions ? layerFilter(layer.Head, layer.Torso) : groupFilter(-ragdollIndex); BlobAssetReference <Unity.Physics.Collider> collider = Unity.Physics.SphereCollider.Create(float3.zero, headRadius, filter); head = CreateDynamicBody(headPosition, quaternion.identity, collider, float3.zero, float3.zero, 5.0f); } entities.Add(head); // Torso float3 torsoSize; float3 torsoPosition; Entity torso; { //UnityEngine.Mesh torsoMesh = (UnityEngine.Mesh)Resources.Load("torso", typeof(UnityEngine.Mesh)); torsoSize = torsoMesh.bounds.size; torsoPosition = headPosition - new float3(0, headRadius * 3.0f / 4.0f + torsoSize.y, 0); CollisionFilter filter = internalCollisions ? layerFilter(layer.Torso, layer.Thigh | layer.Head | layer.UpperArm | layer.Pelvis) : groupFilter(-ragdollIndex); NativeArray <float3> points = new NativeArray <float3>(torsoMesh.vertices.Length, Allocator.Temp); for (int i = 0; i < torsoMesh.vertices.Length; i++) { points[i] = torsoMesh.vertices[i]; } BlobAssetReference <Unity.Physics.Collider> collider = ConvexCollider.Create(points, 0.01f); collider.Value.Filter = filter; torso = CreateDynamicBody(torsoPosition, quaternion.identity, collider, float3.zero, float3.zero, 20.0f); } entities.Add(torso); // Neck { float3 pivotHead = new float3(0, -headRadius, 0); float3 pivotBody = math.transform(math.inverse(GetBodyTransform(torso)), math.transform(GetBodyTransform(head), pivotHead)); float3 axis = new float3(0, 1, 0); float3 perpendicular = new float3(0, 0, 1); float coneAngle = (float)math.PI / 5.0f; float minPerpendicularAngle = 0.0f; // unlimited float maxPerpendicularAngle = (float)math.PI; // unlimited float twistAngle = (float)math.PI / 3.0f; BlobAssetReference <JointData> ragdoll0, ragdoll1; JointData.CreateRagdoll(pivotHead, pivotBody, axis, axis, perpendicular, perpendicular, coneAngle, minPerpendicularAngle, maxPerpendicularAngle, -twistAngle, twistAngle, out ragdoll0, out ragdoll1); CreateJoint(ragdoll0, head, torso); CreateJoint(ragdoll1, head, torso); } // Arms { float armLength = 0.25f; float armRadius = 0.05f; CollisionFilter armUpperFilter = internalCollisions ? layerFilter(layer.UpperArm, layer.Torso | layer.Forearm) : groupFilter(-ragdollIndex); CollisionFilter armLowerFilter = internalCollisions ? layerFilter(layer.Forearm, layer.UpperArm | layer.Hand) : groupFilter(-ragdollIndex); BlobAssetReference <Unity.Physics.Collider> upperArmCollider = Unity.Physics.CapsuleCollider.Create(new float3(-armLength / 2, 0, 0), new float3(armLength / 2, 0, 0), armRadius, armUpperFilter); BlobAssetReference <Unity.Physics.Collider> foreArmCollider = Unity.Physics.CapsuleCollider.Create(new float3(-armLength / 2, 0, 0), new float3(armLength / 2, 0, 0), armRadius, armLowerFilter); float handLength = 0.025f; float handRadius = 0.055f; CollisionFilter handFilter = internalCollisions ? layerFilter(layer.Hand, layer.Forearm) : groupFilter(-ragdollIndex); BlobAssetReference <Unity.Physics.Collider> handCollider = Unity.Physics.CapsuleCollider.Create(new float3(-handLength / 2, 0, 0), new float3(handLength / 2, 0, 0), handRadius, handFilter); for (int i = 0; i < 2; i++) { float s = i * 2 - 1.0f; float3 upperArmPosition = torsoPosition + new float3(s * (torsoSize.x + armLength) / 2.0f, 0.9f * torsoSize.y - armRadius, 0.0f); Entity upperArm = CreateDynamicBody(upperArmPosition, quaternion.identity, upperArmCollider, float3.zero, float3.zero, 10.0f); float3 foreArmPosition = upperArmPosition + new float3(armLength * s, 0, 0); Entity foreArm = CreateDynamicBody(foreArmPosition, quaternion.identity, foreArmCollider, float3.zero, float3.zero, 5.0f); float3 handPosition = foreArmPosition + new float3((armLength + handLength) / 2.0f * s, 0, 0); Entity hand = CreateDynamicBody(handPosition, quaternion.identity, handCollider, float3.zero, float3.zero, 2.0f); entities.Add(upperArm); entities.Add(foreArm); entities.Add(hand); // shoulder { float3 pivotArm = new float3(-s * armLength / 2.0f, 0, 0); float3 pivotBody = math.transform(math.inverse(GetBodyTransform(torso)), math.transform(GetBodyTransform(upperArm), pivotArm)); float3 axis = new float3(s, 0, 0); float3 perpendicular = new float3(0, 0, 1); float coneAngle = (float)math.PI / 2.0f; float minPerpendicularAngle = 0.0f; float maxPerpendicularAngle = (float)math.PI / 2.0f; float twistAngle = (float)math.PI / 4.0f; BlobAssetReference <JointData> ragdoll0, ragdoll1; JointData.CreateRagdoll(pivotArm, pivotBody, axis, axis, perpendicular, perpendicular, coneAngle, minPerpendicularAngle, maxPerpendicularAngle, -twistAngle, twistAngle, out ragdoll0, out ragdoll1); CreateJoint(ragdoll0, upperArm, torso); CreateJoint(ragdoll1, upperArm, torso); } // elbow { float3 pivotUpper = new float3(s * armLength / 2.0f, 0, 0); float3 pivotFore = -pivotUpper; float3 axis = new float3(0, -s, 0); float3 perpendicular = new float3(s, 0, 0); float minAngle = 0.0f; float maxAngle = 3.0f; BlobAssetReference <JointData> hinge = JointData.CreateLimitedHinge(pivotFore, pivotUpper, axis, axis, perpendicular, perpendicular, minAngle, maxAngle); CreateJoint(hinge, foreArm, upperArm); } // wrist { float3 pivotFore = new float3(s * armLength / 2.0f, 0, 0); float3 pivotHand = new float3(-s * handLength / 2.0f, 0, 0); float3 axis = new float3(0, -s, 0); float3 perpendicular = new float3(s, 0, 0); float minAngle = -0.3f; float maxAngle = 0.6f; BlobAssetReference <JointData> hinge = JointData.CreateLimitedHinge(pivotHand, pivotFore, axis, axis, perpendicular, perpendicular, minAngle, maxAngle); CreateJoint(hinge, hand, foreArm); } } } // Pelvis float pelvisRadius = 0.08f; float pelvisLength = 0.22f; float3 pelvisPosition = torsoPosition - new float3(0, pelvisRadius * 0.75f, 0.0f); Entity pelvis; { CollisionFilter filter = internalCollisions ? layerFilter(layer.Pelvis, layer.Torso | layer.Thigh) : groupFilter(-ragdollIndex); BlobAssetReference <Unity.Physics.Collider> collider = Unity.Physics.CapsuleCollider.Create(new float3(-pelvisLength / 2.0f, 0, 0), new float3(pelvisLength / 2.0f, 0, 0), pelvisRadius, filter); pelvis = CreateDynamicBody(pelvisPosition, quaternion.identity, collider, float3.zero, float3.zero, 15.0f); } entities.Add(pelvis); // Waist { float3 pivotTorso = float3.zero; float3 pivotPelvis = math.transform(math.inverse(GetBodyTransform(pelvis)), math.transform(GetBodyTransform(torso), pivotTorso)); float3 axis = new float3(0, -1, 0); float3 perpendicular = new float3(0, 0, 1); float coneAngle = 0.1f; float minPerpendicularAngle = -0.1f; float maxPerpendicularAngle = (float)math.PI; float twistAngle = 0.1f; BlobAssetReference <JointData> ragdoll0, ragdoll1; JointData.CreateRagdoll(pivotPelvis, pivotTorso, axis, axis, perpendicular, perpendicular, coneAngle, minPerpendicularAngle, maxPerpendicularAngle, -twistAngle, twistAngle, out ragdoll0, out ragdoll1); CreateJoint(ragdoll0, pelvis, torso); CreateJoint(ragdoll1, pelvis, torso); } // Legs { float thighLength = 0.32f; float thighRadius = 0.08f; CollisionFilter thighFilter = internalCollisions ? layerFilter(layer.Thigh, layer.Pelvis | layer.Calf) : groupFilter(-ragdollIndex); BlobAssetReference <Unity.Physics.Collider> thighCollider = Unity.Physics.CapsuleCollider.Create(new float3(0, -thighLength / 2, 0), new float3(0, thighLength / 2, 0), thighRadius, thighFilter); float calfLength = 0.32f; float calfRadius = 0.06f; CollisionFilter calfFilter = internalCollisions ? layerFilter(layer.Calf, layer.Thigh | layer.Foot) : groupFilter(-ragdollIndex); BlobAssetReference <Unity.Physics.Collider> calfCollider = Unity.Physics.CapsuleCollider.Create(new float3(0, -calfLength / 2, 0), new float3(0, calfLength / 2, 0), calfRadius, calfFilter); float footLength = 0.08f; float footRadius = 0.06f; CollisionFilter footFilter = internalCollisions ? layerFilter(layer.Foot, layer.Calf) : groupFilter(-ragdollIndex); BlobAssetReference <Unity.Physics.Collider> footCollider = Unity.Physics.CapsuleCollider.Create(new float3(0, 0, 0), new float3(0, 0, footLength), footRadius, footFilter); for (int i = 0; i < 2; i++) { float s = i * 2 - 1.0f; float3 thighPosition = pelvisPosition + new float3(s * pelvisLength / 2.0f, -thighLength / 2.0f, 0.0f); Entity thigh = CreateDynamicBody(thighPosition, quaternion.identity, thighCollider, float3.zero, float3.zero, 10.0f); float3 calfPosition = thighPosition + new float3(0, -(thighLength + calfLength) / 2.0f, 0); Entity calf = CreateDynamicBody(calfPosition, quaternion.identity, calfCollider, float3.zero, float3.zero, 5.0f); float3 footPosition = calfPosition + new float3(0, -calfLength / 2.0f, 0); Entity foot = CreateDynamicBody(footPosition, quaternion.identity, footCollider, float3.zero, float3.zero, 2.0f); entities.Add(thigh); entities.Add(calf); entities.Add(foot); // hip { float3 pivotThigh = new float3(0, thighLength / 2.0f, 0); float3 pivotBody = math.transform(math.inverse(GetBodyTransform(torso)), math.transform(GetBodyTransform(thigh), pivotThigh)); float3 axis = new float3(0, -1, 0); float3 perpendicular = new float3(s, 0, 0); float coneAngle = (float)math.PI / 4.0f; float minPerpendicularAngle = 0.0f; float maxPerpendicularAngle = 0.2f + (float)math.PI / 2.0f; float twistAngle = 0.2f; BlobAssetReference <JointData> ragdoll0, ragdoll1; JointData.CreateRagdoll(pivotThigh, pivotBody, axis, axis, perpendicular, perpendicular, coneAngle, minPerpendicularAngle, maxPerpendicularAngle, -twistAngle, twistAngle, out ragdoll0, out ragdoll1); CreateJoint(ragdoll0, thigh, torso); CreateJoint(ragdoll1, thigh, torso); } // knee { float3 pivotThigh = new float3(0, -thighLength / 2.0f, 0); float3 pivotCalf = math.transform(math.inverse(GetBodyTransform(calf)), math.transform(GetBodyTransform(thigh), pivotThigh)); float3 axis = new float3(-1, 0, 0); float3 perpendicular = new float3(0, 0, 1); float minAngle = -1.2f; float maxAngle = 0.0f; BlobAssetReference <JointData> hinge = JointData.CreateLimitedHinge(pivotCalf, pivotThigh, axis, axis, perpendicular, perpendicular, minAngle, maxAngle); CreateJoint(hinge, calf, thigh); } // ankle { float3 pivotCalf = new float3(0, -calfLength / 2.0f, 0); float3 pivotFoot = float3.zero; float3 axis = new float3(-1, 0, 0); float3 perpendicular = new float3(0, 0, 1); float minAngle = -0.4f; float maxAngle = 0.1f; BlobAssetReference <JointData> hinge = JointData.CreateLimitedHinge(pivotFoot, pivotCalf, axis, axis, perpendicular, perpendicular, minAngle, maxAngle); CreateJoint(hinge, foot, calf); } } } // reposition with offset information if (entities.Length > 0) { float3 center = float3.zero; for (int i = 0; i < entities.Length; i++) { var e = entities[i]; center += EntityManager.GetComponentData <Translation>(e).Value; } center /= entities.Length; for (int i = 0; i < entities.Length; i++) { var e = entities[i]; Translation positionComponent = EntityManager.GetComponentData <Translation>(e); Rotation rotationComponent = EntityManager.GetComponentData <Rotation>(e); float3 position = positionComponent.Value; quaternion rotation = rotationComponent.Value; float3 localPosition = position - center; localPosition = math.rotate(rotationOffset, localPosition); position = localPosition + center + positionOffset; rotation = math.mul(rotation, rotationOffset); positionComponent.Value = position; rotationComponent.Value = rotation; EntityManager.SetComponentData <Translation>(e, positionComponent); EntityManager.SetComponentData <Rotation>(e, rotationComponent); } } }