private void GetChunk(ref Vector3I coord, out VoxelChunk chunk, MyStorageDataTypeFlags required) { using (m_cacheLock.AcquireExclusiveUsing()) { if (!m_cachedChunks.TryGetValue(coord, out chunk)) { chunk = new VoxelChunk(coord); var rangeStart = coord << VoxelChunk.SizeBits; var rangeEnd = ((coord + 1) << VoxelChunk.SizeBits) - 1; if (required != 0) { using (m_storageLock.AcquireSharedUsing()) ReadDatForChunk(chunk, required); } m_chunksbyAge.Enqueue(coord); m_cachedChunks.Add(coord, chunk); var bb = new BoundingBox(rangeStart, rangeEnd); chunk.TreeProxy = m_cacheMap.AddProxy(ref bb, chunk, 0); } else if ((chunk.Cached & required) != required) { using (m_storageLock.AcquireSharedUsing()) ReadDatForChunk(chunk, required & ~chunk.Cached); } } }
void ModAPI.Interfaces.IMyStorage.ReadRange(MyStorageDataCache target, MyStorageDataTypeFlags dataToRead, int lodIndex, Vector3I lodVoxelRangeMin, Vector3I lodVoxelRangeMax) { if ((uint)lodIndex >= (uint)MyCellCoord.MAX_LOD_COUNT) return; ReadRange(target, dataToRead, lodIndex, ref lodVoxelRangeMin, ref lodVoxelRangeMax); }
void VRage.ModAPI.IMyStorage.ReadRange(MyStorageData target, MyStorageDataTypeFlags dataToRead, int lodIndex, Vector3I lodVoxelRangeMin, Vector3I lodVoxelRangeMax, ref MyVoxelRequestFlags requestFlags) { if ((uint)lodIndex >= (uint)MyCellCoord.MAX_LOD_COUNT) return; ReadRange(target, dataToRead, lodIndex, ref lodVoxelRangeMin, ref lodVoxelRangeMax, ref requestFlags); }
public void ReadLod(MyStorageData target, MyStorageDataTypeFlags dataTypes, ref Vector3I targetOffset, int lodIndex, ref Vector3I min, ref Vector3I max) { Debug.Assert(min.IsInsideInclusive(Vector3I.Zero, MaxVector >> lodIndex) && max.IsInsideInclusive(Vector3I.Zero, MaxVector >> lodIndex)); //using (Lock.AcquireSharedUsing()) { if (lodIndex > m_maxLod) { UpdateLodData(lodIndex); } if (dataTypes.Requests(MyStorageDataTypeEnum.Content)) { ReadLod(target, MyStorageDataTypeEnum.Content, Content, targetOffset, lodIndex, min, max); } if (dataTypes.Requests(MyStorageDataTypeEnum.Material)) { ReadLod(target, MyStorageDataTypeEnum.Material, Material, targetOffset, lodIndex, min, max); } } HitCount++; }
protected override void WriteRangeInternal(MyStorageDataCache source, MyStorageDataTypeFlags dataToWrite, ref Vector3I voxelRangeMin, ref Vector3I voxelRangeMax) { ProfilerShort.Begin("MyOctreeStorage.WriteRange"); Debug.Assert(dataToWrite != MyStorageDataTypeFlags.None); if ((dataToWrite & MyStorageDataTypeFlags.Content) != 0) { var args = new WriteRangeArgs() { DataFilter = MyOctreeNode.ContentFilter, DataType = MyStorageDataTypeEnum.Content, Leaves = m_contentLeaves, Nodes = m_contentNodes, Provider = m_dataProvider, Source = source, }; WriteRange(ref args, 0, m_treeHeight + LeafLodCount, Vector3I.Zero, ref voxelRangeMin, ref voxelRangeMax); } if ((dataToWrite & MyStorageDataTypeFlags.Material) != 0) { var args = new WriteRangeArgs() { DataFilter = MyOctreeNode.MaterialFilter, DataType = MyStorageDataTypeEnum.Material, Leaves = m_materialLeaves, Nodes = m_materialNodes, Provider = m_dataProvider, Source = source, }; WriteRange(ref args, 0, m_treeHeight + LeafLodCount, Vector3I.Zero, ref voxelRangeMin, ref voxelRangeMax); } ProfilerShort.End(); }
public VoxelWriteOp(string voxelName, string data, MyStorageDataTypeFlags dataToWrite, Vector3I voxelRangeMin, Vector3I voxelRangeMax) { m_voxelName = voxelName; m_data = data; m_dataType = dataToWrite; m_voxelMin = voxelRangeMin; m_voxelMax = voxelRangeMax; }
void ModAPI.Interfaces.IMyStorage.ReadRange(MyStorageDataCache target, MyStorageDataTypeFlags dataToRead, int lodIndex, Vector3I lodVoxelRangeMin, Vector3I lodVoxelRangeMax) { if ((uint)lodIndex >= (uint)MyCellCoord.MAX_LOD_COUNT) { return; } ReadRange(target, dataToRead, lodIndex, ref lodVoxelRangeMin, ref lodVoxelRangeMax); }
void VRage.ModAPI.IMyStorage.ReadRange(MyStorageData target, MyStorageDataTypeFlags dataToRead, int lodIndex, Vector3I lodVoxelRangeMin, Vector3I lodVoxelRangeMax, ref MyVoxelRequestFlags requestFlags) { if ((uint)lodIndex >= (uint)MyCellCoord.MAX_LOD_COUNT) { return; } ReadRange(target, dataToRead, lodIndex, ref lodVoxelRangeMin, ref lodVoxelRangeMax, ref requestFlags); }
public void ReadRange(MyStorageData target, MyStorageDataTypeFlags dataToRead, int lodIndex, ref Vector3I lodVoxelRangeMin, ref Vector3I lodVoxelRangeMax, ref MyVoxelRequestFlags requestFlags) { ProfilerShort.Begin(GetType().Name + ".ReadRange"); try { const int SUBRANGE_SIZE_SHIFT = 3; const int SUBRANGE_SIZE = 1 << SUBRANGE_SIZE_SHIFT; var threshold = new Vector3I(SUBRANGE_SIZE); var rangeSize = lodVoxelRangeMax - lodVoxelRangeMin + 1; if ((dataToRead & MyStorageDataTypeFlags.Content) != 0) { target.ClearContent(0); } if ((rangeSize.X <= threshold.X && rangeSize.Y <= threshold.Y && rangeSize.Z <= threshold.Z) || !MyFakes.ENABLE_SPLIT_VOXEL_READ_QUERIES) { using (m_lock.AcquireSharedUsing()) { ReadRangeInternal(target, ref Vector3I.Zero, dataToRead, lodIndex, ref lodVoxelRangeMin, ref lodVoxelRangeMax, ref requestFlags); } } else { // These optimizations don't work when splitting the range. requestFlags &= ~(MyVoxelRequestFlags.OneMaterial | MyVoxelRequestFlags.ContentChecked); MyVoxelRequestFlags flags = requestFlags; // splitting to smaller ranges to make sure the lock is not held for too long, preventing write on update thread // subranges could be aligned to multiple of their size for possibly better performance var steps = (rangeSize - 1) >> SUBRANGE_SIZE_SHIFT; for (var it = new Vector3I.RangeIterator(ref Vector3I.Zero, ref steps); it.IsValid(); it.MoveNext()) { flags = requestFlags; var offset = it.Current << SUBRANGE_SIZE_SHIFT; var min = lodVoxelRangeMin + offset; var max = min + SUBRANGE_SIZE - 1; Vector3I.Min(ref max, ref lodVoxelRangeMax, out max); Debug.Assert(min.IsInsideInclusive(ref lodVoxelRangeMin, ref lodVoxelRangeMax)); Debug.Assert(max.IsInsideInclusive(ref lodVoxelRangeMin, ref lodVoxelRangeMax)); using (m_lock.AcquireSharedUsing()) { ReadRangeInternal(target, ref offset, dataToRead, lodIndex, ref min, ref max, ref flags); } } // If the storage is consistent this should be fine. requestFlags = flags; } } finally { ProfilerShort.End(); } }
protected internal void OnRangeChanged(Vector3I voxelRangeMin, Vector3I voxelRangeMax, MyStorageDataTypeFlags changedData) { if (RangeChanged != null) { m_compressedData = null; this.ClampVoxelCoord(ref voxelRangeMin); this.ClampVoxelCoord(ref voxelRangeMax); RangeChanged(voxelRangeMin, voxelRangeMax, changedData); } }
/// <summary> /// Resets the data specified by flags to values from data provider, or default if no provider is assigned. /// </summary> /// <param name="dataToReset"></param> public void Reset(MyStorageDataTypeFlags dataToReset) { MyPrecalcComponent.AssertUpdateThread(); using (m_storageLock.AcquireExclusiveUsing()) { m_compressedData = null; ResetInternal(dataToReset); } OnRangeChanged(Vector3I.Zero, Size - 1, dataToReset); }
void IMyStorageDataProvider.ReadRange(MyStorageData target, MyStorageDataTypeFlags dataType, ref Vector3I writeOffset, int lodIndex, ref Vector3I minInLod, ref Vector3I maxInLod) { if (dataType.Requests(MyStorageDataTypeEnum.Content)) { ReadContentRange(target, ref writeOffset, lodIndex, ref minInLod, ref maxInLod); } else { ReadMaterialRange(target, ref writeOffset, lodIndex, ref minInLod, ref maxInLod); } }
public void ReadRange(MyStorageDataCache target, MyStorageDataTypeFlags dataToRead, int lodIndex, ref Vector3I lodVoxelRangeMin, ref Vector3I lodVoxelRangeMax) { ProfilerShort.Begin(GetType().Name + ".ReadRange"); try { const int SUBRANGE_SIZE_SHIFT = 3; const int SUBRANGE_SIZE = 1 << SUBRANGE_SIZE_SHIFT; var threshold = new Vector3I(SUBRANGE_SIZE); var rangeSize = lodVoxelRangeMax - lodVoxelRangeMin + 1; if ((dataToRead & MyStorageDataTypeFlags.Content) != 0) { target.ClearContent(0); } if ((dataToRead & MyStorageDataTypeFlags.Material) != 0) { target.ClearMaterials(m_defaultMaterial); } if (rangeSize.X <= threshold.X && rangeSize.Y <= threshold.Y && rangeSize.Z <= threshold.Z) { using (m_lock.AcquireSharedUsing()) { ReadRangeInternal(target, ref Vector3I.Zero, dataToRead, lodIndex, ref lodVoxelRangeMin, ref lodVoxelRangeMax); } } else { // splitting to smaller ranges to make sure the lock is not held for too long, preventing write on update thread // subranges could be aligned to multiple of their size for possibly better performance var steps = (rangeSize - 1) >> SUBRANGE_SIZE_SHIFT; for (var it = new Vector3I.RangeIterator(ref Vector3I.Zero, ref steps); it.IsValid(); it.MoveNext()) { var offset = it.Current << SUBRANGE_SIZE_SHIFT; var min = lodVoxelRangeMin + offset; var max = min + SUBRANGE_SIZE - 1; Vector3I.Min(ref max, ref lodVoxelRangeMax, out max); Debug.Assert(min.IsInsideInclusive(ref lodVoxelRangeMin, ref lodVoxelRangeMax)); Debug.Assert(max.IsInsideInclusive(ref lodVoxelRangeMin, ref lodVoxelRangeMax)); using (m_lock.AcquireSharedUsing()) { ReadRangeInternal(target, ref offset, dataToRead, lodIndex, ref min, ref max); } } } } finally { ProfilerShort.End(); } }
private void ReadDatForChunk(VoxelChunk chunk, MyStorageDataTypeFlags data) { var rangeStart = chunk.Coords << VoxelChunk.SizeBits; var rangeEnd = ((chunk.Coords + 1) << VoxelChunk.SizeBits) - 1; MyStorageData storage = chunk.MakeData(); MyVoxelRequestFlags flags = 0; ReadRangeInternal(storage, ref Vector3I.Zero, data, 0, ref rangeStart, ref rangeEnd, ref flags); chunk.Cached |= data; }
public void ReadRange(MyStorageData target, MyStorageDataTypeFlags dataType, ref Vector3I writeOffset, int lodIndex, ref Vector3I minInLod, ref Vector3I maxInLod) { if (!this.Closed) { MyVoxelDataRequest req = new MyVoxelDataRequest { Target = target, Offset = writeOffset, RequestedData = dataType, Lod = lodIndex, MinInLod = minInLod, MaxInLod = maxInLod }; this.ReadRange(ref req, false); } }
protected override void ResetInternal(MyStorageDataTypeFlags dataToReset) { bool resetContent = (dataToReset & MyStorageDataTypeFlags.Content) != 0; bool resetMaterials = (dataToReset & MyStorageDataTypeFlags.Material) != 0; if (resetContent) { m_contentLeaves.Clear(); m_contentNodes.Clear(); } if (resetMaterials) { m_materialLeaves.Clear(); m_materialNodes.Clear(); } if (m_dataProvider != null) { var cellCoord = new MyCellCoord(m_treeHeight, ref Vector3I.Zero); var leafId = cellCoord.PackId64(); cellCoord.Lod += LeafLodCount; var end = Size - 1; if (resetContent) { m_contentLeaves.Add(leafId, new MyProviderLeaf(m_dataProvider, MyStorageDataTypeEnum.Content, ref cellCoord)); } if (resetMaterials) { m_materialLeaves.Add(leafId, new MyProviderLeaf(m_dataProvider, MyStorageDataTypeEnum.Material, ref cellCoord)); } } else { var nodeId = new MyCellCoord(m_treeHeight - 1, ref Vector3I.Zero).PackId64(); if (resetContent) { m_contentNodes.Add(nodeId, new MyOctreeNode()); } if (resetMaterials) { m_materialNodes.Add(nodeId, new MyOctreeNode()); } } }
void IMyOctreeLeafNode.ReadRange(MyStorageData target, MyStorageDataTypeFlags types, ref Vector3I writeOffset, int lodIndex, ref Vector3I minInLod, ref Vector3I maxInLod, ref MyVoxelRequestFlags flags) { int num = this.m_cell.Lod - lodIndex; Vector3I vectori = this.m_cell.CoordInLod << num; MyVoxelDataRequest request = new MyVoxelDataRequest { Target = target, Offset = writeOffset, Lod = lodIndex, MinInLod = (Vector3I)(minInLod + vectori), MaxInLod = (Vector3I)(maxInLod + vectori), RequestFlags = flags, RequestedData = types }; this.m_provider.ReadRange(ref request, false); flags = request.Flags; }
private void ReadRangeAdviseCache(MyStorageData target, MyStorageDataTypeFlags dataToRead, ref Vector3I lodVoxelRangeMin, ref Vector3I lodVoxelRangeMax) { // Skip if too many cached cells if (m_pendingChunksToWrite.Count > WriteCacheCap) { ReadRange(target, dataToRead, 0, ref lodVoxelRangeMin, ref lodVoxelRangeMax); return; } if (CachedWrites) { var lodDiff = VoxelChunk.SizeBits; var chunkMin = lodVoxelRangeMin >> lodDiff; var chunkMax = lodVoxelRangeMax >> lodDiff; var pos = Vector3I.Zero; for (pos.Z = chunkMin.Z; pos.Z <= chunkMax.Z; ++pos.Z) { for (pos.Y = chunkMin.Y; pos.Y <= chunkMax.Y; ++pos.Y) { for (pos.X = chunkMin.X; pos.X <= chunkMax.X; ++pos.X) { var celPos = pos << lodDiff; var lodCkStart = pos << lodDiff; lodCkStart = Vector3I.Max(lodCkStart, lodVoxelRangeMin); var targetOffset = lodCkStart - lodVoxelRangeMin; var lodCkEnd = ((pos + 1) << lodDiff) - 1; lodCkEnd = Vector3I.Min(lodCkEnd, lodVoxelRangeMax); VoxelChunk chunk; GetChunk(ref pos, out chunk, dataToRead); lodCkStart -= celPos; lodCkEnd -= celPos; using (chunk.Lock.AcquireSharedUsing()) chunk.ReadLod(target, dataToRead, ref targetOffset, 0, ref lodCkStart, ref lodCkEnd); } } } } }
public void OnStorageChanged(Vector3I minChanged, Vector3I maxChanged, MyStorageDataTypeFlags dataChanged) { ProfilerShort.Begin("MyVoxelMap::storage_RangeChanged"); minChanged = Vector3I.Clamp(minChanged, m_storageMin, m_storageMax); maxChanged = Vector3I.Clamp(maxChanged, m_storageMin, m_storageMax); Debug.Assert(minChanged.IsInsideInclusive(ref m_storageMin, ref m_storageMax) && maxChanged.IsInsideInclusive(ref m_storageMin, ref m_storageMax)); // Physics doesn't care about materials, just shape of things. if ((dataChanged & MyStorageDataTypeFlags.Content) != 0 && Physics != null) { Physics.InvalidateRange(minChanged, maxChanged); } ProfilerShort.End(); }
public unsafe void PostProcess(VrVoxelMesh mesh, MyStorageDataTypeFlags dataTypes) { if (dataTypes.Requests(MyStorageDataTypeEnum.Material)) { VrVoxelVertex *vertices = mesh.Vertices; int vertexCount = mesh.VertexCount; Vector3 start = (Vector3)mesh.Start; float scale = mesh.Scale; for (int i = 0; i < vertexCount; i++) { Vector3 position = (start + vertices[i].Position) * scale; Vector3 vector3 = this.Material.GetColorShift(position, vertices[i].Material, 1024f); if (vector3 != Vector3.Zero) { vertices[i].Color.PackedValue = PackColorShift(vector3 * new Vector3(360f, 100f, 100f)); } } } }
private static Color GetColorForDirty(MyStorageDataTypeFlags dirty) { switch (dirty) { case MyStorageDataTypeFlags.Content: return(Color.Blue); case MyStorageDataTypeFlags.Material: return(Color.Red); case MyStorageDataTypeFlags.ContentAndMaterial: return(Color.Magenta); case MyStorageDataTypeFlags.None: return(Color.Green); default: return(Color.White); } }
public void Write(MyStorageData source, MyStorageDataTypeFlags dataTypes, ref Vector3I targetOffset, ref Vector3I min, ref Vector3I max) { //using (Lock.AcquireExclusiveUsing()) { //if (false) // disabled for testing :D if (dataTypes.Requests(MyStorageDataTypeEnum.Content)) { Write(source, MyStorageDataTypeEnum.Content, Content, targetOffset, min, max); } if (dataTypes.Requests(MyStorageDataTypeEnum.Material)) { Write(source, MyStorageDataTypeEnum.Material, Material, targetOffset, min, max); } Cached |= dataTypes; Dirty |= dataTypes; m_maxLod = 0; } }
/// <summary> /// Invalidates voxel cache /// </summary> /// <param name="minChanged">Inclusive min</param> /// <param name="maxChanged">Inclusive max</param> private void storage_RangeChanged(Vector3I minChanged, Vector3I maxChanged, MyStorageDataTypeFlags dataChanged) { ProfilerShort.Begin("MyVoxelMap::storage_RangeChanged"); Debug.Assert(minChanged.IsInsideInclusive(ref m_storageMin, ref m_storageMax) && maxChanged.IsInsideInclusive(ref m_storageMin, ref m_storageMax)); // Physics doesn't care about materials, just shape of things. if ((dataChanged & MyStorageDataTypeFlags.Content) != 0 && Physics != null) { Physics.InvalidateRange(minChanged, maxChanged); } if (Render is MyRenderComponentVoxelMap) { (Render as MyRenderComponentVoxelMap).InvalidateRange(minChanged, maxChanged); } ProfilerShort.End(); }
public void WriteRange(MyStorageDataCache source, MyStorageDataTypeFlags dataToWrite, ref Vector3I voxelRangeMin, ref Vector3I voxelRangeMax) { MyPrecalcComponent.AssertUpdateThread(); ProfilerShort.Begin(GetType().Name + ".WriteRange"); try { using (m_lock.AcquireExclusiveUsing()) { m_compressedData = null; WriteRangeInternal(source, dataToWrite, ref voxelRangeMin, ref voxelRangeMax); } ProfilerShort.BeginNextBlock(GetType().Name + ".OnRangeChanged"); OnRangeChanged(voxelRangeMin, voxelRangeMax, dataToWrite); } finally { ProfilerShort.End(); } }
protected override void ReadRangeInternal(MyStorageDataCache target, ref Vector3I targetWriteOffset, MyStorageDataTypeFlags dataToRead, int lodIndex, ref Vector3I lodVoxelCoordStart, ref Vector3I lodVoxelCoordEnd) { bool hasLod = lodIndex <= (m_treeHeight + LeafLodCount); Debug.Assert(dataToRead != MyStorageDataTypeFlags.None); if ((dataToRead & MyStorageDataTypeFlags.Content) != 0) { if (hasLod) { ReadRange(target, ref targetWriteOffset, MyStorageDataTypeEnum.Content, m_treeHeight, m_contentNodes, m_contentLeaves, lodIndex, ref lodVoxelCoordStart, ref lodVoxelCoordEnd); } } if ((dataToRead & MyStorageDataTypeFlags.Material) != 0) { if (hasLod) { ReadRange(target, ref targetWriteOffset, MyStorageDataTypeEnum.Material, m_treeHeight, m_materialNodes, m_materialLeaves, lodIndex, ref lodVoxelCoordStart, ref lodVoxelCoordEnd); } } }
/// <summary> /// For debugging/testing only! This can be very slow for large storage. /// </summary> public void Voxelize(MyStorageDataTypeFlags data) { var cache = new MyStorageDataCache(); cache.Resize(new Vector3I(LeafSizeInVoxels)); var leafCount = (Size / LeafSizeInVoxels); Vector3I leaf = Vector3I.Zero; var end = leafCount - 1; for (var it = new Vector3I.RangeIterator(ref Vector3I.Zero, ref end); it.IsValid(); it.GetNext(out leaf)) { Debug.WriteLine("Processing {0} / {1}", leaf, end); var min = leaf * LeafSizeInVoxels; var max = min + (LeafSizeInVoxels - 1); ReadRangeInternal(cache, ref Vector3I.Zero, data, 0, ref min, ref max); WriteRangeInternal(cache, data, ref min, ref max); } OnRangeChanged(Vector3I.Zero, Size - 1, data); }
void IMyOctreeLeafNode.ReadRange(MyStorageData target, MyStorageDataTypeFlags types, ref Vector3I writeOffset, int lodIndex, ref Vector3I minInLod, ref Vector3I maxInLod, ref MyVoxelRequestFlags flags) { var lodShift = m_cell.Lod - lodIndex; var leafMinInLod = m_cell.CoordInLod << lodShift; var min = minInLod + leafMinInLod; var max = maxInLod + leafMinInLod; AssertRangeIsInside(lodIndex, ref min, ref max); ProfilerShort.Begin("MyProviderLeaf.ReadRange"); MyVoxelDataRequest req = new MyVoxelDataRequest() { Target = target, Offset = writeOffset, Lod = lodIndex, minInLod = min, maxInLod = max, RequestFlags = flags, RequestedData = types }; m_provider.ReadRange(ref req); flags = req.Flags; ProfilerShort.End(); }
/// <param name="minVoxelChanged">Inclusive min.</param> /// <param name="maxVoxelChanged">Inclusive max.</param> private void storage_RangeChanged(Vector3I minChanged, Vector3I maxChanged, MyStorageDataTypeFlags changedData) { MyPrecalcComponent.AssertUpdateThread(); ProfilerShort.Begin("MyVoxelGeometry.storage_RangeChanged"); minChanged -= MyPrecalcComponent.InvalidatedRangeInflate; maxChanged += MyPrecalcComponent.InvalidatedRangeInflate; m_storage.ClampVoxelCoord(ref minChanged); m_storage.ClampVoxelCoord(ref maxChanged); var minCellChanged = minChanged >> MyVoxelConstants.GEOMETRY_CELL_SIZE_IN_VOXELS_BITS; var maxCellChanged = maxChanged >> MyVoxelConstants.GEOMETRY_CELL_SIZE_IN_VOXELS_BITS; using (m_lock.AcquireExclusiveUsing()) { if (minCellChanged == Vector3I.Zero && maxCellChanged == m_cellsCount - 1) { m_cellsByCoordinate.Clear(); m_coordinateToMesh.Clear(); m_isEmptyCache.Reset(); } else { MyCellCoord cell = new MyCellCoord(); cell.CoordInLod = minCellChanged; for (var it = new Vector3I.RangeIterator(ref minCellChanged, ref maxCellChanged); it.IsValid(); it.GetNext(out cell.CoordInLod)) { var key = cell.PackId64(); m_cellsByCoordinate.Remove(key); m_coordinateToMesh.Remove(key); SetEmpty(ref cell, false); } } } ProfilerShort.End(); }
public MyStorageData(Vector3I size, byte[] content = null, byte[] material = null, byte[] occlusion = null) { m_dataByType = new byte[(int)MyStorageDataTypeEnum.NUM_STORAGE_DATA_TYPES][]; Resize(size); if (content != null) { m_storedTypes |= MyStorageDataTypeFlags.Content; this[MyStorageDataTypeEnum.Content] = content; } if (material != null) { m_storedTypes |= MyStorageDataTypeFlags.Material; this[MyStorageDataTypeEnum.Material] = material; } if (occlusion != null) { m_storedTypes |= MyStorageDataTypeFlags.Occlusion; this[MyStorageDataTypeEnum.Occlusion] = occlusion; } }
/// <summary> /// Invalidates voxel cache /// </summary> /// <param name="minChanged">Inclusive min</param> /// <param name="maxChanged">Inclusive max</param> private void storage_RangeChanged(Vector3I minChanged, Vector3I maxChanged, MyStorageDataTypeFlags dataChanged) { ProfilerShort.Begin("MyVoxelMap::storage_RangeChanged"); Debug.Assert(minChanged.IsInsideInclusive(ref m_storageMin, ref m_storageMax) && maxChanged.IsInsideInclusive(ref m_storageMin, ref m_storageMax)); // Physics doesn't care about materials, just shape of things. if ((dataChanged & MyStorageDataTypeFlags.Content) != 0 && Physics != null) { Physics.InvalidateRange(minChanged, maxChanged); } if (Render is MyRenderComponentVoxelMap) { (Render as MyRenderComponentVoxelMap).InvalidateRange(minChanged, maxChanged); } ContentChanged = true; ProfilerShort.End(); }
public MyStorageData(MyStorageDataTypeFlags typesToStore = MyStorageDataTypeFlags.ContentAndMaterial) { m_storedTypes = typesToStore; m_dataByType = new byte[(int)MyStorageDataTypeEnum.NUM_STORAGE_DATA_TYPES][]; }
public void ReadLod(MyStorageData target, MyStorageDataTypeFlags dataTypes, ref Vector3I targetOffset, int lodIndex, ref Vector3I min, ref Vector3I max) { Debug.Assert(min.IsInsideInclusive(Vector3I.Zero, MaxVector >> lodIndex) && max.IsInsideInclusive(Vector3I.Zero, MaxVector >> lodIndex)); //using (Lock.AcquireSharedUsing()) { if (lodIndex > MaxLod) UpdateLodData(lodIndex); if (dataTypes.Requests(MyStorageDataTypeEnum.Content)) { ReadLod(target, MyStorageDataTypeEnum.Content, Content, targetOffset, lodIndex, min, max); } if (dataTypes.Requests(MyStorageDataTypeEnum.Material)) { ReadLod(target, MyStorageDataTypeEnum.Material, Material, targetOffset, lodIndex, min, max); } } HitCount++; }
private void storage_RangeChangedPlanet(Vector3I minChanged, Vector3I maxChanged, MyStorageDataTypeFlags dataChanged) { ProfilerShort.Begin("MyVoxelMap::storage_RangeChanged"); Vector3I minSector = minChanged / PHYSICS_SECTOR_SIZE_METERS; Vector3I maxSector = maxChanged / PHYSICS_SECTOR_SIZE_METERS; MyVoxelPhysics voxelMap; if (m_physicsShapes != null) { for (var it = new Vector3I_RangeIterator(ref minSector, ref maxSector); it.IsValid(); it.MoveNext()) { if (m_physicsShapes.TryGetValue(it.Current, out voxelMap)) { if (voxelMap != null) { voxelMap.OnStorageChanged(minChanged, maxChanged, dataChanged); } } } } if (Render is MyRenderComponentVoxelMap) { (Render as MyRenderComponentVoxelMap).InvalidateRange(minChanged, maxChanged); } OnRangeChanged(minChanged, maxChanged, dataChanged); ProfilerShort.End(); }
void ModAPI.Interfaces.IMyStorage.WriteRange(MyStorageDataCache source, MyStorageDataTypeFlags dataToWrite, Vector3I voxelRangeMin, Vector3I voxelRangeMax) { WriteRange(source, dataToWrite, ref voxelRangeMin, ref voxelRangeMax); }
protected abstract void ResetInternal(MyStorageDataTypeFlags dataToReset);
protected abstract void WriteRangeInternal(MyStorageData source, MyStorageDataTypeFlags dataToWrite, ref Vector3I voxelRangeMin, ref Vector3I voxelRangeMax);
private void ReadRangeAdviseCache(MyStorageData target, MyStorageDataTypeFlags dataToRead, ref Vector3I lodVoxelRangeMin, ref Vector3I lodVoxelRangeMax) { // Skip if too many cached cells if (m_pendingChunksToWrite.Count > WriteCacheCap) { ReadRange(target, dataToRead, 0, ref lodVoxelRangeMin, ref lodVoxelRangeMax); return; } if (CachedWrites) { var lodDiff = VoxelChunk.SizeBits; var chunkMin = lodVoxelRangeMin >> lodDiff; var chunkMax = lodVoxelRangeMax >> lodDiff; var pos = Vector3I.Zero; for (pos.Z = chunkMin.Z; pos.Z <= chunkMax.Z; ++pos.Z) for (pos.Y = chunkMin.Y; pos.Y <= chunkMax.Y; ++pos.Y) for (pos.X = chunkMin.X; pos.X <= chunkMax.X; ++pos.X) { var celPos = pos << lodDiff; var lodCkStart = pos << lodDiff; lodCkStart = Vector3I.Max(lodCkStart, lodVoxelRangeMin); var targetOffset = lodCkStart - lodVoxelRangeMin; var lodCkEnd = ((pos + 1) << lodDiff) - 1; lodCkEnd = Vector3I.Min(lodCkEnd, lodVoxelRangeMax); VoxelChunk chunk; GetChunk(ref pos, out chunk, dataToRead); lodCkStart -= celPos; lodCkEnd -= celPos; using (chunk.Lock.AcquireSharedUsing()) chunk.ReadLod(target, dataToRead, ref targetOffset, 0, ref lodCkStart, ref lodCkEnd); } } }
public void ReadRange(MyStorageData target, MyStorageDataTypeFlags dataToRead, int lodIndex, ref Vector3I lodVoxelRangeMin, ref Vector3I lodVoxelRangeMax, ref MyVoxelRequestFlags requestFlags) { ProfilerShort.Begin(GetType().Name + ".ReadRange"); if ((dataToRead & MyStorageDataTypeFlags.Content) != 0) { target.ClearContent(0); } if (requestFlags.HasFlags(MyVoxelRequestFlags.AdviseCache) && lodIndex == 0 && CachedWrites) { ReadRangeAdviseCache(target, dataToRead, ref lodVoxelRangeMin, ref lodVoxelRangeMax); ProfilerShort.End(); return; } if (CachedWrites && lodIndex <= VoxelChunk.SizeBits && m_cachedChunks.Count > 0) { // read occlusion separate if (dataToRead.Requests(MyStorageDataTypeEnum.Occlusion)) { using (m_storageLock.AcquireSharedUsing()) ReadRangeInternal(target, ref Vector3I.Zero, MyStorageDataTypeFlags.Occlusion, lodIndex, ref lodVoxelRangeMin, ref lodVoxelRangeMax, ref requestFlags); dataToRead ^= MyStorageDataTypeFlags.Occlusion; } if (m_tmpChunks == null) m_tmpChunks = new List<VoxelChunk>(); var lodDiff = VoxelChunk.SizeBits - lodIndex; // We fetch which chunks overlap our current range from the chunk tree, then we read all data from storage and apply those changes var querybb = new BoundingBox(lodVoxelRangeMin << lodIndex, lodVoxelRangeMax << lodIndex); using (m_cacheLock.AcquireSharedUsing()) m_cacheMap.OverlapAllBoundingBox(ref querybb, m_tmpChunks, 0, false); if (m_tmpChunks.Count > 0) { var chunkMin = lodVoxelRangeMin >> lodDiff; var chunkMax = lodVoxelRangeMax >> lodDiff; bool readFromStorage = false; if ((chunkMax - chunkMin + 1).Size > m_tmpChunks.Count) { using (m_storageLock.AcquireSharedUsing()) ReadRangeInternal(target, ref Vector3I.Zero, dataToRead, lodIndex, ref lodVoxelRangeMin, ref lodVoxelRangeMax, ref requestFlags); readFromStorage = true; } for (int i = 0; i < m_tmpChunks.Count; ++i) { var chunk = m_tmpChunks[i]; var pos = chunk.Coords; var celPos = pos << lodDiff; var lodCkStart = pos << lodDiff; lodCkStart = Vector3I.Max(lodCkStart, lodVoxelRangeMin); var targetOffset = lodCkStart - lodVoxelRangeMin; var lodCkEnd = ((pos + 1) << lodDiff) - 1; lodCkEnd = Vector3I.Min(lodCkEnd, lodVoxelRangeMax); lodCkStart -= celPos; lodCkEnd -= celPos; if ((chunk.Cached & dataToRead) != dataToRead && !readFromStorage) { using (m_storageLock.AcquireSharedUsing()) if ((chunk.Cached & dataToRead) != dataToRead) ReadDatForChunk(chunk, dataToRead); } using (chunk.Lock.AcquireSharedUsing()) chunk.ReadLod(target, !readFromStorage ? dataToRead : dataToRead & chunk.Cached, ref targetOffset, lodIndex, ref lodCkStart, ref lodCkEnd); } m_tmpChunks.Clear(); ProfilerShort.End(); return; } } // all else using (m_storageLock.AcquireSharedUsing()) ReadRangeInternal(target, ref Vector3I.Zero, dataToRead, lodIndex, ref lodVoxelRangeMin, ref lodVoxelRangeMax, ref requestFlags); ProfilerShort.End(); }
public void ReadRange(MyStorageData target, MyStorageDataTypeFlags dataToRead, int lodIndex, ref Vector3I lodVoxelRangeMin, ref Vector3I lodVoxelRangeMax) { MyVoxelRequestFlags flags = 0; ReadRange(target, dataToRead, lodIndex, ref lodVoxelRangeMin, ref lodVoxelRangeMax, ref flags); }
public void WriteRange(MyStorageData source, MyStorageDataTypeFlags dataToWrite, ref Vector3I voxelRangeMin, ref Vector3I voxelRangeMax) { MyPrecalcComponent.AssertUpdateThread(); ProfilerShort.Begin(GetType().Name + ".WriteRange"); try { m_compressedData = null; if (CachedWrites && (m_pendingChunksToWrite.Count < WriteCacheCap || OverlapsAnyCachedCell(voxelRangeMin, voxelRangeMax))) { var lodDiff = VoxelChunk.SizeBits; var chunkMin = voxelRangeMin >> lodDiff; var chunkMax = voxelRangeMax >> lodDiff; var pos = Vector3I.Zero; for (pos.Z = chunkMin.Z; pos.Z <= chunkMax.Z; ++pos.Z) for (pos.Y = chunkMin.Y; pos.Y <= chunkMax.Y; ++pos.Y) for (pos.X = chunkMin.X; pos.X <= chunkMax.X; ++pos.X) { var celPos = pos << lodDiff; var lodCkStart = pos << lodDiff; lodCkStart = Vector3I.Max(lodCkStart, voxelRangeMin); var lodCkEnd = ((pos + 1) << lodDiff) - 1; lodCkEnd = Vector3I.Min(lodCkEnd, voxelRangeMax); var targetOffset = lodCkStart - voxelRangeMin; VoxelChunk chunk; // Do not read the chunk if the range overlaps the whole chunk var toRead = (lodCkEnd - lodCkStart + 1).Size != VoxelChunk.Volume ? dataToWrite : 0; GetChunk(ref pos, out chunk, toRead); lodCkStart -= celPos; lodCkEnd -= celPos; using (chunk.Lock.AcquireExclusiveUsing()) { bool dirty = chunk.Dirty != 0; chunk.Write(source, dataToWrite, ref targetOffset, ref lodCkStart, ref lodCkEnd); if (!dirty) m_pendingChunksToWrite.Enqueue(pos); } } } else { using (m_storageLock.AcquireExclusiveUsing()) WriteRangeInternal(source, dataToWrite, ref voxelRangeMin, ref voxelRangeMax); } ProfilerShort.BeginNextBlock(GetType().Name + ".OnRangeChanged"); OnRangeChanged(voxelRangeMin, voxelRangeMax, dataToWrite); } finally { ProfilerShort.End(); } }
/// <param name="minVoxelChanged">Inclusive min.</param> /// <param name="maxVoxelChanged">Inclusive max.</param> private void storage_RangeChanged(Vector3I minChanged, Vector3I maxChanged, MyStorageDataTypeFlags changedData) { MyPrecalcComponent.AssertUpdateThread(); ProfilerShort.Begin("MyVoxelGeometry.storage_RangeChanged"); minChanged -= MyPrecalcComponent.InvalidatedRangeInflate; maxChanged += MyPrecalcComponent.InvalidatedRangeInflate; m_storage.ClampVoxelCoord(ref minChanged); m_storage.ClampVoxelCoord(ref maxChanged); var minCellChanged = minChanged >> MyVoxelConstants.GEOMETRY_CELL_SIZE_IN_VOXELS_BITS; var maxCellChanged = maxChanged >> MyVoxelConstants.GEOMETRY_CELL_SIZE_IN_VOXELS_BITS; using (m_lock.AcquireExclusiveUsing()) { if (minCellChanged == Vector3I.Zero && maxCellChanged == m_cellsCount - 1) { m_cellsByCoordinate.Clear(); m_coordinateToMesh.Clear(); m_isEmptyCache.Reset(); } else { MyCellCoord cell = new MyCellCoord(); cell.CoordInLod = minCellChanged; for (var it = new Vector3I_RangeIterator(ref minCellChanged, ref maxCellChanged); it.IsValid(); it.GetNext(out cell.CoordInLod)) { var key = cell.PackId64(); m_cellsByCoordinate.Remove(key); m_coordinateToMesh.Remove(key); SetEmpty(ref cell, false); } } } ProfilerShort.End(); }
protected abstract void ReadRangeInternal(MyStorageData target, ref Vector3I targetWriteRange, MyStorageDataTypeFlags dataToRead, int lodIndex, ref Vector3I lodVoxelRangeMin, ref Vector3I lodVoxelRangeMax, ref MyVoxelRequestFlags requestFlags);
private void OnStorageChanged(Vector3I minVoxelChanged, Vector3I maxVoxelChanged, MyStorageDataTypeFlags changedData) { if (!changedData.HasFlag(MyStorageDataTypeFlags.Content)) { return; } InvalidateRange(minVoxelChanged, maxVoxelChanged); }
void VRage.ModAPI.IMyStorage.WriteRange(MyStorageData source, MyStorageDataTypeFlags dataToWrite, Vector3I voxelRangeMin, Vector3I voxelRangeMax) { WriteRange(source, dataToWrite, ref voxelRangeMin, ref voxelRangeMax); }
protected internal void OnRangeChanged(Vector3I voxelRangeMin, Vector3I voxelRangeMax, MyStorageDataTypeFlags changedData) { if (RangeChanged != null) { RangeChanged(this, voxelRangeMin, voxelRangeMax, changedData); } }
void IMyOctreeLeafNode.ReadRange(MyStorageData target, MyStorageDataTypeFlags types, ref Vector3I writeOffset, int lodIndex, ref Vector3I minInLod, ref Vector3I maxInLod, ref MyVoxelRequestFlags flags) { m_octree.ReadRange(target, m_dataType, ref writeOffset, lodIndex, ref minInLod, ref maxInLod); }
public void Write(MyStorageData source, MyStorageDataTypeFlags dataTypes, ref Vector3I targetOffset, ref Vector3I min, ref Vector3I max) { //using (Lock.AcquireExclusiveUsing()) { //if (false) // disabled for testing :D if (dataTypes.Requests(MyStorageDataTypeEnum.Content)) { Write(source, MyStorageDataTypeEnum.Content, Content, targetOffset, min, max); } if (dataTypes.Requests(MyStorageDataTypeEnum.Material)) { Write(source, MyStorageDataTypeEnum.Material, Material, targetOffset, min, max); } Cached |= dataTypes; Dirty |= dataTypes; MaxLod = 0; } }
private void storage_RangeChangedPlanet(Vector3I minChanged, Vector3I maxChanged, MyStorageDataTypeFlags dataChanged) { ProfilerShort.Begin("MyVoxelMap::storage_RangeChanged"); Vector3I minSector = minChanged / PHYSICS_SECTOR_SIZE_METERS; Vector3I maxSector = maxChanged/PHYSICS_SECTOR_SIZE_METERS; Vector3I increment = m_storage.Size / (m_numCells+1); for (var it = new Vector3I.RangeIterator(ref minSector, ref maxSector); it.IsValid(); it.MoveNext()) { MyVoxelPhysics voxelMap = CreatePhysicsShape(ref increment, ref it); voxelMap.OnStorageChanged(minChanged, maxChanged, dataChanged); } if (Render is MyRenderComponentVoxelMap) { (Render as MyRenderComponentVoxelMap).InvalidateRange(minChanged, maxChanged); } ProfilerShort.End(); }
private void ReadDatForChunk(VoxelChunk chunk, MyStorageDataTypeFlags data) { var rangeStart = chunk.Coords << VoxelChunk.SizeBits; var rangeEnd = ((chunk.Coords + 1) << VoxelChunk.SizeBits) - 1; MyStorageData storage = chunk.MakeData(); MyVoxelRequestFlags flags = 0; ReadRangeInternal(storage, ref Vector3I.Zero, data, 0, ref rangeStart, ref rangeEnd, ref flags); chunk.Cached |= data; chunk.MaxLod = 0; }
void IMyStorageDataProvider.ReadRange(MyStorageData target, MyStorageDataTypeFlags dataType, ref Vector3I writeOffset, int lodIndex, ref Vector3I minInLod, ref Vector3I maxInLod) { if (dataType.Requests(MyStorageDataTypeEnum.Content)) ReadContentRange(target, ref writeOffset, lodIndex, ref minInLod, ref maxInLod); else ReadMaterialRange(target, ref writeOffset, lodIndex, ref minInLod, ref maxInLod); }