//[Conditional("DEBUG")] private void FixCacheMaterial(Vector3I voxelStart, Vector3I voxelEnd) { var mcount = Sandbox.Definitions.MyDefinitionManager.Static.VoxelMaterialCount; voxelEnd = Vector3I.Min(voxelEnd - voxelStart, m_cache.Size3D); voxelStart = Vector3I.Zero; var it = new Vector3I_RangeIterator(ref voxelStart, ref voxelEnd); var pos = it.Current; for (; it.IsValid(); it.GetNext(out pos)) { var lin = m_cache.ComputeLinear(ref pos); var mat = m_cache.Material(lin); if (mat >= mcount && mat != MyVoxelConstants.NULL_MATERIAL) { //Debug.Fail(String.Format("VoxelData contains invalid materials (id: {0}).", m_cache.Material(lin))); m_cache.Material(lin, MyVoxelConstants.NULL_MATERIAL); } } }
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 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 void ProcessCell(MyStorageData cache, IMyStorage storage, Vector3I cell, long detectorId) { //bool m_miningDebug = false; if (cache == null || storage == null) { return; } Vector3I vector3I = cell << 3; Vector3I lodVoxelRangeMax = vector3I + 7; // Advice cache because of performance issues var flag = MyVoxelRequestFlags.ContentCheckedDeep; Stopwatch stopwatch = Stopwatch.StartNew(); storage.ReadRange(cache, MyStorageDataTypeFlags.Content, 0, vector3I, lodVoxelRangeMax, ref flag); stopwatch.Stop(); int readingTime = (int)((stopwatch.ElapsedTicks * 1000000) / Stopwatch.Frequency); if (readingTime > 1000) { int changeAmount = (int)(readingTime / 1000); if (MyAPIGateway.Physics.ServerSimulationRatio < 1.00f) { sleepTimer += changeAmount * 100; } else { sleepTimer = Math.Max(sleepTimer - 1, 1); } MyAPIGateway.Parallel.Sleep(sleepTimer); } //if (m_miningDebug) //Logging.Instance.WriteLine($"ProcessCell.ReadRange(1) took {(stopwatch.ElapsedTicks * 1000000)/Stopwatch.Frequency} microseconds"); if (cache.ContainsVoxelsAboveIsoLevel()) { //Stopwatch stopwatch2 = Stopwatch.StartNew(); storage.ReadRange(cache, MyStorageDataTypeFlags.Material, 0, vector3I, lodVoxelRangeMax, ref flag); //stopwatch2.Stop(); //if (m_miningDebug) //Logging.Instance.WriteLine($"ProcessCell.ReadRange(2) took {(stopwatch2.ElapsedTicks * 1000000)/Stopwatch.Frequency} microseconds"); Vector3I p = default(Vector3I); p.Z = 0; while (p.Z < 8) { p.Y = 0; while (p.Y < 8) { p.X = 0; while (p.X < 8) { int linearIdx = cache.ComputeLinear(ref p); if (cache.Content(linearIdx) > 127) { byte b = cache.Material(linearIdx); if (HasFilterUpgrade) { var voxelDefinition = MyDefinitionManager.Static.GetVoxelMaterialDefinition(b); if (voxelDefinition != null && voxelDefinition.MinedOre != null) { foreach (string mat in OreListSelected) { if (voxelDefinition.MinedOre.ToLower() == mat.ToLower()) { Materials.AddMaterial(b, vector3I + p); break; } } } else { Materials.AddMaterial(b, vector3I + p); } } else { Materials.AddMaterial(b, vector3I + p); } } p.X++; } p.Y++; } p.Z++; } } }
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 unsafe void CalculateDistanceFieldInternal(Vector3 localPos, int faceHint, Vector3I min, Vector3I max, Vector3I writeOffsetLoc, MyStorageData target, float lodVoxelSize) { Vector3I vectori; this.PrepareCache(); Vector3 vector = localPos; if (faceHint == -1) { vectori.Z = min.Z; while (vectori.Z <= max.Z) { vectori.Y = min.Y; while (true) { if (vectori.Y > max.Y) { float *singlePtr3 = (float *)ref localPos.Z; singlePtr3[0] += lodVoxelSize; localPos.Y = vector.Y; int *numPtr3 = (int *)ref vectori.Z; numPtr3[0]++; break; } vectori.X = min.X; Vector3I p = (Vector3I)(vectori + writeOffsetLoc); int linearIdx = target.ComputeLinear(ref p); while (true) { if (vectori.X > max.X) { float *singlePtr2 = (float *)ref localPos.Y; singlePtr2[0] += lodVoxelSize; localPos.X = vector.X; int *numPtr2 = (int *)ref vectori.Y; numPtr2[0]++; break; } byte content = (byte)(((MathHelper.Clamp(-(this.SignedDistanceLocal(localPos, lodVoxelSize) / lodVoxelSize), -1f, 1f) * 0.5f) + 0.5f) * 255f); target.Content(linearIdx, content); linearIdx += target.StepLinear; float *singlePtr1 = (float *)ref localPos.X; singlePtr1[0] += lodVoxelSize; int *numPtr1 = (int *)ref vectori.X; numPtr1[0]++; } } } } else { vectori.Z = min.Z; while (vectori.Z <= max.Z) { vectori.Y = min.Y; while (true) { if (vectori.Y > max.Y) { float *singlePtr6 = (float *)ref localPos.Z; singlePtr6[0] += lodVoxelSize; localPos.Y = vector.Y; int *numPtr6 = (int *)ref vectori.Z; numPtr6[0]++; break; } vectori.X = min.X; Vector3I p = (Vector3I)(vectori + writeOffsetLoc); int linearIdx = target.ComputeLinear(ref p); while (true) { if (vectori.X > max.X) { float *singlePtr5 = (float *)ref localPos.Y; singlePtr5[0] += lodVoxelSize; localPos.X = vector.X; int *numPtr5 = (int *)ref vectori.Y; numPtr5[0]++; break; } byte content = (byte)(((MathHelper.Clamp(-(this.SignedDistanceLocal(localPos, lodVoxelSize, faceHint) / lodVoxelSize), -1f, 1f) * 0.5f) + 0.5f) * 255f); target.Content(linearIdx, content); linearIdx += target.StepLinear; float *singlePtr4 = (float *)ref localPos.X; singlePtr4[0] += lodVoxelSize; int *numPtr4 = (int *)ref vectori.X; numPtr4[0]++; } } } } }
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 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)); }
private void ExecuteQuery() { try { var shape = _component._cachedRegion; var worldMin = shape.Center - shape.Radius; var worldMax = shape.Center + shape.Radius; Vector3I voxMin, voxMax; MyVoxelCoordSystems.WorldPositionToVoxelCoord(_vox.PositionLeftBottomCorner, ref worldMin, out voxMin); MyVoxelCoordSystems.WorldPositionToVoxelCoord(_vox.PositionLeftBottomCorner, ref worldMax, out voxMax); { var tmp = Vector3I.Max(voxMin, voxMax); voxMin = Vector3I.Min(voxMin, voxMax); voxMax = tmp; } { voxMin = voxMin >> _component.Definition.LevelOfDetail; voxMax = (voxMax >> _component.Definition.LevelOfDetail) + 1; } _storage.Resize(voxMin, voxMax); // ReSharper disable once RedundantCast ((IMyStorage)_vox.Storage).ReadRange(_storage, MyStorageDataTypeFlags.ContentAndMaterial, _component.Definition.LevelOfDetail, in voxMin, in voxMax); for (var i = 0; i < _countsWorking.Length; i++) { _countsWorking[i] = 0; } for (var itr = new Vector3I_RangeIterator(ref voxMin, ref voxMax); itr.IsValid(); itr.MoveNext()) { var local = itr.Current; var localRoot = local << _component.Definition.LevelOfDetail; Vector3D box; MyVoxelCoordSystems.VoxelCoordToWorldPosition(_vox.PositionLeftBottomCorner, ref localRoot, out box); if (!shape.Intersects(new BoundingBoxD(box, box + (1 << _component.Definition.LevelOfDetail)))) { continue; } var stor = local - voxMin; var idx = _storage.ComputeLinear(ref stor); var content = _storage.Content(idx); if (content == 0) { continue; } if (_component.Definition.Mode == VoxelPowerCountMode.Surface) { if (content == byte.MaxValue) { continue; } content = 1; } _countsWorking[_storage.Material(idx)] += content; } { var tmp = _countsWorking; _countsWorking = Counts; Counts = tmp; } } finally { _currentlyExecuting = false; _component.QueryFinishedAsync(); } }
private unsafe void ProcessCell(MyStorageData cache, IMyStorage storage, Vector3I cell, long detectorId) { Vector3I lodVoxelRangeMin = cell << 3; Vector3I lodVoxelRangeMax = (Vector3I)(lodVoxelRangeMin + 7); storage.ReadRange(cache, MyStorageDataTypeFlags.Content, 2, lodVoxelRangeMin, lodVoxelRangeMax); if (cache.ContainsVoxelsAboveIsoLevel()) { Vector3I vectori3; MyVoxelRequestFlags preciseOrePositions = MyVoxelRequestFlags.PreciseOrePositions; storage.ReadRange(cache, MyStorageDataTypeFlags.Material, 2, lodVoxelRangeMin, lodVoxelRangeMax, ref preciseOrePositions); MaterialPositionData[] materialData = MaterialData; vectori3.Z = 0; while (vectori3.Z < 8) { vectori3.Y = 0; while (true) { if (vectori3.Y >= 8) { int *numPtr4 = (int *)ref vectori3.Z; numPtr4[0]++; break; } vectori3.X = 0; while (true) { if (vectori3.X >= 8) { int *numPtr3 = (int *)ref vectori3.Y; numPtr3[0]++; break; } int linearIdx = cache.ComputeLinear(ref vectori3); if (cache.Content(linearIdx) > 0x7f) { byte index = cache.Material(linearIdx); Vector3D vectord = ((vectori3 + lodVoxelRangeMin) * 4f) + 2f; Vector3 *vectorPtr1 = (Vector3 *)ref materialData[index].Sum; vectorPtr1[0] += vectord; int *numPtr1 = (int *)ref materialData[index].Count; numPtr1[0]++; } int *numPtr2 = (int *)ref vectori3.X; numPtr2[0]++; } } } MyEntityOreDeposit item = null; for (int i = 0; i < materialData.Length; i++) { if (materialData[i].Count != 0) { MyVoxelMaterialDefinition voxelMaterialDefinition = MyDefinitionManager.Static.GetVoxelMaterialDefinition((byte)i); if ((voxelMaterialDefinition != null) && voxelMaterialDefinition.IsRare) { if (item == null) { item = new MyEntityOreDeposit(this.VoxelMap, cell, detectorId); } MyEntityOreDeposit.Data data = new MyEntityOreDeposit.Data { Material = voxelMaterialDefinition, AverageLocalPosition = (Vector3)Vector3D.Transform((materialData[i].Sum / ((float)materialData[i].Count)) - this.VoxelMap.SizeInMetresHalf, Quaternion.CreateFromRotationMatrix(this.VoxelMap.WorldMatrix)) }; item.Materials.Add(data); } } } if (item != null) { this.m_result.Add(item); } else { this.m_emptyCells.Add(cell); } Array.Clear(materialData, 0, materialData.Length); } }
public unsafe void ReadMaterialRange(ref MyVoxelDataRequest req, bool detectOnly = false) { Vector3I vectori4; req.Flags = req.RequestFlags & MyVoxelRequestFlags.RequestFlags; Vector3I minInLod = req.MinInLod; Vector3I maxInLod = req.MaxInLod; float lodSize = 1 << (req.Lod & 0x1f); bool flag = req.RequestFlags.HasFlags(MyVoxelRequestFlags.SurfaceMaterial); bool flag2 = req.RequestFlags.HasFlags(MyVoxelRequestFlags.ConsiderContent); bool preciseOrePositions = req.RequestFlags.HasFlags(MyVoxelRequestFlags.PreciseOrePositions); this.m_planetShape.PrepareCache(); if (this.m_biomes != null) { if (req.SizeLinear > 0x7d) { BoundingBox request = new BoundingBox((Vector3)(minInLod * lodSize), (Vector3)(maxInLod * lodSize)); this.PrepareRulesForBoxInternal(ref request); } else if (!m_rangeClean || !ReferenceEquals(CachedProvider, this)) { this.CleanRules(); } } Vector3 vector = (minInLod + 0.5f) * lodSize; Vector3 pos = vector; Vector3I vectori3 = (Vector3I)(-minInLod + req.Offset); if (detectOnly) { vectori4.Z = minInLod.Z; while (vectori4.Z <= maxInLod.Z) { vectori4.Y = minInLod.Y; while (true) { if (vectori4.Y > maxInLod.Y) { float *singlePtr3 = (float *)ref pos.Z; singlePtr3[0] += lodSize; pos.Y = vector.Y; int *numPtr3 = (int *)ref vectori4.Z; numPtr3[0]++; break; } vectori4.X = minInLod.X; while (true) { byte num2; if (vectori4.X > maxInLod.X) { float *singlePtr2 = (float *)ref pos.Y; singlePtr2[0] += lodSize; pos.X = vector.X; int *numPtr2 = (int *)ref vectori4.Y; numPtr2[0]++; break; } MyVoxelMaterialDefinition definition = this.GetMaterialForPosition(ref pos, lodSize, out num2, preciseOrePositions); if ((definition != null) && (definition.Index != 0xff)) { return; } float *singlePtr1 = (float *)ref pos.X; singlePtr1[0] += lodSize; int *numPtr1 = (int *)ref vectori4.X; numPtr1[0]++; } } } MyVoxelRequestFlags *flagsPtr1 = (MyVoxelRequestFlags *)ref req.Flags; *((int *)flagsPtr1) |= 8; } else { bool flag4 = true; MyStorageData target = req.Target; vectori4.Z = minInLod.Z; while (true) { while (true) { if (vectori4.Z <= maxInLod.Z) { vectori4.Y = minInLod.Y; break; } if (flag4) { MyVoxelRequestFlags *flagsPtr2 = (MyVoxelRequestFlags *)ref req.Flags; *((int *)flagsPtr2) |= 8; } return; } while (true) { if (vectori4.Y > maxInLod.Y) { float *singlePtr6 = (float *)ref pos.Z; singlePtr6[0] += lodSize; pos.Y = vector.Y; int *numPtr6 = (int *)ref vectori4.Z; numPtr6[0]++; break; } vectori4.X = minInLod.X; Vector3I p = (Vector3I)(vectori4 + vectori3); int linearIdx = target.ComputeLinear(ref p); while (true) { if (vectori4.X <= maxInLod.X) { byte num4; if ((!flag || (target.Material(linearIdx) == 0)) && (!flag2 || (target.Content(linearIdx) != 0))) { byte num5; MyVoxelMaterialDefinition definition2 = this.GetMaterialForPosition(ref pos, lodSize, out num5, preciseOrePositions); num4 = (definition2 != null) ? definition2.Index : ((byte)0xff); } else { num4 = 0xff; } target.Material(linearIdx, num4); flag4 &= num4 == 0xff; linearIdx += target.StepLinear; float *singlePtr4 = (float *)ref pos.X; singlePtr4[0] += lodSize; int *numPtr4 = (int *)ref vectori4.X; numPtr4[0]++; continue; } else { float *singlePtr5 = (float *)ref pos.Y; singlePtr5[0] += lodSize; pos.X = vector.X; int *numPtr5 = (int *)ref vectori4.Y; numPtr5[0]++; } break; } } } } }
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 void ProcessCell(MyStorageData cache, IMyStorage storage, Vector3I cell) { var min = cell << MyOreDetectorComponent.CELL_SIZE_IN_VOXELS_BITS; var max = min + (MyOreDetectorComponent.CELL_SIZE_IN_LOD_VOXELS - 1); storage.PinAndExecute(() => { storage.ReadRange(cache, MyStorageDataTypeFlags.Content, MyOreDetectorComponent.QUERY_LOD, min, max); if (!cache.ContainsVoxelsAboveIsoLevel()) { return; } storage.ReadRange(cache, MyStorageDataTypeFlags.Material, MyOreDetectorComponent.QUERY_LOD, min, max); }); var materialData = MaterialData; Vector3I c; for (c.Z = 0; c.Z < MyOreDetectorComponent.CELL_SIZE_IN_LOD_VOXELS; ++c.Z) { for (c.Y = 0; c.Y < MyOreDetectorComponent.CELL_SIZE_IN_LOD_VOXELS; ++c.Y) { for (c.X = 0; c.X < MyOreDetectorComponent.CELL_SIZE_IN_LOD_VOXELS; ++c.X) { int i = cache.ComputeLinear(ref c); if (cache.Content(i) > MyVoxelDataConstants.IsoLevel) { const float VOXEL_SIZE = MyVoxelConstants.VOXEL_SIZE_IN_METRES * (1 << MyOreDetectorComponent.QUERY_LOD); const float VOXEL_SIZE_HALF = VOXEL_SIZE * 0.5f; var material = cache.Material(i); Vector3D localPos = (c + min) * VOXEL_SIZE + VOXEL_SIZE_HALF; materialData[material].Sum += localPos; materialData[material].Count += 1; var pos = Vector3.Transform(localPos - VoxelMap.SizeInMetresHalf, Quaternion.CreateFromRotationMatrix(VoxelMap.WorldMatrix)); Vector3D worldpos; MyVoxelCoordSystems.LocalPositionToWorldPosition((VoxelMap.PositionComp.GetPosition() - (Vector3D)VoxelMap.StorageMin), ref pos, out worldpos); if (materialData[material].Positions == null) { materialData[material].Positions = new List <Vector3D>(); } materialData[material].Positions.Add(worldpos); } } } } MyEntityOreDeposit result = null; for (int materialIdx = 0; materialIdx < materialData.Length; ++materialIdx) { if (materialData[materialIdx].Count == 0) { continue; } var material = MyDefinitionManager.Static.GetVoxelMaterialDefinition((byte)materialIdx); if (material != null && material.IsRare) { if (result == null) { result = new MyEntityOreDeposit(VoxelMap, cell); } result.Materials.Add(new MyEntityOreDeposit.Data() { Material = material, AverageLocalPosition = Vector3D.Transform((materialData[materialIdx].Sum / materialData[materialIdx].Count - VoxelMap.SizeInMetresHalf), Quaternion.CreateFromRotationMatrix(VoxelMap.WorldMatrix)), Positions = materialData[materialIdx].Positions, }); } } if (result != null) { m_result.Add(result); } else { m_emptyCells.Add(cell); } Array.Clear(materialData, 0, materialData.Length); return; }
/// <summary> /// Start the reads if it is not already running. /// </summary> /// <param name="onFinished">Invoked when reads finish, not invoked if already running.</param> /// <returns>True if started, false if already running.</returns> public void Read() { Profiler.StartProfileBlock(); m_throwOutVoxelData = Globals.ElapsedTime + Static.LifeSpan_VoxelData; NeedsUpdate = false; Vector3D m_oreDetectorPosition = m_oreDetector.GetPosition(); Vector3D worldMin = m_oreDetectorPosition - m_maxRange; Vector3D worldMax = m_oreDetectorPosition + m_maxRange; float rangeSquared = m_maxRange * m_maxRange; Vector3I odPosVoxelStorage, m_localMin, m_localMax; MyVoxelCoordSystems.WorldPositionToVoxelCoord(m_voxel.PositionLeftBottomCorner, ref m_oreDetectorPosition, out odPosVoxelStorage); MyVoxelCoordSystems.WorldPositionToVoxelCoord(m_voxel.PositionLeftBottomCorner, ref worldMin, out m_localMin); MyVoxelCoordSystems.WorldPositionToVoxelCoord(m_voxel.PositionLeftBottomCorner, ref worldMax, out m_localMax); MyVoxelBase vox = m_voxel as MyVoxelBase; if (m_voxel == null || m_voxel.Storage == null) { Profiler.EndProfileBlock(); return; } m_localMin = Vector3I.Clamp(m_localMin, vox.StorageMin, vox.StorageMax); m_localMax = Vector3I.Clamp(m_localMax, vox.StorageMin, vox.StorageMax); m_localMin >>= QUERY_LOD; m_localMax >>= QUERY_LOD; odPosVoxelStorage >>= QUERY_LOD; Log.DebugLog("minLocal: " + m_localMin + ", maxLocal: " + m_localMax + ", odPosVoxelStorage: " + odPosVoxelStorage); Vector3I size = m_localMax - m_localMin; Log.DebugLog("number of coords in box: " + (size.X + 1) * (size.Y + 1) * (size.Z + 1)); //ulong processed = 0; foreach (List <Vector3I> locations in m_materialLocations2.Values) { locations.Clear(); } Vector3I vector = new Vector3I(); for (vector.X = m_localMin.X; vector.X < m_localMax.X; vector.X += QUERY_STEP) { for (vector.Y = m_localMin.Y; vector.Y < m_localMax.Y; vector.Y += QUERY_STEP) { for (vector.Z = m_localMin.Z; vector.Z < m_localMax.Z; vector.Z += QUERY_STEP) { if (vector.DistanceSquared(odPosVoxelStorage) <= rangeSquared) { m_voxel.Storage.ReadRange(m_storage, MyStorageDataTypeFlags.ContentAndMaterial, QUERY_LOD, vector, vector + QUERY_MAX); Vector3I index = Vector3I.Zero; Vector3I size3D = m_storage.Size3D; for (index.X = 0; index.X < size3D.X; index.X++) { for (index.Y = 0; index.Y < size3D.Y; index.Y++) { for (index.Z = 0; index.Z < size3D.Z; index.Z++) { int linear = m_storage.ComputeLinear(ref index); if (m_storage.Content(linear) > MyVoxelConstants.VOXEL_ISO_LEVEL) { byte mat = m_storage.Material(linear); if (Static.RareMaterials[mat]) { //Log.DebugLog("mat: " + mat + ", content: " + m_storage.Content(linear) + ", vector: " + vector + ", position: " + vector + index // + ", name: " + MyDefinitionManager.Static.GetVoxelMaterialDefinition(mat).MinedOre, "Read()"); //m_materialLocations[vector + index] = mat; List <Vector3I> locations; if (!m_materialLocations2.TryGetValue(mat, out locations)) { locations = new List <Vector3I>(1000); m_materialLocations2.Add(mat, locations); } locations.Add(vector + index); //processed++; goto Finished_Deposit; } } } } } Finished_Deposit :; //processed++; } } } } //Log.DebugLog("read " + processed + ", chunks" + ", number of mats: " + m_materialLocations.Count, Logger.severity.DEBUG); Profiler.EndProfileBlock(); }