/// <summary> /// Sends a merge job message if mergedMeshId has more than pendingThreshold pending lod meshes. /// </summary> /// <returns>True if message was sent; false otherwise</returns> internal static bool TryStartMerge(this MyMergedLodMeshId mergedLodMeshId, uint clipmapId, int pendingThreshold, List <LodMeshId> outLodMeshesSent, ulong workId) { Debug.Assert(outLodMeshesSent != null && outLodMeshesSent.Count == 0, "Lod mesh list not empty!"); var pendingLodMeshes = mergedLodMeshId.Info.PendingLodMeshes; var mergedLodMeshes = mergedLodMeshId.Info.MergedLodMeshes; bool pendingMeshesOverThreshold = pendingLodMeshes.Count >= pendingThreshold; if (pendingMeshesOverThreshold) { foreach (LodMeshId lodMesh in pendingLodMeshes) { m_tmpBatches.AddArray(lodMesh.Info.DataBatches); outLodMeshesSent.Add(lodMesh); m_tmpMetadata.Add(lodMesh.Info.BatchMetadata); } foreach (LodMeshId lodMesh in mergedLodMeshes) { m_tmpBatches.AddArray(lodMesh.Info.DataBatches); outLodMeshesSent.Add(lodMesh); m_tmpMetadata.Add(lodMesh.Info.BatchMetadata); } pendingLodMeshes.Clear(); mergedLodMeshes.Clear(); MyVoxelCellInfo cellInfo = MyMeshes.GetVoxelInfo(mergedLodMeshId); MyRenderProxy.MergeVoxelMeshes(clipmapId, workId, m_tmpMetadata, new MyCellCoord(cellInfo.Lod, cellInfo.Coord), m_tmpBatches); m_tmpBatches.Clear(); m_tmpMetadata.SetSize(0); } return(pendingMeshesOverThreshold); }
internal void Update() { if (!IsUsed()) { return; } bool invalidateLod = false; foreach (var proxyIndex in m_dirtyProxyIndices) { var cellProxy = m_mergedLodMeshProxies[proxyIndex]; if (MyMeshes.CanStartMerge(cellProxy.MeshId, 1)) { Vector3I mergeCell = MyMeshes.GetVoxelInfo(cellProxy.MeshId).Coord; int divideIndex = GetDivideIndexFromMergeCell(ref mergeCell); MyMergedLodMeshId mergedId = MyMeshes.GetMergedLodMesh(cellProxy.MeshId, 0); invalidateLod |= mergedId.Info.MergedLodMeshes.Count > 0; mergedId.Info.PendingLodMeshes.UnionWith(mergedId.Info.MergedLodMeshes); mergedId.Info.MergedLodMeshes.Clear(); TryCancelMergeJob(divideIndex, MeshId.NULL); TryStartMergeJob(divideIndex, 1); } } m_dirtyProxyIndices.Clear(); if (invalidateLod) { InvalidateAllMergedMeshesInLod(); } }
internal static bool UnmergeLodMesh(this MyMergedLodMeshId mergedLodMesh, LodMeshId lodMesh) { var pendingLodMeshes = mergedLodMesh.Info.PendingLodMeshes; var mergedLodMeshes = mergedLodMesh.Info.MergedLodMeshes; bool alreadyMerged = mergedLodMeshes.Contains(lodMesh); if (alreadyMerged) { MyMeshes.UnlinkLodMeshFromMerged(lodMesh); } if (pendingLodMeshes.Remove(lodMesh)) { Debug.Assert(!alreadyMerged, "Lod mesh set as pending and merged at the same time!"); } if (alreadyMerged) { mergedLodMeshes.Remove(lodMesh); pendingLodMeshes.UnionWith(mergedLodMeshes); mergedLodMeshes.Clear(); } return(alreadyMerged); }
internal void Clear() { WorldMatrix = MatrixD.Zero; CommonObjectData = default(MyObjectDataCommon); NonVoxelObjectData = MyObjectDataNonVoxel.Invalid; VoxelCommonObjectData = MyObjectDataVoxelCommon.Invalid; Mesh = LodMeshId.NULL; MergedMesh = MyMergedLodMeshId.NULL; Instancing = InstancingId.NULL; DepthShaders = MyMaterialShadersBundleId.NULL; Shaders = MyMaterialShadersBundleId.NULL; ForwardShaders = MyMaterialShadersBundleId.NULL; DrawSubmesh = default(MyDrawSubmesh); PerMaterialIndex = 0; SectionSubmeshes = null; InstanceCount = 0; StartInstance = 0; SkinningMatrices = null; Type = MyMaterialType.OPAQUE; Flags = 0; Lod = 0; ObjectBuffer = null; Parent = null; Material = MyStringId.NullOrEmpty; }
internal void UpdateMesh(MyRenderMessageUpdateMergedVoxelMesh updateMessage) { int divideIndex = GetDivideIndexFromMergeCell(ref updateMessage.Metadata.Cell.CoordInLod); // A job wasn't cancelled in time and made it here if (m_mergeJobs[divideIndex].CurrentWorkId != updateMessage.WorkId) { return; } MyMergedLodMeshId mergedId = MyMeshes.GetMergedLodMesh(m_mergedLodMeshProxies[divideIndex].MeshId, 0); bool mergeSuccessful = m_mergedLodMeshProxies[divideIndex].UpdateMergedMesh(updateMessage); if (mergeSuccessful) { Debug.Assert(mergedId.Info.MergedLodMeshes.Count == 0, "Merging into an already merged mesh"); mergedId.Info.MergedLodMeshes.UnionWith(m_mergeJobs[divideIndex].LodMeshesBeingMerged); SwitchMergeState(divideIndex, true); } else { mergedId.Info.PendingLodMeshes.UnionWith(m_mergeJobs[divideIndex].LodMeshesBeingMerged); } ResetMerge(divideIndex); }
internal bool OnAddedToScene(MyClipmapCellProxy cellProxy) { if (!IsUsed()) { return(false); } bool lodAabbChanged = false; int rootProxy = m_boundingBoxes.GetRoot(); BoundingBoxD lodAabbBefore = BoundingBoxD.CreateInvalid(); if (rootProxy != -1) { lodAabbBefore = m_boundingBoxes.GetAabb(rootProxy); } BoundingBoxD cellAabb = (BoundingBoxD)cellProxy.LocalAabb; m_cellProxyToAabbProxy.Add(cellProxy, m_boundingBoxes.AddProxy(ref cellAabb, null, 0)); if (rootProxy != -1) { BoundingBoxD lodAabbAfter = m_boundingBoxes.GetAabb(rootProxy); lodAabbChanged = lodAabbBefore.Equals(lodAabbAfter); } if (lodAabbChanged) { InvalidateAllMergedMeshesInLod(); } Vector3D translation = cellProxy.Translation; int divideIndex = GetDivideIndex(ref translation); m_trackedActors[divideIndex].Add(cellProxy.Actor); MyMergedLodMeshId mergedLodMeshId = MyMeshes.GetMergedLodMesh(m_mergedLodMeshProxies[divideIndex].MeshId, 0); LodMeshId lodMeshToMerge = MyMeshes.GetLodMesh(cellProxy.MeshId, 0); bool mergedMesh = mergedLodMeshId.MergeLodMesh(lodMeshToMerge); if (mergedMesh) { InvalidateAllMergedMeshesInLod(); } TryCancelMergeJob(divideIndex, MeshId.NULL); bool startedMerge = TryStartMergeJob(divideIndex, 1000); bool shouldMarkDirty = !mergedMesh && !startedMerge; if (shouldMarkDirty) { m_dirtyProxyIndices.Add(divideIndex); } return(shouldMarkDirty); }
internal bool OnDeleteCell(MyClipmapCellProxy cellProxy) { if (!IsUsed()) { return(false); } bool unloadedCell = false; Vector3D translation = cellProxy.Translation; int divideIndex; if (TryGetDivideIndex(ref translation, out divideIndex)) { MyMergedLodMeshId mergedLodMeshId = MyMeshes.GetMergedLodMesh(m_mergedLodMeshProxies[divideIndex].MeshId, 0); LodMeshId lodMeshId = MyMeshes.GetLodMesh(cellProxy.MeshId, 0); bool unmergedMesh = mergedLodMeshId.UnmergeLodMesh(lodMeshId); if (unmergedMesh) { InvalidateAllMergedMeshesInLod(); } TryCancelMergeJob(divideIndex, cellProxy.MeshId); cellProxy.Unload(); unloadedCell = true; TryStartMergeJob(divideIndex, 1000); if (unmergedMesh && unloadedCell) { m_dirtyProxyIndices.Add(divideIndex); } m_trackedActors[divideIndex].Remove(cellProxy.Actor); } int proxyId; if (m_cellProxyToAabbProxy.TryGetValue(cellProxy, out proxyId)) { m_boundingBoxes.RemoveProxy(m_cellProxyToAabbProxy[cellProxy]); m_cellProxyToAabbProxy.Remove(cellProxy); } return(unloadedCell); }
private void InvalidateAllMergedMeshesInLod() { // TODO: Redistribute actors for (int divideIndex = 0; divideIndex < m_lodDivisions; ++divideIndex) { MyMergedLodMeshId mergedLodMeshId = MyMeshes.GetMergedLodMesh(m_mergedLodMeshProxies[divideIndex].MeshId, 0); bool markDirty = mergedLodMeshId.Info.MergedLodMeshes.Count > 0; mergedLodMeshId.Info.PendingLodMeshes.UnionWith(mergedLodMeshId.Info.MergedLodMeshes); mergedLodMeshId.Info.MergedLodMeshes.Clear(); SwitchMergeState(divideIndex, false); if (markDirty) { m_dirtyProxyIndices.Add(divideIndex); } } }
internal static bool MergeLodMesh(this MyMergedLodMeshId mergedLodMesh, LodMeshId lodMesh) { var pendingLodMeshes = mergedLodMesh.Info.PendingLodMeshes; var mergedLodMeshes = mergedLodMesh.Info.MergedLodMeshes; bool alreadyMerged = mergedLodMeshes.Contains(lodMesh); if (alreadyMerged) { pendingLodMeshes.UnionWith(mergedLodMeshes); mergedLodMeshes.Clear(); } else { pendingLodMeshes.Add(lodMesh); } MyMeshes.LinkLodMeshToMerged(lodMesh, mergedLodMesh); return(alreadyMerged); }
internal static bool CanStartMerge(this MyMergedLodMeshId mergedLodMeshId, int pendingThreshold) { var pendingLodMeshes = mergedLodMeshId.Info.PendingLodMeshes; return(pendingLodMeshes.Count >= pendingThreshold); }
internal override bool RebuildLodProxy(int lodNum, bool skinningEnabled, MySkinningComponent skinning) { Debug.Assert(Mesh.Info.LodsNum == 1); MyRenderLod lod = null; int partCount; LodMeshId lodMesh = new LodMeshId(); MyMergedLodMeshId mergedLodMesh = new MyMergedLodMeshId(); VertexLayoutId vertexLayout; bool isMergedMesh = MyMeshes.IsMergedVoxelMesh(Mesh); if (!isMergedMesh) { if (!Owner.IsVisible) { return(false); } lodMesh = MyMeshes.GetLodMesh(Mesh, 0); vertexLayout = lodMesh.VertexLayout; partCount = lodMesh.Info.PartsNum; } else { mergedLodMesh = MyMeshes.GetMergedLodMesh(Mesh, 0); if (mergedLodMesh.VertexLayout == VertexLayoutId.NULL || mergedLodMesh.Info.MergedLodMeshes.Count == 0) { return(false); } partCount = mergedLodMesh.Info.PartsNum; vertexLayout = mergedLodMesh.VertexLayout; } MyObjectPoolManager.Init(ref m_lods[lodNum]); lod = m_lods[lodNum]; lod.VertexLayout1 = vertexLayout; // Hide proxies when they will already be rendered in a merged mesh if (!MyMeshes.IsLodMeshMerged(lodMesh)) { AddToRenderables(); } Debug.Assert(partCount > 0); lod.VertexShaderFlags = MyShaderUnifiedFlags.USE_VOXEL_DATA | MyShaderUnifiedFlags.USE_VOXEL_MORPHING | MyShaderUnifiedFlags.DITHERED; bool initializeProxies = true; //isMergedMesh || !MyMeshes.IsLodMeshMerged(lodMesh); bool initializeDepthProxy = true; //!isMergedMesh && Num > 0; int numToInitialize = (initializeProxies ? partCount : 0) + (initializeDepthProxy ? 1 : 0); if (numToInitialize > 0) { lod.AllocateProxies(numToInitialize); } AnyDrawOutsideViewDistance = false; int constantBufferSize = GetConstantBufferSize(lod, skinningEnabled); if (initializeProxies) { for (int partIndex = 0; partIndex < partCount; partIndex++) { CreateRenderableProxyForPart(lodNum, constantBufferSize, partIndex, partIndex, false); } } if (initializeDepthProxy) { CreateRenderableProxyForPart(lodNum, constantBufferSize, numToInitialize - 1, 0, true); } return(true); }
internal void Clear() { WorldMatrix = MatrixD.Zero; CommonObjectData = default(MyObjectDataCommon); NonVoxelObjectData = MyObjectDataNonVoxel.Invalid; VoxelCommonObjectData = MyObjectDataVoxelCommon.Invalid; Mesh = LodMeshId.NULL; MergedMesh = MyMergedLodMeshId.NULL; Instancing = InstancingId.NULL; DepthShaders = MyMaterialShadersBundleId.NULL; Shaders = MyMaterialShadersBundleId.NULL; ForwardShaders = MyMaterialShadersBundleId.NULL; DrawSubmesh = default(MyDrawSubmesh); PerMaterialIndex = 0; SectionSubmeshes = null; InstanceCount = 0; StartInstance = 0; SkinningMatrices = null; Type = MyMaterialType.OPAQUE; Flags = 0; Lod = 0; ObjectBuffer = null; Parent = null; Material = MyMeshMaterialId.NULL; UnusedMaterials = UnusedMaterials ?? new HashSet<string>(); UnusedMaterials.Clear(); }
internal override unsafe bool RebuildLodProxy(int lodNum, bool skinningEnabled, MySkinningComponent skinning) { Debug.Assert(Mesh.Info.LodsNum == 1); MyRenderLod lod = null; int partCount; LodMeshId lodMesh = new LodMeshId(); MyMergedLodMeshId mergedLodMesh = new MyMergedLodMeshId(); VertexLayoutId vertexLayout; bool isMergedMesh = MyMeshes.IsMergedVoxelMesh(Mesh); if (!isMergedMesh) { lodMesh = MyMeshes.GetLodMesh(Mesh, 0); // Don't create proxies when they will already be rendered in a merged mesh if (MyMeshes.IsLodMeshMerged(lodMesh) || !Owner.IsVisible) return false; vertexLayout = lodMesh.VertexLayout; partCount = lodMesh.Info.PartsNum; } else { mergedLodMesh = MyMeshes.GetMergedLodMesh(Mesh, 0); if (mergedLodMesh.VertexLayout == VertexLayoutId.NULL || mergedLodMesh.Info.MergedLodMeshes.Count == 0) return false; partCount = mergedLodMesh.Info.PartsNum; vertexLayout = mergedLodMesh.VertexLayout; } MyObjectPoolManager.Init(ref m_lods[lodNum]); lod = m_lods[lodNum]; lod.VertexLayout1 = vertexLayout; AddToRenderables(); Debug.Assert(partCount > 0); lod.VertexShaderFlags = MyShaderUnifiedFlags.USE_VOXEL_DATA | MyShaderUnifiedFlags.USE_VOXEL_MORPHING | MyShaderUnifiedFlags.DITHERED; bool initializeProxies = true;//isMergedMesh || !MyMeshes.IsLodMeshMerged(lodMesh); bool initializeDepthProxy = true;//!isMergedMesh && Num > 0; int numToInitialize = (initializeProxies ? partCount : 0) + (initializeDepthProxy ? 1 : 0); if (numToInitialize > 0) lod.AllocateProxies(numToInitialize); AnyDrawOutsideViewDistance = false; if (initializeProxies) { for (int partIndex = 0; partIndex < partCount; partIndex++) { CreateRenderableProxyForPart(lod, GetConstantBufferSize(lod, skinningEnabled), partIndex, partIndex, false); } } if (initializeDepthProxy) CreateRenderableProxyForPart(lod, GetConstantBufferSize(lod, skinningEnabled), numToInitialize - 1, 0, true); return true; }