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); }
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); }
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); }
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); }
public static void CutOutShapeWithProperties( MyVoxelBase voxelMap, MyShape shape, out float voxelsCountInPercent, out MyVoxelMaterialDefinition voxelMaterial, Dictionary <MyVoxelMaterialDefinition, int> exactCutOutMaterials = null, bool updateSync = false, bool onlyCheck = false, bool applyDamageMaterial = false, bool onlyApplyMaterial = false) { if (MySession.Static.EnableVoxelDestruction == false) { voxelsCountInPercent = 0; voxelMaterial = null; return; } ProfilerShort.Begin("MyVoxelGenerator::CutOutShapeWithProperties()"); int originalSum = 0; int removedSum = 0; bool materials = exactCutOutMaterials != null; // Bring the shape into voxel space. var oldTranmsform = shape.Transformation; var newTransf = oldTranmsform * voxelMap.PositionComp.WorldMatrixInvScaled; newTransf.Translation += voxelMap.SizeInMetresHalf; shape.Transformation = newTransf; // This boundary should now be in our local space var bbox = shape.GetWorldBoundaries(); Vector3I minCorner, maxCorner; ComputeShapeBounds(voxelMap, ref bbox, Vector3.Zero, voxelMap.Storage.Size, out minCorner, out maxCorner); bool readMaterial = exactCutOutMaterials != null || applyDamageMaterial; var cacheMin = minCorner - 1; var cacheMax = maxCorner + 1; //try on making the read/write cell alligned see MyOctreeStorage.WriteRange - Micro octree leaf /*const int SHIFT = 4; * const int REM = (1 << SHIFT) - 1; * const int MASK = ~REM; * cacheMin &= MASK; * cacheMax = (cacheMax + REM) & MASK;*/ voxelMap.Storage.ClampVoxelCoord(ref cacheMin); voxelMap.Storage.ClampVoxelCoord(ref cacheMax); m_cache.Resize(cacheMin, cacheMax); m_cache.ClearMaterials(0); // Advise that the read content shall be cached MyVoxelRequestFlags flags = MyVoxelRequestFlags.AdviseCache; voxelMap.Storage.ReadRange(m_cache, readMaterial ? MyStorageDataTypeFlags.ContentAndMaterial : MyStorageDataTypeFlags.Content, 0, ref cacheMin, ref cacheMax, ref flags); Vector3I center; if (materials) { center = m_cache.Size3D / 2; voxelMaterial = MyDefinitionManager.Static.GetVoxelMaterialDefinition(m_cache.Material(ref center)); } else { center = (cacheMin + cacheMax) / 2; voxelMaterial = voxelMap.Storage.GetMaterialAt(ref center); } MyVoxelMaterialDefinition voxelMat = null; ProfilerShort.Begin("Main loop"); Vector3I pos; for (pos.X = minCorner.X; pos.X <= maxCorner.X; ++pos.X) { for (pos.Y = minCorner.Y; pos.Y <= maxCorner.Y; ++pos.Y) { for (pos.Z = minCorner.Z; pos.Z <= maxCorner.Z; ++pos.Z) { // get original amount var relPos = pos - cacheMin; var lin = m_cache.ComputeLinear(ref relPos); var original = m_cache.Content(lin); if (original == MyVoxelConstants.VOXEL_CONTENT_EMPTY) // if there is nothing to remove { continue; } Vector3D spos = (Vector3D)(pos - voxelMap.StorageMin) * MyVoxelConstants.VOXEL_SIZE_IN_METRES; var volume = shape.GetVolume(ref spos); if (volume == 0f) // if there is no intersection { continue; } var maxRemove = (int)(volume * MyVoxelConstants.VOXEL_CONTENT_FULL); var toRemove = maxRemove; // (int)(maxRemove * voxelMat.DamageRatio); var newVal = Math.Max(original - toRemove, 0); //MathHelper.Clamp(original - toRemove, 0, original-maxRemove); var removed = original - newVal; if (!onlyCheck && !onlyApplyMaterial) { m_cache.Content(lin, (byte)newVal); } originalSum += original; removedSum += removed; if (readMaterial) { voxelMat = MyDefinitionManager.Static.GetVoxelMaterialDefinition(m_cache.Material(lin)); } if (exactCutOutMaterials != null) { int value = 0; exactCutOutMaterials.TryGetValue(voxelMat, out value); value += (MyFakes.ENABLE_REMOVED_VOXEL_CONTENT_HACK ? (int)(removed * 3.9f) : removed); exactCutOutMaterials[voxelMat] = value; } if (applyDamageMaterial && voxelMat.HasDamageMaterial && !onlyCheck) { m_cache.Material(lin, voxelMat.DamagedMaterialId); } } } } if (removedSum > 0 && updateSync && Sync.IsServer) { shape.SendDrillCutOutRequest(voxelMap, applyDamageMaterial); } ProfilerShort.BeginNextBlock("Write"); if (removedSum > 0 && !onlyCheck) { // Clear all small voxel that may have been created during explosion. They can be created even outside the range of // explosion sphere, e.g. if you have three voxels in a row A, B, C, where A is 255, B is 60, and C is 255. During the // explosion you change C to 0, so now we have 255, 60, 0. Than another explosion that will change A to 0, so we // will have 0, 60, 0. But B was always outside the range of the explosion. So this is why we need to do -1/+1 and remove // B voxels too. //!! TODO AR & MK : check if this is needed !! //RemoveSmallVoxelsUsingChachedVoxels(); var dataTypeFlags = applyDamageMaterial ? MyStorageDataTypeFlags.ContentAndMaterial : MyStorageDataTypeFlags.Content; if (MyFakes.LOG_NAVMESH_GENERATION) { MyAIComponent.Static.Pathfinding.VoxelPathfinding.DebugLog.LogStorageWrite(voxelMap, m_cache, dataTypeFlags, cacheMin, cacheMax); } voxelMap.Storage.WriteRange(m_cache, dataTypeFlags, ref cacheMin, ref cacheMax); } ProfilerShort.End(); voxelsCountInPercent = (originalSum > 0f) ? (float)removedSum / (float)originalSum : 0f; shape.Transformation = oldTranmsform; if (removedSum > 0) { OnVoxelChanged(MyVoxelBase.OperationType.Cut, voxelMap, shape); } ProfilerShort.End(); }
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; }
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(); #if !XB1 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); #else // XB1 System.Diagnostics.Debug.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); #endif // XB1 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); }
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); }
public MyIsoMesh Precalc(IMyStorage storage, int lod, Vector3I voxelStart, Vector3I voxelEnd, bool generateMaterials, bool useAmbient, bool doNotCheck = false) { // change range so normal can be computed at edges (expand by 1 in all directions) voxelStart -= 1; voxelEnd += 1; if (storage == null) { return(null); } using (storage.Pin()) { if (storage.Closed) { return(null); } MyVoxelRequestFlags request = MyVoxelRequestFlags.ContentChecked; // | (doNotCheck ? MyVoxelRequestFlags.DoNotCheck : 0); //if (lod == 0 && generateMaterials) request |= MyVoxelRequestFlags.AdviseCache; bool readAmbient = false; if (generateMaterials && storage.DataProvider != null && storage.DataProvider.ProvidesAmbient) { readAmbient = true; } m_cache.Resize(voxelStart, voxelEnd); if (readAmbient) { m_cache.StoreOcclusion = true; } storage.ReadRange(m_cache, MyStorageDataTypeFlags.Content, lod, ref voxelStart, ref voxelEnd, ref request); if (request.HasFlag(MyVoxelRequestFlags.EmptyContent) || request.HasFlag(MyVoxelRequestFlags.FullContent) || (!request.HasFlag(MyVoxelRequestFlags.ContentChecked) && !m_cache.ContainsIsoSurface())) { //if(generateMaterials && lod == 0) Debugger.Break(); //storage.DebugDrawChunk(voxelStart, voxelEnd); return(null); } var center = (storage.Size / 2) * MyVoxelConstants.VOXEL_SIZE_IN_METRES; var voxelSize = MyVoxelConstants.VOXEL_SIZE_IN_METRES * (1 << lod); var vertexCellOffset = voxelStart - AffectedRangeOffset; double numCellsHalf = 0.5 * (m_cache.Size3D.X - 3); var posOffset = ((Vector3D)vertexCellOffset + numCellsHalf) * (double)voxelSize; if (generateMaterials) { // 255 is the new black m_cache.ClearMaterials(255); } if (readAmbient) { m_cache.Clear(MyStorageDataTypeEnum.Occlusion, 0); } IsoMesher mesher = new IsoMesher(); ProfilerShort.Begin("Dual Contouring"); unsafe { fixed(byte *content = m_cache[MyStorageDataTypeEnum.Content]) fixed(byte *material = m_cache[MyStorageDataTypeEnum.Material]) { var size3d = m_cache.Size3D; Debug.Assert(size3d.X == size3d.Y && size3d.Y == size3d.Z); mesher.Calculate(size3d.X, content, material, m_buffer, useAmbient, posOffset - center); } } ProfilerShort.End(); if (generateMaterials) { request = 0; request |= MyVoxelRequestFlags.SurfaceMaterial; request |= MyVoxelRequestFlags.ConsiderContent; var req = readAmbient ? MyStorageDataTypeFlags.Material | MyStorageDataTypeFlags.Occlusion : MyStorageDataTypeFlags.Material; storage.ReadRange(m_cache, req, lod, ref voxelStart, ref voxelEnd, ref request); FixCacheMaterial(voxelStart, voxelEnd); unsafe { fixed(byte *content = m_cache[MyStorageDataTypeEnum.Content]) fixed(byte *material = m_cache[MyStorageDataTypeEnum.Material]) { int materialOverride = request.HasFlag(MyVoxelRequestFlags.OneMaterial) ? m_cache.Material(0) : -1; var size3d = m_cache.Size3D; Debug.Assert(size3d.X == size3d.Y && size3d.Y == size3d.Z); if (readAmbient) fixed(byte *ambient = m_cache[MyStorageDataTypeEnum.Occlusion]) mesher.CalculateMaterials(size3d.X, content, material, ambient, materialOverride); else { mesher.CalculateMaterials(size3d.X, content, material, null, materialOverride); } } } } else { m_cache.ClearMaterials(0); } mesher.Finish(m_buffer); if (m_buffer.VerticesCount == 0 || m_buffer.Triangles.Count == 0) { return(null); } ProfilerShort.Begin("Geometry post-processing"); { var positions = m_buffer.Positions.GetInternalArray(); var vertexCells = m_buffer.Cells.GetInternalArray(); var materials = m_buffer.Materials.GetInternalArray(); for (int i = 0; i < m_buffer.VerticesCount; i++) { Debug.Assert(positions[i].IsInsideInclusive(ref Vector3.MinusOne, ref Vector3.One)); vertexCells[i] += vertexCellOffset; Debug.Assert(vertexCells[i].IsInsideInclusive(voxelStart + 1, voxelEnd - 1)); Debug.Assert(materials[i] != MyVoxelConstants.NULL_MATERIAL); } m_buffer.PositionOffset = posOffset; m_buffer.PositionScale = new Vector3((float)(numCellsHalf * voxelSize)); m_buffer.CellStart = voxelStart + 1; m_buffer.CellEnd = voxelEnd - 1; } ProfilerShort.End(); // Replace filled mesh with new one. // This way prevents allocation of meshes which then end up empty. var buffer = m_buffer; m_buffer = new MyIsoMesh(); return(buffer); } }
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; }
private bool IsValidVoxelTarget(NaniteMiningItem target, IMyEntity entity) { if (entity == null) { return(false); } byte material2 = 0; float amount = 0; IMyVoxelBase voxel = entity as IMyVoxelBase; Vector3D targetMin = target.Position; Vector3D targetMax = target.Position; Vector3I minVoxel, maxVoxel; MyVoxelCoordSystems.WorldPositionToVoxelCoord(voxel.PositionLeftBottomCorner, ref targetMin, out minVoxel); MyVoxelCoordSystems.WorldPositionToVoxelCoord(voxel.PositionLeftBottomCorner, ref targetMax, out maxVoxel); MyVoxelBase voxelBase = voxel as MyVoxelBase; minVoxel += voxelBase.StorageMin; maxVoxel += voxelBase.StorageMin; voxel.Storage.ClampVoxel(ref minVoxel); voxel.Storage.ClampVoxel(ref maxVoxel); MyStorageData cache = new MyStorageData(); cache.Resize(minVoxel, maxVoxel); var flag = MyVoxelRequestFlags.AdviseCache; cache.ClearContent(0); cache.ClearMaterials(0); byte original = 0; voxel.Storage.ReadRange(cache, MyStorageDataTypeFlags.ContentAndMaterial, 0, minVoxel, maxVoxel, ref flag); original = cache.Content(0); material2 = cache.Material(0); if (original == MyVoxelConstants.VOXEL_CONTENT_EMPTY) { Logging.Instance.WriteLine("[Mining] Content is empty!", 2); MyAPIGateway.Utilities.InvokeOnGameThread(() => { AddMinedPosition(target); }); return(false); } Logging.Instance.WriteLine($"[Mining] Material: SizeLinear: {cache.SizeLinear}, Size3D: {cache.Size3D}, AboveISO: {cache.ContainsVoxelsAboveIsoLevel()}", 2); cache.Content(0, 0); var voxelMat = target.Definition; target.Amount = CalculateAmount(voxelMat, original * 8f); Logging.Instance.WriteLine($"[Mining] Removing: {target.Position} ({material2} {amount})", 2); if (material2 == 0) { Logging.Instance.WriteLine("[Mining] Material is 0", 2); MyAPIGateway.Utilities.InvokeOnGameThread(() => { AddMinedPosition(target); }); return(false); } if (target.Amount == 0f) { Logging.Instance.WriteLine("[Mining] Amount is 0", 2); MyAPIGateway.Utilities.InvokeOnGameThread(() => { AddMinedPosition(target); }); return(false); } return(true); }
public static void RemoveVoxelContent(long voxelId, Vector3D position, out byte materialRemoved, out float amountOfMaterial) { materialRemoved = 0; amountOfMaterial = 0f; IMyEntity entity; if (!MyAPIGateway.Entities.TryGetEntityById(voxelId, out entity)) { return; } var voxel = entity as IMyVoxelBase; var targetMin = position; var targetMax = position; Vector3I minVoxel, maxVoxel; MyVoxelCoordSystems.WorldPositionToVoxelCoord(voxel.PositionLeftBottomCorner, ref targetMin, out minVoxel); MyVoxelCoordSystems.WorldPositionToVoxelCoord(voxel.PositionLeftBottomCorner, ref targetMax, out maxVoxel); MyVoxelBase voxelBase = voxel as MyVoxelBase; minVoxel += voxelBase.StorageMin; maxVoxel += voxelBase.StorageMin + 1; voxel.Storage.ClampVoxel(ref minVoxel); voxel.Storage.ClampVoxel(ref maxVoxel); MyStorageData cache = new MyStorageData(); cache.Resize(minVoxel, maxVoxel); var flag = MyVoxelRequestFlags.AdviseCache; cache.ClearContent(0); cache.ClearMaterials(0); byte original = 0; byte material = 0; // I don't really think pinning is necessary since I'm in the main thread, but this hasn't been working for awhile, so I'll keep it here. voxel.Storage.PinAndExecute(() => { voxel.Storage.ReadRange(cache, MyStorageDataTypeFlags.ContentAndMaterial, 0, minVoxel, maxVoxel, ref flag); // Grab content and material original = cache.Content(0); material = cache.Material(0); if (original == MyVoxelConstants.VOXEL_CONTENT_EMPTY) { //Logging.Instance.WriteLine(string.Format("Content is empty")); return; } // Remove Content Logging.Instance.WriteLine($"Material: SizeLinear: {cache.SizeLinear}, Size3D: {cache.Size3D}, AboveISO: {cache.ContainsVoxelsAboveIsoLevel()}"); cache.Content(0, 0); voxel.Storage.WriteRange(cache, MyStorageDataTypeFlags.ContentAndMaterial, minVoxel, maxVoxel); }); // Calculate Material Mined var voxelMat = MyDefinitionManager.Static.GetVoxelMaterialDefinition(material); materialRemoved = material; amountOfMaterial = CalculateAmount(voxelMat, original * 3.9f); // This will sync the clients. Apparently voxel writes do not sync, lovely. if (Sync.IsServer) { VoxelRemovalData data = new VoxelRemovalData(); data.VoxelID = voxelId; data.Position = position; MyAPIGateway.Multiplayer.SendMessageToOthers(8969, ASCIIEncoding.ASCII.GetBytes(MyAPIGateway.Utilities.SerializeToXML(data))); } }
private void ReadVoxel(IMyVoxelBase voxel, Vector3D position, Dictionary <Vector3D, NaniteMiningItem> targets, HashSet <string> allowedOreList = null) { var m_cache = new MyStorageData(); NaniteShapeSphere shapeSphere = new NaniteShapeSphere(); shapeSphere.Center = position; shapeSphere.Radius = NaniteConstructionManager.Settings.MiningRadius / 2; //NaniteShapeCapsule shapeCapsule = new NaniteShapeCapsule(); //shapeCapsule.A = positionA; //shapeCapsule.B = positionB; //shapeCapsule.Radius = NaniteConstructionManager.Settings.MiningRadius; Vector3I minCorner, maxCorner, numCells; GetVoxelShapeDimensions(voxel, shapeSphere, out minCorner, out maxCorner, out numCells); var cacheMin = minCorner - 1; var cacheMax = maxCorner + 1; //bool bRareOnly = true; //if (allowedOreList != null && allowedOreList.Contains("Stone")) // bRareOnly = false; m_cache.Resize(cacheMin, cacheMax); m_cache.ClearContent(0); m_cache.ClearMaterials(0); var flags = MyVoxelRequestFlags.AdviseCache; voxel.Storage.ReadRange(m_cache, MyStorageDataTypeFlags.ContentAndMaterial, 0, cacheMin, cacheMax, ref flags); //voxel.Storage.PinAndExecute(() => { Vector3I pos; for (pos.X = minCorner.X; pos.X <= maxCorner.X; ++pos.X) { for (pos.Y = minCorner.Y; pos.Y <= maxCorner.Y; ++pos.Y) { for (pos.Z = minCorner.Z; pos.Z <= maxCorner.Z; ++pos.Z) { // get original amount var relPos = pos - cacheMin; var lin = m_cache.ComputeLinear(ref relPos); //var relPos = pos - cacheMin; // Position of voxel in local space var original = m_cache.Content(lin); // Content at this position if (original == MyVoxelConstants.VOXEL_CONTENT_EMPTY) { continue; } var material = m_cache.Material(lin); // Material at this position Vector3D vpos; MyVoxelCoordSystems.VoxelCoordToWorldPosition(voxel.PositionLeftBottomCorner, ref pos, out vpos); if (targets.ContainsKey(vpos)) { continue; } /* * var volume = shapeSphere.GetVolume(ref vpos); * if (volume == 0f) // Shape and voxel do not intersect at this position, so continue * continue; */ // Pull information about voxel required for later processing var voxelMat = MyDefinitionManager.Static.GetVoxelMaterialDefinition(material); //if ((bRareOnly && voxelMat.IsRare) || !bRareOnly) //if(voxelMat.IsRare) if (allowedOreList != null)// || (allowedOreList == null && bRareOnly && voxelMat.IsRare)) { if (allowedOreList != null && !allowedOreList.Contains(voxelMat.MinedOre)) { continue; } NaniteMiningItem miningItem = new NaniteMiningItem(); miningItem.Position = vpos; miningItem.VoxelMaterial = material; miningItem.VoxelId = voxel.EntityId; miningItem.Amount = original; // * 3.9f; miningItem.MiningHammer = this; targets.Add(vpos, miningItem); //count++; } //m_cache.Content(lin, 0); //m_cache.Material(lin, 0); } } } //voxel.Storage.WriteRange(m_cache, MyStorageDataTypeFlags.ContentAndMaterial, cacheMin, cacheMax); }; /* * int count = 0; * for (var itCells = new Vector3I_RangeIterator(ref Vector3I.Zero, ref numCells); itCells.IsValid(); itCells.MoveNext()) * { * Vector3I cellMinCorner, cellMaxCorner; * GetCellCorners(ref minCorner, ref maxCorner, ref itCells, out cellMinCorner, out cellMaxCorner); * * var cacheMin = cellMinCorner - 1; * var cacheMax = cellMaxCorner + 1; * voxel.Storage.ClampVoxel(ref cacheMin); * voxel.Storage.ClampVoxel(ref cacheMax); * * m_cache.Resize(cacheMin, cacheMax); * voxel.Storage.ReadRange(m_cache, MyStorageDataTypeFlags.ContentAndMaterial, 0, cacheMin, cacheMax); * * for (var it = new Vector3I_RangeIterator(ref cellMinCorner, ref cellMaxCorner); it.IsValid(); it.MoveNext()) * { * var relPos = it.Current - cacheMin; // Position of voxel in local space * var original = m_cache.Content(ref relPos); // Content at this position * var material = m_cache.Material(ref relPos); // Material at this position * * if (original == MyVoxelConstants.VOXEL_CONTENT_EMPTY) * continue; * * Vector3D vpos; * MyVoxelCoordSystems.VoxelCoordToWorldPosition(voxel.PositionLeftBottomCorner, ref it.Current, out vpos); * if (targets.ContainsKey(vpos)) * continue; * * var volume = shapeSphere.GetVolume(ref vpos); * if (volume == 0f) // Shape and voxel do not intersect at this position, so continue * continue; * * // Pull information about voxel required for later processing * var voxelMat = MyDefinitionManager.Static.GetVoxelMaterialDefinition(m_cache.Material(ref relPos)); * //if ((bRareOnly && voxelMat.IsRare) || !bRareOnly) * //if(voxelMat.IsRare) * if (allowedOreList != null)// || (allowedOreList == null && bRareOnly && voxelMat.IsRare)) * { * if (allowedOreList != null && !allowedOreList.Contains(voxelMat.MinedOre)) * continue; * * NaniteMiningItem miningItem = new NaniteMiningItem(); * miningItem.Position = vpos; * miningItem.VoxelMaterial = material; * miningItem.VoxelId = voxel.EntityId; * miningItem.Amount = original; // * 3.9f; * miningItem.MiningHammer = this; * targets.Add(vpos, miningItem); * count++; * } * } * } */ //Logging.Instance.WriteLine(string.Format("Voxels Read: {0} - {1}", voxel.GetType().Name, count)); }
public unsafe MyStorageBase Compatibility_LoadCellStorage(int fileVersion, Stream stream) { Vector3I vectori; Vector3I vectori2; Vector3I vectori6; vectori.X = stream.ReadInt32(); vectori.Y = stream.ReadInt32(); vectori.Z = stream.ReadInt32(); MyOctreeStorage storage = new MyOctreeStorage(null, vectori); vectori2.X = stream.ReadInt32(); vectori2.Y = stream.ReadInt32(); vectori2.Z = stream.ReadInt32(); Vector3I vectori3 = (Vector3I)(vectori / vectori2); Dictionary <byte, MyVoxelMaterialDefinition> mapping = null; if (fileVersion == 2) { mapping = this.Compatibility_LoadMaterialIndexMapping(stream); } else { int num2 = fileVersion; } Vector3I zero = Vector3I.Zero; Vector3I end = new Vector3I(7); MyStorageData source = new MyStorageData(MyStorageDataTypeFlags.All); source.Resize(Vector3I.Zero, end); vectori6.X = 0; while (vectori6.X < vectori3.X) { vectori6.Y = 0; while (true) { if (vectori6.Y >= vectori3.Y) { int *numPtr6 = (int *)ref vectori6.X; numPtr6[0]++; break; } vectori6.Z = 0; while (true) { if (vectori6.Z >= vectori3.Z) { int *numPtr5 = (int *)ref vectori6.Y; numPtr5[0]++; break; } MyVoxelContentConstitution constitution = (MyVoxelContentConstitution)stream.ReadByteNoAlloc(); switch (constitution) { case MyVoxelContentConstitution.Empty: source.ClearContent(0); break; case MyVoxelContentConstitution.Full: source.ClearContent(0xff); break; case MyVoxelContentConstitution.Mixed: Vector3I vectori7; vectori7.X = 0; while (vectori7.X < 8) { vectori7.Y = 0; while (true) { if (vectori7.Y >= 8) { int *numPtr3 = (int *)ref vectori7.X; numPtr3[0]++; break; } vectori7.Z = 0; while (true) { if (vectori7.Z >= 8) { int *numPtr2 = (int *)ref vectori7.Y; numPtr2[0]++; break; } source.Content(ref vectori7, stream.ReadByteNoAlloc()); int *numPtr1 = (int *)ref vectori7.Z; numPtr1[0]++; } } } break; default: break; } zero = vectori6 * 8; storage.WriteRange(source, MyStorageDataTypeFlags.Content, zero, (Vector3I)(zero + 7), true, false); int *numPtr4 = (int *)ref vectori6.Z; numPtr4[0]++; } } } try { vectori6.X = 0; while (vectori6.X < vectori3.X) { vectori6.Y = 0; while (true) { if (vectori6.Y >= vectori3.Y) { int *numPtr12 = (int *)ref vectori6.X; numPtr12[0]++; break; } vectori6.Z = 0; while (true) { if (vectori6.Z >= vectori3.Z) { int *numPtr11 = (int *)ref vectori6.Y; numPtr11[0]++; break; } MyVoxelMaterialDefinition definition = null; if (stream.ReadByteNoAlloc() == 1) { source.ClearMaterials(this.Compatibility_LoadCellVoxelMaterial(stream, mapping).Index); } else { Vector3I vectori8; vectori8.X = 0; while (vectori8.X < 8) { vectori8.Y = 0; while (true) { if (vectori8.Y >= 8) { int *numPtr9 = (int *)ref vectori8.X; numPtr9[0]++; break; } vectori8.Z = 0; while (true) { if (vectori8.Z >= 8) { int *numPtr8 = (int *)ref vectori8.Y; numPtr8[0]++; break; } definition = this.Compatibility_LoadCellVoxelMaterial(stream, mapping); stream.ReadByteNoAlloc(); source.Material(ref vectori8, definition.Index); int *numPtr7 = (int *)ref vectori8.Z; numPtr7[0]++; } } } } zero = vectori6 * 8; storage.WriteRange(source, MyStorageDataTypeFlags.Material, zero, (Vector3I)(zero + 7), true, false); int *numPtr10 = (int *)ref vectori6.Z; numPtr10[0]++; } } } } catch (EndOfStreamException exception) { MySandboxGame.Log.WriteLine(exception); } return(storage); }