public bool IsChildActiveAndBelongsToShape(T child, bool filterOutInvalid = true)
        {
            var meshFilter = (UnityComponent)child as MeshFilter;

            if (meshFilter != null)
            {
                if (meshFilter.sharedMesh == null)
                {
                    return(false);
                }

                var renderer = meshFilter.GetComponent <MeshRenderer>();
                if (renderer == null || !renderer.enabled)
                {
                    return(false);
                }

                if (filterOutInvalid && !meshFilter.sharedMesh.IsValidForConversion(m_Shape.gameObject))
                {
                    return(false);
                }
            }

            if (m_CheckIfComponentBelongsToShape)
            {
                if (PhysicsShapeExtensions.GetPrimaryBody(child.gameObject) != m_PrimaryBody)
                {
                    return(false);
                }

                child.gameObject.GetComponentsInParent(true, s_PhysicsShapes);
                if (s_PhysicsShapes[0] != m_Shape)
                {
                    s_PhysicsShapes.Clear();
                    return(false);
                }
            }

            // do not simply use GameObject.activeInHierarchy because it will be false when instantiating a prefab
            var t = child.transform;
            var activeInHierarchy = t.gameObject.activeSelf;

            while (activeInHierarchy && t != m_Root)
            {
                t = t.parent;
                activeInHierarchy &= t.gameObject.activeSelf;
            }

            return(activeInHierarchy);
        }
 public GetActiveChildrenScope(PhysicsShapeAuthoring shape, Transform root)
 {
     m_Disposed    = false;
     m_Shape       = shape;
     m_Root        = root;
     m_PrimaryBody = PhysicsShapeExtensions.GetPrimaryBody(root.gameObject);
     m_CheckIfComponentBelongsToShape = root.transform.IsChildOf(shape.transform);
     if (s_BufferUsed)
     {
         throw new InvalidOperationException($"Cannot nest two {GetType()}");
     }
     s_BufferUsed = true;
     root.GetComponentsInChildren(true, s_Buffer);
 }
Example #3
0
        static void GetQuantizedTransformations(
            float4x4 leafToBody, Aabb bounds,
            out float3 translation, out quaternion orientationQ, out float3 scale, out float3x3 shear,
            float linearPrecision = k_DefaultLinearPrecision
            )
        {
            translation = RoundToNearest(leafToBody.c3.xyz, linearPrecision);

            var farthestPoint =
                math.abs(math.lengthsq(bounds.Max) > math.lengthsq(bounds.Min) ? bounds.Max : bounds.Min);

            // round scale using precision inversely proportional to mesh size along largest axis
            // (i.e. amount to scale farthest point one unit of linear precision)
            var scalePrecision = linearPrecision / math.max(math.cmax(farthestPoint), math.FLT_MIN_NORMAL);

            scale = RoundToNearest(leafToBody.DecomposeScale(), scalePrecision);
            if (math.determinant(leafToBody) < 0f)
            {
                scale.x *= -1f;
            }

            shear = new float3x3(
                leafToBody.c0.xyz / math.max(math.abs(scale.x), math.FLT_MIN_NORMAL) * math.sign(scale.x),
                leafToBody.c1.xyz / math.max(math.abs(scale.y), math.FLT_MIN_NORMAL) * math.sign(scale.y),
                leafToBody.c2.xyz / math.max(math.abs(scale.z), math.FLT_MIN_NORMAL) * math.sign(scale.z)
                );
            var orientation = float3x3.LookRotationSafe(shear.c2, shear.c1);

            // if shear is very nearly identity, hash it as identity
            // TODO: quantize shear
            shear = math.mul(shear, math.inverse(orientation));
            if (!PhysicsShapeExtensions.HasShear(new float4x4(shear, 0f)))
            {
                shear = float3x3.identity;
            }

            // round orientation using precision inversely proportional to scaled mesh size
            // (i.e. radians to rotate farthest scaled point one unit of linear precision)
            var angularPrecision = math.min(linearPrecision / math.length(farthestPoint * scale), math.PI);
            var axisPrecision    = math.min(math.cos(angularPrecision), math.sin(angularPrecision));

            orientation.c0 = math.normalize(RoundToNearest(orientation.c0, axisPrecision));
            orientation.c1 = math.normalize(RoundToNearest(orientation.c1, axisPrecision));
            orientation.c2 = math.normalize(RoundToNearest(orientation.c2, axisPrecision));

            translation  = Sanitize(translation);
            orientationQ = new quaternion(Sanitize(orientation));
            scale        = Sanitize(scale);
            shear        = Sanitize(shear);
        }
Example #4
0
        internal override ShapeComputationData GenerateComputationData(
            PhysicsShapeAuthoring shape, ColliderInstance colliderInstance,
            NativeList <float3> allConvexHullPoints, NativeList <float3> allMeshVertices, NativeList <int3> allMeshTriangles
            )
        {
            var res = new ShapeComputationData();

            res.Instance              = colliderInstance;
            res.Material              = ProduceMaterial(shape);
            res.CollisionFilter       = ProduceCollisionFilter(shape);
            res.ForceUniqueIdentifier = shape.ForceUnique ? (uint)shape.GetInstanceID() : 0u;

            var         transform    = shape.transform;
            var         localToWorld = transform.localToWorldMatrix;
            var         shapeToWorld = shape.GetShapeToWorldMatrix();
            EulerAngles orientation;

            res.ShapeType = shape.ShapeType;
            switch (shape.ShapeType)
            {
            case ShapeType.Box:
            {
                res.BoxProperties = shape.GetBoxProperties(out orientation)
                                    .BakeToBodySpace(localToWorld, shapeToWorld, orientation);
                break;
            }

            case ShapeType.Capsule:
            {
                res.CapsuleProperties = shape.GetCapsuleProperties()
                                        .BakeToBodySpace(localToWorld, shapeToWorld)
                                        .ToRuntime();
                break;
            }

            case ShapeType.Sphere:
            {
                res.SphereProperties = shape.GetSphereProperties(out orientation)
                                       .BakeToBodySpace(localToWorld, shapeToWorld, ref orientation);
                break;
            }

            case ShapeType.Cylinder:
            {
                res.CylinderProperties = shape.GetCylinderProperties(out orientation)
                                         .BakeToBodySpace(localToWorld, shapeToWorld, orientation);
                break;
            }

            case ShapeType.Plane:
            {
                shape.GetPlaneProperties(out var center, out var size, out orientation);
                PhysicsShapeExtensions.BakeToBodySpace(
                    center, size, orientation, localToWorld, shapeToWorld,
                    out res.PlaneVertices.c0, out res.PlaneVertices.c1, out res.PlaneVertices.c2, out res.PlaneVertices.c3
                    );
                break;
            }

            case ShapeType.ConvexHull:
            {
                res.ConvexHullProperties.Filter               = res.CollisionFilter;
                res.ConvexHullProperties.Material             = res.Material;
                res.ConvexHullProperties.GenerationParameters = shape.ConvexHullGenerationParameters.ToRunTime();

                res.Instance.Hash = shape.GetBakedConvexInputs();

                if (BlobComputationContext.NeedToComputeBlobAsset(res.Instance.Hash))
                {
                    if (TryGetRegisteredConvexInputs(res.Instance.Hash, out var convexInputs))
                    {
                        res.ConvexHullProperties.PointCount  = convexInputs.PointCount;
                        res.ConvexHullProperties.PointsStart = convexInputs.PointsStart;
                    }
                    else
                    {
                        using (var pointCloud = new NativeList <float3>(65535, Allocator.Temp))
                        {
                            shape.GetBakedConvexProperties(pointCloud);
                            if (pointCloud.Length == 0)
                            {
                                throw new InvalidOperationException(
                                          $"No vertices associated with {shape.name}. Add a {typeof(MeshFilter)} component or assign a readable {nameof(PhysicsShapeAuthoring.CustomMesh)}."
                                          );
                            }

                            res.ConvexHullProperties.PointCount  = pointCloud.Length;
                            res.ConvexHullProperties.PointsStart = allConvexHullPoints.Length;
                            allConvexHullPoints.AddRange(pointCloud);
                        }
                    }
                }

                break;
            }

            case ShapeType.Mesh:
            {
                res.MeshProperties.Filter   = res.CollisionFilter;
                res.MeshProperties.Material = res.Material;

                res.Instance.Hash = shape.GetBakedMeshInputs();

                if (BlobComputationContext.NeedToComputeBlobAsset(res.Instance.Hash))
                {
                    if (TryGetRegisteredMeshInputs(res.Instance.Hash, out var meshInputs))
                    {
                        res.MeshProperties.VerticesStart  = meshInputs.VerticesStart;
                        res.MeshProperties.VertexCount    = meshInputs.VertexCount;
                        res.MeshProperties.TrianglesStart = meshInputs.TrianglesStart;
                        res.MeshProperties.TriangleCount  = meshInputs.TriangleCount;
                    }
                    else
                    {
                        const int defaultVertexCount = 2048;
                        using (var vertices = new NativeList <float3>(defaultVertexCount, Allocator.Temp))
                            using (var triangles = new NativeList <int3>(defaultVertexCount - 2, Allocator.Temp))
                            {
                                shape.GetBakedMeshProperties(vertices, triangles);
                                if (vertices.Length == 0 || triangles.Length == 0)
                                {
                                    throw new InvalidOperationException(
                                              $"Invalid mesh data associated with {shape.name}. " +
                                              $"Add a {typeof(MeshFilter)} component or assign a {nameof(PhysicsShapeAuthoring.CustomMesh)}. " +
                                              "Ensure that you have enabled Read/Write on the mesh's import settings."
                                              );
                                }

                                res.MeshProperties.VerticesStart  = allMeshVertices.Length;
                                res.MeshProperties.VertexCount    = vertices.Length;
                                res.MeshProperties.TrianglesStart = allMeshTriangles.Length;
                                res.MeshProperties.TriangleCount  = triangles.Length;
                                allMeshVertices.AddRange(vertices);
                                allMeshTriangles.AddRange(triangles);
                            }
                    }
                }

                break;
            }
            }

            return(res);
        }