Esempio n. 1
0
        internal static void CombineSubMeshes(TreeInfo treeInfo,
                                              MeshQuery[] meshQueries,
                                              VertexChannelFlags vertexChannelMask)
        {
            var subMeshCounts = treeInfo.subMeshCounts;

            subMeshCounts.Clear();

            var treeBrushNodeIDs   = treeInfo.treeBrushes;
            var treeBrushNodeCount = (Int32)(treeBrushNodeIDs.Count);

            if (treeBrushNodeCount <= 0)
            {
                return;
            }

            uniqueMeshDescriptions.Clear();
            for (int b = 0, count_b = treeBrushNodeCount; b < count_b; b++)
            {
                var brushNodeID = treeBrushNodeIDs[b];
                if (!CSGManager.IsValidNodeID(brushNodeID))
                {
                    continue;
                }

                var brushNodeIndex = brushNodeID - 1;
                var nodeType       = nodeFlags[brushNodeIndex].nodeType;
                if (nodeType != CSGNodeType.Brush)
                {
                    continue;
                }

                var brushInfo = nodeHierarchies[brushNodeIndex].brushInfo;
                if (brushInfo == null)
                {
                    continue;
                }

                var treeNodeID         = nodeHierarchies[brushNodeIndex].treeNodeID;
                var chiselLookupValues = ChiselTreeLookup.Value[treeNodeID - 1];

                if (!chiselLookupValues.brushRenderBuffers.TryGetValue(brushNodeIndex, out var brushRenderBuffer) ||
                    !brushRenderBuffer.IsCreated)
                {
                    continue;
                }

                ref var brushRenderBufferRef = ref brushRenderBuffer.Value;
                ref var surfaces             = ref brushRenderBufferRef.surfaces;
Esempio n. 2
0
        private static GeneratedMeshDescription[] GetMeshDescriptions(Int32 treeNodeID,
                                                                      MeshQuery[]            meshTypes,
                                                                      VertexChannelFlags vertexChannelMask)
        {
            if (meshTypes == null)
            {
                throw new ArgumentNullException("meshTypes");
            }

            if (meshTypes.Length == 0)
            {
                return(null);
            }

            Int32 meshDescriptionCount;

            GCHandle nativeMeshTypeHandle = GCHandle.Alloc(meshTypes, GCHandleType.Pinned);
            IntPtr   nativeMeshTypePtr    = nativeMeshTypeHandle.AddrOfPinnedObject();

            var result = GenerateMeshDescriptions(treeNodeID, meshTypes.Length, nativeMeshTypePtr, vertexChannelMask, out meshDescriptionCount);

            nativeMeshTypeHandle.Free();
            if (!result || meshDescriptionCount == 0)
            {
                return(null);
            }

            var meshDescriptions       = new GeneratedMeshDescription[meshDescriptionCount];
            var meshDescriptionsHandle = GCHandle.Alloc(meshDescriptions, GCHandleType.Pinned);
            var meshDescriptionsPtr    = meshDescriptionsHandle.AddrOfPinnedObject();

            result = GetMeshDescriptions(treeNodeID, meshDescriptionCount, meshDescriptionsPtr);

            meshDescriptionsHandle.Free();

            if (!result ||
                meshDescriptions[0].vertexCount <= 0 ||
                meshDescriptions[0].indexCount <= 0)
            {
                return(null);
            }

            return(meshDescriptions);
        }
 /// <summary>Determines what meshes would be generated from the tree from the given <paramref name="meshQuery"/> and <paramref name="vertexChannelMask"/>.</summary>
 /// <remarks>See the [Create Unity Meshes](~/documentation/createUnityMesh.md) article for more information.</remarks>
 /// <param name="meshQuery">An array of <see cref="Chisel.Core.MeshQuery"/>'s which describe which surfaces should be combined into meshes</param>
 /// <param name="vertexChannelMask">A mask to prevent certain vertex channels to be generated. By default this value is to <see cref="Chisel.Core.VertexChannelFlags.All"/>.</param>
 /// <returns>An array of <see cref="Chisel.Core.GeneratedMeshDescription"/>'s that can be used to generate <see cref="Chisel.Core.GeneratedMeshContents"/> using <see cref="Chisel.Core.CSGTree.GetGeneratedMesh"/></returns>
 /// <seealso cref="Chisel.Core.CSGTree.GetGeneratedMesh"/>
 public GeneratedMeshDescription[]       GetMeshDescriptions(MeshQuery[] meshQuery, VertexChannelFlags vertexChannelMask = VertexChannelFlags.All)
 {
     if (meshQuery == null)
     {
         throw new ArgumentNullException("meshQuery");
     }
     return(GetMeshDescriptions(treeNodeID, meshQuery, vertexChannelMask));
 }
Esempio n. 4
0
        internal static GeneratedMeshDescription[] GetMeshDescriptions(Int32 treeNodeID,
                                                                       MeshQuery[]          meshQueries,
                                                                       VertexChannelFlags vertexChannelMask)
        {
            if (!AssertNodeIDValid(treeNodeID) || !AssertNodeType(treeNodeID, CSGNodeType.Tree))
            {
                return(null);
            }
            if (meshQueries == null)
            {
                throw new ArgumentNullException("meshTypes");
            }

            if (meshQueries.Length == 0)
            {
                Debug.Log("meshQueries.Length == 0");
                return(null);
            }

            if (!IsValidNodeID(treeNodeID))
            {
                Debug.LogError("GenerateMeshDescriptions: Invalid node index used");
                return(null);
            }

            var treeNodeIndex = treeNodeID - 1;
            var treeInfo      = nodeHierarchies[treeNodeIndex].treeInfo;

            if (treeInfo == null)
            {
                Debug.LogError("GenerateMeshDescriptions: Invalid node index used");
                return(null);
            }

            treeInfo.subMeshCounts.Clear();
            treeInfo.meshDescriptions.Clear();

            if (nodeFlags[treeNodeIndex].IsNodeFlagSet(NodeStatusFlags.TreeNeedsUpdate))
            {
                UnityEngine.Profiling.Profiler.BeginSample("UpdateTreeMesh");
                try
                {
                    var handle = UpdateTreeMeshes(new int[] { treeNodeID });
                    handle.Complete();
                } finally { UnityEngine.Profiling.Profiler.EndSample(); }
            }

            UnityEngine.Profiling.Profiler.BeginSample("CombineSubMeshes");
            try
            {
                CombineSubMeshes(treeInfo, meshQueries, vertexChannelMask);
            } finally { UnityEngine.Profiling.Profiler.EndSample(); }


            {
                var flags = nodeFlags[treeNodeIndex];
                flags.UnSetNodeFlag(NodeStatusFlags.TreeMeshNeedsUpdate);
                nodeFlags[treeNodeIndex] = flags;
            }

            if (treeInfo.subMeshCounts.Count <= 0)
            {
                return(null);
            }

            for (int i = (int)treeInfo.subMeshCounts.Count - 1; i >= 0; i--)
            {
                var subMesh = treeInfo.subMeshCounts[i];

                // Make sure the meshDescription actually holds a mesh
                if (subMesh.vertexCount == 0 ||
                    subMesh.indexCount == 0)
                {
                    continue;
                }

                // Make sure the mesh is valid
                if (subMesh.vertexCount >= kMaxVertexCount)
                {
                    Debug.LogError("Mesh has too many vertices (" + subMesh.vertexCount + " > " + kMaxVertexCount + ")");
                    continue;
                }

                var description = new GeneratedMeshDescription
                {
                    meshQuery         = subMesh.meshQuery,
                    surfaceParameter  = subMesh.surfaceIdentifier,
                    meshQueryIndex    = subMesh.meshIndex,
                    subMeshQueryIndex = subMesh.subMeshIndex,

                    geometryHashValue = subMesh.geometryHash,
                    surfaceHashValue  = subMesh.surfaceHash,

                    vertexCount = subMesh.vertexCount,
                    indexCount  = subMesh.indexCount
                };

                treeInfo.meshDescriptions.Add(description);
            }

            if (treeInfo.meshDescriptions == null ||
                treeInfo.meshDescriptions.Count == 0 ||
                treeInfo.meshDescriptions[0].vertexCount <= 0 ||
                treeInfo.meshDescriptions[0].indexCount <= 0)
            {
                return(null);
            }

            return(treeInfo.meshDescriptions.ToArray());
        }
Esempio n. 5
0
 private static GeneratedMeshDescription[] GetMeshDescriptions(Int32 treeNodeID,
                                                               MeshQuery[]                meshQueries,
                                                               VertexChannelFlags vertexChannelMask)
 {
     return(CSGManager.GetMeshDescriptions(treeNodeID, meshQueries, vertexChannelMask));
 }
Esempio n. 6
0
 /// <summary>Constructs a <see cref="RealtimeCSG.Foundation.MeshQuery"/> to use to specify which surfaces should be combined into meshes, and should they be subdivided by a particular layer parameter index.</summary>
 /// <param name="query">Which layer combination would we like to look for and generate a mesh with.</param>
 /// <param name="mask">What layers do we ignore, and what layers do we include in our comparison. When this value is <see cref="RealtimeCSG.Foundation.LayerUsageFlags.None"/>, <paramref name="mask"/> is set to be equal to <paramref name="query"/>.</param>
 /// <param name="parameterIndex">Which parameter index we use to, for example, differentiate between different [UnityEngine.Material](https://docs.unity3d.com/ScriptReference/Material.html)s</param>
 /// <param name="vertexChannels">Which vertex channels need to be used for the meshes we'd like to generate.</param>
 /// <seealso cref="RealtimeCSG.Foundation.SurfaceLayers" />
 public MeshQuery(LayerUsageFlags query, LayerUsageFlags mask = LayerUsageFlags.None, LayerParameterIndex parameterIndex = LayerParameterIndex.None, VertexChannelFlags vertexChannels = VertexChannelFlags.Position)
 {
     if (mask == LayerUsageFlags.None)
     {
         mask = query;
     }
     this.layers          = ((uint)query & ~BitMask) | ((uint)parameterIndex << BitShift);
     this.maskAndChannels = ((uint)mask & ~BitMask) | ((uint)vertexChannels << BitShift);
 }
Esempio n. 7
0
        internal static void CombineSubMeshes(TreeInfo treeInfo,
                                              MeshQuery[]                       meshQueries,
                                              VertexChannelFlags vertexChannelMask)
        {
            var subMeshCounts = treeInfo.subMeshCounts;

            subMeshCounts.Clear();

            var treeBrushNodeIDs   = treeInfo.treeBrushes;
            var treeBrushNodeCount = (Int32)(treeBrushNodeIDs.Count);

            if (treeBrushNodeCount <= 0)
            {
                return;
            }

            var uniqueMeshDescriptions = new Dictionary <MeshID, int>();

            for (Int32 b = 0, count_b = treeBrushNodeCount; b < count_b; b++)
            {
                var nodeID    = treeBrushNodeIDs[b];
                var nodeIndex = nodeID - 1;
                var nodeType  = nodeFlags[nodeIndex].nodeType;
                if (nodeType != CSGNodeType.Brush)
                {
                    continue;
                }

                var brushOutput = nodeHierarchies[nodeIndex].brushOutput;
                //var operation_type_bits = GetNodeOperationByIndex(nodeIndex);
                if (brushOutput == null //||
                    //brush.triangleMesh == null //||
                    //((int)operation_type_bits & InfiniteBrushBits) == InfiniteBrushBits
                    )
                {
                    continue;
                }


                var renderBuffers = brushOutput.renderBuffers;
                if (renderBuffers.surfaceRenderBuffers.Count == 0)
                {
                    continue;
                }

                var surfaceRenderBuffers = renderBuffers.surfaceRenderBuffers;
                for (int j = 0, count_j = (int)renderBuffers.surfaceRenderBuffers.Count; j < count_j; j++)
                {
                    var brushSurfaceBuffer = surfaceRenderBuffers[j];
                    var surfaceVertexCount = (brushSurfaceBuffer.vertices == null) ? 0 : brushSurfaceBuffer.vertices.Length;
                    var surfaceIndexCount  = (brushSurfaceBuffer.indices == null) ? 0 : brushSurfaceBuffer.indices.Length;

                    if (surfaceVertexCount <= 0 || surfaceIndexCount <= 0)
                    {
                        continue;
                    }

                    var surfaceParameter = (brushSurfaceBuffer.meshQuery.LayerParameterIndex == LayerParameterIndex.None) ? 0 : brushSurfaceBuffer.surfaceParameter;
                    var meshID           = new MeshID()
                    {
                        meshQuery = brushSurfaceBuffer.meshQuery, surfaceParameter = surfaceParameter
                    };

                    int generatedMeshIndex;
                    if (!uniqueMeshDescriptions.TryGetValue(meshID, out generatedMeshIndex))
                    {
                        generatedMeshIndex = -1;
                    }
                    if (generatedMeshIndex == -1 ||
                        (subMeshCounts[generatedMeshIndex].vertexCount + surfaceVertexCount) >= kMaxVertexCount)
                    {
                        int meshIndex, subMeshIndex;
                        if (generatedMeshIndex != -1)
                        {
                            generatedMeshIndex = (int)subMeshCounts.Count;
                            var prevMeshCountIndex = generatedMeshIndex;
                            subMeshIndex = subMeshCounts[prevMeshCountIndex].subMeshIndex + 1;
                            meshIndex    = subMeshCounts[prevMeshCountIndex].meshIndex;
                        }
                        else
                        {
                            generatedMeshIndex = (int)subMeshCounts.Count;
                            meshIndex          = generatedMeshIndex;
                            subMeshIndex       = 0;
                        }

                        uniqueMeshDescriptions[meshID] = generatedMeshIndex;
                        SubMeshCounts newSubMesh = new SubMeshCounts();
                        newSubMesh.meshIndex         = meshIndex;
                        newSubMesh.subMeshIndex      = subMeshIndex;
                        newSubMesh.meshQuery         = meshID.meshQuery;
                        newSubMesh.surfaceIdentifier = surfaceParameter;
                        newSubMesh.indexCount        = surfaceIndexCount;
                        newSubMesh.vertexCount       = surfaceVertexCount;
                        newSubMesh.surfaceHash       = brushSurfaceBuffer.surfaceHash;
                        newSubMesh.geometryHash      = brushSurfaceBuffer.geometryHash;
                        newSubMesh.surfaces.Add(brushSurfaceBuffer);

                        subMeshCounts.Add(newSubMesh);
                        continue;
                    }

                    var currentSubMesh = subMeshCounts[generatedMeshIndex];
                    currentSubMesh.indexCount  += surfaceIndexCount;
                    currentSubMesh.vertexCount += surfaceVertexCount;
                    currentSubMesh.surfaceHash  = Hashing.XXH64_mergeRound(currentSubMesh.surfaceHash, brushSurfaceBuffer.surfaceHash);
                    currentSubMesh.geometryHash = Hashing.XXH64_mergeRound(currentSubMesh.geometryHash, brushSurfaceBuffer.geometryHash);
                    currentSubMesh.surfaces.Add(brushSurfaceBuffer);
                }
            }

            for (int i = (int)subMeshCounts.Count - 1; i >= 0; i--)
            {
                if (subMeshCounts[i].vertexCount != 0 &&
                    subMeshCounts[i].indexCount != 0)
                {
                    continue;
                }
                subMeshCounts.RemoveAt(i);
            }
        }
Esempio n. 8
0
        internal static GeneratedMeshDescription[] GetMeshDescriptions(Int32 treeNodeID,
                                                                       MeshQuery[] meshQueries,
                                                                       VertexChannelFlags vertexChannelMask)
        {
            if (!AssertNodeIDValid(treeNodeID) || !AssertNodeType(treeNodeID, CSGNodeType.Tree))
            {
                return(null);
            }
            if (meshQueries == null)
            {
                throw new ArgumentNullException("meshTypes");
            }

            if (meshQueries.Length == 0)
            {
                return(null);
            }

            if (!IsValidNodeID(treeNodeID))
            {
                Debug.LogError("GenerateMeshDescriptions: Invalid node index used");
                return(null);
            }

            var treeNodeIndex = treeNodeID - 1;
            var treeInfo      = nodeHierarchies[treeNodeIndex].treeInfo;

            if (treeInfo == null)
            {
                Debug.LogError("GenerateMeshDescriptions: Invalid node index used");
                return(null);
            }

            treeInfo.subMeshCounts.Clear();
            treeInfo.meshDescriptions.Clear();

            if (nodeFlags[treeNodeIndex].IsNodeFlagSet(NodeStatusFlags.TreeNeedsUpdate))
            {
                UpdateTreeMesh(treeNodeID);
            }

            CombineSubMeshes(treeInfo, meshQueries, vertexChannelMask);

            if (treeInfo.subMeshCounts.Count <= 0)
            {
                nodeFlags[treeNodeIndex].UnSetNodeFlag(NodeStatusFlags.TreeMeshNeedsUpdate);
                //				Debug.LogWarning("GetMeshDescriptions: No meshes found");
                return(null);
            }

            if (treeInfo.meshDescriptions == null ||
                treeInfo.meshDescriptions.Count == 0 ||
                treeInfo.meshDescriptions[0].vertexCount <= 0 ||
                treeInfo.meshDescriptions[0].indexCount <= 0)
            {
                return(null);
            }

            nodeFlags[treeNodeIndex].UnSetNodeFlag(NodeStatusFlags.TreeMeshNeedsUpdate);
            return(treeInfo.meshDescriptions.ToArray());
        }
Esempio n. 9
0
 private static extern bool GenerateMeshDescriptions(Int32 treeNodeID,
                                                     Int32 meshTypeCount,
                                                     [In] IntPtr meshTypes,
                                                     VertexChannelFlags vertexChannelMask,
                                                     [Out] out Int32 meshDescriptionCount);