예제 #1
0
        public static void CopyFromPositionOnly(this UnityEngine.Mesh mesh, GeneratedMeshContents contents)
        {
            if (object.ReferenceEquals(contents, null))
            {
                throw new ArgumentNullException("contents");
            }

            if (contents.description.vertexCount < 3 ||
                contents.description.indexCount < 3)
            {
                mesh.Clear();
                return;
            }

            mesh.SetVertices(contents.positions);

            mesh.SetTriangles(contents.indices.ToArray(), 0, false);
            mesh.bounds = contents.bounds;
        }
 /// <summary>Creates and returns a <see cref="Chisel.Core.GeneratedMeshContents"/> for a given <see cref="Chisel.Core.GeneratedMeshDescription"/> created by <see cref="Chisel.Core.CSGTree.GetMeshDescriptions"/></summary>
 /// <remarks>See the [Create Unity Meshes](~/documentation/createUnityMesh.md) article for more information.</remarks>
 /// <param name="meshDescription">A <see cref="Chisel.Core.GeneratedMeshDescription"/> created by <see cref="Chisel.Core.CSGTree.GetMeshDescriptions"/>.</param>
 /// <param name="previousGeneratedMeshContents">The previously generated <see cref="Chisel.Core.GeneratedMeshContents"/>, this can reuse allocated memory if the mesh hasn't changed shape. (optional)</param>
 /// <returns>A <see cref="Chisel.Core.GeneratedMeshContents"/> that can be used to initialize a [UnityEngine.Mesh](https://docs.unity3d.com/ScriptReference/Mesh.html) with.</returns>
 /// <seealso cref="Chisel.Core.CSGTree.GetMeshDescriptions"/>
 public GeneratedMeshContents            GetGeneratedMesh(GeneratedMeshDescription meshDescription, GeneratedMeshContents previousGeneratedMeshContents = null)
 {
     return(GetGeneratedMesh(treeNodeID, meshDescription, previousGeneratedMeshContents));
 }
예제 #3
0
        internal static GeneratedMeshContents GetGeneratedMesh(int treeNodeID, GeneratedMeshDescription meshDescription)
        {
            if (!AssertNodeIDValid(treeNodeID) || !AssertNodeType(treeNodeID, CSGNodeType.Tree))
            {
                return(null);
            }
            if (meshDescription.vertexCount <= 3 ||
                meshDescription.indexCount <= 3)
            {
                Debug.LogWarning(string.Format("{0} called with a {1} that isn't valid", typeof(CSGTree).Name, typeof(GeneratedMeshDescription).Name));
                return(null);
            }

            var meshIndex    = meshDescription.meshQueryIndex;
            var subMeshIndex = meshDescription.subMeshQueryIndex;

            if (meshIndex < 0)
            {
                Debug.LogError("GetGeneratedMesh: MeshIndex cannot be negative"); return(null);
            }
            if (subMeshIndex < 0)
            {
                Debug.LogError("GetGeneratedMesh: SubMeshIndex cannot be negative"); return(null);
            }

            if (nodeHierarchies[treeNodeID - 1].treeInfo == null)
            {
                Debug.LogWarning("Tree has not been initialized properly"); return(null);
            }

            TreeInfo tree = nodeHierarchies[treeNodeID - 1].treeInfo;

            if (tree == null)
            {
                Debug.LogError("GetGeneratedMesh: Invalid node index used"); return(null);
            }
            if (tree.subMeshCounts == null)
            {
                Debug.LogWarning("Tree has not been initialized properly"); return(null);
            }



            int subMeshCountSize = (int)tree.subMeshCounts.Count;

            if (subMeshIndex >= (int)subMeshCountSize)
            {
                Debug.LogError("GetGeneratedMesh: SubMeshIndex is higher than the number of generated meshes"); return(null);
            }
            if (meshIndex >= (int)subMeshCountSize)
            {
                Debug.LogError("GetGeneratedMesh: MeshIndex is higher than the number of generated meshes"); return(null);
            }

            int foundIndex = -1;

            for (int i = 0; i < subMeshCountSize; i++)
            {
                if (meshIndex == tree.subMeshCounts[i].meshIndex &&
                    subMeshIndex == tree.subMeshCounts[i].subMeshIndex)
                {
                    foundIndex = i;
                    break;
                }
            }
            if (foundIndex < 0 || foundIndex >= subMeshCountSize)
            {
                Debug.LogError("GetGeneratedMesh: Could not find mesh associated with MeshIndex/SubMeshIndex pair"); return(null);
            }

            var subMeshCount = tree.subMeshCounts[foundIndex];

            if (subMeshCount.indexCount > meshDescription.indexCount)
            {
                Debug.LogError("GetGeneratedMesh: The destination indices array (" + meshDescription.indexCount + ") is smaller than the size of the source data (" + (int)subMeshCount.indexCount + ")"); return(null);
            }
            if (subMeshCount.vertexCount > meshDescription.vertexCount)
            {
                Debug.LogError("GetGeneratedMesh: The destination vertices array (" + meshDescription.vertexCount + ") is smaller than the size of the source data (" + (int)subMeshCount.vertexCount + ")"); return(null);
            }
            if (subMeshCount.indexCount == 0 || subMeshCount.vertexCount == 0)
            {
                Debug.LogWarning("GetGeneratedMesh: Mesh is empty"); return(null);
            }


            var generatedMesh      = new GeneratedMeshContents();
            var usedVertexChannels = meshDescription.meshQuery.UsedVertexChannels;
            var vertexCount        = meshDescription.vertexCount;
            var indexCount         = meshDescription.indexCount;

            generatedMesh.description = meshDescription;

            // create our arrays on the managed side with the correct size

            bool useTangents = ((usedVertexChannels & VertexChannelFlags.Tangent) == VertexChannelFlags.Tangent);
            bool useNormals  = ((usedVertexChannels & VertexChannelFlags.Normal) == VertexChannelFlags.Normal);
            bool useUV0      = ((usedVertexChannels & VertexChannelFlags.UV0) == VertexChannelFlags.UV0);

            generatedMesh.tangents     = useTangents ? new NativeArray <float4>(vertexCount, Allocator.Persistent) : default;
            generatedMesh.normals      = useNormals  ? new NativeArray <float3>(vertexCount, Allocator.Persistent) : default;
            generatedMesh.uv0          = useUV0      ? new NativeArray <float2>(vertexCount, Allocator.Persistent) : default;
            generatedMesh.positions    = new NativeArray <float3>(vertexCount, Allocator.Persistent);
            generatedMesh.indices      = new NativeArray <int>   (indexCount, Allocator.Persistent);
            generatedMesh.brushIndices = new NativeArray <int>   (indexCount / 3, Allocator.Persistent);

            generatedMesh.bounds = new Bounds();

            var submeshVertexCount = subMeshCount.vertexCount;
            var submeshIndexCount  = subMeshCount.indexCount;

            if (subMeshCount.surfaces == null ||
                submeshVertexCount != generatedMesh.positions.Length ||
                submeshIndexCount != generatedMesh.indices.Length ||
                generatedMesh.indices == null ||
                generatedMesh.positions == null)
            {
                return(null);
            }


            var submeshSurfaces = new NativeArray <SubMeshSurface>(subMeshCount.surfaces.Count, Allocator.TempJob);

            for (int n = 0; n < subMeshCount.surfaces.Count; n++)
            {
                submeshSurfaces[n] = subMeshCount.surfaces[n];
            }

            var generateVertexBuffersJob = new GenerateVertexBuffersJob
            {
                meshQuery         = subMeshCount.meshQuery,
                surfaceIdentifier = subMeshCount.surfaceIdentifier,

                submeshIndexCount  = subMeshCount.indexCount,
                submeshVertexCount = subMeshCount.vertexCount,

                submeshSurfaces = submeshSurfaces,

                generatedMeshIndices      = generatedMesh.indices,
                generatedMeshBrushIndices = generatedMesh.brushIndices,
                generatedMeshPositions    = generatedMesh.positions,
                generatedMeshTangents     = generatedMesh.tangents,
                generatedMeshNormals      = generatedMesh.normals,
                generatedMeshUV0          = generatedMesh.uv0
            };

            generateVertexBuffersJob.Run();

            generateVertexBuffersJob.submeshSurfaces.Dispose();
            generateVertexBuffersJob.submeshSurfaces = default;

            var min = new Vector3(float.PositiveInfinity, float.PositiveInfinity, float.PositiveInfinity);
            var max = new Vector3(float.NegativeInfinity, float.NegativeInfinity, float.NegativeInfinity);

            for (int i = 0, count = subMeshCount.indexCount; i < count; i++)
            {
                var position = generatedMesh.positions[generatedMesh.indices[i]];
                min.x = Mathf.Min(min.x, position.x);
                min.y = Mathf.Min(min.y, position.y);
                min.z = Mathf.Min(min.z, position.z);

                max.x = Mathf.Max(max.x, position.x);
                max.y = Mathf.Max(max.y, position.y);
                max.z = Mathf.Max(max.z, position.z);
            }

            var boundsCenter = (max + min) * 0.5f;
            var boundsSize   = (max - min);

            if (float.IsInfinity(boundsSize.x) || float.IsInfinity(boundsSize.y) || float.IsInfinity(boundsSize.z) ||
                float.IsNaN(boundsSize.x) || float.IsNaN(boundsSize.y) || float.IsNaN(boundsSize.z))
            {
                return(null);
            }

            generatedMesh.bounds = new Bounds(boundsCenter, boundsSize);
            return(generatedMesh);
        }
예제 #4
0
 private static GeneratedMeshContents GetGeneratedMesh(int treeNodeID, GeneratedMeshDescription meshDescription, GeneratedMeshContents previousGeneratedMeshContents)
 {
     return(CSGManager.GetGeneratedMesh(treeNodeID, meshDescription, previousGeneratedMeshContents));
 }
예제 #5
0
        static bool GenerateVertexBuffers(SubMeshCounts subMeshCount, GeneratedMeshContents generatedMesh)
        {
            var submeshVertexCount = subMeshCount.vertexCount;
            var submeshIndexCount  = subMeshCount.indexCount;
            var subMeshSurfaces    = subMeshCount.surfaces;

            if (subMeshSurfaces == null ||
                submeshVertexCount != generatedMesh.positions.Length ||
                submeshIndexCount != generatedMesh.indices.Length ||
                generatedMesh.indices == null ||
                generatedMesh.positions == null)
            {
                return(false);
            }

            bool needTangents    = generatedMesh.tangents != null && (((Int32)subMeshCount.meshQuery.UsedVertexChannels & (Int32)VertexChannelFlags.Tangent) != 0);
            bool needNormals     = generatedMesh.normals != null && (((Int32)subMeshCount.meshQuery.UsedVertexChannels & (Int32)VertexChannelFlags.Normal) != 0);
            bool needUV0s        = generatedMesh.uv0 != null && (((Int32)subMeshCount.meshQuery.UsedVertexChannels & (Int32)VertexChannelFlags.UV0) != 0);
            bool needTempNormals = needTangents && !needNormals;
            bool needTempUV0     = needTangents && !needUV0s;

            var normals = !needTempNormals ? generatedMesh.normals : new Vector3[submeshVertexCount];
            var uv0s    = !needTempUV0     ? generatedMesh.uv0     : new Vector2[submeshVertexCount];

            // double snap_size = 1.0 / ants.SnapDistance();

            // copy all the vertices & indices to the sub-meshes for each material
            for (int surfaceIndex = 0, indexOffset = 0, vertexOffset = 0, surfaceCount = (int)subMeshSurfaces.Count;
                 surfaceIndex < surfaceCount;
                 ++surfaceIndex)
            {
                var sourceBuffer = subMeshSurfaces[surfaceIndex];
                if (sourceBuffer.indices == null ||
                    sourceBuffer.vertices == null ||
                    sourceBuffer.indices.Length == 0 ||
                    sourceBuffer.vertices.Length == 0)
                {
                    continue;
                }
                for (int i = 0, sourceIndexCount = sourceBuffer.indices.Length; i < sourceIndexCount; i++)
                {
                    generatedMesh.indices[indexOffset] = (int)(sourceBuffer.indices[i] + vertexOffset);
                    indexOffset++;
                }

                var sourceVertexCount = sourceBuffer.vertices.Length;
                Array.Copy(sourceBuffer.vertices, 0, generatedMesh.positions, vertexOffset, sourceVertexCount);

                if (needUV0s || needTangents)
                {
                    Array.Copy(sourceBuffer.uv0, 0, uv0s, vertexOffset, sourceVertexCount);
                }
                if (needNormals || needTangents)
                {
                    Array.Copy(sourceBuffer.normals, 0, normals, vertexOffset, sourceVertexCount);
                }
                vertexOffset += sourceVertexCount;
            }

            if (needTangents)
            {
                ComputeTangents(generatedMesh.indices,
                                generatedMesh.positions,
                                uv0s,
                                normals,
                                generatedMesh.tangents);
            }
            return(true);
        }
예제 #6
0
        internal static GeneratedMeshContents GetGeneratedMesh(int treeNodeID, GeneratedMeshDescription meshDescription, GeneratedMeshContents previousGeneratedMeshContents)
        {
            if (!AssertNodeIDValid(treeNodeID) || !AssertNodeType(treeNodeID, CSGNodeType.Tree))
            {
                return(null);
            }
            if (meshDescription.vertexCount <= 0 ||
                meshDescription.indexCount <= 0)
            {
                Debug.LogWarning(string.Format("{0} called with a {1} that isn't valid", typeof(CSGTree).Name, typeof(GeneratedMeshDescription).Name));
                return(null);
            }

            var meshIndex    = meshDescription.meshQueryIndex;
            var subMeshIndex = meshDescription.subMeshQueryIndex;

            if (meshIndex < 0)
            {
                Debug.LogError("GetGeneratedMesh: MeshIndex cannot be negative"); return(null);
            }
            if (subMeshIndex < 0)
            {
                Debug.LogError("GetGeneratedMesh: SubMeshIndex cannot be negative"); return(null);
            }

            if (nodeHierarchies[treeNodeID - 1].treeInfo == null)
            {
                Debug.LogWarning("Tree has not been initialized properly"); return(null);
            }

            TreeInfo tree = nodeHierarchies[treeNodeID - 1].treeInfo;

            if (tree == null)
            {
                Debug.LogError("GetGeneratedMesh: Invalid node index used"); return(null);
            }
            if (tree.subMeshCounts == null)
            {
                Debug.LogWarning("Tree has not been initialized properly"); return(null);
            }



            int subMeshCountSize = (int)tree.subMeshCounts.Count;

            if (subMeshIndex >= (int)subMeshCountSize)
            {
                Debug.LogError("GetGeneratedMesh: SubMeshIndex is higher than the number of generated meshes"); return(null);
            }
            if (meshIndex >= (int)subMeshCountSize)
            {
                Debug.LogError("GetGeneratedMesh: MeshIndex is higher than the number of generated meshes"); return(null);
            }

            int foundIndex = -1;

            for (int i = 0; i < subMeshCountSize; i++)
            {
                if (meshIndex == tree.subMeshCounts[i].meshIndex &&
                    subMeshIndex == tree.subMeshCounts[i].subMeshIndex)
                {
                    foundIndex = i;
                    break;
                }
            }
            if (foundIndex < 0 || foundIndex >= subMeshCountSize)
            {
                Debug.LogError("GetGeneratedMesh: Could not find mesh associated with MeshIndex/SubMeshIndex pair"); return(null);
            }

            var subMeshCount = tree.subMeshCounts[foundIndex];

            if (subMeshCount.indexCount > meshDescription.indexCount)
            {
                Debug.LogError("GetGeneratedMesh: The destination indices array (" + meshDescription.indexCount + ") is smaller than the size of the source data (" + (int)subMeshCount.indexCount + ")"); return(null);
            }
            if (subMeshCount.vertexCount > meshDescription.vertexCount)
            {
                Debug.LogError("GetGeneratedMesh: The destination vertices array (" + meshDescription.vertexCount + ") is smaller than the size of the source data (" + (int)subMeshCount.vertexCount + ")"); return(null);
            }
            if (subMeshCount.indexCount == 0 || subMeshCount.vertexCount == 0)
            {
                Debug.LogWarning("GetGeneratedMesh: Mesh is empty"); return(null);
            }



            var generatedMesh      = (previousGeneratedMeshContents != null) ? previousGeneratedMeshContents : new GeneratedMeshContents();
            var usedVertexChannels = meshDescription.meshQuery.UsedVertexChannels;
            var vertexCount        = meshDescription.vertexCount;
            var indexCount         = meshDescription.indexCount;

            generatedMesh.description = meshDescription;

            // create our arrays on the managed side with the correct size
            generatedMesh.tangents  = ((usedVertexChannels & VertexChannelFlags.Tangent) == 0) ? null : (generatedMesh.tangents != null && generatedMesh.tangents.Length == vertexCount) ? generatedMesh.tangents : new Vector4[vertexCount];
            generatedMesh.normals   = ((usedVertexChannels & VertexChannelFlags.Normal) == 0) ? null : (generatedMesh.normals != null && generatedMesh.normals.Length == vertexCount) ? generatedMesh.normals  : new Vector3[vertexCount];
            generatedMesh.uv0       = ((usedVertexChannels & VertexChannelFlags.UV0) == 0) ? null : (generatedMesh.uv0 != null && generatedMesh.uv0.Length == vertexCount) ? generatedMesh.uv0      : new Vector2[vertexCount];
            generatedMesh.positions = (generatedMesh.positions != null && generatedMesh.positions.Length == vertexCount) ? generatedMesh.positions : new Vector3[vertexCount];
            generatedMesh.indices   = (generatedMesh.indices != null && generatedMesh.indices.Length == indexCount) ? generatedMesh.indices   : new int    [indexCount];

            generatedMesh.bounds = new Bounds();


            bool result = CSGManager.GenerateVertexBuffers(subMeshCount, generatedMesh);

            if (!result)
            {
                return(null);
            }

            var min = new Vector3(float.PositiveInfinity, float.PositiveInfinity, float.PositiveInfinity);
            var max = new Vector3(float.NegativeInfinity, float.NegativeInfinity, float.NegativeInfinity);

            for (int i = 0, count = subMeshCount.indexCount; i < count; i++)
            {
                var position = generatedMesh.positions[generatedMesh.indices[i]];
                min.x = Mathf.Min(min.x, position.x);
                min.y = Mathf.Min(min.y, position.y);
                min.z = Mathf.Min(min.z, position.z);

                max.x = Mathf.Max(max.x, position.x);
                max.y = Mathf.Max(max.y, position.y);
                max.z = Mathf.Max(max.z, position.z);
            }

            var boundsCenter = (max + min) * 0.5f;
            var boundsSize   = (max - min);

            if (float.IsInfinity(boundsSize.x) || float.IsInfinity(boundsSize.y) || float.IsInfinity(boundsSize.z) ||
                float.IsNaN(boundsSize.x) || float.IsNaN(boundsSize.y) || float.IsNaN(boundsSize.z))
            {
                return(null);
            }

            generatedMesh.bounds = new Bounds(boundsCenter, boundsSize);
            return(generatedMesh);
        }
예제 #7
0
        private static GeneratedMeshContents GetGeneratedMesh(int treeNodeID, GeneratedMeshDescription meshDescription, GeneratedMeshContents previousGeneratedMeshContents)
        {
            if (meshDescription.vertexCount <= 0 ||
                meshDescription.indexCount <= 0)
            {
                Debug.LogWarning(string.Format("{0} called with a {1} that isn't valid", typeof(CSGTree).Name, typeof(GeneratedMeshDescription).Name));
                return(null);
            }

            var generatedMesh      = (previousGeneratedMeshContents != null) ? previousGeneratedMeshContents : new GeneratedMeshContents();
            var usedVertexChannels = meshDescription.meshQuery.UsedVertexChannels;
            var vertexCount        = meshDescription.vertexCount;
            var indexCount         = meshDescription.indexCount;
            var meshIndex          = meshDescription.meshQueryIndex;
            var subMeshIndex       = meshDescription.subMeshQueryIndex;

            generatedMesh.description = meshDescription;

            // create our arrays on the managed side with the correct size
            generatedMesh.tangents  = ((usedVertexChannels & VertexChannelFlags.Tangent) == 0) ? null : (generatedMesh.tangents != null && generatedMesh.tangents.Length == vertexCount) ? generatedMesh.tangents : new Vector4[vertexCount];
            generatedMesh.normals   = ((usedVertexChannels & VertexChannelFlags.Normal) == 0) ? null : (generatedMesh.normals != null && generatedMesh.normals.Length == vertexCount) ? generatedMesh.normals  : new Vector3[vertexCount];
            generatedMesh.uv0       = ((usedVertexChannels & VertexChannelFlags.UV0) == 0) ? null : (generatedMesh.uv0 != null && generatedMesh.uv0.Length == vertexCount) ? generatedMesh.uv0      : new Vector2[vertexCount];
            generatedMesh.positions = (generatedMesh.positions != null && generatedMesh.positions.Length == vertexCount) ? generatedMesh.positions : new Vector3[vertexCount];
            generatedMesh.indices   = (generatedMesh.indices != null && generatedMesh.indices.Length == indexCount) ? generatedMesh.indices   : new int    [indexCount];

            var indicesHandle  = GCHandle.Alloc(generatedMesh.indices, GCHandleType.Pinned);
            var positionHandle = GCHandle.Alloc(generatedMesh.positions, GCHandleType.Pinned);
            var tangentHandle  = new GCHandle();
            var normalHandle   = new GCHandle();
            var uv0Handle      = new GCHandle();

            var indicesPtr  = indicesHandle.AddrOfPinnedObject();
            var positionPtr = positionHandle.AddrOfPinnedObject();
            var tangentPtr  = IntPtr.Zero;
            var normalPtr   = IntPtr.Zero;
            var uv0Ptr      = IntPtr.Zero;

            if (generatedMesh.tangents != null)
            {
                tangentHandle = GCHandle.Alloc(generatedMesh.tangents, GCHandleType.Pinned); tangentPtr = tangentHandle.AddrOfPinnedObject();
            }
            if (generatedMesh.normals != null)
            {
                normalHandle = GCHandle.Alloc(generatedMesh.normals, GCHandleType.Pinned); normalPtr = normalHandle.AddrOfPinnedObject();
            }
            if (generatedMesh.uv0 != null)
            {
                uv0Handle = GCHandle.Alloc(generatedMesh.uv0, GCHandleType.Pinned); uv0Ptr = uv0Handle.AddrOfPinnedObject();
            }

            var boundsCenter = Vector3.zero;
            var boundsSize   = Vector3.zero;
            var result       = GetGeneratedMesh((Int32)treeNodeID,
                                                (Int32)meshIndex,
                                                (Int32)subMeshIndex,

                                                (Int32)indexCount,
                                                indicesPtr,

                                                (Int32)vertexCount,
                                                positionPtr,
                                                tangentPtr,
                                                normalPtr,
                                                uv0Ptr,
                                                out boundsCenter,
                                                out boundsSize);

            if (generatedMesh.uv0 != null)
            {
                uv0Handle.Free();
            }
            if (generatedMesh.normals != null)
            {
                normalHandle.Free();
            }
            if (generatedMesh.tangents != null)
            {
                tangentHandle.Free();
            }
            positionHandle.Free();
            indicesHandle.Free();

            if (!result ||
                float.IsInfinity(boundsSize.x) || float.IsInfinity(boundsSize.y) || float.IsInfinity(boundsSize.z) ||
                float.IsNaN(boundsSize.x) || float.IsNaN(boundsSize.y) || float.IsNaN(boundsSize.z))
            {
                return(null);
            }

            generatedMesh.bounds = new Bounds(boundsCenter, boundsSize);
            return(generatedMesh);
        }