public void DoWork(WorkData workData = null) { try { // LOD above is 5 we decrease it by 2 so our LOD now is 3 Min <<= 2; Max <<= 2; MyStorageData cache = Cache; cache.Resize(new Vector3I(8)); for (int x = Min.X; x <= Max.X; x++) { for (int y = Min.Y; y <= Max.Y; y++) { for (int z = Min.Z; z <= Max.Z; z++) { ProcessCell(cache, VoxelMap.Storage, new Vector3I(x, y, z), 0); } } } Callback(); } catch (Exception e) { Logging.Instance.WriteLine($"{e}"); Callback(); } }
void VRage.ModAPI.IMyStorage.ReadRange(MyStorageData 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); }
/// <summary> /// Create a new Asteroid, ready for some manipulation. /// </summary> /// <param name="name"></param> /// <param name="size">Currently the size must be multiple of 64, eg. 128x64x256</param> /// <param name="position"></param> public static IMyVoxelMap CreateNewAsteroid(string storageName, Vector3I size, Vector3D position) { var cache = new MyStorageData(); // new storage is created completely full // no geometry will be created because that requires full-empty transition var storage = MyAPIGateway.Session.VoxelMaps.CreateStorage(size); // midspace's Note: The following steps appear redundant, as the storage space is created empty. /* // always ensure cache is large enough for whatever you plan to load into it cache.Resize(size); // range is specified using inclusive min and max coordinates // Choose a reasonable size of range you plan to work with, to avoid high memory usage // memory size in bytes required by cache is computed as Size.X * Size.Y * Size.Z * 2, where Size is size of the range. // min and max coordinates are inclusive, so if you want to read 8^3 voxels starting at coordinate [8,8,8], you // should pass in min = [8,8,8], max = [15,15,15] // For LOD, you should only use LOD0 or LOD1 // When you write data inside cache back to storage, you always write to LOD0 (the most detailed LOD), LOD1 can only be read from. storage.ReadRange(cache, MyStorageDataTypeFlags.All, 0, Vector3I.Zero, size - 1); // resets all loaded content to empty cache.ClearContent(0); // write new data back to the storage storage.WriteRange(cache, MyStorageDataTypeFlags.Content, Vector3I.Zero, size - 1); */ return MyAPIGateway.Session.VoxelMaps.CreateVoxelMap(storageName, storage, position, 0); }
public static MyStorageData GetVoxelCacheInSphere(this IMyVoxelBase Voxel, BoundingSphereD Sphere, out Vector3I refCorner, out Vector3I refMaxCorner) { if (Voxel == null) { throw new ArgumentNullException(nameof(Voxel)); } if (Voxel.Storage == null) { throw new ArgumentException("Voxel.Storage is null"); } BoundingBoxD SphereBound = VoxelHelpers.GetWorldBoundariesForSphere(Sphere); Vector3I minCorner, maxCorner; Voxel.MyVoxelGenerator_ComputeShapeBounds(ref SphereBound, out minCorner, out maxCorner); Vector3I minCorner1 = minCorner - 1; Vector3I maxCorner1 = maxCorner + 1; Voxel.Storage_ClampVoxelCoord(ref minCorner1, 1); Voxel.Storage_ClampVoxelCoord(ref maxCorner1, 1); MyStorageData cache = new MyStorageData(MyStorageDataTypeFlags.ContentAndMaterial); cache.Resize(minCorner1, maxCorner1); MyVoxelRequestFlags myVoxelRequestFlags = MyVoxelRequestFlags.AdviseCache | MyVoxelRequestFlags.ConsiderContent; Voxel.Storage.ReadRange(cache, MyStorageDataTypeFlags.ContentAndMaterial, 0, minCorner1, maxCorner1, ref myVoxelRequestFlags); refCorner = minCorner1; refMaxCorner = maxCorner1; return(cache); }
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++; }
internal void BuildFrom(MyStorageData source) { Debug.Assert(source.Size3D == new Vector3I(m_octree.TreeWidth)); var enumer = new MyStorageData.MortonEnumerator(source, m_dataType); m_octree.Build(enumer); }
public bool TryGetUniformValue(out byte uniformValue) { MyStorageData filteredValueBuffer = FilteredValueBuffer; MyVoxelDataRequest request = new MyVoxelDataRequest { Target = null, Offset = Vector3I.Zero, Lod = this.m_cell.Lod, MinInLod = this.m_cell.CoordInLod, MaxInLod = this.m_cell.CoordInLod, RequestedData = this.m_dataType.ToFlags() }; this.m_provider.ReadRange(ref request, true); if ((request.Flags & MyVoxelRequestFlags.EmptyData) > 0) { uniformValue = (this.m_dataType == MyStorageDataTypeEnum.Material) ? ((byte)0xff) : ((byte)0); return(true); } if ((this.m_dataType != MyStorageDataTypeEnum.Content) || ((request.Flags & MyVoxelRequestFlags.FullContent) <= 0)) { uniformValue = 0; return(false); } uniformValue = 0xff; return(true); }
byte IMyOctreeLeafNode.GetFilteredValue() { MyStorageData filteredValueBuffer = FilteredValueBuffer; this.m_provider.ReadRange(filteredValueBuffer, this.m_dataType.ToFlags(), ref Vector3I.Zero, this.m_cell.Lod, ref this.m_cell.CoordInLod, ref this.m_cell.CoordInLod); return((this.m_dataType == MyStorageDataTypeEnum.Material) ? filteredValueBuffer.Material(0) : filteredValueBuffer.Content(0)); }
public void GetFilledStorageBounds(out Vector3I min, out Vector3I max) { min = Vector3I.MaxValue; max = Vector3I.MinValue; Vector3I sz = Size; Vector3I SMax = Size - 1; MyStorageData data = new MyStorageData(); data.Resize(Size); Storage.ReadRange(data, MyStorageDataTypeFlags.Content, 0, Vector3I.Zero, SMax); for (int z = 0; z < sz.Z; ++z) { for (int y = 0; y < sz.Y; ++y) { for (int x = 0; x < sz.X; ++x) { if (data.Content(x, y, z) > MyVoxelConstants.VOXEL_ISO_LEVEL) { Vector3I l = Vector3I.Max(new Vector3I(x - 1, y - 1, z - 1), Vector3I.Zero); min = Vector3I.Min(l, min); Vector3I h = Vector3I.Min(new Vector3I(x + 1, y + 1, z + 1), SMax); max = Vector3I.Max(h, max); } } } } }
private bool FindMaterial(IMyStorage storage, byte[] findMaterial) { if (findMaterial.Length == 0) { return(false); } var oldCache = new MyStorageData(); oldCache.Resize(storage.Size); storage.ReadRange(oldCache, MyStorageDataTypeFlags.ContentAndMaterial, 2, Vector3I.Zero, storage.Size - 1); //MyAPIGateway.Utilities.ShowMessage("check", string.Format("SizeLinear {0} {1}.", oldCache.SizeLinear, oldCache.StepLinear)); Vector3I p; for (p.Z = 0; p.Z < storage.Size.Z; ++p.Z) { for (p.Y = 0; p.Y < storage.Size.Y; ++p.Y) { for (p.X = 0; p.X < storage.Size.X; ++p.X) { var content = oldCache.Content(ref p); var material = oldCache.Material(ref p); if (content > 0 && findMaterial.Contains(material)) { return(true); } } } } return(false); }
public override void Perform() { MyVoxelBase base2 = MySession.Static.VoxelMaps.TryGetVoxelMapByNameStart(this.m_voxelName); if (base2 != null) { base2.Storage.WriteRange(MyStorageData.FromBase64(this.m_data), this.m_dataType, this.m_voxelMin, this.m_voxelMax, true, false); } }
public static MyVoxelMaterialDefinition GetMaterialAt(this VRage.Game.Voxels.IMyStorage self, ref Vector3D localCoords) { Vector3I lodVoxelRangeMin = Vector3D.Floor(localCoords / 1.0); MyStorageData target = new MyStorageData(MyStorageDataTypeFlags.All); target.Resize(Vector3I.One); self.ReadRange(target, MyStorageDataTypeFlags.Material, 0, lodVoxelRangeMin, lodVoxelRangeMin); return(MyDefinitionManager.Static.GetVoxelMaterialDefinition(target.Material(0))); }
void VRage.ModAPI.IMyStorage.ReadRange(MyStorageData 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); }
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(); } }
public static MyVoxelMaterialDefinition GetMaterialAt(this VRage.Game.Voxels.IMyStorage self, ref Vector3I voxelCoords) { MyStorageData target = new MyStorageData(MyStorageDataTypeFlags.All); target.Resize(Vector3I.One); self.ReadRange(target, MyStorageDataTypeFlags.All, 0, voxelCoords, voxelCoords); byte materialIndex = target.Material(0); return((materialIndex != 0xff) ? MyDefinitionManager.Static.GetVoxelMaterialDefinition(materialIndex) : null); }
void ShrinkVMap() { Vector3I min, max; m_selectedVoxel.GetFilledStorageBounds(out min, out max); MyVoxelMapStorageDefinition def = null; if (m_selectedVoxel.AsteroidName != null) { MyDefinitionManager.Static.TryGetVoxelMapStorageDefinition(m_selectedVoxel.AsteroidName, out def); } var origSize = m_selectedVoxel.Size; var tightSize = max - min + 1; var storage = new MyOctreeStorage(null, tightSize); var offset = (storage.Size - tightSize) / 2 + 1; MyStorageData data = new MyStorageData(); data.Resize(tightSize); m_selectedVoxel.Storage.ReadRange(data, MyStorageDataTypeFlags.ContentAndMaterial, 0, min, max); min = offset; max = offset + tightSize - 1; storage.WriteRange(data, MyStorageDataTypeFlags.ContentAndMaterial, ref min, ref max); var newMap = MyWorldGenerator.AddVoxelMap(m_selectedVoxel.StorageName, storage, m_selectedVoxel.WorldMatrix); m_selectedVoxel.Close(); newMap.Save = true; if (def == null) { ShowAlert("Voxel map {0} does not have a definition, the shrunk voxel map will be saved with the world instead.", m_selectedVoxel.StorageName); } else { byte[] cVmapData; newMap.Storage.Save(out cVmapData); using (var ostream = MyFileSystem.OpenWrite(Path.Combine(MyFileSystem.ContentPath, def.StorageFile), FileMode.Open)) { ostream.Write(cVmapData, 0, cVmapData.Length); } var notification = new MyHudNotification(MyStringId.GetOrCompute("Voxel prefab {0} updated succesfuly (size changed from {1} to {2})."), 4000); notification.SetTextFormatArguments(def.Id.SubtypeName, origSize, storage.Size); MyHud.Notifications.Add(notification); } }
public static void PaintInShape(MyVoxelBase voxelMap, MyShape shape, byte materialIdx) { using (voxelMap.Pin()) { if (!voxelMap.MarkedForClose) { Vector3I vectori; Vector3I maxCorner; Vector3I minCorner; GetVoxelShapeDimensions(voxelMap, shape, out minCorner, out maxCorner, out vectori); if (m_cache == null) { m_cache = new MyStorageData(MyStorageDataTypeFlags.All); } Vector3I_RangeIterator it = new Vector3I_RangeIterator(ref Vector3I.Zero, ref vectori); while (true) { Vector3I vectori2; Vector3I vectori3; if (!it.IsValid()) { MySandboxGame.Static.Invoke(delegate { if (voxelMap.Storage != null) { voxelMap.Storage.NotifyChanged(minCorner, maxCorner, MyStorageDataTypeFlags.All); } }, "PaintInShape notify"); break; } GetCellCorners(ref minCorner, ref maxCorner, ref it, out vectori2, out vectori3); m_cache.Resize(vectori2, vectori3); MyVoxelRequestFlags considerContent = MyVoxelRequestFlags.ConsiderContent; voxelMap.Storage.ReadRange(m_cache, MyStorageDataTypeFlags.All, 0, vectori2, vectori3, ref considerContent); Vector3I_RangeIterator iterator2 = new Vector3I_RangeIterator(ref vectori2, ref vectori3); while (true) { Vector3D vectord; if (!iterator2.IsValid()) { voxelMap.Storage.WriteRange(m_cache, MyStorageDataTypeFlags.Material, vectori2, vectori3, false, true); it.MoveNext(); break; } Vector3I p = iterator2.Current - vectori2; MyVoxelCoordSystems.VoxelCoordToWorldPosition(voxelMap.PositionLeftBottomCorner, ref iterator2.Current, out vectord); if ((shape.GetVolume(ref vectord) > 0.5f) && (m_cache.Material(ref p) != 0xff)) { m_cache.Material(ref p, materialIdx); } iterator2.MoveNext(); } } } } }
private static bool HasContentAt(this MyVoxelBase voxel, ref Vector3D localPosition) { Vector3I voxelCoord; MyVoxelCoordSystems.LocalPositionToVoxelCoord(ref localPosition, out voxelCoord); MyStorageData cache = new MyStorageData(); cache.Resize(Vector3I.One); voxel.Storage.ReadRange(cache, MyStorageDataTypeFlags.Content, 0, ref voxelCoord, ref voxelCoord); return(cache.Content(0) > MyVoxelConstants.VOXEL_ISO_LEVEL); }
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 static void GetMaterialContent(this VRage.Game.Voxels.IMyStorage self, ref Vector3I voxelCoords, out byte material, out byte content) { MyStorageData myStorageData = new MyStorageData(MyStorageDataTypeFlags.ContentAndMaterial); myStorageData.Resize(Vector3I.One); myStorageData.ClearMaterials(0); self.ReadRange(myStorageData, MyStorageDataTypeFlags.ContentAndMaterial, 0, voxelCoords, voxelCoords); material = myStorageData.Material(0); content = myStorageData.Content(0); }
unsafe void IWork.DoWork(WorkData workData) { try { if (this.m_result == null) { this.m_result = new List <MyEntityOreDeposit>(); this.m_emptyCells = new List <Vector3I>(); } MyStorageData cache = Cache; cache.Resize(new Vector3I(8)); IMyStorage storage = this.VoxelMap.Storage; if (storage != null) { using (StoragePin pin = storage.Pin()) { if (pin.Valid) { Vector3I vectori; vectori.Z = this.Min.Z; while (vectori.Z <= this.Max.Z) { vectori.Y = this.Min.Y; while (true) { if (vectori.Y > this.Max.Y) { int *numPtr3 = (int *)ref vectori.Z; numPtr3[0]++; break; } vectori.X = this.Min.X; while (true) { if (vectori.X > this.Max.X) { int *numPtr2 = (int *)ref vectori.Y; numPtr2[0]++; break; } this.ProcessCell(cache, storage, vectori, this.DetectorId); int *numPtr1 = (int *)ref vectori.X; numPtr1[0]++; } } } } } } } finally { } }
public override void Perform() { var map = MySession.Static.VoxelMaps.TryGetVoxelMapByNameStart(m_voxelName); Debug.Assert(map != null); if (map == null) { return; } map.Storage.WriteRange(MyStorageData.FromBase64(m_data), m_dataType, m_voxelMin, m_voxelMax); }
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; }
private static void VoxelReading() { var camera = MySector.MainCamera; if (camera == null) { return; } var offset = 0; // MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF; var targetPosition = camera.Position + (Vector3D)camera.ForwardVector * 4.5f - offset; MyVoxelBase targetVoxelMap = null; foreach (var voxelMap in MySession.Static.VoxelMaps.Instances) { if (voxelMap.PositionComp.WorldAABB.Contains(targetPosition) == ContainmentType.Contains) { targetVoxelMap = voxelMap; break; } } if (targetVoxelMap == null) { return; } var targetMin = targetPosition - Vector3.One * MyVoxelConstants.VOXEL_SIZE_IN_METRES; var targetMax = targetPosition + Vector3.One * MyVoxelConstants.VOXEL_SIZE_IN_METRES; Vector3I minVoxel, maxVoxel; MyVoxelCoordSystems.WorldPositionToVoxelCoord(targetVoxelMap.PositionLeftBottomCorner, ref targetMin, out minVoxel); MyVoxelCoordSystems.WorldPositionToVoxelCoord(targetVoxelMap.PositionLeftBottomCorner, ref targetMax, out maxVoxel); MyVoxelCoordSystems.VoxelCoordToWorldPosition(targetVoxelMap.PositionLeftBottomCorner, ref minVoxel, out targetMin); MyVoxelCoordSystems.VoxelCoordToWorldPosition(targetVoxelMap.PositionLeftBottomCorner, ref maxVoxel, out targetMax); { BoundingBoxD bbox = BoundingBoxD.CreateInvalid(); bbox.Include(targetMin); bbox.Include(targetMax); VRageRender.MyRenderProxy.DebugDrawAABB(bbox, Vector3.One, 1f, 1f, true); } if (MyInput.Static.IsNewLeftMousePressed()) { var cache = new MyStorageData(); cache.Resize(minVoxel, maxVoxel); targetVoxelMap.Storage.ReadRange(cache, MyStorageDataTypeFlags.Content, 0, ref minVoxel, ref maxVoxel); targetVoxelMap.Storage.WriteRange(cache, MyStorageDataTypeFlags.Content, ref minVoxel, ref maxVoxel); Debug.Assert(true); } }
/// <summary> /// called multiple times for ships, to be kept up to date. /// </summary> public override void UpdateAfterSimulation10() { if (CommandAsteroidEditClear.ActiveVoxelDeleter) { var worldMatrix = MyAPIGateway.Session.Player.Controller.ControlledEntity.Entity.WorldMatrix; var position = worldMatrix.Translation + worldMatrix.Forward * 1.6f + worldMatrix.Up * 1.35f + worldMatrix.Right * 0.1f; var currentAsteroidList = new List <IMyVoxelBase>(); var bb = new BoundingBoxD(position - 0.2f, position + 0.2f); MyAPIGateway.Session.VoxelMaps.GetInstances(currentAsteroidList, v => v.IsBoxIntersectingBoundingBoxOfThisVoxelMap(ref bb)); if (currentAsteroidList.Count > 0) { _isInRange = true; var storage = currentAsteroidList[0].Storage; var point = new Vector3I(position - currentAsteroidList[0].PositionLeftBottomCorner); var cache = new MyStorageData(); var min = (point / 64) * 64; var max = min + 63; var size = max - min; cache.Resize(size); storage.ReadRange(cache, MyStorageDataTypeFlags.ContentAndMaterial, (int)VRageRender.MyLodTypeEnum.LOD0, min, max); Vector3I p = point - min; var content = cache.Content(ref p); if (content > 0) { content = 0x00; cache.Content(ref p, content); storage.WriteRange(cache, MyStorageDataTypeFlags.ContentAndMaterial, min, max); } //storage = null; } else { _isInRange = false; } } if (CommandAsteroidEditSet.ActiveVoxelSetter) { var worldMatrix = MyAPIGateway.Session.Player.Controller.ControlledEntity.Entity.WorldMatrix; CommandAsteroidEditSet.ActiveVoxelSetterPosition = worldMatrix.Translation + worldMatrix.Forward * 1.6f + worldMatrix.Up * 1.35f + worldMatrix.Right * 0.1f; } else { CommandAsteroidEditSet.ActiveVoxelSetterPosition = null; } }
/// <summary> /// called multiple times for ships, to be kept up to date. /// </summary> public override void UpdateAfterSimulation10() { if (CommandAsteroidEditClear.ActiveVoxelDeleter) { var worldMatrix = MyAPIGateway.Session.Player.Controller.ControlledEntity.Entity.WorldMatrix; var position = worldMatrix.Translation + worldMatrix.Forward * 1.6f + worldMatrix.Up * 1.35f + worldMatrix.Right * 0.1f; var currentAsteroidList = new List<IMyVoxelBase>(); var bb = new BoundingBoxD(position - 0.2f, position + 0.2f); MyAPIGateway.Session.VoxelMaps.GetInstances(currentAsteroidList, v => v.IsBoxIntersectingBoundingBoxOfThisVoxelMap(ref bb)); if (currentAsteroidList.Count > 0) { _isInRange = true; var storage = currentAsteroidList[0].Storage; var point = new Vector3I(position - currentAsteroidList[0].PositionLeftBottomCorner); var cache = new MyStorageData(); var min = (point / 64) * 64; var max = min + 63; var size = max - min; cache.Resize(size); storage.ReadRange(cache, MyStorageDataTypeFlags.ContentAndMaterial, (int)VRageRender.MyLodTypeEnum.LOD0, min, max); Vector3I p = point - min; var content = cache.Content(ref p); if (content > 0) { content = 0x00; cache.Content(ref p, content); storage.WriteRange(cache, MyStorageDataTypeFlags.ContentAndMaterial, min, max); } //storage = null; } else { _isInRange = false; } } if (CommandAsteroidEditSet.ActiveVoxelSetter) { var worldMatrix = MyAPIGateway.Session.Player.Controller.ControlledEntity.Entity.WorldMatrix; CommandAsteroidEditSet.ActiveVoxelSetterPosition = worldMatrix.Translation + worldMatrix.Forward * 1.6f + worldMatrix.Up * 1.35f + worldMatrix.Right * 0.1f; } else { CommandAsteroidEditSet.ActiveVoxelSetterPosition = null; } }
public static MyDefinitionId?VoxelMaterialAt(this MyVoxelBase voxel, Vector3D min, Vector3D grow, ref MyStorageData cache) { if (cache == null) { cache = new MyStorageData(); } var shape = new BoundingBoxD(Vector3D.Min(min, min + grow), Vector3D.Max(min, min + grow)); Vector3I voxMin; Vector3I voxMax; Vector3I voxCells; GetVoxelShapeDimensions(voxel, shape, out voxMin, out voxMax, out voxCells); Vector3I_RangeIterator cellsItr = new Vector3I_RangeIterator(ref Vector3I.Zero, ref voxCells); while (cellsItr.IsValid()) { Vector3I cellMinCorner; Vector3I cellMaxCorner; GetCellCorners(ref voxMin, ref voxMax, ref cellsItr, out cellMinCorner, out cellMaxCorner); Vector3I rangeMin = cellMinCorner - 1; Vector3I rangeMax = cellMaxCorner + 1; voxel.Storage.ClampVoxelCoord(ref rangeMin); voxel.Storage.ClampVoxelCoord(ref rangeMax); cache.Resize(rangeMin, rangeMax); voxel.Storage.ReadRange(cache, MyStorageDataTypeFlags.Material, 0, rangeMin, rangeMax); var mortonCode = -1; var maxMortonCode = cache.Size3D.Size; while (++mortonCode < maxMortonCode) { Vector3I pos; MyMortonCode3D.Decode(mortonCode, out pos); var content = cache.Content(ref pos); if (content <= MyVoxelConstants.VOXEL_CONTENT_EMPTY) { continue; } var material = cache.Material(ref pos); var def = MyDefinitionManager.Static.GetVoxelMaterialDefinition(material); if (def != null) { return(def.Id); } } cellsItr.MoveNext(); } return(null); }
public static MyVoxelMaterialDefinition GetMaterialAt_R(this IMyStorage self, ref Vector3I voxelCoords) { MyVoxelMaterialDefinition def; var cache = new MyStorageData(); cache.Resize(Vector3I.One); cache.ClearMaterials(0); self.ReadRange(cache, MyStorageDataTypeFlags.Material, 0, voxelCoords, voxelCoords); def = MyDefinitionManager.Static.GetVoxelMaterialDefinition(cache.Material(0)); return(def); }
private void WriteChunk(ref Vector3I coords, VoxelChunk chunk) { // We assume that we are locked here. Debug.Assert(m_storageLock.Owned); var start = coords << VoxelChunk.SizeBits; var end = ((coords + 1) << VoxelChunk.SizeBits) - 1; MyStorageData storage = chunk.MakeData(); WriteRangeInternal(storage, chunk.Dirty, ref start, ref end); chunk.Dirty = 0; }
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); } }
private unsafe void DrawMaterialsInfo(MyStorageData data) { int *counts = stackalloc int[256]; int cellCount = data.SizeLinear / data.StepLinear; for (int i = 0; i < data.SizeLinear; i += data.StepLinear) { byte mat = data.Material(i); counts[mat]++; } Section("Probing Materials ({0} {1})", cellCount, cellCount > 1 ? "voxels" : "voxel"); List <MatInfo> hits = new List <MatInfo>(); for (int i = 0; i < 256; i++) { if (counts[i] > 0) { hits.Add(new MatInfo() { Material = (byte)i, Count = counts[i] }); } } hits.Sort(); int maxMaterial = MyDefinitionManager.Static.VoxelMaterialCount; foreach (var info in hits) { if (info.Material == MyVoxelConstants.NULL_MATERIAL) { Text(" Null Material: {0}", info.Count); } else if (info.Material > maxMaterial) { Text(" Invalid Material({1}): {0}", info.Count, info.Material); } else { Text(" {1}: {0}", info.Count, MyDefinitionManager.Static.GetVoxelMaterialDefinition(info.Material).Id.SubtypeName); } } }
private void DrawContentsInfo(MyStorageData data) { byte min, max; uint sum = 0; uint nonZero = 0; uint nonFull = 0; min = byte.MaxValue; max = 0; int cellCount = data.SizeLinear / data.StepLinear; for (int i = 0; i < data.SizeLinear; i += data.StepLinear) { byte content = data.Content(i); if (min > content) { min = content; } if (max < content) { max = content; } sum += content; if (content != 0) { nonZero++; } if (content != 255) { nonFull++; } } Section("Probing Contents ({0} {1})", cellCount, cellCount > 1 ? "voxels" : "voxel"); Text("Min: {0}", min); Text("Average: {0}", sum / cellCount); Text("Max: {0}", max); VSpace(5); Text("Non-Empty: {0}", nonZero); Text("Non-Full: {0}", nonFull); }
private bool ReplaceAsteroidMaterial(ulong steamId, IMyVoxelBase originalAsteroid, string searchMaterialName1, string searchMaterialName2) { MyVoxelMaterialDefinition material1; string suggestedMaterials = ""; if (!Support.FindMaterial(searchMaterialName1, out material1, ref suggestedMaterials)) { MyAPIGateway.Utilities.SendMessage(steamId, "Invalid Material1 specified.", "Cannot find the material '{0}'.\r\nTry the following: {1}", searchMaterialName1, suggestedMaterials); return(true); } MyVoxelMaterialDefinition material2; if (!Support.FindMaterial(searchMaterialName2, out material2, ref suggestedMaterials)) { MyAPIGateway.Utilities.SendMessage(steamId, "Invalid Material2 specified.", "Cannot find the material '{0}'.\r\nTry the following: {1}", searchMaterialName2, suggestedMaterials); return(true); } var oldStorage = originalAsteroid.Storage; var oldCache = new MyStorageData(); oldCache.Resize(oldStorage.Size); oldStorage.ReadRange(oldCache, MyStorageDataTypeFlags.ContentAndMaterial, 0, Vector3I.Zero, oldStorage.Size - 1); Vector3I p; for (p.Z = 0; p.Z < oldStorage.Size.Z; ++p.Z) { for (p.Y = 0; p.Y < oldStorage.Size.Y; ++p.Y) { for (p.X = 0; p.X < oldStorage.Size.X; ++p.X) { var material = oldCache.Material(ref p); if (material == material1.Index) { oldCache.Material(ref p, material2.Index); } } } } oldStorage.WriteRange(oldCache, MyStorageDataTypeFlags.ContentAndMaterial, Vector3I.Zero, oldStorage.Size - 1); MyAPIGateway.Utilities.SendMessage(steamId, "Asteroid", "'{0}' material '{1}' replaced with '{2}'.", originalAsteroid.StorageName, material1.Id.SubtypeName, material2.Id.SubtypeName); return(true); }
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(); }
protected abstract void ReadRangeInternal(MyStorageData target, ref Vector3I targetWriteRange, MyStorageDataTypeFlags dataToRead, int lodIndex, ref Vector3I lodVoxelRangeMin, ref Vector3I lodVoxelRangeMax, ref MyVoxelRequestFlags requestFlags);
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(); }
protected abstract void WriteRangeInternal(MyStorageData source, MyStorageDataTypeFlags dataToWrite, ref Vector3I voxelRangeMin, ref Vector3I voxelRangeMax);
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); }
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); } } }
private void UpdateLoad() { ConstructAreas(); if (m_checkQueue.Count == 0) { bool finishedLoading = true; m_ground = MySession.Static.VoxelMaps.TryGetVoxelMapByNameStart("Ground"); if (m_ground != null) { m_worldArea = m_ground.SizeInMetres.X * m_ground.SizeInMetres.Z; m_voxelCache = new MyStorageData(); m_voxelCache.Resize(Vector3I.One * 3); InvalidateAreaValues(); if (m_highLevelBoxes.Count == 0) { // MW: we need to find some candidates for forest starting points finishedLoading = false; m_findValidForestPhase = true; } } if (finishedLoading) { m_loadPhase = false; if (LoadFinished != null) LoadFinished(); } } }
internal void ReadMaterialRange(MyStorageData target, ref Vector3I writeOffset, int lodIndex, ref Vector3I minInLod, ref Vector3I maxInLod) { float lodVoxelSizeHalf; BoundingBox queryBox; BoundingSphere querySphere; SetupReading(lodIndex, ref minInLod, ref maxInLod, out lodVoxelSizeHalf, out queryBox, out querySphere); float lodVoxelSize = 2f * lodVoxelSizeHalf; var overlappedDeposits = OverlappedDeposits; { ProfilerShort.Begin("Testing deposit shapes"); overlappedDeposits.Clear(); ContainmentType testDeposits = ContainmentType.Disjoint; for (int i = 0; i < m_data.Deposits.Length; ++i) { var test = m_data.Deposits[i].Shape.Contains(ref queryBox, ref querySphere, lodVoxelSize); if (test != ContainmentType.Disjoint) { overlappedDeposits.Add(m_data.Deposits[i]); testDeposits = ContainmentType.Intersects; } } ProfilerShort.End(); if (testDeposits == ContainmentType.Disjoint) { ProfilerShort.Begin("target.BlockFillMaterial"); target.BlockFillMaterial(writeOffset, writeOffset + (maxInLod - minInLod), m_data.DefaultMaterial.Index); ProfilerShort.End(); return; } } ProfilerShort.Begin("Material computation"); Vector3I v; for (v.Z = minInLod.Z; v.Z <= maxInLod.Z; ++v.Z) { for (v.Y = minInLod.Y; v.Y <= maxInLod.Y; ++v.Y) { for (v.X = minInLod.X; v.X <= maxInLod.X; ++v.X) { Vector3 localPos = v * lodVoxelSize; float closestDistance = 1f; byte closestMaterialIdx = m_data.DefaultMaterial.Index; if (!MyFakes.DISABLE_COMPOSITE_MATERIAL) { foreach (var deposit in overlappedDeposits) { float distance = deposit.Shape.SignedDistance(ref localPos, MyVoxelConstants.VOXEL_SIZE_IN_METRES, m_data.MacroModule, m_data.DetailModule); if (distance < 0f && distance <= closestDistance) { closestDistance = distance; // DA: Pass default material to the layered deposit so only that does these if-s. var materialDef = deposit.GetMaterialForPosition(ref localPos, lodVoxelSize); closestMaterialIdx = materialDef == null ? m_data.DefaultMaterial.Index : materialDef.Index; } } } var write = v - minInLod + writeOffset; target.Material(ref write, closestMaterialIdx); } } } ProfilerShort.End(); }
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++; }
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; } }
public void LogStorageWrite(MyVoxelBase map, MyStorageData source, MyStorageDataTypeFlags dataToWrite, Vector3I voxelRangeMin, Vector3I voxelRangeMax) { var str = source.ToBase64(); m_log.WriteLine(String.Format("VOXOP: {0} {1} {2} {3} {4}", map.StorageName, voxelRangeMin, voxelRangeMax, dataToWrite, str)); }
private static MyStorageBase Compatibility_LoadCellStorage(int fileVersion, Stream stream) { // Size of this voxel map (in voxels) Vector3I tmpSize; tmpSize.X = stream.ReadInt32(); tmpSize.Y = stream.ReadInt32(); tmpSize.Z = stream.ReadInt32(); var storage = new MyOctreeStorage(null, tmpSize); // Size of data cell in voxels. Has to be the same as current size specified by our constants. Vector3I cellSize; cellSize.X = stream.ReadInt32(); cellSize.Y = stream.ReadInt32(); cellSize.Z = stream.ReadInt32(); Trace.Assert(cellSize.X == MyVoxelConstants.DATA_CELL_SIZE_IN_VOXELS && cellSize.Y == MyVoxelConstants.DATA_CELL_SIZE_IN_VOXELS && cellSize.Z == MyVoxelConstants.DATA_CELL_SIZE_IN_VOXELS); Vector3I cellsCount = tmpSize / cellSize; Dictionary<byte, MyVoxelMaterialDefinition> mappingTable = null; if (fileVersion == STORAGE_TYPE_VERSION_CELL) { // loading material names->index mappings mappingTable = Compatibility_LoadMaterialIndexMapping(stream); } else if (fileVersion == 1) { // material name->index mappings were not saved in this version } var startCoord = Vector3I.Zero; var endCoord = new Vector3I(MyVoxelConstants.DATA_CELL_SIZE_IN_VOXELS - 1); var cache = new MyStorageData(); cache.Resize(Vector3I.Zero, endCoord); Vector3I cellCoord; for (cellCoord.X = 0; cellCoord.X < cellsCount.X; cellCoord.X++) { for (cellCoord.Y = 0; cellCoord.Y < cellsCount.Y; cellCoord.Y++) { for (cellCoord.Z = 0; cellCoord.Z < cellsCount.Z; cellCoord.Z++) { MyVoxelRangeType cellType = (MyVoxelRangeType)stream.ReadByteNoAlloc(); // Cell's are FULL by default, therefore we don't need to change them switch (cellType) { case MyVoxelRangeType.EMPTY: cache.ClearContent(MyVoxelConstants.VOXEL_CONTENT_EMPTY); break; case MyVoxelRangeType.FULL: cache.ClearContent(MyVoxelConstants.VOXEL_CONTENT_FULL); break; case MyVoxelRangeType.MIXED: Vector3I v; for (v.X = 0; v.X < MyVoxelConstants.DATA_CELL_SIZE_IN_VOXELS; v.X++) { for (v.Y = 0; v.Y < MyVoxelConstants.DATA_CELL_SIZE_IN_VOXELS; v.Y++) { for (v.Z = 0; v.Z < MyVoxelConstants.DATA_CELL_SIZE_IN_VOXELS; v.Z++) { cache.Content(ref v, stream.ReadByteNoAlloc()); } } } break; } startCoord = cellCoord * MyVoxelConstants.DATA_CELL_SIZE_IN_VOXELS; endCoord = startCoord + (MyVoxelConstants.DATA_CELL_SIZE_IN_VOXELS - 1); storage.WriteRange(cache, MyStorageDataTypeFlags.Content, ref startCoord, ref endCoord); } } } try { // In case materials are not saved, catch any exceptions caused by this. // Read materials and indestructible for (cellCoord.X = 0; cellCoord.X < cellsCount.X; cellCoord.X++) { for (cellCoord.Y = 0; cellCoord.Y < cellsCount.Y; cellCoord.Y++) { for (cellCoord.Z = 0; cellCoord.Z < cellsCount.Z; cellCoord.Z++) { bool isSingleMaterial = stream.ReadByteNoAlloc() == 1; MyVoxelMaterialDefinition material = null; if (isSingleMaterial) { material = Compatibility_LoadCellVoxelMaterial(stream, mappingTable); cache.ClearMaterials(material.Index); } else { byte indestructibleContent; Vector3I voxelCoordInCell; for (voxelCoordInCell.X = 0; voxelCoordInCell.X < MyVoxelConstants.DATA_CELL_SIZE_IN_VOXELS; voxelCoordInCell.X++) { for (voxelCoordInCell.Y = 0; voxelCoordInCell.Y < MyVoxelConstants.DATA_CELL_SIZE_IN_VOXELS; voxelCoordInCell.Y++) { for (voxelCoordInCell.Z = 0; voxelCoordInCell.Z < MyVoxelConstants.DATA_CELL_SIZE_IN_VOXELS; voxelCoordInCell.Z++) { material = Compatibility_LoadCellVoxelMaterial(stream, mappingTable); indestructibleContent = stream.ReadByteNoAlloc(); cache.Material(ref voxelCoordInCell, material.Index); } } } } startCoord = cellCoord * MyVoxelConstants.DATA_CELL_SIZE_IN_VOXELS; endCoord = startCoord + (MyVoxelConstants.DATA_CELL_SIZE_IN_VOXELS - 1); storage.WriteRange(cache, MyStorageDataTypeFlags.Material, ref startCoord, ref endCoord); } } } } catch (EndOfStreamException ex) { MySandboxGame.Log.WriteLine(ex); } return storage; }
void VRage.ModAPI.IMyStorage.WriteRange(MyStorageData source, MyStorageDataTypeFlags dataToWrite, Vector3I voxelRangeMin, Vector3I voxelRangeMax) { WriteRange(source, dataToWrite, ref voxelRangeMin, ref voxelRangeMax); }
public static MyVoxelMaterialDefinition GetMaterialAt(this IMyStorage self, ref Vector3I voxelCoords) { MyVoxelMaterialDefinition def; MyStorageData cache = new MyStorageData(); cache.Resize(Vector3I.One); cache.ClearMaterials(0); self.ReadRange(cache, MyStorageDataTypeFlags.Material, 0, ref voxelCoords, ref voxelCoords); def = MyDefinitionManager.Static.GetVoxelMaterialDefinition(cache.Material(0)); return def; }
public static MyVoxelMaterialDefinition GetMaterialAt(this IMyStorage self, ref Vector3D localCoords) { MyVoxelMaterialDefinition def; Vector3I voxelCoords = Vector3D.Floor(localCoords / MyVoxelConstants.VOXEL_SIZE_IN_METRES); MyStorageData cache = new MyStorageData(); cache.Resize(Vector3I.One); cache.ClearMaterials(0); self.ReadRange(cache, MyStorageDataTypeFlags.Material, 0, ref voxelCoords, ref voxelCoords); def = MyDefinitionManager.Static.GetVoxelMaterialDefinition(cache.Material(0)); return def; }
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 GetFilledStorageBounds(out Vector3I min, out Vector3I max) { min = Vector3I.MaxValue; max = Vector3I.MinValue; Vector3I sz = Size; Vector3I SMax = Size - 1; MyStorageData data = new MyStorageData(); data.Resize(Size); Storage.ReadRange(data, MyStorageDataTypeFlags.Content, 0, Vector3I.Zero, SMax); for (int z = 0; z < sz.Z; ++z) for (int y = 0; y < sz.Y; ++y) for (int x = 0; x < sz.X; ++x) { if (data.Content(x, y, z) > MyVoxelConstants.VOXEL_ISO_LEVEL) { Vector3I l = Vector3I.Max(new Vector3I(x - 1, y - 1, z - 1), Vector3I.Zero); min = Vector3I.Min(l, min); Vector3I h = Vector3I.Min(new Vector3I(x + 1, y + 1, z + 1), SMax); max = Vector3I.Max(h, max); } } }
public unsafe bool ChangeMaterials(Dictionary<byte, byte> map) { int rewrites = 0; if ((Size + 1).Size > 4 * 1024 * 1024) { MyLog.Default.Error("Cannot overwrite materials for a storage 4 MB or larger."); return false; } Vector3I minCorner = Vector3I.Zero; Vector3I maxCorner = Size - 1; // I don't like this but write range will also allocate so f.. it. MyStorageData cache = new MyStorageData(); cache.Resize(Size); ReadRange(cache, MyStorageDataTypeFlags.Material, 0, ref minCorner, ref maxCorner); var len = cache.SizeLinear; fixed (byte* data = cache[MyStorageDataTypeEnum.Material]) for (int i = 0; i < len; i++) { byte to; if (map.TryGetValue(data[i], out to)) data[i] = to; } if (rewrites > 0) this.WriteRange(cache, MyStorageDataTypeFlags.Material, ref minCorner, ref maxCorner); return rewrites > 0; }
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(); } }
// Linearly interpolates position, normal and material on poly-cube edge. Interpolated point is where an isosurface cuts an edge between two vertices, each with their own scalar value. void GetVertexInterpolation(MyStorageData cache, MyTemporaryVoxel inputVoxelA, MyTemporaryVoxel inputVoxelB, int edgeIndex) { MyEdge edge = m_edges[edgeIndex]; byte contentA = cache.Content(inputVoxelA.IdxInCache); byte contentB = cache.Content(inputVoxelB.IdxInCache); byte materialA = cache.Material(inputVoxelA.IdxInCache); byte materialB = cache.Material(inputVoxelB.IdxInCache); if (Math.Abs(MyVoxelConstants.VOXEL_ISO_LEVEL - contentA) < 0.00001f) { edge.Position = inputVoxelA.Position; edge.Normal = inputVoxelA.Normal; edge.Material = materialA; edge.Ambient = inputVoxelA.Ambient; return; } if (Math.Abs(MyVoxelConstants.VOXEL_ISO_LEVEL - contentB) < 0.00001f) { edge.Position = inputVoxelB.Position; edge.Normal = inputVoxelB.Normal; edge.Material = materialB; edge.Ambient = inputVoxelB.Ambient; return; } float mu = (float)(MyVoxelConstants.VOXEL_ISO_LEVEL - contentA) / (float)(contentB - contentA); Debug.Assert(mu > 0.0f && mu < 1.0f); edge.Position.X = inputVoxelA.Position.X + mu * (inputVoxelB.Position.X - inputVoxelA.Position.X); edge.Position.Y = inputVoxelA.Position.Y + mu * (inputVoxelB.Position.Y - inputVoxelA.Position.Y); edge.Position.Z = inputVoxelA.Position.Z + mu * (inputVoxelB.Position.Z - inputVoxelA.Position.Z); //edge.Normal = ComputeVertexNormal(ref edge.Position); edge.Normal.X = inputVoxelA.Normal.X + mu * (inputVoxelB.Normal.X - inputVoxelA.Normal.X); edge.Normal.Y = inputVoxelA.Normal.Y + mu * (inputVoxelB.Normal.Y - inputVoxelA.Normal.Y); edge.Normal.Z = inputVoxelA.Normal.Z + mu * (inputVoxelB.Normal.Z - inputVoxelA.Normal.Z); if (MyUtils.IsZero(edge.Normal)) edge.Normal = inputVoxelA.Normal; else edge.Normal = MyUtils.Normalize(edge.Normal); if (MyUtils.IsZero(edge.Normal)) edge.Normal = inputVoxelA.Normal; float mu2 = ((float)contentB) / (((float)contentA) + ((float)contentB)); edge.Material = (mu2 <= 0.5f) ? materialA : materialB; edge.Ambient = inputVoxelA.Ambient + mu2 * (inputVoxelB.Ambient - inputVoxelA.Ambient); return; }
internal void ReadContentRange(MyStorageData target, ref Vector3I writeOffset, int lodIndex, ref Vector3I minInLod, ref Vector3I maxInLod) { float lodVoxelSizeHalf; BoundingBox queryBox; BoundingSphere querySphere; SetupReading(lodIndex, ref minInLod, ref maxInLod, out lodVoxelSizeHalf, out queryBox, out querySphere); float lodVoxelSize = 2f * lodVoxelSizeHalf; ProfilerShort.Begin("Testing removed shapes"); var overlappedRemovedShapes = OverlappedRemovedShapes; overlappedRemovedShapes.Clear(); ContainmentType testRemove = ContainmentType.Disjoint; for (int i = 0; i < m_data.RemovedShapes.Length; ++i) { var test = m_data.RemovedShapes[i].Contains(ref queryBox, ref querySphere, lodVoxelSize); if (test == ContainmentType.Contains) { testRemove = ContainmentType.Contains; break; // completely empty so we can leave } else if (test == ContainmentType.Intersects) { testRemove = ContainmentType.Intersects; overlappedRemovedShapes.Add(m_data.RemovedShapes[i]); } } ProfilerShort.End(); if (testRemove == ContainmentType.Contains) { ProfilerShort.Begin("target.BlockFillContent"); target.BlockFillContent(writeOffset, writeOffset + (maxInLod - minInLod), MyVoxelConstants.VOXEL_CONTENT_EMPTY); ProfilerShort.End(); return; } ProfilerShort.Begin("Testing filled shapes"); var overlappedFilledShapes = OverlappedFilledShapes; overlappedFilledShapes.Clear(); ContainmentType testFill = ContainmentType.Disjoint; for (int i = 0; i < m_data.FilledShapes.Length; ++i) { var test = m_data.FilledShapes[i].Contains(ref queryBox, ref querySphere, lodVoxelSize); if (test == ContainmentType.Contains) { overlappedFilledShapes.Clear(); testFill = ContainmentType.Contains; break; } else if (test == ContainmentType.Intersects) { overlappedFilledShapes.Add(m_data.FilledShapes[i]); testFill = ContainmentType.Intersects; } } ProfilerShort.End(); if (testFill == ContainmentType.Disjoint) { ProfilerShort.Begin("target.BlockFillContent"); target.BlockFillContent(writeOffset, writeOffset + (maxInLod - minInLod), MyVoxelConstants.VOXEL_CONTENT_EMPTY); ProfilerShort.End(); return; } else if (testRemove == ContainmentType.Disjoint && testFill == ContainmentType.Contains) { ProfilerShort.Begin("target.BlockFillContent"); target.BlockFillContent(writeOffset, writeOffset + (maxInLod - minInLod), MyVoxelConstants.VOXEL_CONTENT_FULL); ProfilerShort.End(); return; } ProfilerShort.Begin("Distance field computation"); Vector3I v = minInLod; Vector3 localPos = v * lodVoxelSize; Vector3 localPosStart = v * lodVoxelSize; var writeOffsetLoc = writeOffset - minInLod; for (v.Z = minInLod.Z; v.Z <= maxInLod.Z; ++v.Z) { for (v.Y = minInLod.Y; v.Y <= maxInLod.Y; ++v.Y) { v.X = minInLod.X; var write2 = v + writeOffsetLoc; var write = target.ComputeLinear(ref write2); for (; v.X <= maxInLod.X; ++v.X) { //Vector3 localPos = v * lodVoxelSize; //ProfilerShort.Begin("Dist filled"); float distFill; if (testFill == ContainmentType.Contains) { distFill = -1f; } else { //ProfilerShort.Begin("shape distances"); distFill = 1f; foreach (var shape in overlappedFilledShapes) { distFill = Math.Min(distFill, shape.SignedDistance(ref localPos, lodVoxelSize, m_data.MacroModule, m_data.DetailModule)); if (distFill <= -1) break; } //ProfilerShort.End(); } //ProfilerShort.BeginNextBlock("Dist removed"); float distRemoved = 1f; if (testRemove != ContainmentType.Disjoint) { foreach (var shape in overlappedRemovedShapes) { distRemoved = Math.Min(distRemoved, shape.SignedDistance(ref localPos, lodVoxelSize, m_data.MacroModule, m_data.DetailModule)); if (distRemoved <= -1) break; } } //ProfilerShort.BeginNextBlock("content"); float signedDist = MathHelper.Max(distFill, -distRemoved); var fillRatio = MathHelper.Clamp(-signedDist, -1f, 1f) * 0.5f + 0.5f; byte content = (byte)(fillRatio * MyVoxelConstants.VOXEL_CONTENT_FULL); target.Content(write, content); Debug.Assert(Math.Abs((((float)content) / MyVoxelConstants.VOXEL_CONTENT_FULL) - fillRatio) <= 0.5f); //ProfilerShort.End(); write += target.StepLinear; localPos.X += lodVoxelSize; } localPos.Y += lodVoxelSize; localPos.X = localPosStart.X; } localPos.Z += lodVoxelSize; localPos.Y = localPosStart.Y; } ProfilerShort.End(); }
private Vector3I ComputeTemporaryVoxelData(MyStorageData cache, ref Vector3I coord0, int cubeIndex, int lod) { int coord0LinIdx = coord0.X * m_sX + coord0.Y * m_sY + coord0.Z * m_sZ; MyTemporaryVoxel tempVoxel0 = m_temporaryVoxels[coord0LinIdx]; MyTemporaryVoxel tempVoxel1 = m_temporaryVoxels[coord0LinIdx + m_sX]; MyTemporaryVoxel tempVoxel2 = m_temporaryVoxels[coord0LinIdx + m_sX + m_sZ]; MyTemporaryVoxel tempVoxel3 = m_temporaryVoxels[coord0LinIdx + m_sZ]; MyTemporaryVoxel tempVoxel4 = m_temporaryVoxels[coord0LinIdx + m_sY]; MyTemporaryVoxel tempVoxel5 = m_temporaryVoxels[coord0LinIdx + m_sX + m_sY]; MyTemporaryVoxel tempVoxel6 = m_temporaryVoxels[coord0LinIdx + m_sX + m_sY + m_sZ]; MyTemporaryVoxel tempVoxel7 = m_temporaryVoxels[coord0LinIdx + m_sY + m_sZ]; Vector3I coord1 = new Vector3I(coord0.X + 1, coord0.Y + 0, coord0.Z + 0); Vector3I coord2 = new Vector3I(coord0.X + 1, coord0.Y + 0, coord0.Z + 1); Vector3I coord3 = new Vector3I(coord0.X + 0, coord0.Y + 0, coord0.Z + 1); Vector3I coord4 = new Vector3I(coord0.X + 0, coord0.Y + 1, coord0.Z + 0); Vector3I coord5 = new Vector3I(coord0.X + 1, coord0.Y + 1, coord0.Z + 0); Vector3I coord6 = new Vector3I(coord0.X + 1, coord0.Y + 1, coord0.Z + 1); Vector3I coord7 = new Vector3I(coord0.X + 0, coord0.Y + 1, coord0.Z + 1); Vector3I tempVoxelCoord0 = coord0; Vector3I tempVoxelCoord1 = coord1; Vector3I tempVoxelCoord2 = coord2; Vector3I tempVoxelCoord3 = coord3; Vector3I tempVoxelCoord4 = coord4; Vector3I tempVoxelCoord5 = coord5; Vector3I tempVoxelCoord6 = coord6; Vector3I tempVoxelCoord7 = coord7; tempVoxel0.IdxInCache = cache.ComputeLinear(ref tempVoxelCoord0); tempVoxel1.IdxInCache = cache.ComputeLinear(ref tempVoxelCoord1); tempVoxel2.IdxInCache = cache.ComputeLinear(ref tempVoxelCoord2); tempVoxel3.IdxInCache = cache.ComputeLinear(ref tempVoxelCoord3); tempVoxel4.IdxInCache = cache.ComputeLinear(ref tempVoxelCoord4); tempVoxel5.IdxInCache = cache.ComputeLinear(ref tempVoxelCoord5); tempVoxel6.IdxInCache = cache.ComputeLinear(ref tempVoxelCoord6); tempVoxel7.IdxInCache = cache.ComputeLinear(ref tempVoxelCoord7); //tempVoxel0.Position.X = m_originPosition.X + (coord0.X) * m_voxelSizeInMeters; //tempVoxel0.Position.Y = m_originPosition.Y + (coord0.Y) * m_voxelSizeInMeters; //tempVoxel0.Position.Z = m_originPosition.Z + (coord0.Z) * m_voxelSizeInMeters; tempVoxel0.Position.X = (m_voxelStart.X + coord0.X) * m_voxelSizeInMeters; tempVoxel0.Position.Y = (m_voxelStart.Y + coord0.Y) * m_voxelSizeInMeters; tempVoxel0.Position.Z = (m_voxelStart.Z + coord0.Z) * m_voxelSizeInMeters; tempVoxel1.Position.X = tempVoxel0.Position.X + m_voxelSizeInMeters; tempVoxel1.Position.Y = tempVoxel0.Position.Y; tempVoxel1.Position.Z = tempVoxel0.Position.Z; tempVoxel2.Position.X = tempVoxel0.Position.X + m_voxelSizeInMeters; tempVoxel2.Position.Y = tempVoxel0.Position.Y; tempVoxel2.Position.Z = tempVoxel0.Position.Z + m_voxelSizeInMeters; tempVoxel3.Position.X = tempVoxel0.Position.X; tempVoxel3.Position.Y = tempVoxel0.Position.Y; tempVoxel3.Position.Z = tempVoxel0.Position.Z + m_voxelSizeInMeters; tempVoxel4.Position.X = tempVoxel0.Position.X; tempVoxel4.Position.Y = tempVoxel0.Position.Y + m_voxelSizeInMeters; tempVoxel4.Position.Z = tempVoxel0.Position.Z; tempVoxel5.Position.X = tempVoxel0.Position.X + m_voxelSizeInMeters; tempVoxel5.Position.Y = tempVoxel0.Position.Y + m_voxelSizeInMeters; tempVoxel5.Position.Z = tempVoxel0.Position.Z; tempVoxel6.Position.X = tempVoxel0.Position.X + m_voxelSizeInMeters; tempVoxel6.Position.Y = tempVoxel0.Position.Y + m_voxelSizeInMeters; tempVoxel6.Position.Z = tempVoxel0.Position.Z + m_voxelSizeInMeters; tempVoxel7.Position.X = tempVoxel0.Position.X; tempVoxel7.Position.Y = tempVoxel0.Position.Y + m_voxelSizeInMeters; tempVoxel7.Position.Z = tempVoxel0.Position.Z + m_voxelSizeInMeters; // Normals at grid corners (calculated from gradient) GetVoxelNormal(tempVoxel0, ref coord0, ref tempVoxelCoord0, tempVoxel0); GetVoxelNormal(tempVoxel1, ref coord1, ref tempVoxelCoord1, tempVoxel0); GetVoxelNormal(tempVoxel2, ref coord2, ref tempVoxelCoord2, tempVoxel0); GetVoxelNormal(tempVoxel3, ref coord3, ref tempVoxelCoord3, tempVoxel0); GetVoxelNormal(tempVoxel4, ref coord4, ref tempVoxelCoord4, tempVoxel0); GetVoxelNormal(tempVoxel5, ref coord5, ref tempVoxelCoord5, tempVoxel0); GetVoxelNormal(tempVoxel6, ref coord6, ref tempVoxelCoord6, tempVoxel0); GetVoxelNormal(tempVoxel7, ref coord7, ref tempVoxelCoord7, tempVoxel0); // Ambient occlusion colors at grid corners // IMPORTANT: At this point normals must be calculated because GetVoxelAmbientAndSun() will be retrieving them from temp table and not checking if there is actual value GetVoxelAmbient(tempVoxel0, ref coord0, ref tempVoxelCoord0); GetVoxelAmbient(tempVoxel1, ref coord1, ref tempVoxelCoord1); GetVoxelAmbient(tempVoxel2, ref coord2, ref tempVoxelCoord2); GetVoxelAmbient(tempVoxel3, ref coord3, ref tempVoxelCoord3); GetVoxelAmbient(tempVoxel4, ref coord4, ref tempVoxelCoord4); GetVoxelAmbient(tempVoxel5, ref coord5, ref tempVoxelCoord5); GetVoxelAmbient(tempVoxel6, ref coord6, ref tempVoxelCoord6); GetVoxelAmbient(tempVoxel7, ref coord7, ref tempVoxelCoord7); // Find the vertices where the surface intersects the cube int edgeVal = MyMarchingCubesConstants.EdgeTable[cubeIndex]; if ((edgeVal & 1) == 1) { GetVertexInterpolation(cache, tempVoxel0, tempVoxel1, 0); } if ((edgeVal & 2) == 2) { GetVertexInterpolation(cache, tempVoxel1, tempVoxel2, 1); } if ((edgeVal & 4) == 4) { GetVertexInterpolation(cache, tempVoxel2, tempVoxel3, 2); } if ((edgeVal & 8) == 8) { GetVertexInterpolation(cache, tempVoxel3, tempVoxel0, 3); } if ((edgeVal & 16) == 16) { GetVertexInterpolation(cache, tempVoxel4, tempVoxel5, 4); } if ((edgeVal & 32) == 32) { GetVertexInterpolation(cache, tempVoxel5, tempVoxel6, 5); } if ((edgeVal & 64) == 64) { GetVertexInterpolation(cache, tempVoxel6, tempVoxel7, 6); } if ((edgeVal & 128) == 128) { GetVertexInterpolation(cache, tempVoxel7, tempVoxel4, 7); } if ((edgeVal & 256) == 256) { GetVertexInterpolation(cache, tempVoxel0, tempVoxel4, 8); } if ((edgeVal & 512) == 512) { GetVertexInterpolation(cache, tempVoxel1, tempVoxel5, 9); } if ((edgeVal & 1024) == 1024) { GetVertexInterpolation(cache, tempVoxel2, tempVoxel6, 10); } if ((edgeVal & 2048) == 2048) { GetVertexInterpolation(cache, tempVoxel3, tempVoxel7, 11); } return tempVoxelCoord0; }
private static void VoxelReading() { var camera = MySector.MainCamera; if (camera == null) return; var offset = 0; // MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF; var targetPosition = camera.Position + (Vector3D)camera.ForwardVector * 4.5f - offset; MyVoxelBase targetVoxelMap = null; foreach (var voxelMap in MySession.Static.VoxelMaps.Instances) { if (voxelMap.PositionComp.WorldAABB.Contains(targetPosition) == ContainmentType.Contains) { targetVoxelMap = voxelMap; break; } } if (targetVoxelMap == null) return; var targetMin = targetPosition - Vector3.One * MyVoxelConstants.VOXEL_SIZE_IN_METRES; var targetMax = targetPosition + Vector3.One * MyVoxelConstants.VOXEL_SIZE_IN_METRES; Vector3I minVoxel, maxVoxel; MyVoxelCoordSystems.WorldPositionToVoxelCoord(targetVoxelMap.PositionLeftBottomCorner, ref targetMin, out minVoxel); MyVoxelCoordSystems.WorldPositionToVoxelCoord(targetVoxelMap.PositionLeftBottomCorner, ref targetMax, out maxVoxel); MyVoxelCoordSystems.VoxelCoordToWorldPosition(targetVoxelMap.PositionLeftBottomCorner, ref minVoxel, out targetMin); MyVoxelCoordSystems.VoxelCoordToWorldPosition(targetVoxelMap.PositionLeftBottomCorner, ref maxVoxel, out targetMax); { BoundingBoxD bbox = BoundingBoxD.CreateInvalid(); bbox.Include(targetMin); bbox.Include(targetMax); VRageRender.MyRenderProxy.DebugDrawAABB(bbox, Vector3.One, 1f, 1f, true); } if (MyInput.Static.IsNewLeftMousePressed()) { var cache = new MyStorageData(); cache.Resize(minVoxel, maxVoxel); targetVoxelMap.Storage.ReadRange(cache, MyStorageDataTypeFlags.Content, 0, ref minVoxel, ref maxVoxel); targetVoxelMap.Storage.WriteRange(cache, MyStorageDataTypeFlags.Content, ref minVoxel, ref maxVoxel); Debug.Assert(true); } }
private unsafe void ReadLod(MyStorageData target, MyStorageDataTypeEnum dataType, byte[] dataArray, Vector3I tofft, int lod, Vector3I min, Vector3I max) { int offset = 0; for (int i = 0; i < lod; ++i) { offset += Volume >> (i + i + i); } var sy = Size >> lod; var sz = sy * sy; min.Y *= sy; min.Z *= sz; max.Y *= sy; max.Z *= sz; int tsx = target.StepX, tsy = target.StepY, tsz = target.StepZ; tofft.Y *= tsy; tofft.Z *= tsz; fixed (byte* fixedDataArray = dataArray) fixed (byte* targetData = target[dataType]) { byte* voxel = fixedDataArray + offset; int x, y, z; int tx, ty, tz; for (z = min.Z, tz = tofft.Z; z <= max.Z; z += sz, tz += tsz) for (y = min.Y, ty = tofft.Y; y <= max.Y; y += sy, ty += tsy) for (x = min.X, tx = tofft.X; x <= max.X; ++x, tx += tsx) { targetData[tz + ty + tx] = voxel[z + y + x]; } } }
public bool ChangeMaterials(byte[] materialChangeFrom, byte[] materialChangeTo) { int rewrites = 0; if (materialChangeFrom != null && materialChangeTo != null) { int maxIndex = Math.Min(materialChangeFrom.Length, materialChangeTo.Length); if (maxIndex > 0) { Vector3I minCorner = Vector3I.Zero; Vector3I maxCorner = this.Size-1; MyStorageData cache = new MyStorageData(); cache.Resize(this.Size); cache.ClearMaterials(0); this.ReadRange(cache, MyStorageDataTypeFlags.Material, 0, ref minCorner, ref maxCorner); byte[] data = cache[MyStorageDataTypeEnum.Material]; int i, j; for (i = 0; i < data.Length; i++) { if (data[i] > 0) { for (j = 0; j < maxIndex; j++) { if (data[i] == materialChangeFrom[j]) { data[i] = materialChangeTo[j]; rewrites++; break; } } } } if (rewrites > 0) this.WriteRange(cache, MyStorageDataTypeFlags.Material, ref minCorner, ref maxCorner); } } return (rewrites > 0); }
private unsafe void Write(MyStorageData source, MyStorageDataTypeEnum dataType, byte[] dataArray, Vector3I tofft, Vector3I min, Vector3I max) { Debug.Assert(Cached.Requests(dataType) || (min == Vector3I.Zero && max == MaxVector)); var sy = Size; var sz = sy * sy; min.Y *= sy; min.Z *= sz; max.Y *= sy; max.Z *= sz; int tsx = source.StepX, tsy = source.StepY, tsz = source.StepZ; tofft.Y *= tsy; tofft.Z *= tsz; fixed (byte* voxel = dataArray) fixed (byte* sourceData = source[dataType]) { int x, y, z; int tx, ty, tz; for (z = min.Z, tz = tofft.Z; z <= max.Z; z += sz, tz += tsz) for (y = min.Y, ty = tofft.Y; y <= max.Y; y += sy, ty += tsy) for (x = min.X, tx = tofft.X; x <= max.X; ++x, tx += tsx) { voxel[z + y + x] = sourceData[tz + ty + tx]; } } }
public override bool Invoke(ulong steamId, long playerId, string messageText) { // voxelset [0/off] [1/on] [A] [B] [C/Clear] if (messageText.StartsWith("/voxelset ", StringComparison.InvariantCultureIgnoreCase)) { var strings = messageText.Split(' '); if (strings.Length > 1) { if (strings[1].Equals("off", StringComparison.InvariantCultureIgnoreCase) || strings[1].Equals("0", StringComparison.InvariantCultureIgnoreCase)) { ActiveVoxelSetterPosition = null; _activeVoxelSetterPositionA = null; _activeVoxelSetterPositionB = null; _activeVoxelSetterNameA = null; _activeVoxelSetterNameB = null; ActiveVoxelSetter = false; MyAPIGateway.Utilities.ShowNotification("Voxel setter off", 1000, MyFontEnum.Green); return true; } if (strings[1].Equals("on", StringComparison.InvariantCultureIgnoreCase) || strings[1].Equals("1", StringComparison.InvariantCultureIgnoreCase)) { ActiveVoxelSetterPosition = null; _activeVoxelSetterPositionA = null; _activeVoxelSetterPositionB = null; _activeVoxelSetterNameA = null; _activeVoxelSetterNameB = null; ActiveVoxelSetter = true; MyAPIGateway.Utilities.ShowNotification("Voxel setter activated", 1000, MyFontEnum.Green); return true; } if (!ActiveVoxelSetter) { MyAPIGateway.Utilities.ShowNotification("Voxel setter hasn't been actived.", 2000, MyFontEnum.Red); return true; } if (strings[1].Equals("A", StringComparison.InvariantCultureIgnoreCase)) { var tmp = ActiveVoxelSetterPosition; if (tmp.HasValue) { var currentAsteroidList = new List<IMyVoxelBase>(); var bb = new BoundingBoxD(tmp.Value - 0.2f, tmp.Value + 0.2f); MyAPIGateway.Session.VoxelMaps.GetInstances(currentAsteroidList, v => v.IsBoxIntersectingBoundingBoxOfThisVoxelMap(ref bb)); if (currentAsteroidList.Count > 0) { _activeVoxelSetterNameA = currentAsteroidList[0].StorageName; _activeVoxelSetterPositionA = tmp; } } if (_activeVoxelSetterPositionA.HasValue) MyAPIGateway.Utilities.ShowMessage(_activeVoxelSetterNameA, "Voxel setter point A: active"); //MyAPIGateway.Utilities.ShowNotification("Voxel setter A: active.", 1000, MyFontEnum.Green); else MyAPIGateway.Utilities.ShowNotification("Voxel setter A: invalid.", 1000, MyFontEnum.Red); return true; } if (strings[1].Equals("B", StringComparison.InvariantCultureIgnoreCase)) { var tmp = ActiveVoxelSetterPosition; if (tmp.HasValue) { var currentAsteroidList = new List<IMyVoxelBase>(); var bb = new BoundingBoxD(tmp.Value - 0.2f, tmp.Value + 0.2f); MyAPIGateway.Session.VoxelMaps.GetInstances(currentAsteroidList, v => v.IsBoxIntersectingBoundingBoxOfThisVoxelMap(ref bb)); if (currentAsteroidList.Count > 0) { _activeVoxelSetterNameB = currentAsteroidList[0].StorageName; _activeVoxelSetterPositionB = tmp; } } if (_activeVoxelSetterPositionB.HasValue) MyAPIGateway.Utilities.ShowMessage(_activeVoxelSetterNameB, "Voxel setter point B: active"); //MyAPIGateway.Utilities.ShowNotification("Voxel setter B: active.", 1000, MyFontEnum.Green); else MyAPIGateway.Utilities.ShowNotification("Voxel setter B: invalid.", 1000, MyFontEnum.Red); return true; } if (strings[1].Equals("C", StringComparison.InvariantCultureIgnoreCase) || strings[1].Equals("Clear", StringComparison.InvariantCultureIgnoreCase)) { if (_activeVoxelSetterPositionA.HasValue && _activeVoxelSetterPositionB.HasValue && _activeVoxelSetterNameA == _activeVoxelSetterNameB) { var currentAsteroidList = new List<IMyVoxelBase>(); MyAPIGateway.Session.VoxelMaps.GetInstances(currentAsteroidList, v => v.StorageName.Equals(_activeVoxelSetterNameA, StringComparison.InvariantCultureIgnoreCase)); if (currentAsteroidList.Count > 0) { var storage = currentAsteroidList[0].Storage; var point1 = new Vector3I(_activeVoxelSetterPositionA.Value - currentAsteroidList[0].PositionLeftBottomCorner); var point2 = new Vector3I(_activeVoxelSetterPositionB.Value - currentAsteroidList[0].PositionLeftBottomCorner); var cache = new MyStorageData(); var size = storage.Size; cache.Resize(size); storage.ReadRange(cache, MyStorageDataTypeFlags.ContentAndMaterial, (int)VRageRender.MyLodTypeEnum.LOD0, Vector3I.Zero, size - 1); var min = Vector3I.Min(point1, point2); var max = Vector3I.Max(point1, point2); MyAPIGateway.Utilities.ShowMessage("Cutting", min.ToString() + " " + max.ToString()); //MyAPIGateway.Utilities.ShowNotification("cutting:" + min.ToString() + " " + max.ToString(), 5000, MyFontEnum.Blue); Vector3I p; for (p.Z = min.Z; p.Z <= max.Z; ++p.Z) for (p.Y = min.Y; p.Y <= max.Y; ++p.Y) for (p.X = min.X; p.X <= max.X; ++p.X) cache.Content(ref p, 0); storage.WriteRange(cache, MyStorageDataTypeFlags.ContentAndMaterial, Vector3I.Zero, size - 1); } } else if (_activeVoxelSetterNameA != _activeVoxelSetterNameB) { MyAPIGateway.Utilities.ShowNotification("Voxel setter Cut: different asteroids.", 2000, MyFontEnum.Red); } else { MyAPIGateway.Utilities.ShowNotification("Voxel setter Cut: invalid points.", 2000, MyFontEnum.Red); } return true; } if (strings[1].Equals("F", StringComparison.InvariantCultureIgnoreCase) || strings[1].Equals("Fill", StringComparison.InvariantCultureIgnoreCase)) { if (_activeVoxelSetterPositionA.HasValue && _activeVoxelSetterPositionB.HasValue && _activeVoxelSetterNameA == _activeVoxelSetterNameB) { var currentAsteroidList = new List<IMyVoxelBase>(); MyAPIGateway.Session.VoxelMaps.GetInstances(currentAsteroidList, v => v.StorageName.Equals(_activeVoxelSetterNameA, StringComparison.InvariantCultureIgnoreCase)); if (currentAsteroidList.Count > 0) { var storage = currentAsteroidList[0].Storage; var point1 = new Vector3I(_activeVoxelSetterPositionA.Value - currentAsteroidList[0].PositionLeftBottomCorner); var point2 = new Vector3I(_activeVoxelSetterPositionB.Value - currentAsteroidList[0].PositionLeftBottomCorner); var cache = new MyStorageData(); var size = storage.Size; cache.Resize(size); storage.ReadRange(cache, MyStorageDataTypeFlags.ContentAndMaterial, (int)VRageRender.MyLodTypeEnum.LOD0, Vector3I.Zero, size - 1); var min = Vector3I.Min(point1, point2); var max = Vector3I.Max(point1, point2); MyAPIGateway.Utilities.ShowMessage("Filling", min.ToString() + " " + max.ToString()); //MyAPIGateway.Utilities.ShowNotification("filling:" + min.ToString() + " " + max.ToString(), 5000, MyFontEnum.Blue); Vector3I p; for (p.Z = min.Z; p.Z <= max.Z; ++p.Z) for (p.Y = min.Y; p.Y <= max.Y; ++p.Y) for (p.X = min.X; p.X <= max.X; ++p.X) cache.Content(ref p, 0xff); storage.WriteRange(cache, MyStorageDataTypeFlags.ContentAndMaterial, Vector3I.Zero, size - 1); } } else if (_activeVoxelSetterNameA != _activeVoxelSetterNameB) { MyAPIGateway.Utilities.ShowNotification("Voxel setter Cut: different asteroids.", 2000, MyFontEnum.Red); } else { MyAPIGateway.Utilities.ShowNotification("Voxel setter Cut: invalid points.", 2000, MyFontEnum.Red); } return true; } } } return false; }