Exemple #1
0
        // Create a compound collider containing an array of other colliders.
        // The source colliders are copied into the compound, so that it becomes one blob.
        public static unsafe BlobAssetReference <Collider> Create(NativeArray <ColliderBlobInstance> children)
        {
            SafetyChecks.CheckNotEmptyAndThrow(children, nameof(children));

            // Get the total required memory size for the compound plus all its children,
            // and the combined filter of all children
            // TODO: Verify that the size is enough
            int             totalSize = Math.NextMultipleOf16(UnsafeUtility.SizeOf <CompoundCollider>());
            CollisionFilter filter    = children[0].Collider.Value.Filter;
            var             srcToDestInstanceAddrs = new NativeHashMap <long, long>(children.Length, Allocator.Temp);

            for (var childIndex = 0; childIndex < children.Length; childIndex++)
            {
                var child       = children[childIndex];
                var instanceKey = (long)child.Collider.GetUnsafePtr();
                if (srcToDestInstanceAddrs.ContainsKey(instanceKey))
                {
                    continue;
                }
                totalSize += Math.NextMultipleOf16(child.Collider.Value.MemorySize);
                filter     = CollisionFilter.CreateUnion(filter, child.Collider.Value.Filter);
                srcToDestInstanceAddrs.Add(instanceKey, 0L);
            }
            totalSize += (children.Length + BoundingVolumeHierarchy.Constants.MaxNumTreeBranches) * UnsafeUtility.SizeOf <BoundingVolumeHierarchy.Node>();

            // Allocate the collider
            var compoundCollider = (CompoundCollider *)UnsafeUtility.Malloc(totalSize, 16, Allocator.Temp);

            UnsafeUtility.MemClear(compoundCollider, totalSize);
            compoundCollider->m_Header.Type          = ColliderType.Compound;
            compoundCollider->m_Header.CollisionType = CollisionType.Composite;
            compoundCollider->m_Header.Version       = 1;
            compoundCollider->m_Header.Magic         = 0xff;
            compoundCollider->m_Header.Filter        = filter;

            // Initialize children array
            Child *childrenPtr = (Child *)((byte *)compoundCollider + UnsafeUtility.SizeOf <CompoundCollider>());

            compoundCollider->m_ChildrenBlob.Offset = (int)((byte *)childrenPtr - (byte *)(&compoundCollider->m_ChildrenBlob.Offset));
            compoundCollider->m_ChildrenBlob.Length = children.Length;
            byte *end = (byte *)childrenPtr + UnsafeUtility.SizeOf <Child>() * children.Length;

            end = (byte *)Math.NextMultipleOf16((ulong)end);

            uint maxTotalNumColliderKeyBits = 0;

            // Copy children
            for (int i = 0; i < children.Length; i++)
            {
                Collider *collider       = (Collider *)children[i].Collider.GetUnsafePtr();
                var       srcInstanceKey = (long)collider;
                var       dstAddr        = srcToDestInstanceAddrs[srcInstanceKey];
                if (dstAddr == 0L)
                {
                    dstAddr = (long)end;
                    srcToDestInstanceAddrs[srcInstanceKey] = dstAddr;
                    UnsafeUtility.MemCpy(end, collider, collider->MemorySize);
                    end += Math.NextMultipleOf16(collider->MemorySize);
                }
                childrenPtr[i].m_ColliderOffset  = (int)((byte *)dstAddr - (byte *)(&childrenPtr[i].m_ColliderOffset));
                childrenPtr[i].CompoundFromChild = children[i].CompoundFromChild;

                maxTotalNumColliderKeyBits = math.max(maxTotalNumColliderKeyBits, collider->TotalNumColliderKeyBits);
            }

            // Build mass properties
            compoundCollider->MassProperties = compoundCollider->BuildMassProperties();

            // Build bounding volume
            int numNodes = compoundCollider->BuildBoundingVolume(out NativeArray <BoundingVolumeHierarchy.Node> nodes);
            int bvhSize  = numNodes * UnsafeUtility.SizeOf <BoundingVolumeHierarchy.Node>();

            compoundCollider->m_BvhNodesBlob.Offset = (int)(end - (byte *)(&compoundCollider->m_BvhNodesBlob.Offset));
            compoundCollider->m_BvhNodesBlob.Length = numNodes;
            UnsafeUtility.MemCpy(end, nodes.GetUnsafeReadOnlyPtr(), bvhSize);
            compoundCollider->UpdateCachedBoundingRadius();
            end += bvhSize;

            // Validate nesting level of composite colliders.
            compoundCollider->TotalNumColliderKeyBits = maxTotalNumColliderKeyBits + compoundCollider->NumColliderKeyBits;

            // If TotalNumColliderKeyBits is greater than 32, it means maximum nesting level of composite colliders has been breached.
            // ColliderKey has 32 bits so it can't handle infinite nesting of composite colliders.
            if (compoundCollider->TotalNumColliderKeyBits > 32)
            {
                SafetyChecks.ThrowArgumentException(nameof(children), "Composite collider exceeded maximum level of nesting!");
            }

            // Copy to blob asset
            int usedSize = (int)(end - (byte *)compoundCollider);

            UnityEngine.Assertions.Assert.IsTrue(usedSize < totalSize);
            compoundCollider->MemorySize = usedSize;
            var blob = BlobAssetReference <Collider> .Create(compoundCollider, usedSize);

            UnsafeUtility.Free(compoundCollider, Allocator.Temp);

            return(blob);
        }
Exemple #2
0
        // Create a compound collider containing an array of other colliders.
        // The source colliders are copied into the compound, so that it becomes one blob.
        public static unsafe BlobAssetReference <Collider> Create(NativeArray <ColliderBlobInstance> children)
        {
            if (children.Length == 0)
            {
                throw new ArgumentException();
            }

            // Get the total required memory size for the compound plus all its children,
            // and the combined filter of all children
            // TODO: Verify that the size is enough
            int             totalSize = Math.NextMultipleOf16(UnsafeUtility.SizeOf <CompoundCollider>());
            CollisionFilter filter    = children[0].Collider.Value.Filter;

            foreach (var child in children)
            {
                totalSize += Math.NextMultipleOf16(child.Collider.Value.MemorySize);
                filter     = CollisionFilter.CreateUnion(filter, child.Collider.Value.Filter);
            }
            totalSize += (children.Length + BoundingVolumeHierarchy.Constants.MaxNumTreeBranches) * UnsafeUtility.SizeOf <BoundingVolumeHierarchy.Node>();

            // Allocate the collider
            var compoundCollider = (CompoundCollider *)UnsafeUtility.Malloc(totalSize, 16, Allocator.Temp);

            UnsafeUtility.MemClear(compoundCollider, totalSize);
            compoundCollider->m_Header.Type          = ColliderType.Compound;
            compoundCollider->m_Header.CollisionType = CollisionType.Composite;
            compoundCollider->m_Header.Version       = 0;
            compoundCollider->m_Header.Magic         = 0xff;
            compoundCollider->m_Header.Filter        = filter;

            // Initialize children array
            Child *childrenPtr = (Child *)((byte *)compoundCollider + UnsafeUtility.SizeOf <CompoundCollider>());

            compoundCollider->m_ChildrenBlob.Offset = (int)((byte *)childrenPtr - (byte *)(&compoundCollider->m_ChildrenBlob.Offset));
            compoundCollider->m_ChildrenBlob.Length = children.Length;
            byte *end = (byte *)childrenPtr + UnsafeUtility.SizeOf <Child>() * children.Length;

            end = (byte *)Math.NextMultipleOf16((ulong)end);

            // Copy children
            for (int i = 0; i < children.Length; i++)
            {
                Collider *collider = (Collider *)children[i].Collider.GetUnsafePtr();
                UnsafeUtility.MemCpy(end, collider, collider->MemorySize);
                childrenPtr[i].m_ColliderOffset  = (int)(end - (byte *)(&childrenPtr[i].m_ColliderOffset));
                childrenPtr[i].CompoundFromChild = children[i].CompoundFromChild;
                end += Math.NextMultipleOf16(collider->MemorySize);
            }

            // Build mass properties
            compoundCollider->MassProperties = compoundCollider->BuildMassProperties();

            // Build bounding volume
            int numNodes = compoundCollider->BuildBoundingVolume(out NativeArray <BoundingVolumeHierarchy.Node> nodes);
            int bvhSize  = numNodes * UnsafeUtility.SizeOf <BoundingVolumeHierarchy.Node>();

            compoundCollider->m_BvhNodesBlob.Offset = (int)(end - (byte *)(&compoundCollider->m_BvhNodesBlob.Offset));
            compoundCollider->m_BvhNodesBlob.Length = numNodes;
            UnsafeUtility.MemCpy(end, nodes.GetUnsafeReadOnlyPtr(), bvhSize);
            end += bvhSize;
            nodes.Dispose();

            // Copy to blob asset
            int usedSize = (int)(end - (byte *)compoundCollider);

            UnityEngine.Assertions.Assert.IsTrue(usedSize < totalSize);
            compoundCollider->MemorySize = usedSize;
            var blob = BlobAssetReference <Collider> .Create(compoundCollider, usedSize);

            UnsafeUtility.Free(compoundCollider, Allocator.Temp);

            return(blob);
        }