internal MyVoxelPhysicsBody(MyVoxelMap voxelMap): base(voxelMap, RigidBodyFlag.RBF_STATIC) { m_voxelMap = voxelMap; Vector3I storageSize = m_voxelMap.Size; Vector3I numCels = storageSize >> MyVoxelConstants.GEOMETRY_CELL_SIZE_IN_VOXELS_BITS; m_cellsOffset = m_voxelMap.StorageMin >> MyVoxelConstants.GEOMETRY_CELL_SIZE_IN_VOXELS_BITS; HkUniformGridShape shape = new HkUniformGridShape( new HkUniformGridShapeArgs() { CellsCount = numCels, CellSize = MyVoxelConstants.GEOMETRY_CELL_SIZE_IN_METRES, CellOffset = MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF, CellExpand = MyVoxelConstants.VOXEL_SIZE_IN_METRES, }); shape.SetShapeRequestHandler(RequestShapeBlocking); CreateFromCollisionObject(shape, -m_voxelMap.SizeInMetresHalf, m_voxelMap.WorldMatrix, collisionFilter: MyPhysics.StaticCollisionLayer); shape.Base.RemoveReference(); if (ENABLE_AABB_PHANTOM) { m_aabbPhantom = new Havok.HkpAabbPhantom(new BoundingBox(Vector3.Zero, m_voxelMap.SizeInMetres), 0); m_aabbPhantom.CollidableAdded = AabbPhantom_CollidableAdded; m_aabbPhantom.CollidableRemoved = AabbPhantom_CollidableRemoved; } if (MyFakes.ENABLE_PHYSICS_HIGH_FRICTION) Friction = 0.65f; MaterialType = Sandbox.Common.MyMaterialType.ROCK; }
public MyVoxelPrecalcTaskItem(MyLodTypeEnum type, MyVoxelMap voxelMap, MyVoxelGeometry.CellData cache, Vector3I voxelStart) { Type = type; VoxelMap = voxelMap; Cache = cache; VoxelStart = voxelStart; }
IMyVoxelMap IMyVoxelMaps.CreateVoxelMap(string storageName, IMyStorage storage, Vector3D position,long voxelMapId) { var voxelMap = new MyVoxelMap(); voxelMap.EntityId = voxelMapId; voxelMap.Init(storageName, storage as Sandbox.Engine.Voxels.IMyStorage, position); MyEntities.Add(voxelMap); return voxelMap; }
public void CutVoxelMap(MyVoxelMap voxelMap) { if (voxelMap == null) return; CopyVoxelMap(voxelMap); voxelMap.SyncObject.SendCloseRequest(); Deactivate(); }
public void CopyVoxelMap(MyVoxelMap voxelMap) { if (voxelMap == null) return; m_copiedVoxelMaps.Clear(); m_copiedVoxelMapOffsets.Clear(); CopyVoxelMapInternal(voxelMap); Activate(); }
public void Begin(MyVoxelMap voxelMap, ref Vector3I cellCoord) { VoxelMap = voxelMap; CellCoord = cellCoord; Center = voxelMap.GetRenderCellPositionAbsolute(ref cellCoord) + MyVoxelConstants.RENDER_CELL_SIZE_IN_METRES_HALF; Contains = true; m_positionScale = MyVoxelCacheRender.CellVertexPositionScale; m_positionOffset = MyVoxelCacheRender.CellVertexPositionOffset(ref cellCoord); MyVoxelCacheCellRenderHelper.Begin(); }
public MyVoxelNavigationMesh(MyVoxelMap voxelMap, MyNavmeshCoordinator coordinator, Func<long> timestampFunction) : base(coordinator.Links, 16, timestampFunction) { m_voxelMap = voxelMap; m_cellSize = m_voxelMap.SizeInMetres / m_voxelMap.Storage.Geometry.CellsCount * (1 << NAVMESH_LOD); m_processedCells = new MyVector3ISet(); m_markedForAddition = new MyVector3ISet(); m_toAdd = new MyBinaryStructHeap<float, Vector3I>(128); m_connectionHelper = new MyVoxelConnectionHelper(); m_navmeshCoordinator = coordinator; m_higherLevel = new MyHighLevelGroup(this, coordinator.HighLevelLinks, timestampFunction); m_higherLevelHelper = new MyVoxelHighLevelHelper(this); m_debugCellEdges = new Dictionary<ulong, List<DebugDrawEdge>>(); voxelMap.Storage.RangeChanged += OnStorageChanged; }
public static void PaintInShape( MyVoxelMap voxelMap, MyShape shape, byte materialIdx, bool updateSync = false) { Profiler.Begin("MyVoxelGenerator::PaintInShape()"); if (voxelMap == null) { return; } if (updateSync && Sync.IsServer) { shape.SendPaintRequest(voxelMap.SyncObject, materialIdx); } Vector3I minCorner = voxelMap.GetVoxelCoordinateFromMeters(shape.GetMin()); Vector3I maxCorner = voxelMap.GetVoxelCoordinateFromMeters(shape.GetMax()); voxelMap.FixVoxelCoord(ref minCorner); voxelMap.FixVoxelCoord(ref maxCorner); m_cache.Resize(ref minCorner, ref maxCorner); voxelMap.Storage.ReadRange(m_cache, false, true, MyVoxelGeometry.GetLodIndex(MyLodTypeEnum.LOD0), ref minCorner, ref maxCorner); Vector3I tempVoxelCoord; for (tempVoxelCoord.X = minCorner.X; tempVoxelCoord.X <= maxCorner.X; tempVoxelCoord.X++) for (tempVoxelCoord.Y = minCorner.Y; tempVoxelCoord.Y <= maxCorner.Y; tempVoxelCoord.Y++) for (tempVoxelCoord.Z = minCorner.Z; tempVoxelCoord.Z <= maxCorner.Z; tempVoxelCoord.Z++) { var relPos = tempVoxelCoord - minCorner; m_cache.Material(ref relPos, materialIdx); // set material } Profiler.End(); }
public static MyVoxelCacheCellRender GetCell(MyVoxelMap voxelMap, ref Vector3I renderCellCoord, MyLodTypeEnum cellHashType) { MyVoxelCacheCellRender ret = GetCellFromCache(voxelMap.VoxelMapId, ref renderCellCoord, cellHashType); if (ret == null) { ret = LoadCell(voxelMap, ref renderCellCoord, cellHashType); } if (ret != null) { UpdateCell(voxelMap.VoxelMapId, ref renderCellCoord, cellHashType); } return ret; }
private void RemoveVoxelMap(MyVoxelMap map) { map.Save = true; map.RangeChanged -= m_voxelMap_RangeChangedDelegate; if (m_voxelMaps.ContainsKey(map)) { var item = m_voxelMaps[map]; m_sector.EnableItem(item, false); m_voxelMaps.Remove(map); } else { Debug.Fail("Voxel map was no longer tracked"); } }
void InsertVoxelMap() { MatrixD worldMatrix = MatrixD.CreateWorld(MySector.MainCamera.Position + 25 * MySector.MainCamera.ForwardVector, MySector.MainCamera.ForwardVector, MySector.MainCamera.UpVector); //m_voxelMap = MyWorldGenerator.AddAsteroidPrefab("DeformedSphere2_64x64x64", worldMatrix.Translation, "Test"); string[] vms = new string[] { "small_horse_overhang", //"small_largestone", //"small_mediumstone", "small_overhang_flat", //"small_smallstone" }; Matrix wm = Matrix.CreateRotationX(-MathHelper.PiOver2); // for (int i = 0; i < vms.Length; i++) { // wm.Translation = worldMatrix.Translation; var name = vms[0]; var fileName = MyWorldGenerator.GetVoxelPrefabPath(name); var storage = Sandbox.Engine.Voxels.MyStorageBase.Load(fileName); m_voxelMap = MyWorldGenerator.AddVoxelMap(name, storage, worldMatrix); //m_voxelMap = Sandbox.Game.World.MyWorldGenerator.AddAsteroidPrefab(vms[0], worldMatrix, "Test"); m_voxelMap.IsStaticForCluster = false; // m_voxelMap.WorldMatrix = wm; // worldMatrix.Translation += new Vector3D(100, 0, 0); } }
private void ChangeClipboardPreview(bool visible) { if (m_copiedVoxelMaps.Count == 0 || !visible) { foreach (var voxelMap in m_previewVoxelMaps) { MyEntities.EnableEntityBoundingBoxDraw(voxelMap, false); if (m_shouldMarkForClose) voxelMap.Close(); } m_previewVoxelMaps.Clear(); m_visible = false; return; } MyEntities.RemapObjectBuilderCollection(m_copiedVoxelMaps); for (int i = 0; i < m_copiedVoxelMaps.Count; ++i) { var voxelMapOb = m_copiedVoxelMaps[i]; var storage = m_copiedStorages[i]; MyVoxelBase previewVoxelMap = null; if (voxelMapOb is MyObjectBuilder_VoxelMap) { previewVoxelMap = new MyVoxelMap(); } if (voxelMapOb is MyObjectBuilder_Planet) { m_planetMode = true; IsActive = visible; m_visible = visible; continue; } var pos = voxelMapOb.PositionAndOrientation.Value.Position; previewVoxelMap.Init(voxelMapOb, storage); previewVoxelMap.BeforePaste(); DisablePhysicsRecursively(previewVoxelMap); MakeTransparent(previewVoxelMap); MyEntities.Add(previewVoxelMap); previewVoxelMap.PositionLeftBottomCorner = m_pastePosition - previewVoxelMap.Storage.Size * 0.5f; previewVoxelMap.PositionComp.SetPosition(m_pastePosition); previewVoxelMap.Save = false; m_previewVoxelMaps.Add(previewVoxelMap); IsActive = visible; m_visible = visible; m_shouldMarkForClose = true; } }
private void OnCutAsteroidConfirm(MyVoxelMap targetVoxelMap) { Debug.Assert(targetVoxelMap != null); //Check if entity wasn't deleted by someone else during waiting if (MyEntities.EntityExists(targetVoxelMap.EntityId)) { DeactivateCopyPaste(true); DeactivateCopyPasteFloatingObject(true); targetVoxelMap.SyncObject.SendCloseRequest(); } }
public static MyVoxelMap AddVoxelMap(string storageName, MyStorageBase storage, MatrixD worldMatrix, long entityId=0, bool lazyPhysics = false) { ProfilerShort.Begin("AddVoxelMap"); var voxelMap = new MyVoxelMap(); if (entityId != 0) { voxelMap.EntityId = entityId; } voxelMap.DelayRigidBodyCreation = lazyPhysics; voxelMap.Init(storageName, storage, worldMatrix); MyEntities.Add(voxelMap); MyEntities.RaiseEntityCreated(voxelMap); ProfilerShort.End(); return voxelMap; }
public static void FillInShape( MyVoxelMap voxelMap, MyShape shape, out float voxelsCountInPercent, byte materialIdx, float fillRatio = 1, bool updateSync = false, bool onlyCheck = false) { Profiler.Begin("MyVoxelGenerator::FillInShape()"); if (voxelMap == null) { voxelsCountInPercent = 0f; return; } if (updateSync && Sync.IsServer) { shape.SendFillRequest(voxelMap.SyncObject, materialIdx, fillRatio); } int originalSum = 0; int filledSum = 0; Vector3I minCorner = voxelMap.GetVoxelCoordinateFromMeters(shape.GetMin() - MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF * 1.01f); Vector3I maxCorner = voxelMap.GetVoxelCoordinateFromMeters(shape.GetMax() + MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF * 1.01f); voxelMap.FixVoxelCoord(ref minCorner); voxelMap.FixVoxelCoord(ref maxCorner); m_cache.Resize(ref minCorner, ref maxCorner); voxelMap.Storage.ReadRange(m_cache, true, true, MyVoxelGeometry.GetLodIndex(MyLodTypeEnum.LOD0), ref minCorner, ref maxCorner); Vector3I tempVoxelCoord; for (tempVoxelCoord.X = minCorner.X; tempVoxelCoord.X <= maxCorner.X; tempVoxelCoord.X++) for (tempVoxelCoord.Y = minCorner.Y; tempVoxelCoord.Y <= maxCorner.Y; tempVoxelCoord.Y++) for (tempVoxelCoord.Z = minCorner.Z; tempVoxelCoord.Z <= maxCorner.Z; tempVoxelCoord.Z++) { var relPos = tempVoxelCoord - minCorner; // get original amount var original = m_cache.Content(ref relPos); if (original == MyVoxelConstants.VOXEL_CONTENT_FULL) // if there is nothing to add continue; var vpos = voxelMap.GetVoxelPositionAbsolute(ref tempVoxelCoord); var volume = shape.GetVolume(ref vpos); if (volume <= 0f) // there is nothing to fill continue; m_cache.Material(ref relPos, materialIdx); // set material var maxFill = (int)(volume * MyVoxelConstants.VOXEL_CONTENT_FULL); var toFill = (int)(maxFill * fillRatio); if (original > maxFill) maxFill = original; var newVal = MathHelper.Clamp(original + toFill, 0, maxFill); if (!onlyCheck) m_cache.Content(ref relPos, (byte)newVal); originalSum += original; filledSum += original + newVal; } if (filledSum > 0 && !onlyCheck) { voxelMap.Storage.WriteRange(m_cache, true, true, ref minCorner, ref maxCorner); voxelMap.InvalidateCache(minCorner - 1, maxCorner + 1); } voxelsCountInPercent = (originalSum > 0f) ? (float)filledSum / (float)originalSum : 0f; Profiler.End(); }
private void MakeVisible(MyVoxelMap voxelMap) { voxelMap.Render.Transparency = 0f; }
private void MakeTransparent(MyVoxelMap voxelMap) { voxelMap.Render.Transparency = MyGridConstants.BUILDER_TRANSPARENCY; }
private void CopyVoxelMapInternal(MyVoxelMap toCopy) { m_copiedVoxelMaps.Add((MyObjectBuilder_VoxelMap)toCopy.GetObjectBuilder(true)); if (m_copiedVoxelMaps.Count == 1) { MatrixD pasteMatrix = GetPasteMatrix(); Vector3D dragPointGlobal = toCopy.WorldMatrix.Translation; m_dragPointToPositionLocal = Vector3D.TransformNormal(toCopy.PositionComp.GetPosition() - dragPointGlobal, toCopy.PositionComp.WorldMatrixNormalizedInv); m_dragDistance = (float)(dragPointGlobal - pasteMatrix.Translation).Length(); } m_copiedVoxelMapOffsets.Add(toCopy.WorldMatrix.Translation - m_copiedVoxelMaps[0].PositionAndOrientation.Value.Position); }
private static MyVoxelCacheCellRender LoadCell(MyVoxelMap voxelMap, ref Vector3I renderCellCoord, MyLodTypeEnum cellHashType) { Profiler.Begin("AddCell"); MyVoxelCacheCellRender ret = AddCell(voxelMap.VoxelMapId, ref renderCellCoord, cellHashType); ret.Begin(voxelMap, ref renderCellCoord); ret.CellHashType = cellHashType; Profiler.End(); if (cellHashType == MyLodTypeEnum.LOD0) { Profiler.Begin("LOD0 - queue cells"); m_dataCellsQueue.Clear(); // Create normal (LOD0) version for (int dataX = 0; dataX < MyVoxelConstants.RENDER_CELL_SIZE_IN_GEOMETRY_CELLS; dataX++) { for (int dataY = 0; dataY < MyVoxelConstants.RENDER_CELL_SIZE_IN_GEOMETRY_CELLS; dataY++) { for (int dataZ = 0; dataZ < MyVoxelConstants.RENDER_CELL_SIZE_IN_GEOMETRY_CELLS; dataZ++) { // Don't precalculate this cells now. Store it in queue and calculate all cells at once by MyVoxelPrecalc.PrecalcQueue() Vector3I dataCellCoord = new Vector3I( renderCellCoord.X * MyVoxelConstants.RENDER_CELL_SIZE_IN_GEOMETRY_CELLS + dataX, renderCellCoord.Y * MyVoxelConstants.RENDER_CELL_SIZE_IN_GEOMETRY_CELLS + dataY, renderCellCoord.Z * MyVoxelConstants.RENDER_CELL_SIZE_IN_GEOMETRY_CELLS + dataZ); MyVoxelGeometry.CellData cachedDataCell = voxelMap.Geometry.GetCellLater(MyLodTypeEnum.LOD0, ref dataCellCoord); if (cachedDataCell != null) { m_dataCellsQueue.Add(cachedDataCell); } } } } Profiler.BeginNextBlock("LOD0 - PrecalcQueue"); // Precalculate all queued data cells in parallel threads - using multiple cores if possible. MyVoxelPrecalc.PrecalcQueue(); Profiler.BeginNextBlock("LOD0 - AddTriangles"); ret.AddTriangles(m_dataCellsQueue); Profiler.End(); } else if (cellHashType == MyLodTypeEnum.LOD1) { Profiler.Begin("LOD1 - PrecalcImmediatelly"); m_helperLodCachedDataCell.Reset(); // Create LOD1 render cell MyVoxelPrecalc.PrecalcImmediatelly( new MyVoxelPrecalcTaskItem( MyLodTypeEnum.LOD1, voxelMap, m_helperLodCachedDataCell, new Vector3I( renderCellCoord.X * MyVoxelConstants.RENDER_CELL_SIZE_IN_GEOMETRY_CELLS, renderCellCoord.Y * MyVoxelConstants.RENDER_CELL_SIZE_IN_GEOMETRY_CELLS, renderCellCoord.Z * MyVoxelConstants.RENDER_CELL_SIZE_IN_GEOMETRY_CELLS))); Profiler.BeginNextBlock("LOD1 - AddTriangles"); m_dataCellsQueue.Clear(); m_dataCellsQueue.Add(m_helperLodCachedDataCell); ret.AddTriangles(m_dataCellsQueue); Profiler.End(); } else { throw new InvalidBranchException(); } ret.End(); return ret; }
static void SpawnAsteroidConfirmedSuccess(ref SpawnAsteroidConfirmedMsg msg, MyNetworkClient sender) { MyStorageBase storage; SpawnAsteroidMsg asteroid = msg.AsteroidDetails; string storageName; using (MyRandom.Instance.PushSeed(asteroid.RandomSeed)) { if (!asteroid.IsProcedural) { var storageNameBase = asteroid.StorageName ?? (asteroid.Asteroid + "-" + asteroid.RandomSeed); storageName = MakeStorageName(storageNameBase); storage = CreateAsteroidStorage(asteroid.Asteroid, asteroid.RandomSeed); } else { var storageNameBase = asteroid.StorageName ?? "ProcAsteroid" + "-" + asteroid.RandomSeed + "r" + asteroid.ProceduralRadius; storageName = MakeStorageName(storageNameBase); storage = CreateProceduralAsteroidStorage(asteroid.RandomSeed, asteroid.ProceduralRadius, 0.03f); } } var pastedVoxelMap = new MyVoxelMap(); pastedVoxelMap.EntityId = msg.EntityId; pastedVoxelMap.Init(storageName, storage, asteroid.Position - storage.Size * 0.5f); MyEntities.Add(pastedVoxelMap); }
// Remove cell - after voxels were changed, etc. public static void RemoveCell(MyVoxelMap voxelMap, ref Vector3I cellCoord, MyLodTypeEnum cellHashType) { Int64 key = MySession.Static.VoxelMaps.GetCellHashCode(voxelMap.VoxelMapId, ref cellCoord, cellHashType); // If cell is in cache, we remove it from dictionary and move it to the beginning of priority linked list LinkedListNode<MyVoxelCacheCellRender> ret; if (m_cellsByCoordinate.TryGetValue(key, out ret) == true) { m_cellsByCoordinate.Remove(key); ret.Value.Reset(); // Move it to the beginning of priority linked list Debug.Assert(Thread.CurrentThread == MySandboxGame.Static.UpdateThread); m_priority.Remove(ret); m_priority.AddFirst(ret); VRageRender.MyRenderProxy.InvalidateRenderVoxelCell(voxelMap.GetRenderObjectID(ref cellCoord), (VRageRender.MyLodTypeEnum)(int)cellHashType); } }
public static void MakeCrater(MyVoxelMap voxelMap, BoundingSphere sphere, Vector3 normal, MyVoxelMaterialDefinition material, ref bool changed, out Vector3I minChanged, out Vector3I maxChanged) { Profiler.Begin("MakeCrater"); Vector3I minCorner = voxelMap.GetVoxelCoordinateFromMeters(sphere.Center - (sphere.Radius + MyVoxelConstants.VOXEL_SIZE_IN_METRES)); Vector3I maxCorner = voxelMap.GetVoxelCoordinateFromMeters(sphere.Center + (sphere.Radius + MyVoxelConstants.VOXEL_SIZE_IN_METRES)); voxelMap.FixVoxelCoord(ref minCorner); voxelMap.FixVoxelCoord(ref maxCorner); // We are tracking which voxels were changed, so we can invalidate only needed cells in the cache minChanged = maxCorner; maxChanged = minCorner; Profiler.Begin("Reading cache"); m_cache.Resize(ref minCorner, ref maxCorner); voxelMap.Storage.ReadRange(m_cache, true, true, MyVoxelGeometry.GetLodIndex(MyLodTypeEnum.LOD0), ref minCorner, ref maxCorner); Profiler.End(); Profiler.Begin("Changing cache"); int removedVoxelContent = 0; Vector3I tempVoxelCoord; Vector3I cachePos; for (tempVoxelCoord.Z = minCorner.Z, cachePos.Z = 0; tempVoxelCoord.Z <= maxCorner.Z; tempVoxelCoord.Z++, ++cachePos.Z) { for (tempVoxelCoord.Y = minCorner.Y, cachePos.Y = 0; tempVoxelCoord.Y <= maxCorner.Y; tempVoxelCoord.Y++, ++cachePos.Y) { for (tempVoxelCoord.X = minCorner.X, cachePos.X = 0; tempVoxelCoord.X <= maxCorner.X; tempVoxelCoord.X++, ++cachePos.X) { bool cellChanged = false; Vector3 voxelPosition = voxelMap.GetVoxelPositionAbsolute(ref tempVoxelCoord); float addDist = (voxelPosition - sphere.Center).Length(); float addDiff = addDist - sphere.Radius; byte newContent; if (addDiff > MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF) { newContent = MyVoxelConstants.VOXEL_CONTENT_EMPTY; } else if (addDiff < -MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF) { newContent = MyVoxelConstants.VOXEL_CONTENT_FULL; } else { // This formula will work even if diff is positive or negative newContent = (byte)(MyVoxelConstants.VOXEL_ISO_LEVEL - addDiff / MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF * MyVoxelConstants.VOXEL_ISO_LEVEL); } byte originalContent = m_cache.Content(ref cachePos); if (newContent > originalContent && originalContent > 0) { if (material != null) { m_cache.Material(ref cachePos, material.Index); } cellChanged = true; m_cache.Content(ref cachePos, newContent); } float delDist = (voxelPosition - (sphere.Center + sphere.Radius * 0.7f * normal)).Length(); float delDiff = delDist - sphere.Radius; byte contentToRemove; if (delDiff > MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF) { contentToRemove = MyVoxelConstants.VOXEL_CONTENT_EMPTY; } else if (delDiff < -MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF) { contentToRemove = MyVoxelConstants.VOXEL_CONTENT_FULL; } else { // This formula will work even if diff is positive or negative contentToRemove = (byte)(MyVoxelConstants.VOXEL_ISO_LEVEL - delDiff / MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF * MyVoxelConstants.VOXEL_ISO_LEVEL); } originalContent = m_cache.Content(ref cachePos); if (originalContent > MyVoxelConstants.VOXEL_CONTENT_EMPTY && contentToRemove > MyVoxelConstants.VOXEL_CONTENT_EMPTY) { cellChanged = true; int newVal = originalContent - contentToRemove; if (newVal < MyVoxelConstants.VOXEL_CONTENT_EMPTY) newVal = MyVoxelConstants.VOXEL_CONTENT_EMPTY; m_cache.Content(ref cachePos, (byte)newVal); removedVoxelContent += originalContent - newVal; } float setDist = (voxelPosition - (sphere.Center - sphere.Radius * 0.5f * normal)).Length(); float setDiff = setDist - sphere.Radius / 4f; if (setDiff <= MyVoxelConstants.VOXEL_SIZE_IN_METRES * 1.5f) // could be VOXEL_SIZE_IN_METRES_HALF, but we want to set material in empty cells correctly { byte indestructibleContentToSet = MyVoxelConstants.VOXEL_CONTENT_FULL; if (setDiff >= MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF) // outside { indestructibleContentToSet = MyVoxelConstants.VOXEL_CONTENT_EMPTY; } else if (setDiff >= -MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF) // boundary { indestructibleContentToSet = (byte)(MyVoxelConstants.VOXEL_ISO_LEVEL - setDiff / MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF * MyVoxelConstants.VOXEL_ISO_LEVEL); } MyVoxelMaterialDefinition originalMaterial = MyDefinitionManager.Static.GetVoxelMaterialDefinition(m_cache.Material(ref cachePos)); // Change the material: // - always on boundaries between material and nothing // - smoothly on inner boundaries MyVoxelMaterialDefinition newMaterial = material; if (setDiff > 0) { byte content = m_cache.Content(ref cachePos); if (content == MyVoxelConstants.VOXEL_CONTENT_FULL) newMaterial = originalMaterial; if (setDiff >= MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF && content != MyVoxelConstants.VOXEL_CONTENT_EMPTY) // set material behind boundary only for empty voxels newMaterial = originalMaterial; } if (originalMaterial == newMaterial) { continue; } m_cache.Material(ref cachePos, newMaterial.Index); cellChanged = true; } float dist = (voxelPosition - sphere.Center).Length(); float diff = dist - sphere.Radius; if (diff <= 0f) { originalContent = m_cache.Content(ref cachePos); if (originalContent > MyVoxelConstants.VOXEL_CONTENT_EMPTY) { bool result = m_cache.WrinkleVoxelContent(ref cachePos, MyVoxelConstants.DEFAULT_WRINKLE_WEIGHT_ADD, MyVoxelConstants.DEFAULT_WRINKLE_WEIGHT_REMOVE); if (cellChanged == false) cellChanged = result; } } if (cellChanged) { if (tempVoxelCoord.X < minChanged.X) minChanged.X = tempVoxelCoord.X; if (tempVoxelCoord.Y < minChanged.Y) minChanged.Y = tempVoxelCoord.Y; if (tempVoxelCoord.Z < minChanged.Z) minChanged.Z = tempVoxelCoord.Z; if (tempVoxelCoord.X > maxChanged.X) maxChanged.X = tempVoxelCoord.X; if (tempVoxelCoord.Y > maxChanged.Y) maxChanged.Y = tempVoxelCoord.Y; if (tempVoxelCoord.Z > maxChanged.Z) maxChanged.Z = tempVoxelCoord.Z; changed = true; } } } } Profiler.End(); if (changed) { Profiler.Begin("RemoveSmallVoxelsUsingChachedVoxels"); RemoveSmallVoxelsUsingChachedVoxels(); Profiler.BeginNextBlock("Writing cache"); voxelMap.Storage.WriteRange(m_cache, true, true, ref minCorner, ref maxCorner); Profiler.End(); } Profiler.End(); }
// Remove cell for voxels specified be min/max corner. Used after explosion when we want to remove a lot of voxels/cell from cache. // This is efficient method, because it doesn't invalidate cache after every voxel change. // Method knows that adjacent cells need to be removed too (because of MCA), so it invalidates them too. public static void RemoveCellForVoxels(MyVoxelMap voxelMap, Vector3I minVoxel, Vector3I maxVoxel) { // Calculate voxel for boundary things... minVoxel -= MyVoxelPrecalc.InvalidatedRangeInflate; maxVoxel += MyVoxelPrecalc.InvalidatedRangeInflate; if (maxVoxel.X > voxelMap.SizeMinusOne.X) maxVoxel.X = voxelMap.SizeMinusOne.X; if (maxVoxel.Y > voxelMap.SizeMinusOne.Y) maxVoxel.Y = voxelMap.SizeMinusOne.Y; if (maxVoxel.Z > voxelMap.SizeMinusOne.Z) maxVoxel.Z = voxelMap.SizeMinusOne.Z; // Min/max cell Vector3I minCell = voxelMap.GetVoxelRenderCellCoordinate(ref minVoxel); Vector3I maxCell = voxelMap.GetVoxelRenderCellCoordinate(ref maxVoxel); // Invalidate cells Vector3I tempCellCoord; for (tempCellCoord.X = minCell.X; tempCellCoord.X <= maxCell.X; tempCellCoord.X++) { for (tempCellCoord.Y = minCell.Y; tempCellCoord.Y <= maxCell.Y; tempCellCoord.Y++) { for (tempCellCoord.Z = minCell.Z; tempCellCoord.Z <= maxCell.Z; tempCellCoord.Z++) { RemoveCell(voxelMap, ref tempCellCoord, MyLodTypeEnum.LOD0); RemoveCell(voxelMap, ref tempCellCoord, MyLodTypeEnum.LOD1); } } } }
public static void CutOutShape( MyVoxelMap voxelMap, MyShape shape, out float voxelsCountInPercent, out MyVoxelMaterialDefinition voxelMaterial, float removeRatio = 1, Dictionary<MyVoxelMaterialDefinition, int> exactCutOutMaterials = null, bool updateSync = true, bool onlyCheck = false) { Profiler.Begin("MyVoxelGenerator::CutOutShape()"); if (updateSync && Sync.IsServer) { shape.SendCutOutRequest(voxelMap.SyncObject, removeRatio); } int originalSum = 0; int removedSum = 0; Vector3I minCorner = voxelMap.GetVoxelCoordinateFromMeters(shape.GetMin()); Vector3I maxCorner = voxelMap.GetVoxelCoordinateFromMeters(shape.GetMax()); voxelMap.FixVoxelCoord(ref minCorner); voxelMap.FixVoxelCoord(ref maxCorner); var cacheMin = minCorner - 1; var cacheMax = maxCorner + 1; voxelMap.FixVoxelCoord(ref cacheMin); voxelMap.FixVoxelCoord(ref cacheMax); m_cache.Resize(ref cacheMin, ref cacheMax); voxelMap.Storage.ReadRange(m_cache, true, true, MyVoxelGeometry.GetLodIndex(MyLodTypeEnum.LOD0), ref cacheMin, ref cacheMax); { Vector3I exactCenter = voxelMap.GetVoxelCoordinateFromMeters(shape.GetCenter()); exactCenter -= cacheMin; exactCenter = Vector3I.Clamp(exactCenter, Vector3I.Zero, m_cache.Size3D-1); voxelMaterial = MyDefinitionManager.Static.GetVoxelMaterialDefinition(m_cache.Material(ref exactCenter)); } Vector3I tempVoxelCoord; for (tempVoxelCoord.X = minCorner.X; tempVoxelCoord.X <= maxCorner.X; tempVoxelCoord.X++) for (tempVoxelCoord.Y = minCorner.Y; tempVoxelCoord.Y <= maxCorner.Y; tempVoxelCoord.Y++) for (tempVoxelCoord.Z = minCorner.Z; tempVoxelCoord.Z <= maxCorner.Z; tempVoxelCoord.Z++) { var relPos = tempVoxelCoord - cacheMin; // get original amount var original = m_cache.Content(ref relPos); if (original == MyVoxelConstants.VOXEL_CONTENT_EMPTY) // if there is nothing to remove continue; var vpos = voxelMap.GetVoxelPositionAbsolute(ref tempVoxelCoord); var volume = shape.GetVolume(ref vpos); if (volume == 0f) // if there is no intersection continue; var maxRemove = (int)(volume * MyVoxelConstants.VOXEL_CONTENT_FULL); var voxelMat = MyDefinitionManager.Static.GetVoxelMaterialDefinition(m_cache.Material(ref relPos)); var toRemove = (int)(maxRemove * removeRatio * voxelMat.DamageRatio); if (voxelMap.Storage is MyCellStorage) { if (toRemove < MyCellStorage.Quantizer.GetMinimumQuantizableValue()) toRemove = MyCellStorage.Quantizer.GetMinimumQuantizableValue(); } var newVal = MathHelper.Clamp(original - toRemove, 0, maxRemove); var removed = Math.Abs(original - newVal); if (!onlyCheck) m_cache.Content(ref relPos, (byte)newVal); originalSum += original; removedSum += removed; 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 (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(); voxelMap.Storage.WriteRange(m_cache, true, false, ref cacheMin, ref cacheMax); voxelMap.InvalidateCache(cacheMin, cacheMax); } voxelsCountInPercent = (originalSum > 0f) ? (float)removedSum / (float)originalSum : 0f; Profiler.End(); }
/// <summary> /// Adds the vertices from the physical body (rock) that is inside the given OBB /// </summary> /// <param name="voxelMap"></param> /// <param name="border"></param> /// <param name="originPosition"></param> /// <param name="obb"></param> /// <param name="bbList"></param> private void AddVoxelVertices(MyVoxelMap voxelMap, float border, Vector3D originPosition, MyOrientedBoundingBoxD obb, List<BoundingBoxD> bbList) { AddVoxelMesh(voxelMap, voxelMap.Storage, null, border, originPosition, obb, bbList); }
public static MyVoxelMap AddVoxelMap(string storageName, MyStorageBase storage, Vector3 positionMinCorner, long entityId = 0) { var voxelMap = new MyVoxelMap(); voxelMap.EntityId = entityId; voxelMap.Init(storageName, storage, positionMinCorner); MyEntities.Add(voxelMap); return voxelMap; }
/// <summary> /// Finds closest object (grid or voxel map) for placement of blocks . /// </summary> public bool FindClosestPlacementObject(out MyCubeGrid closestGrid, out MyVoxelMap closestVoxelMap) { closestGrid = null; closestVoxelMap = null; if (MySession.ControlledEntity == null) return false; m_hitInfo = null; LineD line = new LineD(IntersectionStart, IntersectionStart + IntersectionDirection * IntersectionDistance); MyPhysics.CastRay(line.From, line.To, m_tmpHitList, MyPhysics.ObjectDetectionCollisionLayer); // Remove character hits. m_tmpHitList.RemoveAll(delegate(MyPhysics.HitInfo hitInfo) { return (hitInfo.HkHitInfo.GetHitEntity() == MySession.ControlledEntity.Entity); }); if (m_tmpHitList.Count == 0) return false; var hit = m_tmpHitList[0]; closestGrid = hit.HkHitInfo.GetHitEntity() as MyCubeGrid; if (closestGrid != null) { m_hitInfo = hit; } if (MyFakes.ENABLE_BLOCK_PLACEMENT_ON_VOXEL) { closestVoxelMap = hit.HkHitInfo.GetHitEntity() as MyVoxelMap; if (closestVoxelMap != null) m_hitInfo = hit; } return closestGrid != null || closestVoxelMap != null; }
private void RegisterVoxelMap(int item, MyVoxelMap voxelMap) { voxelMap.Save = false; voxelMap.RangeChanged += m_voxelMap_RangeChangedDelegate; m_voxelMaps[voxelMap] = item; MyEntityReferenceComponent component; if (!voxelMap.Components.TryGet(out component)) { voxelMap.Components.Add(component = new MyEntityReferenceComponent()); } DisableOtherItemsInVMap(voxelMap); component.Ref(); }
static void SpawnAsteroid(SpawnAsteroidInfo asteroidInfo) { if (MySession.Static.CreativeMode || MyEventContext.Current.IsLocallyInvoked || MySession.Static.HasPlayerAdminRights(MyEventContext.Current.Sender.Value)) { MyStorageBase storage; string storageName; using (MyRandom.Instance.PushSeed(asteroidInfo.RandomSeed)) { if (!asteroidInfo.IsProcedural) { var storageNameBase = asteroidInfo.Asteroid + "-" + asteroidInfo.RandomSeed; storageName = MakeStorageName(storageNameBase); storage = CreateAsteroidStorage(asteroidInfo.Asteroid, asteroidInfo.RandomSeed); } else { var storageNameBase = "ProcAsteroid" + "-" + asteroidInfo.RandomSeed + "r" + asteroidInfo.ProceduralRadius; storageName = MakeStorageName(storageNameBase); storage = CreateProceduralAsteroidStorage(asteroidInfo.RandomSeed, asteroidInfo.ProceduralRadius, 0.03f); } } var pastedVoxelMap = new MyVoxelMap(); pastedVoxelMap.CreatedByUser = true; pastedVoxelMap.Save = true; pastedVoxelMap.AsteroidName = asteroidInfo.Asteroid; pastedVoxelMap.Init(storageName, storage, asteroidInfo.Position - storage.Size * 0.5f); MyEntities.Add(pastedVoxelMap); MyEntities.RaiseEntityCreated(pastedVoxelMap); } }
public void SetTargetVoxel(Vector3D pos, MyVoxelMap voxelMap) { UnsetTarget(); MyVoxelCoordSystems.WorldPositionToVoxelCoord(voxelMap.PositionLeftBottomCorner, ref pos, out m_targetInVoxelCoord); SetMTargetPosition(pos); m_currentTarget = MyAiTargetEnum.VOXEL; }