// 27 Slicer // Copyright 2021 Deftly Games // https://slicer.deftly.games/ using System; using UnityEngine; using UnityEngine.Rendering; namespace Slicer.Core { /// /// Contains useful methods for slicing meshes /// public static class MeshUtility { /// /// Creates a copy of a mesh. /// /// The mesh to make a copy of. /// Returns the copy of the mesh. public static Mesh CopyMesh(Mesh origMesh) { if (origMesh == null) { return null; } var newMesh = Mesh.Instantiate(origMesh); var mode = Application.isPlaying ? "Runtime" : "Editor"; newMesh.name = $"{origMesh.name} {mode} Sliced"; newMesh.MarkDynamic(); return newMesh; } /// /// Creates a copy of a mesh. /// /// The mesh to make a copy of. /// Returns the copy of the mesh. public static void CopyMesh(Mesh sourceMesh, Mesh destMesh) { if (sourceMesh == null) { throw new ArgumentNullException(nameof(sourceMesh)); } if (destMesh == null) { throw new ArgumentNullException(nameof(destMesh)); } destMesh.Clear(); sourceMesh.GetVertices(TempCollections.Vector3); destMesh.SetVertices(TempCollections.Vector3); sourceMesh.GetNormals(TempCollections.Vector3); destMesh.SetNormals(TempCollections.Vector3); CopyUVs(sourceMesh, destMesh); sourceMesh.GetColors(TempCollections.Colors); destMesh.SetColors(TempCollections.Colors); sourceMesh.GetTangents(TempCollections.Vector4); destMesh.SetTangents(TempCollections.Vector4); var subMeshCount = sourceMesh.subMeshCount; destMesh.subMeshCount = subMeshCount; for (int i = 0; i < subMeshCount; i++) { var meshTopology = sourceMesh.GetTopology(i); sourceMesh.GetIndices(TempCollections.Integers, i); destMesh.SetIndices(TempCollections.Integers, meshTopology, i); } } private static void CopyUVs(Mesh sourceMesh, Mesh destMesh) { // Reset the modified UVs back to the original for (int uvChannel = 0; uvChannel < 7; uvChannel++) { var uvDimension = sourceMesh.GetVertexAttributeDimension(uvChannel + VertexAttribute.TexCoord0); switch (uvDimension) { case 2: sourceMesh.GetUVs(uvChannel, TempCollections.Vector2); destMesh.SetUVs(uvChannel, TempCollections.Vector2); break; case 3: sourceMesh.GetUVs(uvChannel, TempCollections.Vector3); destMesh.SetUVs(uvChannel, TempCollections.Vector3); break; case 4: sourceMesh.GetUVs(uvChannel, TempCollections.Vector4); destMesh.SetUVs(uvChannel, TempCollections.Vector4); break; default: continue; } } } /// /// Converts a meshes bounds into a bounds in slicer space (local space of the parent SlicerComponent). /// /// The mesh to encapsulate into the returned bounds. /// The transform of the GameObject that contains the mesh. /// The transform of the GameObject containing the SlicerController. /// The bounds that contains the meshes transformed vectors. public static Bounds CalculateBounds(Mesh mesh, Transform childTransform, Transform rootTransform) { // This matrix converts the local mesh vertex dependent on the transform // position, scale and orientation into a global position var matrix = MatrixUtility.BuildTransformMatrix(childTransform, rootTransform); var origSharedMesh = mesh; origSharedMesh.GetVertices(TempCollections.Vector3); var transformedBounds = VectorUtility.CalculateBounds(TempCollections.Vector3, matrix); TempCollections.Vector3.Clear(); return transformedBounds; } /// /// Resets the UVs in destMesh back to the UVs in sourceMesh /// /// The source mesh /// The destination mesh public static void ResetUV(Mesh sourceMesh, Mesh destMesh) { CopyUVs(sourceMesh, destMesh); } } }