static BlobAssetReference <Collider> CreateMeshTerrain(NativeArray <float> heights, int2 size, float3 scale) { var vertices = new NativeList <float3>(Allocator.Temp); var triangles = new NativeList <int3>(Allocator.Temp); var vertexIndex = 0; for (int i = 0; i < size.x - 1; i++) { for (int j = 0; j < size.y - 1; j++) { int i0 = i; int i1 = i + 1; int j0 = j; int j1 = j + 1; float3 v0 = new float3(i0, heights[i0 + size.x * j0], j0) * scale; float3 v1 = new float3(i1, heights[i1 + size.x * j0], j0) * scale; float3 v2 = new float3(i0, heights[i0 + size.x * j1], j1) * scale; float3 v3 = new float3(i1, heights[i1 + size.x * j1], j1) * scale; vertices.Add(v1); vertices.Add(v0); vertices.Add(v2); vertices.Add(v1); vertices.Add(v2); vertices.Add(v3); triangles.Add(new int3(vertexIndex++, vertexIndex++, vertexIndex++)); triangles.Add(new int3(vertexIndex++, vertexIndex++, vertexIndex++)); } } return(MeshCollider.Create(vertices, triangles)); }
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 = InputValues[index]; var vertices = new NativeArray <float3>( inputParameters.VertexCount, Allocator.Temp, NativeArrayOptions.UninitializedMemory ); UnsafeUtility.MemCpy( vertices.GetUnsafePtr(), (float3 *)AllVertices.GetUnsafeReadOnlyPtr() + inputParameters.VerticesStart, UnsafeUtility.SizeOf <float3>() * inputParameters.VertexCount ); var triangles = new NativeArray <int3>( inputParameters.TriangleCount, Allocator.Temp, NativeArrayOptions.UninitializedMemory ); UnsafeUtility.MemCpy( triangles.GetUnsafePtr(), (int3 *)AllIndices.GetUnsafeReadOnlyPtr() + inputParameters.TrianglesStart, UnsafeUtility.SizeOf <int3>() * inputParameters.TriangleCount ); Output[index] = new KeyValuePair <Hash128, BlobAssetReference <Collider> >( InputKeys[index], MeshCollider.Create(vertices, triangles, inputParameters.Filter, inputParameters.Material) ); }
public unsafe void Execute() { if (DummyRun) { return; } MeshCollider.Create(Vertices, Indices); }
public void Execute() { if (DummyRun) { return; } MeshCollider.Create(Vertices, Triangles); }
public void Execute(int index) { var inputParameters = InputValues[index]; Output[index] = new KeyValuePair <Hash128, BlobAssetReference <Collider> >( InputKeys[index], MeshCollider.Create( AllVertices.GetSubArray(inputParameters.VerticesStart, inputParameters.VertexCount), AllIndices.GetSubArray(inputParameters.TrianglesStart, inputParameters.TriangleCount), inputParameters.Filter, inputParameters.Material ) ); }
public static unsafe BlobAssetReference <Collider> Create(float3 *vertices, int *indices, int numVertices, int numIndices, CollisionFilter?filter = null, Material?material = null) { var v = new NativeArray <float3>(numVertices, Allocator.Temp); var vptr = NativeArrayUnsafeUtility.GetUnsafePtr(v); UnsafeUtility.MemCpy(vptr, vertices, numVertices * sizeof(float3)); var i = new NativeArray <int>(numIndices, Allocator.Temp); var iptr = NativeArrayUnsafeUtility.GetUnsafePtr(i); UnsafeUtility.MemCpy(iptr, indices, numIndices * sizeof(int)); var collider = MeshCollider.Create(v, i); v.Dispose(); i.Dispose(); return(collider); }
public void MeshCollider_Create_WhenTriangleIndexOutOfRange_Throws() { int numTriangles = 10; var vertices = new NativeArray <float3>(numTriangles * 3, Allocator.Persistent); var triangles = new NativeArray <int3>(numTriangles, Allocator.Persistent); try { for (int i = 0; i < numTriangles; i++) { int firstVertexIndex = i * 3; vertices[firstVertexIndex] = new float3(firstVertexIndex, 1f * (firstVertexIndex % 2), firstVertexIndex + 1); vertices[firstVertexIndex + 1] = new float3(firstVertexIndex + 1, 1f * ((firstVertexIndex + 1) % 2), firstVertexIndex + 2); vertices[firstVertexIndex + 2] = new float3(firstVertexIndex + 2, 1f * ((firstVertexIndex + 2) % 2), firstVertexIndex + 3); triangles[i] = new int3(firstVertexIndex, firstVertexIndex + 1, firstVertexIndex + 2); } Random rnd = new Random(0x12345678); for (int i = 0; i < 100; i++) { int indexToChange = rnd.NextInt(0, triangles.Length * 3 - 1); int triangleIndex = indexToChange / 3; int vertexInTriangle = indexToChange % 3; int invalidValue = rnd.NextInt() * (rnd.NextBool() ? -1 : 1); var triangle = triangles[triangleIndex]; triangle[vertexInTriangle] = invalidValue; triangles[triangleIndex] = triangle; Assert.Throws <ArgumentException>(() => MeshCollider.Create(vertices, triangles)); triangle[vertexInTriangle] = indexToChange; triangles[triangleIndex] = triangle; } } finally { triangles.Dispose(); vertices.Dispose(); } }
public void Execute(int index) { var inputParameters = InputParameters[index]; var vertices = new NativeArray <float3>( inputParameters.VertexCount, Allocator.Temp, NativeArrayOptions.UninitializedMemory ); UnsafeUtility.MemCpy( vertices.GetUnsafePtr(), (float3 *)AllVertices.GetUnsafeReadOnlyPtr() + inputParameters.VerticesStart, UnsafeUtility.SizeOf <float3>() * inputParameters.VertexCount ); var indices = new NativeArray <int>( inputParameters.IndexCount, Allocator.Temp, NativeArrayOptions.UninitializedMemory ); UnsafeUtility.MemCpy( indices.GetUnsafePtr(), (int *)AllIndices.GetUnsafeReadOnlyPtr() + inputParameters.IndicesStart, UnsafeUtility.SizeOf <int>() * inputParameters.IndexCount ); Output[index] = new KeyValuePair <Entity, LeafShapeData>( inputParameters.BodyEntity, new LeafShapeData { LeafEntity = inputParameters.LeafEntity, ColliderBlobInstance = new CompoundCollider.ColliderBlobInstance { CompoundFromChild = inputParameters.CompoundFromChild, Collider = MeshCollider.Create( vertices, indices, inputParameters.Filter, inputParameters.Material ) } } ); }
// // Random generation // public static unsafe BlobAssetReference <Collider> GenerateRandomMesh(ref Random rnd) { int numTriangles = rnd.NextInt(1, 250); float3[] vertices = new float3[numTriangles * 3]; int[] indices = new int[numTriangles * 3]; int nextIndex = 0; while (numTriangles > 0) { int featureTriangles = math.min(rnd.NextInt(1, 100), numTriangles); int featureType = rnd.NextInt(0, 3); switch (featureType) { case 0: { // Soup for (int i = 0; i < featureTriangles; i++) { float size = rnd.NextFloat(0.1f, 2.5f); size *= size; float3 center = rnd.NextFloat3(-10.0f, 10.0f); for (int j = 0; j < 3; j++) { vertices[nextIndex++] = center + rnd.NextFloat3(-size, size); } } break; } case 1: { // Fan float3 center = rnd.NextFloat3(-10.0f, 10.0f); float3 arm = rnd.NextFloat3Direction() * rnd.NextFloat(0.1f, 1.0f); float3 axis; { float3 unused; Math.CalculatePerpendicularNormalized(math.normalize(arm), out axis, out unused); } float arc = rnd.NextFloat(0.1f, 2.0f * (float)math.PI); arc = math.min(arc, featureTriangles * (float)math.PI / 2.0f); // avoid degenerate triangles featureTriangles = math.min(featureTriangles, (int)(arc / 0.025f)); // avoid degenerate triangles quaternion q = Unity.Mathematics.quaternion.AxisAngle(axis, arc / numTriangles); for (int i = 0; i < featureTriangles; i++) { vertices[nextIndex++] = center; vertices[nextIndex++] = center + arm; arm = math.mul(q, arm); vertices[nextIndex++] = center + arm; } break; } case 2: { // Strip float3 v0 = rnd.NextFloat3(-10.0f, 10.0f); float3 v1 = v0 + rnd.NextFloat3(-0.5f, 0.5f); float3 dir; { float3 unused; Math.CalculatePerpendicularNormalized(math.normalize(v1 - v0), out dir, out unused); } for (int i = 0; i < featureTriangles; i++) { float3 v2 = v0 + rnd.NextFloat(0.25f, 0.5f) * dir; dir = math.mul(Unity.Mathematics.quaternion.AxisAngle(rnd.NextFloat3Direction(), rnd.NextFloat(0.0f, 0.3f)), dir); vertices[nextIndex++] = v0; vertices[nextIndex++] = v1; vertices[nextIndex++] = v2; v0 = v1; v1 = v2; } break; } case 3: { // Grid int quads = featureTriangles / 2; if (quads == 0) { featureTriangles = 0; // Too small, try again for a different feature break; } int rows = rnd.NextInt(1, (int)math.sqrt(quads)); int cols = quads / rows; quads = rows * cols; featureTriangles = quads * 2; float3 origin = rnd.NextFloat3(-10.0f, 10.0f); float3 x = rnd.NextFloat3(-0.5f, 0.5f); float3 y = rnd.NextFloat3(-0.5f, 0.5f); for (int i = 0; i < rows; i++) { for (int j = 0; j < cols; j++) { vertices[nextIndex++] = origin + x * (i + 0) + y * (j + 0); vertices[nextIndex++] = origin + x * (i + 0) + y * (j + 1); vertices[nextIndex++] = origin + x * (i + 1) + y * (j + 1); vertices[nextIndex++] = origin + x * (i + 0) + y * (j + 0); vertices[nextIndex++] = origin + x * (i + 1) + y * (j + 1); vertices[nextIndex++] = origin + x * (i + 0) + y * (j + 1); } } break; } } numTriangles -= featureTriangles; } for (int i = 0; i < indices.Length; i++) { indices[i] = i; } return(MeshCollider.Create(vertices, indices)); }
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); }
public void Execute() => Output[0] = MeshCollider.Create(Points, Indices);
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); }