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 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); }
private void AssignLodMeshToProxy(MeshId mesh, MyRenderableProxy proxy) { if (MyMeshes.IsMergedVoxelMesh(mesh)) { proxy.MergedMesh = MyMeshes.GetMergedLodMesh(mesh, 0); } else { proxy.Mesh = MyMeshes.GetLodMesh(mesh, 0); } }
internal bool ShouldHaveFoliage() { var mesh = Owner.GetRenderable().GetModel(); int voxelLod = MyMeshes.GetVoxelInfo(mesh).Lod; bool voxelMeshNotReady = voxelLod > LodLimit; if (voxelMeshNotReady) { return(false); } int partsNum; if (MyMeshes.IsMergedVoxelMesh(mesh)) { partsNum = MyMeshes.GetMergedLodMesh(mesh, 0).Info.PartsNum; } else { partsNum = MyMeshes.GetLodMesh(mesh, 0).Info.PartsNum; } // only stream stones for lod0 if (voxelLod > 0) { bool allStone = true; for (int i = 0; i < partsNum; i++) { var triple = MyMeshes.GetVoxelPart(mesh, i).Info.MaterialTriple; if (triple.I0 != -1 && MyVoxelMaterials1.Table[triple.I0].HasFoliage && MyVoxelMaterials1.Table[triple.I0].FoliageType == 0) { allStone = false; break; } if (triple.I1 != -1 && MyVoxelMaterials1.Table[triple.I1].HasFoliage && MyVoxelMaterials1.Table[triple.I1].FoliageType == 0) { allStone = false; break; } if (triple.I2 != -1 && MyVoxelMaterials1.Table[triple.I2].HasFoliage && MyVoxelMaterials1.Table[triple.I2].FoliageType == 0) { allStone = false; break; } } if (allStone) { return(false); } } return(true); }
internal static void AssignLodMeshToProxy(this MeshId meshId, MyRenderableProxy proxy) { Debug.Assert(proxy != null, "Proxy cannot be null!"); if (MyMeshes.IsMergedVoxelMesh(meshId)) { proxy.MergedMesh = MyMeshes.GetMergedLodMesh(meshId, 0); } else { proxy.Mesh = MyMeshes.GetLodMesh(meshId, 0); } }
internal static int GetIndexCount(this MeshId meshId) { int indexCount = 0; if (MyMeshes.IsMergedVoxelMesh(meshId)) { indexCount = MyMeshes.GetMergedLodMesh(meshId, 0).Info.IndicesNum; } else { indexCount = MyMeshes.GetLodMesh(meshId, 0).Info.IndicesNum; } return(indexCount); }
internal static MyMeshBuffers GetMeshBuffers(this MeshId meshId) { MyMeshBuffers buffers; if (MyMeshes.IsMergedVoxelMesh(meshId)) { buffers = MyMeshes.GetMergedLodMesh(meshId, 0).Buffers; } else { buffers = MyMeshes.GetLodMesh(meshId, 0).Buffers; } return(buffers); }
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 void DebugDrawCells() { if (!IsUsed()) { return; } foreach (var cellProxy in m_mergedLodMeshProxies) { var mergedMeshId = MyMeshes.GetMergedLodMesh(cellProxy.MeshId, 0); if (mergedMeshId.Info.MergedLodMeshes.Count <= 0) { continue; } BoundingBoxD worldAabb = cellProxy.LocalAabb.Transform(cellProxy.WorldMatrix); MyRenderProxy.DebugDrawAABB(worldAabb, MyClipmap.LOD_COLORS[m_lod], 1.0f, 1.0f, false); } }
private bool TryCancelMergeJob(int divideIndex, MeshId meshIdToRemove) { bool canceled = false; if (m_mergeJobs[divideIndex].LodMeshesBeingMerged.Count > 0) { // Send the cancel message MyRenderProxy.CancelVoxelMeshMerge(m_parentClipmap.Id, m_mergeJobs[divideIndex].CurrentWorkId); if (meshIdToRemove != MeshId.NULL) { m_mergeJobs[divideIndex].LodMeshesBeingMerged.Remove(MyMeshes.GetLodMesh(meshIdToRemove, 0)); } // Put the canceled meshes back into the correct pending queue var mergedId = MyMeshes.GetMergedLodMesh(m_mergedLodMeshProxies[divideIndex].MeshId, 0); mergedId.Info.PendingLodMeshes.UnionWith(m_mergeJobs[divideIndex].LodMeshesBeingMerged); ResetMerge(divideIndex); canceled = true; } return(canceled); }
internal static bool ShouldHaveFoliage(this MeshId mesh) { int partsNum; if (MyMeshes.IsMergedVoxelMesh(mesh)) { partsNum = MyMeshes.GetMergedLodMesh(mesh, 0).Info.PartsNum; } else { partsNum = MyMeshes.GetLodMesh(mesh, 0).Info.PartsNum; } bool shouldHaveFoliage = false; for (int partIndex = 0; partIndex < partsNum; ++partIndex) { var triple = MyMeshes.GetVoxelPart(mesh, partIndex).Info.MaterialTriple; if (triple.I0 >= 0 && MyVoxelMaterials1.Table[triple.I0].HasFoliage) { shouldHaveFoliage = true; break; } if (triple.I1 >= 0 && MyVoxelMaterials1.Table[triple.I1].HasFoliage) { shouldHaveFoliage = true; break; } if (triple.I2 >= 0 && MyVoxelMaterials1.Table[triple.I2].HasFoliage) { shouldHaveFoliage = true; break; } } return(shouldHaveFoliage); }
internal void ResetMeshes() { if (!IsUsed()) { return; } foreach (var mergedProxy in m_mergedLodMeshProxies) { var mergedMeshId = MyMeshes.GetMergedLodMesh(mergedProxy.MeshId, 0); mergedMeshId.Info.PendingLodMeshes.Clear(); mergedMeshId.Info.MergedLodMeshes.Clear(); } for (int divideIndex = 0; divideIndex < m_lodDivisions; ++divideIndex) { SwitchMergeState(divideIndex, false); m_trackedActors[divideIndex].Clear(); ResetMerge(divideIndex); } m_boundingBoxes.Clear(); m_cellProxyToAabbProxy.Clear(); m_dirtyProxyIndices.Clear(); }
internal unsafe void FillStreams() { bool alreadyFilled = m_streams != null && m_streams.Count > 0; if (alreadyFilled) { return; } var mesh = Owner.GetRenderable().GetModel(); int voxelLod = MyMeshes.GetVoxelInfo(mesh).Lod; if (!Owner.IsVisible) { return; } int partsNum; if (MyMeshes.IsMergedVoxelMesh(mesh)) { partsNum = MyMeshes.GetMergedLodMesh(mesh, 0).Info.PartsNum; } else { partsNum = MyMeshes.GetLodMesh(mesh, 0).Info.PartsNum; } m_streams = new Dictionary <int, MyFoliageStream>(); // analyze for (int partIndex = 0; partIndex < partsNum; ++partIndex) { var partInfo = MyMeshes.GetVoxelPart(mesh, partIndex).Info; var triple = partInfo.MaterialTriple; if (triple.I0 != -1 && MyVoxelMaterials1.Table[triple.I0].HasFoliage) { PrepareStream(triple.I0, partInfo.IndexCount / 3, voxelLod); } if (triple.I1 != -1 && MyVoxelMaterials1.Table[triple.I1].HasFoliage) { PrepareStream(triple.I1, partInfo.IndexCount / 3, voxelLod); } if (triple.I2 != -1 && MyVoxelMaterials1.Table[triple.I2].HasFoliage) { PrepareStream(triple.I2, partInfo.IndexCount / 3, voxelLod); } } // prepare foreach (var stream in m_streams.Values) { stream.AllocateStreamOutBuffer(sizeof(Vector3) + sizeof(uint)); } // analyze for (int partIndex = 0; partIndex < partsNum; partIndex++) { var partInfo = MyMeshes.GetVoxelPart(mesh, partIndex).Info; var triple = partInfo.MaterialTriple; if (triple.I0 != -1 && MyVoxelMaterials1.Table[triple.I0].HasFoliage) { FillStreamWithTerrainBatch(triple.I0, 0, partInfo.IndexCount, partInfo.StartIndex, 0); } if (triple.I1 != -1 && MyVoxelMaterials1.Table[triple.I1].HasFoliage) { FillStreamWithTerrainBatch(triple.I1, 1, partInfo.IndexCount, partInfo.StartIndex, 0); } if (triple.I2 != -1 && MyVoxelMaterials1.Table[triple.I2].HasFoliage) { FillStreamWithTerrainBatch(triple.I2, 2, partInfo.IndexCount, partInfo.StartIndex, 0); } } }
internal static BoundingBox?GetBoundingBox(this MeshId meshId, int lod) { return(MyMeshes.IsMergedVoxelMesh(meshId) ? MyMeshes.GetMergedLodMesh(meshId, 0).Info.BoundingBox : MyMeshes.GetLodMesh(meshId, lod).Info.BoundingBox); }
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); }
private void CreateRenderableProxyForPart(MyRenderLod lod, int objectConstantsSize, int proxyIndex, int partIndex, bool shadowsOnly) { var partId = MyMeshes.GetVoxelPart(Mesh, partIndex); var technique = partId.Info.MaterialTriple.IsMultimaterial() ? MyVoxelMesh.MULTI_MATERIAL_TAG : MyVoxelMesh.SINGLE_MATERIAL_TAG; if (shadowsOnly) { technique = MyVoxelMesh.SINGLE_MATERIAL_TAG; } lod.RenderableProxies[proxyIndex].WorldMatrix = Owner.WorldMatrix; //lod.RenderableProxies[p].ObjectData.LocalMatrix = m_owner.WorldMatrix; lod.RenderableProxies[proxyIndex].NonVoxelObjectData = MyObjectDataNonVoxel.Invalid; lod.RenderableProxies[proxyIndex].VoxelCommonObjectData.VoxelOffset = m_voxelOffset; lod.RenderableProxies[proxyIndex].VoxelCommonObjectData.MassiveCenterRadius = Vector4.Zero; // Set in UpdateLodState lod.RenderableProxies[proxyIndex].VoxelCommonObjectData.VoxelScale = m_voxelScale; AssignLodMeshToProxy(Mesh, lod.RenderableProxies[proxyIndex]); lod.RenderableProxies[proxyIndex].DepthShaders = MyMaterialShaders.Get( X.TEXT(MapTechniqueToShaderMaterial(technique)), X.TEXT(MyGeometryRenderer.DEFAULT_DEPTH_PASS), lod.VertexLayout1, lod.VertexShaderFlags | MyShaderUnifiedFlags.DEPTH_ONLY | MapTechniqueToShaderMaterialFlags(technique) | MyShaderUnifiedFlags.DITHERED); lod.RenderableProxies[proxyIndex].Shaders = MyMaterialShaders.Get( X.TEXT(MapTechniqueToShaderMaterial(technique)), X.TEXT(MyGeometryRenderer.DEFAULT_OPAQUE_PASS), lod.VertexLayout1, lod.VertexShaderFlags | MapTechniqueToShaderMaterialFlags(technique) | MyShaderUnifiedFlags.DITHERED); lod.RenderableProxies[proxyIndex].ForwardShaders = MyMaterialShaders.Get( X.TEXT(MapTechniqueToShaderMaterial(technique)), X.TEXT(MyGeometryRenderer.DEFAULT_FORWARD_PASS), lod.VertexLayout1, lod.VertexShaderFlags | MapTechniqueToShaderMaterialFlags(technique) | MyShaderUnifiedFlags.DITHERED); var partInfo = partId.Info; MyDrawSubmesh drawSubmesh; if (shadowsOnly) { MyMeshBuffers buffers; if (MyMeshes.IsMergedVoxelMesh(Mesh)) { buffers = MyMeshes.GetMergedLodMesh(Mesh, 0).Buffers; } else { buffers = MyMeshes.GetLodMesh(Mesh, 0).Buffers; } drawSubmesh = new MyDrawSubmesh { BaseVertex = 0, StartIndex = 0, IndexCount = buffers.IB.Capacity, BonesMapping = null, MaterialId = MyVoxelMaterials1.GetMaterialProxyId(partId.Info.MaterialTriple), Flags = MyDrawSubmesh.MySubmeshFlags.Depth }; } else { drawSubmesh = new MyDrawSubmesh { BaseVertex = partInfo.BaseVertex, StartIndex = partInfo.StartIndex, IndexCount = partInfo.IndexCount, BonesMapping = null, MaterialId = MyVoxelMaterials1.GetMaterialProxyId(partId.Info.MaterialTriple), Flags = MyDrawSubmesh.MySubmeshFlags.Gbuffer | MyDrawSubmesh.MySubmeshFlags.Forward }; } lod.RenderableProxies[proxyIndex].DrawSubmesh = drawSubmesh; lod.RenderableProxies[proxyIndex].SkinningMatrices = null; lod.RenderableProxies[proxyIndex].ObjectBuffer = MyCommon.GetObjectCB(objectConstantsSize); lod.RenderableProxies[proxyIndex].InstanceCount = m_instanceCount; lod.RenderableProxies[proxyIndex].StartInstance = m_startInstance; lod.RenderableProxies[proxyIndex].Flags = MapTechniqueToRenderableFlags(technique) | m_additionalFlags; lod.RenderableProxies[proxyIndex].Type = MapTechniqueToMaterialType(technique); lod.RenderableProxies[proxyIndex].Parent = this; lod.RenderableProxies[proxyIndex].Lod = 0; lod.RenderableProxies[proxyIndex].Instancing = m_instancing; AnyDrawOutsideViewDistance |= lod.RenderableProxies[proxyIndex].Flags.HasFlags(MyRenderableProxyFlags.DrawOutsideViewDistance); ulong sortingKey = 0; My64BitValueHelper.SetBits(ref sortingKey, 36, 2, (ulong)lod.RenderableProxies[proxyIndex].Type); My64BitValueHelper.SetBits(ref sortingKey, 32, 4, (ulong)drawSubmesh.MaterialId.Index); My64BitValueHelper.SetBits(ref sortingKey, 26, 6, (ulong)MyShaderMaterial.GetID(MapTechniqueToShaderMaterial(technique))); My64BitValueHelper.SetBits(ref sortingKey, 22, 4, (ulong)m_voxelLod); My64BitValueHelper.SetBits(ref sortingKey, 16, 6, (ulong)lod.VertexShaderFlags); //My64BitValueHelper.SetBits(ref sortingKey, 14, 6, (ulong)lod.VertexLayout1.Index); //My64BitValueHelper.SetBits(ref sortingKey, 0, 14, (ulong)m_owner.ID); lod.SortingKeys[proxyIndex] = sortingKey; }