private unsafe int BuildBoundingVolume(out NativeArray <BoundingVolumeHierarchy.Node> nodes) { // Create inputs var points = new NativeArray <BoundingVolumeHierarchy.PointAndIndex>(NumChildren, Allocator.Temp, NativeArrayOptions.UninitializedMemory); var aabbs = new NativeArray <Aabb>(NumChildren, Allocator.Temp, NativeArrayOptions.UninitializedMemory); for (int i = 0; i < NumChildren; ++i) { points[i] = new BoundingVolumeHierarchy.PointAndIndex { Position = Children[i].CompoundFromChild.pos, Index = i }; aabbs[i] = Children[i].Collider->CalculateAabb(Children[i].CompoundFromChild); } // Build BVH // Todo: cleanup, better size of nodes array nodes = new NativeArray <BoundingVolumeHierarchy.Node>(2 + NumChildren, Allocator.Temp, NativeArrayOptions.UninitializedMemory) { [0] = BoundingVolumeHierarchy.Node.Empty, [1] = BoundingVolumeHierarchy.Node.Empty }; var bvh = new BoundingVolumeHierarchy(nodes); bvh.Build(points, aabbs, out int numNodes); return(numNodes); }
public static unsafe BlobAssetReference <Collider> Create(NativeArray <float3> vertices, NativeArray <int3> triangles, CollisionFilter filter, Material material) { SafetyChecks.CheckTriangleIndicesInRangeAndThrow(triangles, vertices.Length, nameof(triangles)); // Copy vertices var tempVertices = new NativeArray <float3>(vertices, Allocator.Temp); // Triangle indices - needed for WeldVertices var tempIndices = new NativeArray <int>(triangles.Reinterpret <int>(UnsafeUtility.SizeOf <int3>()), Allocator.Temp); // Build connectivity and primitives NativeList <float3> uniqueVertices = MeshConnectivityBuilder.WeldVertices(tempIndices, tempVertices); var tempTriangleIndices = new NativeArray <int3>(triangles.Length, Allocator.Temp); UnsafeUtility.MemCpy(tempTriangleIndices.GetUnsafePtr(), tempIndices.GetUnsafePtr(), tempIndices.Length * UnsafeUtility.SizeOf <int>()); var connectivity = new MeshConnectivityBuilder(tempTriangleIndices, uniqueVertices); NativeList <MeshConnectivityBuilder.Primitive> primitives = connectivity.EnumerateQuadDominantGeometry(tempTriangleIndices, uniqueVertices); // Build bounding volume hierarchy int nodeCount = math.max(primitives.Length * 2 + 1, 2); // We need at least two nodes - an "invalid" node and a root node. var nodes = new NativeArray <BoundingVolumeHierarchy.Node>(nodeCount, Allocator.Temp); int numNodes = 0; { // Prepare data for BVH var points = new NativeList <BoundingVolumeHierarchy.PointAndIndex>(primitives.Length, Allocator.Temp); var aabbs = new NativeArray <Aabb>(primitives.Length, Allocator.Temp); for (int i = 0; i < primitives.Length; i++) { MeshConnectivityBuilder.Primitive p = primitives[i]; // Skip degenerate triangles if (MeshConnectivityBuilder.IsTriangleDegenerate(p.Vertices[0], p.Vertices[1], p.Vertices[2])) { continue; } aabbs[i] = Aabb.CreateFromPoints(p.Vertices); points.Add(new BoundingVolumeHierarchy.PointAndIndex { Position = aabbs[i].Center, Index = i }); } var bvh = new BoundingVolumeHierarchy(nodes); bvh.Build(points.AsArray(), aabbs, out numNodes, useSah: true); } // Build mesh sections BoundingVolumeHierarchy.Node *nodesPtr = (BoundingVolumeHierarchy.Node *)nodes.GetUnsafePtr(); MeshBuilder.TempSection sections = MeshBuilder.BuildSections(nodesPtr, numNodes, primitives); // Allocate collider int meshDataSize = Mesh.CalculateMeshDataSize(numNodes, sections.Ranges); int totalColliderSize = Math.NextMultipleOf(sizeof(MeshCollider), 16) + meshDataSize; MeshCollider *meshCollider = (MeshCollider *)UnsafeUtility.Malloc(totalColliderSize, 16, Allocator.Temp); // Initialize it { UnsafeUtility.MemClear(meshCollider, totalColliderSize); meshCollider->MemorySize = totalColliderSize; meshCollider->m_Header.Type = ColliderType.Mesh; meshCollider->m_Header.CollisionType = CollisionType.Composite; meshCollider->m_Header.Version += 1; meshCollider->m_Header.Magic = 0xff; ref var mesh = ref meshCollider->Mesh; mesh.Init(nodesPtr, numNodes, sections, filter, material); mesh.UpdateCachedBoundingRadius(); // Calculate combined filter meshCollider->m_Header.Filter = mesh.Sections.Length > 0 ? mesh.Sections[0].Filters[0] : CollisionFilter.Default; for (int i = 0; i < mesh.Sections.Length; ++i) { for (var j = 0; j < mesh.Sections[i].Filters.Length; ++j) { var f = mesh.Sections[i].Filters[j]; meshCollider->m_Header.Filter = CollisionFilter.CreateUnion(meshCollider->m_Header.Filter, f); } } meshCollider->m_Aabb = meshCollider->Mesh.BoundingVolumeHierarchy.Domain; meshCollider->NumColliderKeyBits = meshCollider->Mesh.NumColliderKeyBits; }