Example #1
0
        /// <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);
        }
Example #2
0
 /// <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));
 }
Example #3
0
        /// <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);
        }
Example #4
0
        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);
        }
Example #5
0
        /// <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];
            }
        }
Example #6
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);
        }
Example #7
0
        /// <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);
        }
Example #8
0
 public static bool CopyToNativeData(this ManagedMeshData from, NativeMeshData to, DataFlags dataFlags) => CopyManagedToNativeMeshData(from, to, dataFlags);
Example #9
0
 public static bool CopyToMesh(this NativeMeshData from, Mesh to, DataFlags dataFlags) => CopyNativeDataToMesh(from, to, dataFlags);
Example #10
0
 public static bool CopyToManagedData(this NativeMeshData from, ManagedMeshData to, DataFlags dataFlags) => CopyNativeDataToManagedData(to, from, dataFlags);
Example #11
0
        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);
        }
Example #12
0
        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);
        }