/// <summary> /// Copies mesh data from one native array to another /// </summary> public static bool CopyNativeDataToMesh(NativeMeshData from, Mesh to, DataFlags dataFlags) { if (!from.HasValidData()) { Debug.LogError("Cannot copy data as some of it is invalid"); return(false); } if (to == null) { Debug.LogError("Cannot copy data to null mesh"); return(false); } if ((dataFlags & DataFlags.Vertices) != 0) { to.SetVertices(from.VertexBuffer); } if ((dataFlags & DataFlags.Normals) != 0) { to.SetNormals(from.NormalBuffer); } if ((dataFlags & DataFlags.Tangents) != 0) { to.SetTangents(from.TangentBuffer); } if ((dataFlags & DataFlags.UVs) != 0) { to.SetUVs(0, from.UVBuffer); } if ((dataFlags & DataFlags.Colors) != 0) { to.SetColors(from.ColorBuffer); } if ((dataFlags & DataFlags.Triangles) != 0) { for (int i = 0; i < to.subMeshCount; i++) { var submesh = to.GetSubMesh(i); to.SetIndices ( indices: from.IndexBuffer, indicesStart: submesh.indexStart, indicesLength: submesh.indexCount, topology: submesh.topology, submesh: i, calculateBounds: false, baseVertex: submesh.baseVertex ); } } if ((dataFlags & DataFlags.Bounds) != 0) { to.bounds = from.Bounds[0]; } return(true); }
/// <summary> /// Returns a job chain that will recalculate the bounds of the native data. /// </summary> public static JobHandle RecalculateBounds(NativeMeshData data, JobHandle dependency = default) { return(new RecalculateBoundsJob { bounds = data.Bounds, vertices = data.VertexBuffer }.Schedule(dependency)); }
/// <summary> /// Copies mesh data from managed arrays into native ones. /// </summary> public static bool CopyManagedToNativeMeshData(ManagedMeshData managed, NativeMeshData native, DataFlags dataFlags) { var dataIsValid = true; if (!managed.HasValidData()) { dataIsValid = false; Debug.LogError("Cannot copy data as the managed data is invalid"); } if (!native.HasValidData()) { Debug.LogError("Cannot copy data as the native data is invalid"); dataIsValid = false; } if (!dataIsValid) { return(false); } if ((dataFlags & DataFlags.Vertices) != 0) { managed.Vertices.MemCpy(native.VertexBuffer); } if ((dataFlags & DataFlags.Normals) != 0) { managed.Normals.MemCpy(native.NormalBuffer); } if ((dataFlags & DataFlags.MaskVertices) != 0) { managed.Vertices.MemCpy(native.MaskVertexBuffer); } if ((dataFlags & DataFlags.Tangents) != 0) { managed.Tangents.MemCpy(native.TangentBuffer); } if ((dataFlags & DataFlags.UVs) != 0) { managed.UVs.MemCpy(native.UVBuffer); } if ((dataFlags & DataFlags.Colors) != 0) { managed.Colors.MemCpy(native.ColorBuffer); } if ((dataFlags & DataFlags.Triangles) != 0) { managed.Triangles.MemCpy(native.IndexBuffer); } if ((dataFlags & DataFlags.Bounds) != 0) { native.Bounds[0] = managed.Bounds; } return(true); }
public bool Initialize(GameObject targetObject) { if (Target == null) { Target = new MeshTarget(); } if (!Target.Initialize(targetObject)) { return(false); } // Store the original mesh and make a copy (stored in dynamicMesh). // Assign the copy back to the filter so that this object has a unique mesh. if (!initialized) { OriginalMesh = Target.GetMesh(); if (OriginalMesh == null) { return(false); } DynamicMesh = GameObject.Instantiate(Target.GetMesh()); } // Since this has already been initialized, make a new mesh for the dynamic mesh to reference // so that two Deformables aren't displaying and modifying the same mesh. else if (OriginalMesh != null) { DynamicMesh = GameObject.Instantiate(OriginalMesh); } else { return(false); } // Tell the mesh filter to display the dynamic mesh. Target.SetMesh(DynamicMesh); // Mark the dynamic mesh as dynamic for a hypothetical performance boost. // (I've heard this method doesn't do anything) DynamicMesh.MarkDynamic(); Length = DynamicMesh.vertexCount; // Store mesh information in managed data. originalManaged = new ManagedMeshData(DynamicMesh); dynamicManaged = new ManagedMeshData(DynamicMesh); // Copy the managed data into native data. OriginalNative = new NativeMeshData(originalManaged); DynamicNative = new NativeMeshData(dynamicManaged); initialized = true; return(true); }
/// <summary> /// Copies mesh data from native arrays into managed ones. /// </summary> /// <param name="onlyEssentials">If true, only vertices, normals and bounds are copied. The mask data isn't copied because is only exists in native data.</param> public static void CopyNativeDataToManagedData(ManagedMeshData managed, NativeMeshData native, DataFlags dataFlags) { var dataIsValid = true; if (!managed.HasValidData()) { dataIsValid = false; Debug.LogError("Cannot copy data as the managed data is invalid"); } if (!native.HasValidData()) { Debug.LogError("Cannot copy data as the native data is invalid"); dataIsValid = false; } if (!dataIsValid) { return; } if ((dataFlags & DataFlags.Vertices) != 0) { native.VertexBuffer.MemCpy(managed.Vertices); } if ((dataFlags & DataFlags.Normals) != 0) { native.NormalBuffer.MemCpy(managed.Normals); } if ((dataFlags & DataFlags.Tangents) != 0) { native.TangentBuffer.MemCpy(managed.Tangents); } if ((dataFlags & DataFlags.UVs) != 0) { native.UVBuffer.MemCpy(managed.UVs); } if ((dataFlags & DataFlags.Colors) != 0) { native.ColorBuffer.MemCpy(managed.Colors); } if ((dataFlags & DataFlags.Triangles) != 0) { native.IndexBuffer.CopyTo(managed.Triangles); } if ((dataFlags & DataFlags.Bounds) != 0) { managed.Bounds = native.Bounds[0]; } }
/// <summary> /// Copies mesh data from one native array to another /// </summary> public static bool CopyNativeDataToNativeData(NativeMeshData from, NativeMeshData to, DataFlags dataFlags) { if (!to.HasValidData() || !from.HasValidData()) { Debug.LogError("Cannot copy data as some of it is invalid"); return(false); } if ((dataFlags & DataFlags.Vertices) != 0) { from.VertexBuffer.CopyTo(to.VertexBuffer); } if ((dataFlags & DataFlags.Normals) != 0) { from.NormalBuffer.CopyTo(to.NormalBuffer); } if ((dataFlags & DataFlags.MaskVertices) != 0) { from.MaskVertexBuffer.CopyTo(to.MaskVertexBuffer); } if ((dataFlags & DataFlags.Tangents) != 0) { from.TangentBuffer.CopyTo(to.TangentBuffer); } if ((dataFlags & DataFlags.UVs) != 0) { from.UVBuffer.CopyTo(to.UVBuffer); } if ((dataFlags & DataFlags.Colors) != 0) { from.ColorBuffer.CopyTo(to.ColorBuffer); } if ((dataFlags & DataFlags.Triangles) != 0) { from.IndexBuffer.CopyTo(to.IndexBuffer); } if ((dataFlags & DataFlags.Bounds) != 0) { from.Bounds.CopyTo(to.Bounds); } return(true); }
/// <summary> /// Returns a job chain that will recalculate the normals of the native data. /// </summary> public static JobHandle RecalculateNormals(NativeMeshData data, JobHandle dependency = default) { var length = data.NormalBuffer.Length; dependency = new ResetNormalsJob { normals = data.NormalBuffer }.Schedule(length, 256, dependency); dependency = new AddTriangleNormalToNormalsJob { triangles = data.IndexBuffer, vertices = data.VertexBuffer, normals = data.NormalBuffer }.Schedule(dependency); dependency = new NormalizeNormalsJob { normals = data.NormalBuffer }.Schedule(length, 256, dependency); return(dependency); }
public static bool CopyToNativeData(this ManagedMeshData from, NativeMeshData to, DataFlags dataFlags) => CopyManagedToNativeMeshData(from, to, dataFlags);
public static bool CopyToMesh(this NativeMeshData from, Mesh to, DataFlags dataFlags) => CopyNativeDataToMesh(from, to, dataFlags);
public static bool CopyToManagedData(this NativeMeshData from, ManagedMeshData to, DataFlags dataFlags) => CopyNativeDataToManagedData(to, from, dataFlags);
public bool Initialize(GameObject targetObject) { if (Target == null) { Target = new MeshTarget(); } if (!Target.Initialize(targetObject)) { return(false); } // Store the original mesh and make a copy (stored in DynamicMesh). // Assign the copy back to the filter so that this object has a unique mesh. if (!initialized) { OriginalMesh = Target.GetMesh(); if (OriginalMesh == null) { return(false); } if (!OriginalMesh.isReadable) { Debug.LogError($"The mesh '{OriginalMesh.name}' must have read/write permissions enabled.", OriginalMesh); return(false); } DynamicMesh = GameObject.Instantiate(Target.GetMesh()); } // Since this has already been initialized, make a new mesh for the dynamic mesh to reference // so that two Deformables aren't displaying and modifying the same mesh. else if (OriginalMesh != null) { DynamicMesh = GameObject.Instantiate(OriginalMesh); } else if (DynamicMesh != null) { Debug.Log($"Original mesh is missing. Attempting to create one from dynamic mesh ({DynamicMesh.name}) and original managed mesh data.", targetObject); OriginalMesh = GameObject.Instantiate(DynamicMesh); try { OriginalMesh.vertices = originalManaged.Vertices; OriginalMesh.normals = originalManaged.Normals; OriginalMesh.tangents = originalManaged.Tangents; OriginalMesh.uv = originalManaged.UVs; OriginalMesh.colors = originalManaged.Colors; OriginalMesh.triangles = originalManaged.Triangles; OriginalMesh.bounds = originalManaged.Bounds; } catch (NullReferenceException) { Debug.LogError($"Attempted to recreate original mesh (from {DynamicMesh.name}), but the data was not valid. Please assign a new mesh.", targetObject); return(false); } Debug.Log($"Original mesh was recreated from {DynamicMesh.name}. This is not ideal, but prevents stuff from breaking when an original mesh is deleted. The best solution is to find and reassign the original mesh.", targetObject); } else { return(false); } // Tell the mesh filter to display the dynamic mesh. Target.SetMesh(DynamicMesh); // Mark the dynamic mesh as dynamic for a hypothetical performance boost. // (I've heard this method doesn't do anything) DynamicMesh.MarkDynamic(); Length = DynamicMesh.vertexCount; // Store mesh information in managed data. originalManaged = new ManagedMeshData(DynamicMesh); dynamicManaged = new ManagedMeshData(DynamicMesh); // Copy the managed data into native data. OriginalNative = new NativeMeshData(originalManaged); DynamicNative = new NativeMeshData(dynamicManaged); initialized = true; return(true); }
public bool Initialize(GameObject targetObject) { if (Target == null) { Target = new MeshTarget(); } if (!Target.Initialize(targetObject)) { return(false); } // Store the original mesh and make a copy (stored in DynamicMesh). // Assign the copy back to the filter so that this object has a unique mesh. if (!initialized) { OriginalMesh = Target.GetMesh(); if (OriginalMesh == null) { return(false); } if (!OriginalMesh.isReadable) { Debug.LogError($"The mesh '{OriginalMesh.name}' must have read/write permissions enabled.", OriginalMesh); return(false); } DynamicMesh = GameObject.Instantiate(Target.GetMesh()); } // Since this has already been initialized, make a new mesh for the dynamic mesh to reference // so that two Deformables aren't displaying and modifying the same mesh. else if (OriginalMesh != null) { DynamicMesh = GameObject.Instantiate(OriginalMesh); } else if (DynamicMesh != null) { Debug.Log($"Original mesh is missing. Recreating one from dynamic mesh (\"{DynamicMesh.name}\"). This is not ideal, but prevents stuff from breaking when an original mesh is deleted. The best solution is to find and reassign the original mesh.", targetObject); OriginalMesh = GameObject.Instantiate(DynamicMesh); return(false); } else { return(false); } // Tell the mesh filter to display the dynamic mesh. Target.SetMesh(DynamicMesh); // Mark the dynamic mesh as dynamic for a hypothetical performance boost. // (I've heard this method doesn't do anything) DynamicMesh.MarkDynamic(); Length = DynamicMesh.vertexCount; // Store the native data. OriginalNative = new NativeMeshData(DynamicMesh); DynamicNative = new NativeMeshData(DynamicMesh); #if !UNITY_2019_3_OR_NEWER OriginalManaged = new ManagedMeshData(DynamicMesh); DynamicManaged = new ManagedMeshData(DynamicMesh); #endif initialized = true; return(true); }