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 void Init(MyObjectBuilder_EntityBase builder, IMyStorage storage) { ProfilerShort.Begin("base init"); SyncFlag = true; base.Init(builder); base.Init(null, null, null, null, null); ProfilerShort.BeginNextBlock("Load file"); var ob = (MyObjectBuilder_VoxelMap)builder; if (ob == null) { return; } if (ob.MutableStorage) { StorageName = ob.StorageName; } else { StorageName = string.Format("{0}-{1}", ob.StorageName, m_immutableStorageNameSalt++); } m_storage = storage; m_storage.RangeChanged += storage_RangeChanged; m_storageMax = m_storage.Size; InitVoxelMap(MatrixD.CreateTranslation((Vector3D)ob.PositionAndOrientation.Value.Position + m_storage.Size / 2), m_storage.Size); ProfilerShort.End(); }
public void SetVoxelMapFromBuilder(MyObjectBuilder_EntityBase voxelMap, IMyStorage storage, Vector3 dragPointDelta, float dragVectorLength) { if (IsActive) { Deactivate(); } m_copiedVoxelMaps.Clear(); m_copiedVoxelMapOffsets.Clear(); m_copiedStorages.Clear(); MatrixD pasteMatrix = GetPasteMatrix(); m_dragPointToPositionLocal = dragPointDelta; m_dragDistance = dragVectorLength; Vector3 offset = Vector3.Zero; if (voxelMap is MyObjectBuilder_Planet) { offset = storage.Size / 2.0f; } SetVoxelMapFromBuilderInternal(voxelMap, storage, offset); Activate(); }
public override void DoWork() { ProfilerShort.Begin("MyPrecalcJobPhysicsBatch.DoWork"); try { IMyStorage storage = m_targetPhysics.m_voxelMap.Storage; foreach (var cell in CellBatch) { if (m_isCancelled) { break; } var geometryData = m_targetPhysics.CreateMesh(storage, cell); if (m_isCancelled) { break; } if (!MyIsoMesh.IsEmpty(geometryData)) { var meshShape = m_targetPhysics.CreateShape(geometryData); m_newShapes.Add(cell, meshShape); } else { m_newShapes.Add(cell, (HkBvCompressedMeshShape)HkShape.Empty); } } } finally { ProfilerShort.End(); } }
public override void Init(string storageName, IMyStorage storage, Vector3D positionMinCorner) { m_storageMax = storage.Size; base.Init(storageName, storage, positionMinCorner); m_storage.RangeChanged += storage_RangeChanged; }
public override void Init(MyObjectBuilder_EntityBase builder, IMyStorage storage) { ProfilerShort.Begin("base init"); SyncFlag = true; base.Init(builder); base.Init(null, null, null, null, null); ProfilerShort.BeginNextBlock("Load file"); var ob = (MyObjectBuilder_VoxelMap)builder; if (ob == null) { return; } if (ob.MutableStorage) { StorageName = ob.StorageName; } else { StorageName = GetNewStorageName(ob.StorageName); } m_storage = storage; m_storage.RangeChanged += storage_RangeChanged; m_storageMax = m_storage.Size; InitVoxelMap(MatrixD.CreateWorld((Vector3D)ob.PositionAndOrientation.Value.Position + Vector3D.TransformNormal((Vector3D)m_storage.Size / 2, WorldMatrix), WorldMatrix.Forward, WorldMatrix.Up), m_storage.Size); ProfilerShort.End(); }
internal MyIsoMesh CreateMesh(IMyStorage storage, MyCellCoord coord) { // mk:NOTE This method must be thread safe. Called from worker threads. coord.CoordInLod += m_cellsOffset >> coord.Lod; if (m_voxelMap is MyVoxelPhysics) { var clipmapId = ((MyVoxelPhysics)m_voxelMap).Parent.Render.RenderObjectIDs[0]; var clipmapCellId = MyCellCoord.GetClipmapCellHash(clipmapId, coord.PackId64()); var isoMesh = MyPrecalcJobRender.IsoMeshCache.Read(clipmapCellId); if (isoMesh != null) { return(isoMesh); } } var min = coord.CoordInLod << MyVoxelConstants.GEOMETRY_CELL_SIZE_IN_VOXELS_BITS; var max = min + MyVoxelConstants.GEOMETRY_CELL_SIZE_IN_VOXELS; // overlap to neighbor; introduces extra data but it makes logic for raycasts and collisions simpler (no need to check neighbor cells) min -= 1; max += 2; return(MyPrecalcComponent.IsoMesher.Precalc(storage, coord.Lod, min, max, false, false)); }
public override void Init(string storageName, IMyStorage storage, MatrixD worldMatrix) { m_storageMax = storage.Size; base.Init(storageName, storage, worldMatrix); m_storage.RangeChanged += storage_RangeChanged; }
public static void ClampVoxelCoord(this IMyStorage self, ref Vector3I voxelCoord, int distance = 1) { if (self == null) { return; } Vector3I max = self.Size - distance; Vector3I.Clamp(ref voxelCoord, ref Vector3I.Zero, ref max, out voxelCoord); }
public override void Init(string storageName, IMyStorage storage, MatrixD worldMatrix) { ProfilerShort.Begin("MyVoxelMap::Init"); m_storageMax = storage.Size; base.Init(storageName, storage, worldMatrix); m_storage.RangeChanged += storage_RangeChanged; ProfilerShort.End(); }
virtual public void Init(string storageName, IMyStorage storage, Vector3D positionMinCorner) { SyncFlag = true; base.Init(null); StorageName = storageName; m_storage = storage; InitVoxelMap(positionMinCorner, storage.Size); }
virtual public void Init(string storageName, IMyStorage storage, MatrixD worldMatrix) { SyncFlag = true; base.Init(null); StorageName = storageName; m_storage = storage; InitVoxelMap(worldMatrix, storage.Size); }
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 void Init(IMyStorage storage, Vector3D positionMinCorner, Vector3I storageMin, Vector3I storageMax,MyPlanet parent) { m_parent = parent; base.Init(null); m_storageMax = storageMax; m_storageMin = storageMin; m_storage = storage; InitVoxelMap(positionMinCorner, Size, false); }
public void Init(IMyStorage storage, Vector3D positionMinCorner, Vector3I storageMin, Vector3I storageMax, MyPlanet parent) { m_parent = parent; base.Init(null); m_storageMax = storageMax; m_storageMin = storageMin; m_storage = storage; InitVoxelMap(positionMinCorner, Size, false); }
public void Init(IMyStorage storage, Vector3D positionMinCorner, Vector3I storageMin, Vector3I storageMax) { SyncFlag = true; base.Init(null); m_storageMax = storageMax; m_storageMin = storageMin; m_storage = storage; InitVoxelMap(positionMinCorner, Size, false); }
internal MyIsoMesh CreateMesh(IMyStorage storage, Vector3I coord) { // mk:NOTE This method must be thread safe. Called from worker threads. coord += m_cellsOffset; var min = coord << MyVoxelConstants.GEOMETRY_CELL_SIZE_IN_VOXELS_BITS; var max = min + MyVoxelConstants.GEOMETRY_CELL_SIZE_IN_VOXELS; // overlap to neighbor; introduces extra data but it makes logic for raycasts and collisions simpler (no need to check neighbor cells) min -= 1; max += 2; return(MyPrecalcComponent.IsoMesher.Precalc(storage, 0, min, max, false)); }
protected override void OnLoad(BitStream stream, Action <MyVoxelBase> loadingDoneHandler) { MyVoxelBase map = null; bool isFromPrefab = VRage.Serialization.MySerializer.CreateAndRead <bool>(stream); bool rangeChanged = VRage.Serialization.MySerializer.CreateAndRead <bool>(stream); byte[] data = null; if (rangeChanged) { data = VRage.Serialization.MySerializer.CreateAndRead <byte[]>(stream); } if (isFromPrefab) { var builder = VRage.Serialization.MySerializer.CreateAndRead <MyObjectBuilder_EntityBase>(stream, MyObjectBuilderSerializer.Dynamic); var voxelMap = new MyVoxelMap(); if (rangeChanged && data != null) { IMyStorage storage = MyStorageBase.Load(data); MyEntity entity; if (MyEntities.TryGetEntityById(builder.EntityId, out entity) && entity is MyVoxelMap) { voxelMap = (entity as MyVoxelMap); voxelMap.Storage = storage; } else { voxelMap.Init(builder, storage); MyEntities.Add(voxelMap); } } else { voxelMap.Init(builder); MyEntities.Add(voxelMap); } map = voxelMap; } else { long voxelMapId = VRage.Serialization.MySerializer.CreateAndRead <long>(stream); MyEntity entity = null; MyEntities.TryGetEntityById(voxelMapId, out entity); map = entity as MyVoxelBase; } loadingDoneHandler(map); }
public void Init(IMyStorage storage, MatrixD worldMatrix, Vector3I storageMin, Vector3I storageMax, MyPlanet parent) { m_parent = parent; long hash = storageMin.X; hash = (hash * 397L) ^ (long)storageMin.Y; hash = (hash * 397L) ^ (long)storageMin.Z; hash = (hash * 397L) ^ (long)parent.EntityId; EntityId = MyEntityIdentifier.ConstructId(MyEntityIdentifier.ID_OBJECT_TYPE.VOXEL_PHYSICS, hash & 0x00FFFFFFFFFFFFFF); base.Init(null); InitVoxelMap(worldMatrix, Size, false); }
public void Init(IMyStorage storage, Vector3D positionMinCorner, Vector3I storageMin, Vector3I storageMax, MyPlanet parent) { PositionLeftBottomCorner = positionMinCorner; m_storageMax = storageMax; m_storageMin = storageMin; m_storage = storage; SizeInMetres = Size * MyVoxelConstants.VOXEL_SIZE_IN_METRES; SizeInMetresHalf = SizeInMetres / 2.0f; MatrixD worldMatrix = MatrixD.CreateTranslation(positionMinCorner + SizeInMetresHalf); Init(storage, worldMatrix, storageMin, storageMax, parent); }
/// <summary> /// If already loaded, returns false. Otherwise loads and returns true. /// </summary> public bool Load() { if (IsLoaded) { return(false); } T val = IMyStorage.Load <T>(FileName); //if (val == null) // val = new T(); Value = val; return(true); }
public static MyVoxelMaterialDefinition GetMaterialAt(this IMyStorage self, ref Vector3I voxelCoords) { MyVoxelMaterialDefinition def; MyStorageDataCache cache = new MyStorageDataCache(); 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 static bool CellAffectsTriangles(IMyStorage storage, MyLodTypeEnum lod, ref Vector3I cellCoord) { Profiler.Begin("CellAffectsTriangles"); try { // Fix max cell coordinates so they don't fall from voxelmap var rangeMin = cellCoord << MyVoxelConstants.GEOMETRY_CELL_SIZE_IN_VOXELS_BITS; rangeMin += MyVoxelPrecalc.AffectedRangeOffset; var rangeMax = Vector3I.Min(rangeMin + (MyVoxelConstants.GEOMETRY_CELL_SIZE_IN_VOXELS + MyVoxelPrecalc.AffectedRangeSizeChange - 1), storage.Size - 1); var type = storage.GetRangeType(GetLodIndex(lod), ref rangeMin, ref rangeMax); return(type == MyVoxelRangeType.MIXED); } finally { Profiler.End(); } }
public static void DebugDrawChunk(this IMyStorage self, Vector3I start, Vector3I end, Color?c = null) { if (!c.HasValue) { c = Color.Blue; } var vmaps = MySession.Static.VoxelMaps.Instances.Where(x => x.Storage == self); var box = new BoundingBoxD(start, end + 1); box.Translate(-((Vector3D)self.Size * .5) - .5); foreach (var map in vmaps) { MyRenderProxy.DebugDrawOBB(new MyOrientedBoundingBoxD(box, map.WorldMatrix), c.Value, 0.5f, true, true); } }
public void SetVoxelMapFromBuilder(MyObjectBuilder_VoxelMap voxelMap, IMyStorage storage, Vector3 dragPointDelta, float dragVectorLength) { if (IsActive) { Deactivate(); } m_copiedVoxelMaps.Clear(); m_copiedVoxelMapOffsets.Clear(); m_copiedStorages.Clear(); MatrixD pasteMatrix = GetPasteMatrix(); m_dragPointToPositionLocal = dragPointDelta; m_dragDistance = dragVectorLength; SetVoxelMapFromBuilderInternal(voxelMap, storage, Vector3.Zero); Activate(); }
private void LoadPartialChanges() { bool upgradedFromOld = false; try { using (Stream s = IMyStorage.LoadStream(Files.PARTIAL_CHANGES_FILE(LocalId))) { _partialChanges = new DataContractJsonSerializer(typeof(PartialChanges)).ReadObject(s) as PartialChanges; } } //not found, try upgrading from old version catch { _partialChanges = new PartialChanges(); if (_oldChanges != null) { foreach (var pair in _oldChanges._changedItems) { if (pair.Value.IsDeleted) { PartialChanges.Delete(pair.Key); } else { PartialChanges.New(pair.Key); } } upgradedFromOld = true; } } if (upgradedFromOld) { //make the old Changes null so it doesn't load/waste space _oldChanges = null; } }
internal MyIsoMesh CreateMesh(IMyStorage storage, MyCellCoord coord) { // mk:NOTE This method must be thread safe. Called from worker threads. coord.CoordInLod += m_cellsOffset >> coord.Lod; var min = coord.CoordInLod << MyVoxelConstants.GEOMETRY_CELL_SIZE_IN_VOXELS_BITS; var max = min + MyVoxelConstants.GEOMETRY_CELL_SIZE_IN_VOXELS; // overlap to neighbor; introduces extra data but it makes logic for raycasts and collisions simpler (no need to check neighbor cells) min -= 1; max += 2; var mesh = MyPrecalcComponent.IsoMesher.Precalc(storage, coord.Lod, min, max, false, false); if (mesh == null) { if (MyVoxelDebugInputComponent.PhysicsComponent.Static != null) { MyVoxelDebugInputComponent.PhysicsComponent.Static.Add(m_voxelMap.WorldMatrix, new BoundingBox(min + 1, max - 2), new Vector4I(min, coord.Lod), m_voxelMap); } } return(mesh); }
public void ActivateVoxelClipboard(MyObjectBuilder_EntityBase voxelMap, IMyStorage storage, Vector3 centerDeltaDirection, float dragVectorLength) { MySessionComponentVoxelHand.Static.Enabled = false; m_voxelClipboard.SetVoxelMapFromBuilder(voxelMap, storage, centerDeltaDirection, dragVectorLength); this.Activate(); }
public void ActivateVoxelClipboard(MyObjectBuilder_VoxelMap voxelMap, IMyStorage storage, Vector3 centerDeltaDirection, float dragVectorLength) { if (m_shipCreationClipboard.IsActive) return; MySessionComponentVoxelHand.Static.Enabled = false; DeactivateMultiBlockClipboard(); m_voxelClipboard.SetVoxelMapFromBuilder(voxelMap, storage, centerDeltaDirection, dragVectorLength); }
public void Init(IMyStorage storage, Vector3D positionMinCorner, Vector3I storageMin, Vector3I storageMax) { SyncFlag = true; base.Init(null); m_storageMax = storageMax; m_storageMin = storageMin; m_storage = storage; InitVoxelMap(positionMinCorner, Size,false); }
public override void Init(VRage.ObjectBuilders.MyObjectBuilder_EntityBase builder, IMyStorage storage) { }
public void Init(string storageName, IMyStorage storage, Vector3D positionMinCorner) { MatrixD worldMatrix = MatrixD.CreateTranslation(positionMinCorner + storage.Size / 2); Init(storageName, storage, worldMatrix); }
private static bool CellAffectsTriangles(IMyStorage storage, MyLodTypeEnum lod, ref Vector3I cellCoord) { Profiler.Begin("CellAffectsTriangles"); try { // Fix max cell coordinates so they don't fall from voxelmap var rangeMin = cellCoord << MyVoxelConstants.GEOMETRY_CELL_SIZE_IN_VOXELS_BITS; rangeMin += MyVoxelPrecalc.AffectedRangeOffset; var rangeMax = Vector3I.Min(rangeMin + (MyVoxelConstants.GEOMETRY_CELL_SIZE_IN_VOXELS + MyVoxelPrecalc.AffectedRangeSizeChange - 1), storage.Size - 1); var type = storage.GetRangeType(GetLodIndex(lod), ref rangeMin, ref rangeMax); return type == MyVoxelRangeType.MIXED; } finally { Profiler.End(); } }
public void Init(string storageName, IMyStorage storage, Vector3D positionMinCorner, float averagePlanetRadius, float atmosphereRadius, float maximumHillRadius, float minimumSurfaceRadius, bool hasAtmosphere, Vector3 atmosphereWavelengths,float maxOxygen,float gravityFalloff) { m_gravityFalloff = gravityFalloff; m_maximumOxygen = maxOxygen; m_atmosphereWavelengths = atmosphereWavelengths; m_hasSpawningMaterial = storage.DataProvider.HasMaterialSpawningFlora(); m_maximumHillRadius = maximumHillRadius; m_minimumSurfaceRadius = minimumSurfaceRadius; m_planetRadius = averagePlanetRadius; m_atmosphereRadius = atmosphereRadius; m_hasAtmosphere = hasAtmosphere; base.Init(storageName,storage,positionMinCorner); NeedsUpdate |= MyEntityUpdateEnum.EACH_100TH_FRAME | MyEntityUpdateEnum.BEFORE_NEXT_FRAME; m_storage.RangeChanged += storage_RangeChangedPlanet; if (Physics != null) { Physics.Enabled = false; Physics.Close(); Physics = null; } Vector3I storageSize = storage.Size; m_numCells = new Vector3I(storageSize.X / PHYSICS_SECTOR_SIZE_METERS, storageSize.Y / PHYSICS_SECTOR_SIZE_METERS, storageSize.Z / PHYSICS_SECTOR_SIZE_METERS); m_numCells -= 1; StorageName = storageName; m_storageMax = storage.Size; MyGravityProviderSystem.AddPlanet(this); MyOxygenProviderSystem.AddOxygenGenerator(this); }
private bool FindMaterial(IMyStorage storage, byte[] findMaterial) { if (findMaterial.Length == 0) return false; var oldCache = new MyStorageDataCache(); 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; }
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++; } } }
public StoragePin(MyStorageBase myStorageBase) { m_storage = myStorageBase; }
private void SetVoxelMapFromBuilderInternal(MyObjectBuilder_EntityBase voxelMap, IMyStorage storage, Vector3 offset) { m_copiedVoxelMaps.Add(voxelMap); m_copiedStorages.Add(storage); m_copiedVoxelMapOffsets.Add(offset); }
internal MyIsoMesh CreateMesh(IMyStorage storage, MyCellCoord coord) { // mk:NOTE This method must be thread safe. Called from worker threads. coord.CoordInLod += m_cellsOffset >> coord.Lod; var min = coord.CoordInLod << MyVoxelConstants.GEOMETRY_CELL_SIZE_IN_VOXELS_BITS; var max = min + MyVoxelConstants.GEOMETRY_CELL_SIZE_IN_VOXELS; // overlap to neighbor; introduces extra data but it makes logic for raycasts and collisions simpler (no need to check neighbor cells) min -= 1; max += 2; var mesh = MyPrecalcComponent.IsoMesher.Precalc(storage, coord.Lod, min, max, false, false); if (mesh == null) { if (MyVoxelDebugInputComponent.PhysicsComponent.Static != null) MyVoxelDebugInputComponent.PhysicsComponent.Static.Add(m_voxelMap.WorldMatrix, new BoundingBox(min+1, max-2), new Vector4I(min, coord.Lod), m_voxelMap); } return mesh; }
public MyIsoMesh Precalc(IMyStorage storage, int lod, Vector3I voxelStart, Vector3I voxelEnd, bool generateMaterials, bool useAmbient, bool doNotCheck) { m_resultVerticesCounter = 0; m_resultTrianglesCounter = 0; m_edgeVertexCalcCounter++; m_temporaryVoxelsCounter++; CalcPolygCubeSize(lod, storage.Size); m_voxelStart = voxelStart; //voxelStart = voxelStart; //voxelEnd = voxelEnd; var ssize = storage.Size; m_cache.Resize(voxelStart, voxelEnd); // Load content first, check it if it contains isosurface, early exit if it doesn't. storage.ReadRange(m_cache, MyStorageDataTypeFlags.Content, lod, ref voxelStart, ref voxelEnd); if (!m_cache.ContainsIsoSurface()) { return(null); } storage.ReadRange(m_cache, MyStorageDataTypeFlags.Material, lod, ref voxelStart, ref voxelEnd); ProfilerShort.Begin("Marching cubes"); { // Size of voxel or cell (in meters) and size of voxel map / voxel cells ComputeSizeAndOrigin(lod, storage.Size); var start = Vector3I.Zero; var end = voxelEnd - voxelStart - 3; Vector3I coord0 = start; for (var it = new Vector3I.RangeIterator(ref start, ref end); it.IsValid(); it.GetNext(out coord0)) { int cubeIndex = 0; if (m_cache.Content(coord0.X + 0, coord0.Y + 0, coord0.Z + 0) < MyVoxelConstants.VOXEL_ISO_LEVEL) { cubeIndex |= 1; } if (m_cache.Content(coord0.X + 1, coord0.Y + 0, coord0.Z + 0) < MyVoxelConstants.VOXEL_ISO_LEVEL) { cubeIndex |= 2; } if (m_cache.Content(coord0.X + 1, coord0.Y + 0, coord0.Z + 1) < MyVoxelConstants.VOXEL_ISO_LEVEL) { cubeIndex |= 4; } if (m_cache.Content(coord0.X + 0, coord0.Y + 0, coord0.Z + 1) < MyVoxelConstants.VOXEL_ISO_LEVEL) { cubeIndex |= 8; } if (m_cache.Content(coord0.X + 0, coord0.Y + 1, coord0.Z + 0) < MyVoxelConstants.VOXEL_ISO_LEVEL) { cubeIndex |= 16; } if (m_cache.Content(coord0.X + 1, coord0.Y + 1, coord0.Z + 0) < MyVoxelConstants.VOXEL_ISO_LEVEL) { cubeIndex |= 32; } if (m_cache.Content(coord0.X + 1, coord0.Y + 1, coord0.Z + 1) < MyVoxelConstants.VOXEL_ISO_LEVEL) { cubeIndex |= 64; } if (m_cache.Content(coord0.X + 0, coord0.Y + 1, coord0.Z + 1) < MyVoxelConstants.VOXEL_ISO_LEVEL) { cubeIndex |= 128; } // Cube is entirely in/out of the surface if (MyMarchingCubesConstants.EdgeTable[cubeIndex] == 0) { continue; } // We can get this voxel content right from cache (not using GetVoxelContent method), because after CopyVoxelContents these array must be filled. But only content, not material, normal, etc. Vector3I tempVoxelCoord0 = ComputeTemporaryVoxelData(m_cache, ref coord0, cubeIndex, lod); // Create the triangles CreateTriangles(ref coord0, cubeIndex, ref tempVoxelCoord0); } } ProfilerShort.End(); double numCellsHalf = 0.5f * (m_cache.Size3D.X); var voxelSize = MyVoxelConstants.VOXEL_SIZE_IN_METRES * (1 << lod); var vertexCellOffset = voxelStart - AffectedRangeOffset; IMyIsoMesherOutputBuffer isomesh = new MyIsoMesh(); for (int i = 0; i < m_resultVerticesCounter; i++) { var pos = (m_resultVertices[i].Position - (Vector3)storage.Size / 2) / storage.Size; m_resultVertices[i].Position = pos; m_resultVertices[i].PositionMorph = pos; m_resultVertices[i].NormalMorph = m_resultVertices[i].Normal; m_resultVertices[i].MaterialMorph = m_resultVertices[i].Material; m_resultVertices[i].AmbientMorph = m_resultVertices[i].Ambient; } for (int i = 0; i < m_resultVerticesCounter; i++) { isomesh.WriteVertex(ref m_resultVertices[i].Cell, ref m_resultVertices[i].Position, ref m_resultVertices[i].Normal, (byte)m_resultVertices[i].Material, m_resultVertices[i].Ambient); } for (int i = 0; i < m_resultTrianglesCounter; i++) { isomesh.WriteTriangle(m_resultTriangles[i].VertexIndex0, m_resultTriangles[i].VertexIndex1, m_resultTriangles[i].VertexIndex2); } var mIsoMesh = (MyIsoMesh)isomesh; mIsoMesh.PositionOffset = storage.Size / 2; mIsoMesh.PositionScale = storage.Size; mIsoMesh.CellStart = voxelStart; mIsoMesh.CellEnd = voxelEnd; var vertexCells = mIsoMesh.Cells.GetInternalArray(); for (int i = 0; i < mIsoMesh.VerticesCount; i++) { vertexCells[i] += vertexCellOffset; } return((MyIsoMesh)isomesh); }
public MyIsoMesh Precalc(IMyStorage storage, int lod, Vector3I voxelStart, Vector3I voxelEnd, bool generateMaterials, bool useAmbient, bool doNotCheck, bool adviceCache = false) { m_resultVerticesCounter = 0; m_resultTrianglesCounter = 0; m_edgeVertexCalcCounter++; m_temporaryVoxelsCounter++; CalcPolygCubeSize(lod, storage.Size); m_voxelStart = voxelStart; //voxelStart = voxelStart; //voxelEnd = voxelEnd; var ssize = storage.Size; m_cache.Resize(voxelStart, voxelEnd); // Load content first, check it if it contains isosurface, early exit if it doesn't. storage.ReadRange(m_cache, MyStorageDataTypeFlags.Content, lod, ref voxelStart, ref voxelEnd); if (!m_cache.ContainsIsoSurface()) return null; storage.ReadRange(m_cache, MyStorageDataTypeFlags.Material, lod, ref voxelStart, ref voxelEnd); ProfilerShort.Begin("Marching cubes"); { // Size of voxel or cell (in meters) and size of voxel map / voxel cells ComputeSizeAndOrigin(lod, storage.Size); var start = Vector3I.Zero; var end = voxelEnd - voxelStart - 3; Vector3I coord0 = start; for (var it = new Vector3I_RangeIterator(ref start, ref end); it.IsValid(); it.GetNext(out coord0)) { int cubeIndex = 0; if (m_cache.Content(coord0.X + 0, coord0.Y + 0, coord0.Z + 0) < MyVoxelConstants.VOXEL_ISO_LEVEL) cubeIndex |= 1; if (m_cache.Content(coord0.X + 1, coord0.Y + 0, coord0.Z + 0) < MyVoxelConstants.VOXEL_ISO_LEVEL) cubeIndex |= 2; if (m_cache.Content(coord0.X + 1, coord0.Y + 0, coord0.Z + 1) < MyVoxelConstants.VOXEL_ISO_LEVEL) cubeIndex |= 4; if (m_cache.Content(coord0.X + 0, coord0.Y + 0, coord0.Z + 1) < MyVoxelConstants.VOXEL_ISO_LEVEL) cubeIndex |= 8; if (m_cache.Content(coord0.X + 0, coord0.Y + 1, coord0.Z + 0) < MyVoxelConstants.VOXEL_ISO_LEVEL) cubeIndex |= 16; if (m_cache.Content(coord0.X + 1, coord0.Y + 1, coord0.Z + 0) < MyVoxelConstants.VOXEL_ISO_LEVEL) cubeIndex |= 32; if (m_cache.Content(coord0.X + 1, coord0.Y + 1, coord0.Z + 1) < MyVoxelConstants.VOXEL_ISO_LEVEL) cubeIndex |= 64; if (m_cache.Content(coord0.X + 0, coord0.Y + 1, coord0.Z + 1) < MyVoxelConstants.VOXEL_ISO_LEVEL) cubeIndex |= 128; // Cube is entirely in/out of the surface if (MyMarchingCubesConstants.EdgeTable[cubeIndex] == 0) { continue; } // We can get this voxel content right from cache (not using GetVoxelContent method), because after CopyVoxelContents these array must be filled. But only content, not material, normal, etc. Vector3I tempVoxelCoord0 = ComputeTemporaryVoxelData(m_cache, ref coord0, cubeIndex, lod); // Create the triangles CreateTriangles(ref coord0, cubeIndex, ref tempVoxelCoord0); } } ProfilerShort.End(); double numCellsHalf = 0.5f * (m_cache.Size3D.X); var voxelSize = MyVoxelConstants.VOXEL_SIZE_IN_METRES * (1 << lod); var vertexCellOffset = voxelStart - AffectedRangeOffset; IMyIsoMesherOutputBuffer isomesh = new MyIsoMesh(); for (int i = 0; i < m_resultVerticesCounter; i++) { var pos = (m_resultVertices[i].Position - (Vector3)storage.Size / 2) / storage.Size; m_resultVertices[i].Position = pos; m_resultVertices[i].PositionMorph = pos; m_resultVertices[i].NormalMorph = m_resultVertices[i].Normal; m_resultVertices[i].MaterialMorph = m_resultVertices[i].Material; m_resultVertices[i].AmbientMorph = m_resultVertices[i].Ambient; } for (int i = 0; i < m_resultVerticesCounter; i++) { isomesh.WriteVertex(ref m_resultVertices[i].Cell, ref m_resultVertices[i].Position, ref m_resultVertices[i].Normal, (byte)m_resultVertices[i].Material, m_resultVertices[i].Ambient); } for (int i = 0; i < m_resultTrianglesCounter; i++) { isomesh.WriteTriangle(m_resultTriangles[i].VertexIndex0, m_resultTriangles[i].VertexIndex1, m_resultTriangles[i].VertexIndex2); } var mIsoMesh = (MyIsoMesh)isomesh; mIsoMesh.PositionOffset = storage.Size / 2; mIsoMesh.PositionScale = storage.Size; mIsoMesh.CellStart = voxelStart; mIsoMesh.CellEnd = voxelEnd; var vertexCells = mIsoMesh.Cells.GetInternalArray(); for (int i = 0; i < mIsoMesh.VerticesCount; i++) { vertexCells[i] += vertexCellOffset; } return (MyIsoMesh)isomesh; }
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.HasFlags(MyVoxelRequestFlags.EmptyContent) || request.HasFlags(MyVoxelRequestFlags.FullContent) || (!request.HasFlags(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); } } 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.HasFlags(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); ProfilerShort.End(); 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(); var ambients = m_buffer.Ambient.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); Debug.Assert(ambients[i] >= 0 && ambients[i] <= 1); } 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 MyIsoMesh Precalc(IMyStorage storage, int lod, Vector3I voxelStart, Vector3I voxelEnd, bool generateMaterials) { // change range so normal can be computed at edges (expand by 1 in all directions) voxelStart -= 1; voxelEnd += 1; m_cache.Resize(voxelStart, voxelEnd); storage.ReadRange(m_cache, MyStorageDataTypeFlags.Content, lod, ref voxelStart, ref voxelEnd); if (!m_cache.ContainsIsoSurface()) { return null; } if (generateMaterials) { storage.ReadRange(m_cache, MyStorageDataTypeFlags.Material, lod, ref voxelStart, ref voxelEnd); } else { m_cache.ClearMaterials(0); } var voxelSize = MyVoxelConstants.VOXEL_SIZE_IN_METRES * (1 << lod); ProfilerShort.Begin("Dual Contouring"); unsafe { fixed (byte* voxels = m_cache.Data) { var size3d = m_cache.Size3D; Debug.Assert(size3d.X == size3d.Y && size3d.Y == size3d.Z); IsoMesher.Calculate(size3d.X, (VoxelData*)voxels, m_buffer); } } ProfilerShort.End(); if (m_buffer.VerticesCount == 0 && m_buffer.Triangles.Count == 0) { return null; } ProfilerShort.Begin("Geometry post-processing"); { var vertexCellOffset = voxelStart - AffectedRangeOffset; var positions = m_buffer.Positions.GetInternalArray(); var vertexCells = m_buffer.Cells.GetInternalArray(); for (int i = 0; i < m_buffer.VerticesCount; i++) { Debug.Assert(positions[i].IsInsideInclusive(ref Vector3.MinusOne, ref Vector3.One)); vertexCells[i] += vertexCellOffset; } double numCellsHalf = 0.5 * (m_cache.Size3D.X - 3); m_buffer.PositionOffset = ((Vector3D)vertexCellOffset + numCellsHalf) * (double)voxelSize; m_buffer.PositionScale = new Vector3((float)(numCellsHalf * voxelSize)); } 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; }
private void AddVoxelMesh(MyVoxelBase voxelBase, IMyStorage storage, Dictionary<Vector3I, MyIsoMesh> cache, float border, Vector3D originPosition, MyOrientedBoundingBoxD obb, List<BoundingBoxD> bbList) { bool useCache = cache != null; if (useCache) CheckCacheValidity(); obb.HalfExtent += new Vector3D(border, 0, border); BoundingBoxD bb = obb.GetAABB(); int aabbSideSide = (int)Math.Round(bb.HalfExtents.Max() * 2); bb = new BoundingBoxD(bb.Min, bb.Min + aabbSideSide); bb.Translate(obb.Center - bb.Center); // For debug bbList.Add(new BoundingBoxD(bb.Min, bb.Max)); bb = (BoundingBoxD)bb.TransformFast(voxelBase.PositionComp.WorldMatrixInvScaled); bb.Translate(voxelBase.SizeInMetresHalf); Vector3I min = Vector3I.Round(bb.Min); Vector3I max = min + aabbSideSide; Vector3I geomMin, geomMax; MyVoxelCoordSystems.VoxelCoordToGeometryCellCoord(ref min, out geomMin); MyVoxelCoordSystems.VoxelCoordToGeometryCellCoord(ref max, out geomMax); var cullBox = obb; cullBox.Transform(voxelBase.PositionComp.WorldMatrixInvScaled); cullBox.Center += voxelBase.SizeInMetresHalf; ProfilerShort.Begin("WOOOORK"); Vector3I_RangeIterator it = new Vector3I_RangeIterator(ref geomMin, ref geomMax); MyCellCoord coord = new MyCellCoord(); BoundingBox localAabb; coord.Lod = NAVMESH_LOD; int hits = 0; MyIsoMesh gMesh; Vector3 offset = originPosition - voxelBase.PositionLeftBottomCorner; // Calculate rotation Vector3 gravityVector = -Vector3.Normalize(GameSystems.MyGravityProviderSystem.CalculateTotalGravityInPoint(originPosition)); Vector3 forwardVector = Vector3.CalculatePerpendicularVector(gravityVector); Quaternion quaternion = Quaternion.CreateFromForwardUp(forwardVector, gravityVector); Matrix rotation = Matrix.CreateFromQuaternion(Quaternion.Inverse(quaternion)); Matrix ownRotation = voxelBase.PositionComp.WorldMatrix.GetOrientation(); while (it.IsValid()) { ProfilerShort.Begin("ITERATOR"); if (useCache && cache.TryGetValue(it.Current, out gMesh)) { if (gMesh != null) { AddMeshTriangles(gMesh, offset, rotation, ownRotation); } it.MoveNext(); ProfilerShort.End(); continue; } coord.CoordInLod = it.Current; MyVoxelCoordSystems.GeometryCellCoordToLocalAABB(ref coord.CoordInLod, out localAabb); if (!cullBox.Intersects(ref localAabb)) { hits++; it.MoveNext(); ProfilerShort.End(); continue; } ProfilerShort.End(); var debugBB = new BoundingBoxD(localAabb.Min, localAabb.Max).Translate(-voxelBase.SizeInMetresHalf); bbList.Add(debugBB); ProfilerShort.Begin("Mesh Calc"); var voxelStart = coord.CoordInLod * MyVoxelConstants.GEOMETRY_CELL_SIZE_IN_VOXELS - 1; var voxelEnd = voxelStart + MyVoxelConstants.GEOMETRY_CELL_SIZE_IN_VOXELS //- 1 + 1 // overlap to neighbor so geometry is stitched together within same LOD + 1; // for eg. 9 vertices in row we need 9 + 1 samples (voxels) var generatedMesh = MyPrecalcComponent.IsoMesher.Precalc(storage, NAVMESH_LOD, voxelStart, voxelEnd, false, false, true); ProfilerShort.End(); if (useCache) cache[it.Current] = generatedMesh; if (generatedMesh != null) { ProfilerShort.Begin("Mesh NOT NULL"); AddMeshTriangles(generatedMesh, offset, rotation, ownRotation); ProfilerShort.End(); } it.MoveNext(); } ProfilerShort.End(); }
public MyIsoMesh Precalc(IMyStorage storage, int lod, Vector3I voxelStart, Vector3I voxelEnd, bool generateMaterials) { // change range so normal can be computed at edges (expand by 1 in all directions) voxelStart -= 1; voxelEnd += 1; m_cache.Resize(voxelStart, voxelEnd); storage.ReadRange(m_cache, MyStorageDataTypeFlags.Content, lod, ref voxelStart, ref voxelEnd); if (!m_cache.ContainsIsoSurface()) { return(null); } if (generateMaterials) { storage.ReadRange(m_cache, MyStorageDataTypeFlags.Material, lod, ref voxelStart, ref voxelEnd); } else { m_cache.ClearMaterials(0); } var voxelSize = MyVoxelConstants.VOXEL_SIZE_IN_METRES * (1 << lod); ProfilerShort.Begin("Dual Contouring"); unsafe { fixed(byte *voxels = m_cache.Data) { var size3d = m_cache.Size3D; Debug.Assert(size3d.X == size3d.Y && size3d.Y == size3d.Z); IsoMesher.Calculate(size3d.X, (VoxelData *)voxels, m_buffer); } } ProfilerShort.End(); if (m_buffer.VerticesCount == 0 && m_buffer.Triangles.Count == 0) { return(null); } ProfilerShort.Begin("Geometry post-processing"); { var vertexCellOffset = voxelStart - AffectedRangeOffset; var positions = m_buffer.Positions.GetInternalArray(); var vertexCells = m_buffer.Cells.GetInternalArray(); for (int i = 0; i < m_buffer.VerticesCount; i++) { var min = -Vector3.One; var max = Vector3.One; // Debug.Assert(positions[i].IsInsideInclusive(ref min, ref max)); vertexCells[i] += vertexCellOffset; } float numCellsHalf = 0.5f * (m_cache.Size3D.X - 3); m_buffer.PositionOffset = (vertexCellOffset + numCellsHalf) * voxelSize; m_buffer.PositionScale = new Vector3(numCellsHalf * voxelSize); } 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); }
internal MyIsoMesh CreateMesh(IMyStorage storage, MyCellCoord coord) { // mk:NOTE This method must be thread safe. Called from worker threads. coord.CoordInLod += m_cellsOffset >> coord.Lod; if (m_voxelMap is MyVoxelPhysics) { var clipmapId = ((MyVoxelPhysics)m_voxelMap).Parent.Render.RenderObjectIDs[0]; var clipmapCellId = MyCellCoord.GetClipmapCellHash(clipmapId, coord.PackId64()); var isoMesh = MyPrecalcJobRender.IsoMeshCache.Read(clipmapCellId); if (isoMesh != null) { return isoMesh; } } var min = coord.CoordInLod << MyVoxelConstants.GEOMETRY_CELL_SIZE_IN_VOXELS_BITS; var max = min + MyVoxelConstants.GEOMETRY_CELL_SIZE_IN_VOXELS; // overlap to neighbor; introduces extra data but it makes logic for raycasts and collisions simpler (no need to check neighbor cells) min -= 1; max += 2; return MyPrecalcComponent.IsoMesher.Precalc(storage, coord.Lod, min, max, false, false); }
internal MyIsoMesh CreateMesh(IMyStorage storage, Vector3I coord) { // mk:NOTE This method must be thread safe. Called from worker threads. coord += m_cellsOffset; var min = coord << MyVoxelConstants.GEOMETRY_CELL_SIZE_IN_VOXELS_BITS; var max = min + MyVoxelConstants.GEOMETRY_CELL_SIZE_IN_VOXELS; // overlap to neighbor; introduces extra data but it makes logic for raycasts and collisions simpler (no need to check neighbor cells) min -= 1; max += 2; return MyPrecalcComponent.IsoMesher.Precalc(storage, 0, min, max, false); }