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); }
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); }
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); }