internal MyIsoMesh CreateMesh(IMyStorage storage, MyCellCoord coord) { // mk:NOTE This method must be thread safe. Called from worker threads. coord.CoordInLod += m_cellsOffset >> coord.Lod; if (m_voxelMap is MyVoxelPhysics) { var clipmapId = ((MyVoxelPhysics)m_voxelMap).Parent.Render.RenderObjectIDs[0]; var clipmapCellId = MyCellCoord.GetClipmapCellHash(clipmapId, coord.PackId64()); var isoMesh = MyPrecalcJobRender.IsoMeshCache.Read(clipmapCellId); if (isoMesh != null) { return(isoMesh); } } var min = coord.CoordInLod << MyVoxelConstants.GEOMETRY_CELL_SIZE_IN_VOXELS_BITS; var max = min + MyVoxelConstants.GEOMETRY_CELL_SIZE_IN_VOXELS; // overlap to neighbor; introduces extra data but it makes logic for raycasts and collisions simpler (no need to check neighbor cells) min -= 1; max += 2; return(MyPrecalcComponent.IsoMesher.Precalc(storage, coord.Lod, min, max, false, false)); }
internal void DiscardClippedCells(RequestCollector collector) { foreach (var entry in m_clippedCells) { var data = entry.Value; data.ClippedOut = true; if (UseCache) { var clipmapCellId = MyCellCoord.GetClipmapCellHash(m_clipmap.Id, entry.Key); CellsCache.Write(clipmapCellId, data); Delete(entry.Key, data, false); } else { if (data.Cell != null) { Delete(entry.Key, data); } data.ReadyInClipmap = false; } } m_clippedCells.Clear(); }
internal void InvalidateRange(Vector3I lodMin, Vector3I lodMax) { // MyLog.Default.WriteLine("InvalidateRange Lod: " + m_lodIndex + " Min: " + lodMin + " Max: " + lodMax); var cell = new MyCellCoord(m_lodIndex, lodMin); for (var it = new Vector3I_RangeIterator(ref lodMin, ref lodMax); it.IsValid(); it.GetNext(out cell.CoordInLod)) { MyClipmap_CellData data; var id = cell.PackId64(); // MyLog.Default.WriteLine("Setting to: m_lodIndex " + cell.Lod + " Coord: " + cell.CoordInLod); if (m_storedCellData.TryGetValue(id, out data)) { data.State = CellState.Invalid; //MyLog.Default.WriteLine("Really set to: m_lodIndex " + cell.Lod + " Coord: " + cell.CoordInLod); } if (MyClipmap.UseCache) { var clipmapCellId = MyCellCoord.GetClipmapCellHash(m_clipmap.Id, id); var cachedCell = MyClipmap.CellsCache.Read(clipmapCellId); if (cachedCell != null) { cachedCell.State = CellState.Invalid; } } } }
public override void DoWork() { ProfilerShort.Begin("MyPrecalcJobRender.DoWork"); try { if (m_isCancelled) { return; } m_metadata.Cell = m_args.Cell; m_metadata.LocalAabb = BoundingBox.CreateInvalid(); var cellSize = MyVoxelCoordSystems.RenderCellSizeInLodVoxels(m_args.Cell.Lod); var min = m_args.Cell.CoordInLod * cellSize - 1; var max = min + cellSize - 1 + 1 // overlap to neighbor so geometry is stitched together within same LOD + 1 // extra overlap so there are more vertices for mapping to parent LOD + 1; // for eg. 9 vertices in row we need 9 + 1 samples (voxels) // + 1 // why not // + 1 // martin kroslak approved var clipmapCellId = MyCellCoord.GetClipmapCellHash(m_args.ClipmapId, m_args.Cell.PackId64()); MyIsoMesh highResMesh = IsoMeshCache.Read(clipmapCellId); if (highResMesh == null) { highResMesh = MyPrecalcComponent.IsoMesher.Precalc(m_args.Storage, m_args.Cell.Lod, min, max, true, MyFakes.ENABLE_VOXEL_COMPUTED_OCCLUSION); if (UseIsoCache && highResMesh != null) { IsoMeshCache.Write(clipmapCellId, highResMesh); } } if (m_isCancelled || highResMesh == null) { return; } MyIsoMesh lowResMesh = null; if (m_args.Cell.Lod < 15 && MyFakes.ENABLE_VOXEL_LOD_MORPHING) { var nextLodCell = m_args.Cell; nextLodCell.Lod++; clipmapCellId = MyCellCoord.GetClipmapCellHash(m_args.ClipmapId, nextLodCell.PackId64()); lowResMesh = IsoMeshCache.Read(clipmapCellId); if (lowResMesh == null) { // Less detailed mesh for vertex morph targets min >>= 1; max >>= 1; min -= 1; max += 2; lowResMesh = MyPrecalcComponent.IsoMesher.Precalc(m_args.Storage, m_args.Cell.Lod + 1, min, max, true, MyFakes.ENABLE_VOXEL_COMPUTED_OCCLUSION); if (UseIsoCache && lowResMesh != null) { IsoMeshCache.Write(clipmapCellId, lowResMesh); } } } if (m_isCancelled) { return; } RenderCellBuilder.BuildCell(m_args, highResMesh, lowResMesh, m_batches, out m_metadata); } finally { ProfilerShort.End(); } }
internal void SetCellMesh(MyRenderMessageUpdateClipmapCell msg) { var cellId = msg.Metadata.Cell.PackId64(); MyClipmap_CellData data; var clipmapCellId = MyCellCoord.GetClipmapCellHash(m_clipmap.Id, cellId); // MyCellCoord cellc = new MyCellCoord(); // cellc.SetUnpack(cellId); //MyLog.Default.WriteLine("SetCellMesh Lod: " + cellc.Lod + " Coord: " + cellc.CoordInLod); if (m_storedCellData.TryGetValue(cellId, out data)) { PendingCacheCellData.Remove(clipmapCellId); if (data.State == CellState.Invalid) { // MyLog.Default.WriteLine("Invalid"); //Cell was invalidated while calculating from old data return; } if (data.Cell == null && msg.Batches.Count != 0) { //MyLog.Default.WriteLine("added to nonempty"); data.Cell = m_clipmap.m_cellHandler.CreateCell(m_clipmap.m_scaleGroup, msg.Metadata.Cell, ref m_clipmap.m_worldMatrix); System.Diagnostics.Debug.Assert(data.Cell != null, "Cell not created"); if (data.Cell != null) { if (data.Cell.IsValid()) { data.CellHandler = m_clipmap.m_cellHandler; m_nonEmptyCells[cellId] = data; } } } else if (data.Cell != null && msg.Batches.Count == 0) { //MyLog.Default.WriteLine("removed"); RemoveFromScene(cellId, data); m_nonEmptyCells.Remove(cellId); m_clipmap.m_cellHandler.DeleteCell(data.Cell); m_blendedCells.Remove(cellId); data.Cell = null; data.CellHandler = null; if (UseCache) { CellsCache.Remove(cellId); } } if (data.Cell != null) { //MyLog.Default.WriteLine("mesh updated"); if (data.Cell.IsValid()) { m_clipmap.m_cellHandler.UpdateMesh(data.Cell, msg); } } data.State = CellState.Loaded; data.WasLoaded = true; } else if (PendingCacheCellData.TryGetValue(clipmapCellId, out data)) { if (msg.Batches.Count != 0) { data.Cell = m_clipmap.m_cellHandler.CreateCell(m_clipmap.m_scaleGroup, msg.Metadata.Cell, ref m_clipmap.m_worldMatrix); m_clipmap.m_cellHandler.UpdateMesh(data.Cell, msg); data.CellHandler = m_clipmap.m_cellHandler; } CellsCache.Write(clipmapCellId, data); PendingCacheCellData.Remove(clipmapCellId); data.State = CellState.Loaded; data.WasLoaded = true; } }
private void UnclipCell(RequestCollector collector, MyCellCoord cell, bool isVisible) { var cellId = cell.PackId64(); var clipmapCellId = MyCellCoord.GetClipmapCellHash(m_clipmap.Id, cellId); MyClipmap_CellData data; if (isVisible) { bool highPriority = true; if (m_clippedCells.TryGetValue(cellId, out data)) { m_clippedCells.Remove(cellId); } else { highPriority = false; CellBlendData blendData; if (!m_blendedCells.TryGetValue(cellId, out blendData)) { data = CellsCache.Read(clipmapCellId); if (data == null) //cache miss { data = new MyClipmap_CellData(); ClippingCacheMisses++; } else { //cache hit ClippingCacheHits++; //System.Diagnostics.Debug.Assert((!data.InScene && data.Cell != null) || data.Cell == null, "Not allowed cell state"); data.InScene = false; if (data.Cell != null) { m_nonEmptyCells[cellId] = data; } } } else { data = blendData.CellData; if (blendData.State == BlendState.Removing) { blendData.UndoAfterFinish = true; } if (data.Cell != null) { m_nonEmptyCells[cellId] = data; } } } if (data.State == CellState.Invalid) { if (MyClipmap.UseQueries) { BoundingBoxD bbd; MyVoxelCoordSystems.RenderCellCoordToLocalAABB(ref cell, out bbd); BoundingBox bb = new BoundingBox(bbd); if (m_clipmap.m_prunningFunc == null || m_clipmap.m_prunningFunc(ref bb, false) == ContainmentType.Intersects) { collector.AddRequest(cellId, data, highPriority); } else { data.State = CellState.Loaded; data.WasLoaded = true; } } else { collector.AddRequest(cellId, data, highPriority); } } m_storedCellData.Add(cellId, data); data.ReadyInClipmap = true; data.ClippedOut = false; } else { if (!m_storedCellData.ContainsKey(cellId) && (!PendingCacheCellData.ContainsKey(clipmapCellId) || PendingCacheCellData[clipmapCellId].State == CellState.Invalid) && CellsCache.Read(clipmapCellId) == null) { if (!PendingCacheCellData.TryGetValue(clipmapCellId, out data)) { data = new MyClipmap_CellData(); PendingCacheCellData.Add(clipmapCellId, data); } if (MyClipmap.UseQueries) { BoundingBoxD bbd; MyVoxelCoordSystems.RenderCellCoordToLocalAABB(ref cell, out bbd); BoundingBox bb = new BoundingBox(bbd); if (m_clipmap.m_prunningFunc == null || m_clipmap.m_prunningFunc(ref bb, false) == ContainmentType.Intersects) { data.State = CellState.Invalid; collector.AddRequest(cellId, data, false); } else { data.State = CellState.Loaded; data.WasLoaded = true; } } else { data.State = CellState.Invalid; collector.AddRequest(cellId, data, false); } } } }