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); } }
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); }