public override void Apply() { MyPlanetGeneratorDefinition planetDefinition = MyDefinitionManager.Static.GetDefinition <MyPlanetGeneratorDefinition>(MyStringHash.GetOrCompute(DefinitionName)); if (planetDefinition == null) { string message = String.Format("Definition for planet {0} could not be found. Skipping.", DefinitionName); Debug.Fail(message); MyLog.Default.WriteLine(message); return; } Vector3D position = PositionMinCorner; if (PositionCenter.IsValid()) { position = PositionCenter; var size = MyVoxelCoordSystems.FindBestOctreeSize(Diameter * (1 + planetDefinition.HillParams.Max)); position -= ((Vector3D)size) / 2; } int seed = MyRandom.Instance.Next(); var storageNameBase = DefinitionName + "-" + seed + "d" + Diameter; MyWorldGenerator.CreatePlanet(storageNameBase, planetDefinition.FolderName, ref position, seed, Diameter, MyRandom.Instance.NextLong(), ref planetDefinition, AddGPS); }
public void SetTargetVoxel(Vector3D pos, MyVoxelMap voxelMap) { this.UnsetTarget(); MyVoxelCoordSystems.WorldPositionToVoxelCoord(voxelMap.PositionLeftBottomCorner, ref pos, out this.m_targetInVoxelCoord); this.SetMTargetPosition(pos); this.m_currentTarget = MyAiTargetEnum.VOXEL; }
private int GetDivideIndex(ref Vector3I renderCellCoord) { // TODO: Optimize int divideIndex = 0; if (m_lodDivisions > 1) { BoundingBoxD lodAabb = m_boundingBoxes.GetAabb(m_boundingBoxes.GetRoot()); Vector3I test = Vector3I.Round(lodAabb.Size / (double)MyVoxelCoordSystems.RenderCellSizeInMeters(m_lod)); //Vector3I lodSizeMinusOne = m_parentClipmap.LodSizeMinusOne(m_lod); //Vector3I lodSize = lodSizeMinusOne + Vector3I.One; Vector3I lodSize = test; Vector3I lodSizeMinusOne = test - 1; Vector3I lodDivision = Vector3I.One * (m_lodDivisions - 1); var cellIterator = new Vector3I.RangeIterator(ref Vector3I.Zero, ref lodDivision); for (; cellIterator.IsValid(); cellIterator.MoveNext()) { Vector3I currentDivision = cellIterator.Current; Vector3I min = currentDivision * lodSize / m_lodDivisions; Vector3I max = (currentDivision + Vector3I.One) * lodSize / m_lodDivisions; if (renderCellCoord.IsInsideInclusive(ref min, ref max)) { break; } } Debug.Assert(cellIterator.IsValid(), "Valid division index not found!"); Vector3I foundCell = cellIterator.Current; divideIndex = GetDivideIndexFromMergeCell(ref foundCell); } return(divideIndex); }
public void InvalidateRange(Vector3I minVoxelChanged, Vector3I maxVoxelChanged) { minVoxelChanged -= MyPrecalcComponent.InvalidatedRangeInflate; maxVoxelChanged += MyPrecalcComponent.InvalidatedRangeInflate; m_voxelMap.Storage.ClampVoxelCoord(ref minVoxelChanged); m_voxelMap.Storage.ClampVoxelCoord(ref maxVoxelChanged); Vector3I minCell, maxCell; MyVoxelCoordSystems.VoxelCoordToGeometryCellCoord(ref minVoxelChanged, out minCell); MyVoxelCoordSystems.VoxelCoordToGeometryCellCoord(ref maxVoxelChanged, out maxCell); Vector3I currentCell = minCell; for (var it = new Vector3I.RangeIterator(ref minCell, ref maxCell); it.IsValid(); it.GetNext(out currentCell)) { if (m_processedCells.Contains(ref currentCell)) { RemoveCell(currentCell); } MyCellCoord coord = new MyCellCoord(NAVMESH_LOD, currentCell); m_higherLevelHelper.TryClearCell(coord.PackId64()); } }
internal void InvalidateAll() { MyRenderProxy.InvalidateClipmapRange(m_renderObjectIDs[0], Vector3I.Zero, (m_voxelMap.Storage.Size - 1) >> MyVoxelCoordSystems.RenderCellSizeInLodVoxelsShift(0)); m_renderWorkTracker.InvalidateAll(); }
public override bool Invoke(ulong steamId, long playerId, string messageText) { var currentPlanetList = new List <IMyVoxelBase>(); MyAPIGateway.Session.VoxelMaps.GetInstances(currentPlanetList, v => v is Sandbox.Game.Entities.MyPlanet); Vector3D playerPosition = MyAPIGateway.Session.Player.GetPosition(); var closestDistance = Double.MaxValue; Sandbox.Game.Entities.MyPlanet closestPlanet = null; foreach (var planet in currentPlanetList) { var center = planet.WorldMatrix.Translation; var distance = Vector3D.Distance(playerPosition, center); // use distance to center of planet. if (distance < closestDistance) { closestPlanet = (Sandbox.Game.Entities.MyPlanet)planet; closestDistance = distance; } } if (closestPlanet != null) { if (messageText.StartsWith("/laserup", StringComparison.InvariantCultureIgnoreCase) || messageText.StartsWith("/up", StringComparison.InvariantCultureIgnoreCase)) { var v1 = closestPlanet.WorldMatrix.Translation - playerPosition; v1.Normalize(); var gps = MyAPIGateway.Session.GPS.Create("Laser Up", "", playerPosition + (v1 * -1000), true, false); MyAPIGateway.Session.GPS.AddGps(MyAPIGateway.Session.Player.IdentityId, gps); } if (messageText.StartsWith("/laserdown", StringComparison.InvariantCultureIgnoreCase) || messageText.StartsWith("/down", StringComparison.InvariantCultureIgnoreCase)) { var v1 = closestPlanet.WorldMatrix.Translation - playerPosition; v1.Normalize(); var gps = MyAPIGateway.Session.GPS.Create("Laser Down", "", playerPosition + (v1 * 1000), true, false); MyAPIGateway.Session.GPS.AddGps(MyAPIGateway.Session.Player.IdentityId, gps); Vector3D closestSurfacePoint; MyVoxelCoordSystems.WorldPositionToLocalPosition(closestPlanet.PositionLeftBottomCorner, ref playerPosition, out closestSurfacePoint); var groundPosition = closestPlanet.GetClosestSurfacePointGlobal(ref closestSurfacePoint); //closestPlanet.getgrav //var d = Vector3D.Distance(playerPosition, groundPosition); gps = MyAPIGateway.Session.GPS.Create("Laser Ground", "", groundPosition, true, false); MyAPIGateway.Session.GPS.AddGps(MyAPIGateway.Session.Player.IdentityId, gps); } return(true); } MyAPIGateway.Utilities.ShowMessage("Range", "No planets detected in range."); return(true); }
public static void PaintInShape(MyVoxelBase voxelMap, MyShape shape, byte materialIdx) { Vector3I minCorner, maxCorner, numCells; GetVoxelShapeDimensions(voxelMap, shape, out minCorner, out maxCorner, out numCells); 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); m_cache.Resize(cellMinCorner, cellMaxCorner); voxelMap.Storage.ReadRange(m_cache, MyStorageDataTypeFlags.Material, 0, ref cellMinCorner, ref cellMaxCorner); for (var it = new Vector3I_RangeIterator(ref cellMinCorner, ref cellMaxCorner); it.IsValid(); it.MoveNext()) { var relPos = it.Current - cellMinCorner; Vector3D vpos; MyVoxelCoordSystems.VoxelCoordToWorldPosition(voxelMap.PositionLeftBottomCorner, ref it.Current, out vpos); float volume = shape.GetVolume(ref vpos); if (volume > 0.5f) { m_cache.Material(ref relPos, materialIdx); // set material } } voxelMap.Storage.WriteRange(m_cache, MyStorageDataTypeFlags.Material, ref cellMinCorner, ref cellMaxCorner); } }
/// <summary> /// Checks only immediate children (any deeper would take too long). /// </summary> private static bool ChildrenWereLoaded(LodLevel childLod, ref MyCellCoord thisLodCell) { if (childLod == null) { return(false); } Debug.Assert(thisLodCell.Lod == childLod.m_lodIndex + 1); var childLodCell = new MyCellCoord(); childLodCell.Lod = childLod.m_lodIndex; var shiftToChild = MyVoxelCoordSystems.RenderCellSizeShiftToMoreDetailed(thisLodCell.Lod); var start = thisLodCell.CoordInLod << shiftToChild; var end = start + ((1 << shiftToChild) >> 1); Vector3I.Max(ref childLod.m_lodSizeMinusOne, ref Vector3I.Zero, out childLod.m_lodSizeMinusOne); Vector3I.Min(ref end, ref childLod.m_lodSizeMinusOne, out end); childLodCell.CoordInLod = start; for (var it = new Vector3I_RangeIterator(ref start, ref end); it.IsValid(); it.GetNext(out childLodCell.CoordInLod)) { var key = childLodCell.PackId64(); MyClipmap_CellData data; if (!childLod.m_storedCellData.TryGetValue(key, out data) || !data.WasLoaded) { return(false); } } return(true); }
public void RemoveTooFarCells(List <Vector3D> importantPositions, float maxDistance, MyVector3ISet processedCells) { // remove too far high level info (if it isn't in processed cells) m_removedHLpackedCoord.Clear(); foreach (var cell in m_exploredCells) { Vector3D worldCellCenterPos; Vector3I cellPos = cell; MyVoxelCoordSystems.GeometryCellCenterCoordToWorldPos(m_mesh.VoxelMapReferencePosition, ref cellPos, out worldCellCenterPos); // finding of distance from the nearest important object float dist = float.PositiveInfinity; foreach (Vector3D vec in importantPositions) { float d = Vector3.RectangularDistance(vec, worldCellCenterPos); if (d < dist) { dist = d; } } if (dist > maxDistance && !processedCells.Contains(cellPos)) { MyCellCoord coord = new MyCellCoord(MyVoxelNavigationMesh.NAVMESH_LOD, cellPos); m_removedHLpackedCoord.Add(coord.PackId64()); } } foreach (ulong coord in m_removedHLpackedCoord) { TryClearCell(coord); } }
/// <summary> /// Checks ancestor nodes recursively. /// </summary> private static bool WasAncestorCellLoaded(LodLevel parentLod, ref MyCellCoord thisLodCell) { if (parentLod == null || !parentLod.m_fitsInFrustum) { return(true); } Debug.Assert(thisLodCell.Lod == parentLod.m_lodIndex - 1); var shiftToParent = MyVoxelCoordSystems.RenderCellSizeShiftToLessDetailed(thisLodCell.Lod); var parentCell = new MyCellCoord(thisLodCell.Lod + 1, thisLodCell.CoordInLod >> shiftToParent); MyClipmap_CellData data; if (parentLod.m_storedCellData.TryGetValue(parentCell.PackId64(), out data)) { return(data.WasLoaded); } LodLevel ancestor; if (parentLod.m_clipmap.m_lodLevels.TryGetValue(parentLod.m_lodIndex + 1, out ancestor)) { return(WasAncestorCellLoaded(ancestor, ref parentCell)); } else { return(false); } }
internal void UpdateCellsInScene(float cameraDistance, Vector3D localPosition) { LodLevel parentLod, childLod; GetNearbyLodLevels(out parentLod, out childLod); MyCellCoord thisLodCell = new MyCellCoord(); foreach (var entry in m_nonEmptyCells) { var data = entry.Value; Debug.Assert(data.Cell != null, "Empty cell in m_nonEmptyCells!"); if (data.Cell != null) { thisLodCell.SetUnpack(entry.Key); if (ChildrenWereLoaded(childLod, ref thisLodCell) || (MyVoxelCoordSystems.RenderCellSizeShiftToLessDetailed(thisLodCell.Lod) == 1 && !AllSiblingsWereLoaded(ref thisLodCell)) || !ShouldBeThisLodVisible(cameraDistance) ) { RemoveFromScene(entry.Key, data); } else { AddToScene(entry.Key, data); } } } }
public void RemoveTooFarCells(List <Vector3D> importantPositions, float maxDistance, MyVector3ISet processedCells) { m_removedHLpackedCoord.Clear(); foreach (Vector3I vectori in this.m_exploredCells) { Vector3D vectord; MyVoxelCoordSystems.GeometryCellCenterCoordToWorldPos(this.m_mesh.VoxelMapReferencePosition, ref vectori, out vectord); float positiveInfinity = float.PositiveInfinity; using (List <Vector3D> .Enumerator enumerator2 = importantPositions.GetEnumerator()) { while (enumerator2.MoveNext()) { float num2 = Vector3.RectangularDistance(enumerator2.Current, (Vector3)vectord); if (num2 < positiveInfinity) { positiveInfinity = num2; } } } if ((positiveInfinity > maxDistance) && !processedCells.Contains(vectori)) { m_removedHLpackedCoord.Add(new MyCellCoord(0, vectori).PackId64()); } } foreach (ulong num3 in m_removedHLpackedCoord) { this.TryClearCell(num3); } }
public override void DebugDraw() { base.DebugDraw(); if (MyDebugDrawSettings.DEBUG_DRAW_VOXEL_PHYSICS_PREDICTION) { foreach (var entity in m_nearbyEntities) { if (entity.MarkedForClose) { continue; } var worldAabb = entity.WorldAABB; VRageRender.MyRenderProxy.DebugDrawAABB(worldAabb, Color.Bisque, 1f, 1f, true); VRageRender.MyRenderProxy.DebugDrawLine3D(GetWorldMatrix().Translation, worldAabb.Center, Color.Bisque, Color.BlanchedAlmond, true); var prediction = ComputePredictionOffset(entity); worldAabb.Translate(entity.Physics.LinearVelocity * 2.0f); VRageRender.MyRenderProxy.DebugDrawAABB(worldAabb, Color.Crimson, 1f, 1f, true); } using (var batch = VRageRender.MyRenderProxy.DebugDrawBatchAABB(MatrixD.Identity, Color.Cyan, true, false)) { foreach (var entry in m_workTracker) { BoundingBoxD worldAabb; var localCell = entry.Key; MyVoxelCoordSystems.GeometryCellCoordToWorldAABB(m_voxelMap.PositionLeftBottomCorner, ref localCell, out worldAabb); batch.Add(ref worldAabb); } } } }
// This method initializes voxel map (size, position, etc) but doesn't load voxels // It only presets all materials to values specified in 'defaultMaterial' - so it will become material everywhere. virtual protected void InitVoxelMap(MatrixD worldMatrix, Vector3I size, bool useOffset = true) { NeedsUpdate |= MyEntityUpdateEnum.BEFORE_NEXT_FRAME; NeedsUpdate |= MyEntityUpdateEnum.EACH_10TH_FRAME; var defaultMaterial = MyDefinitionManager.Static.GetDefaultVoxelMaterialDefinition(); SizeInMetres = size * MyVoxelConstants.VOXEL_SIZE_IN_METRES; SizeInMetresHalf = SizeInMetres / 2.0f; PositionComp.LocalAABB = new BoundingBox(-SizeInMetresHalf, SizeInMetresHalf); if (MyPerGameSettings.OffsetVoxelMapByHalfVoxel && useOffset) { worldMatrix.Translation += MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF; PositionLeftBottomCorner += MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF; } PositionComp.SetWorldMatrix(worldMatrix); Debug.Assert((Size.X & MyVoxelConstants.DATA_CELL_SIZE_IN_VOXELS_MASK) == 0); Debug.Assert((Size.Y & MyVoxelConstants.DATA_CELL_SIZE_IN_VOXELS_MASK) == 0); Debug.Assert((Size.Z & MyVoxelConstants.DATA_CELL_SIZE_IN_VOXELS_MASK) == 0); Debug.Assert((Size.X % MyVoxelCoordSystems.RenderCellSizeInLodVoxels(0)) == 0); Debug.Assert((Size.Y % MyVoxelCoordSystems.RenderCellSizeInLodVoxels(0)) == 0); Debug.Assert((Size.Z % MyVoxelCoordSystems.RenderCellSizeInLodVoxels(0)) == 0); ContentChanged = false; }
/// <param name="minCellLod0">Inclusive.</param> /// <param name="maxCellLod0">Inclusive.</param> public void InvalidateRange(Vector3I minCellLod0, Vector3I maxCellLod0) { //Debug.Print("InvalidateRange Clipmap: " + Id + " Min: " + minCellLod0 + " Max: " + maxCellLod0); if (minCellLod0 == Vector3I.Zero && maxCellLod0 == m_sizeLod0 - 1) { for (int lod = 0; lod < m_lodLevels.Length; ++lod) { m_lodLevels[lod].InvalidateAll(); } } else { for (int lod = 0; lod < m_lodLevels.Length; ++lod) { var shift = lod + MyVoxelCoordSystems.RenderCellSizeInLodVoxelsShiftDelta(lod); m_lodLevels[lod].InvalidateRange( minCellLod0 >> shift, maxCellLod0 >> shift); } } m_invalidated = 2; ResetClipping(); }
private static bool ResetVoxelInArea(Vector3D Center, float Radius) { try { BoundingSphereD Sphere = new BoundingSphereD(Center, Radius); List <MyVoxelBase> Maps = MyEntities.GetEntitiesInSphere(ref Sphere).OfType <MyVoxelBase>().ToList(); if (Maps.Count == 0) { return(true); } foreach (var voxelMap in Maps) { using (voxelMap.Pin()) { if (voxelMap.MarkedForClose) { continue; } MyShapeSphere shape = new MyShapeSphere(); shape.Center = Center; shape.Radius = Radius; Vector3I minCorner; Vector3I maxCorner; Vector3I numCells; BoundingBoxD shapeAabb = shape.GetWorldBoundaries(); Vector3I StorageSize = voxelMap.Storage.Size; MyVoxelCoordSystems.WorldPositionToVoxelCoord(voxelMap.PositionLeftBottomCorner, ref shapeAabb.Min, out minCorner); MyVoxelCoordSystems.WorldPositionToVoxelCoord(voxelMap.PositionLeftBottomCorner, ref shapeAabb.Max, out maxCorner); minCorner += voxelMap.StorageMin; maxCorner += voxelMap.StorageMin; maxCorner += 1; StorageSize -= 1; Vector3I.Clamp(ref minCorner, ref Vector3I.Zero, ref StorageSize, out minCorner); Vector3I.Clamp(ref maxCorner, ref Vector3I.Zero, ref StorageSize, out maxCorner); numCells = new Vector3I((maxCorner.X - minCorner.X) / 16, (maxCorner.Y - minCorner.Y) / 16, (maxCorner.Z - minCorner.Z) / 16); minCorner = Vector3I.Max(Vector3I.One, minCorner); maxCorner = Vector3I.Max(minCorner, maxCorner - Vector3I.One); voxelMap.Storage.DeleteRange(MyStorageDataTypeFlags.ContentAndMaterial, minCorner, maxCorner, false); BoundingBoxD cutOutBox = shape.GetWorldBoundaries(); MySandboxGame.Static.Invoke(delegate { if (voxelMap.Storage != null) { voxelMap.Storage.NotifyChanged(minCorner, maxCorner, MyStorageDataTypeFlags.ContentAndMaterial); MyVoxelGenerator.NotifyVoxelChanged(MyVoxelBase.OperationType.Revert, voxelMap, ref cutOutBox); } }, "RevertShape notify"); } } return(true); } catch (Exception ex) { _log.Error(ex, "Voxel reset failed!"); return(false); } }
private float CalculateCellWeight(List <Vector3D> importantPositions, Vector3I cellPos) { Vector3D vectord; Vector3I geometryCellCoord = cellPos; MyVoxelCoordSystems.GeometryCellCenterCoordToWorldPos(this.m_voxelMap.PositionLeftBottomCorner, ref geometryCellCoord, out vectord); float positiveInfinity = float.PositiveInfinity; using (List <Vector3D> .Enumerator enumerator = importantPositions.GetEnumerator()) { while (enumerator.MoveNext()) { float num2 = Vector3.RectangularDistance(enumerator.Current, (Vector3)vectord); if (num2 < positiveInfinity) { positiveInfinity = num2; } } } if (this.m_cellsOnWayCoords.Contains(MyCellCoord.PackId64Static(0, cellPos))) { positiveInfinity -= 8f; } return(GetWeight(positiveInfinity)); }
// NOTE: This method has a problem: "closestPlanetPos" is always a point on the surface // of the planet, so "position" is never more than up*radius far away than the surface. // Also we don't really know if the given position was really fixed or not cause the // modified position may still be colliding. CorrectSpawnLocation2() addresses // all these problems public void CorrectSpawnLocation(ref Vector3D position, double radius) { // Generate up vector according to the gravity of the planet. Vector3D upVector = position - WorldMatrix.Translation; upVector.Normalize(); // Calculate if the position is not inside of the planet: Vector3D localPos; MyVoxelCoordSystems.WorldPositionToLocalPosition(PositionLeftBottomCorner, ref position, out localPos); // Setup safe bounding box for the drone. Vector3D offset = new Vector3D(radius, radius, radius); BoundingBox testBBox = new BoundingBox(localPos - offset, localPos + offset); ContainmentType cType = Storage.Intersect(ref testBBox); int i = 0; while (i < 10 && (cType == ContainmentType.Intersects || cType == ContainmentType.Contains)) { Vector3D closestPlanetPos = GetClosestSurfacePointGlobal(ref position); // Spawn it above the ground in the direction of up vector + 50% of spawn radius (just in case) position = closestPlanetPos + upVector * radius; MyVoxelCoordSystems.WorldPositionToLocalPosition(PositionLeftBottomCorner, ref position, out localPos); testBBox = new BoundingBox(localPos - offset, localPos + offset); cType = Storage.Intersect(ref testBBox); i++; } }
public bool RemoveOneUnusedCell(List <Vector3D> importantPositions) { m_tmpCellSet.Clear(); m_tmpCellSet.Union(this.m_processedCells); bool flag = false; foreach (Vector3I vectori in m_tmpCellSet) { Vector3 vector; Vector3D vectord; Vector3I geometryCellCoord = vectori * 1; MyVoxelCoordSystems.GeometryCellCoordToLocalPosition(ref geometryCellCoord, out vector); vector += new Vector3D(0.5); MyVoxelCoordSystems.LocalPositionToWorldPosition(this.m_voxelMap.PositionLeftBottomCorner, ref vector, out vectord); bool flag2 = true; foreach (Vector3D vectord2 in importantPositions) { if (Vector3D.RectangularDistance(vectord, vectord2) < 50.0) { flag2 = false; break; } } if ((flag2 && !this.m_markedForAddition.Contains(vectori)) && this.RemoveCell(vectori)) { Vector3I cellPos = vectori; this.MarkCellForAddition(cellPos, this.CalculateCellWeight(importantPositions, cellPos)); flag = true; break; } } m_tmpCellSet.Clear(); return(flag); }
public unsafe void MarkBoxForAddition(BoundingBoxD box) { Vector3I vectori; Vector3I vectori2; MyVoxelCoordSystems.WorldPositionToVoxelCoord(this.m_voxelMap.PositionLeftBottomCorner, ref box.Min, out vectori); MyVoxelCoordSystems.WorldPositionToVoxelCoord(this.m_voxelMap.PositionLeftBottomCorner, ref box.Max, out vectori2); this.m_voxelMap.Storage.ClampVoxelCoord(ref vectori, 1); this.m_voxelMap.Storage.ClampVoxelCoord(ref vectori2, 1); Vector3I *vectoriPtr1 = (Vector3I *)ref vectori; MyVoxelCoordSystems.VoxelCoordToGeometryCellCoord(ref (Vector3I) ref vectoriPtr1, out vectori); Vector3I *vectoriPtr2 = (Vector3I *)ref vectori2; MyVoxelCoordSystems.VoxelCoordToGeometryCellCoord(ref (Vector3I) ref vectoriPtr2, out vectori2); Vector3 vector = (vectori + vectori2) * 0.5f; vectori = (Vector3I)(vectori / 1); vectori2 = (Vector3I)(vectori2 / 1); Vector3I_RangeIterator iterator = new Vector3I_RangeIterator(ref vectori, ref vectori2); while (iterator.IsValid()) { if (Vector3.RectangularDistance((Vector3)vectori, vector) <= 1f) { this.MarkCellForAddition(vectori, PresentEntityWeight); } iterator.GetNext(out vectori); } }
public void InvalidateRange(Vector3I minVoxelChanged, Vector3I maxVoxelChanged) { Vector3I vectori; Vector3I vectori2; minVoxelChanged -= MyPrecalcComponent.InvalidatedRangeInflate; maxVoxelChanged = (Vector3I)(maxVoxelChanged + MyPrecalcComponent.InvalidatedRangeInflate); this.m_voxelMap.Storage.ClampVoxelCoord(ref minVoxelChanged, 1); this.m_voxelMap.Storage.ClampVoxelCoord(ref maxVoxelChanged, 1); MyVoxelCoordSystems.VoxelCoordToGeometryCellCoord(ref minVoxelChanged, out vectori); MyVoxelCoordSystems.VoxelCoordToGeometryCellCoord(ref maxVoxelChanged, out vectori2); Vector3I position = vectori; Vector3I_RangeIterator iterator = new Vector3I_RangeIterator(ref vectori, ref vectori2); while (iterator.IsValid()) { if (!this.m_processedCells.Contains(ref position)) { this.m_higherLevelHelper.TryClearCell(new MyCellCoord(0, position).PackId64()); } else if (!this.m_cellsToChangeSet.Contains(ref position)) { this.m_cellsToChange.AddLast(position); this.m_cellsToChangeSet.Add(position); } iterator.GetNext(out position); } }
public static IMyVoxelMap SpawnAsteroid(MyPositionAndOrientation pos, CompositeShapeProviderBuilder provider) { var storage = new OctreeStorageBuilder(provider, MyVoxelCoordSystems.FindBestOctreeSize(provider.Size)); var storageName = $"proc_astr_{provider.Seed}_{provider.Size}_{(long) pos.Position.X}_{(long) pos.Position.Y}_{(long) pos.Position.Z}"; var entityID = GetAsteroidEntityId(storageName); IMyEntity currEntity; if (MyAPIGateway.Entities.TryGetEntityById(entityID, out currEntity)) { return(currEntity as IMyVoxelMap); } var data = storage.GetCompressedData(); var storageInstance = MyAPIGateway.Session.VoxelMaps.CreateStorage(data); var entity = MyAPIGateway.Session.VoxelMaps.CreateVoxelMap(storageName, storageInstance, pos.Position, entityID); entity.Save = false; var realEntity = entity as MyEntity; if (realEntity == null) { return(entity); } MyEntities.RaiseEntityCreated(realEntity); MyEntities.Add(realEntity); return(entity); }
public static ulong CutOutShape(MyVoxelBase voxelMap, MyShape shape) { Vector3I minCorner, maxCorner, numCells; GetVoxelShapeDimensions(voxelMap, shape, out minCorner, out maxCorner, out numCells); ulong changedVolumeAmount = 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; voxelMap.Storage.ClampVoxelCoord(ref cacheMin); voxelMap.Storage.ClampVoxelCoord(ref cacheMax); ulong removedSum = 0; m_cache.Resize(cacheMin, cacheMax); voxelMap.Storage.ReadRange(m_cache, MyStorageDataTypeFlags.Content, 0, ref cacheMin, ref cacheMax); for (var it = new Vector3I.RangeIterator(ref cellMinCorner, ref cellMaxCorner); it.IsValid(); it.MoveNext()) { var relPos = it.Current - cacheMin; // get original amount var original = m_cache.Content(ref relPos); if (original == MyVoxelConstants.VOXEL_CONTENT_EMPTY) // if there is nothing to remove { continue; } Vector3D vpos; MyVoxelCoordSystems.VoxelCoordToWorldPosition(voxelMap.PositionLeftBottomCorner, ref it.Current, out vpos); var volume = shape.GetVolume(ref vpos); if (volume == 0f) // if there is no intersection { continue; } var toRemove = (int)(MyVoxelConstants.VOXEL_CONTENT_FULL - (volume * MyVoxelConstants.VOXEL_CONTENT_FULL)); var newVal = Math.Min(toRemove, original); ulong removed = (ulong)Math.Abs(original - newVal); m_cache.Content(ref relPos, (byte)newVal); removedSum += removed; } if (removedSum > 0) { RemoveSmallVoxelsUsingChachedVoxels(); // must stay because of the around when filling voxels voxelMap.Storage.WriteRange(m_cache, MyStorageDataTypeFlags.Content, ref cacheMin, ref cacheMax); } changedVolumeAmount += removedSum; } return(changedVolumeAmount); }
public static Vector3D VoxelFloatToWorldCoord(MyVoxelBase voxelMap, Vector3D voxelCoords) { Vector3 tmp = voxelCoords - (Vector3D)voxelMap.StorageMin; Vector3D result; MyVoxelCoordSystems.LocalPositionToWorldPosition(voxelMap.PositionLeftBottomCorner, ref tmp, out result); return(result); }
public static Vector3D WorldCoordToVoxelFloat(MyVoxelBase voxelMap, Vector3D worldCoords) { Vector3 tmp; MyVoxelCoordSystems.WorldPositionToLocalPosition(voxelMap.PositionLeftBottomCorner, ref worldCoords, out tmp); tmp += voxelMap.StorageMin; return(Vector3D.Clamp(tmp, Vector3D.Zero, voxelMap.StorageMax)); }
//based on MyGuiScreenHudSpace.DrawOreMarkers private IEnumerable <PositionedOreMarker> CreateMarkers() { MyHudOreMarkers oreMarkers = MyHud.OreMarkers; Vector3D controlledEntityPosition = Vector3D.Zero; if (MySession.Static != null && MySession.Static.ControlledEntity != null) { controlledEntityPosition = ((MyEntity)MySession.Static.ControlledEntity).WorldMatrix.Translation; } PositionedOreMarker[] nearestOreDeposits = new PositionedOreMarker[MyDefinitionManager.Static.VoxelMaterialCount]; float[] nearestDistancesSquared = new float[nearestOreDeposits.Length]; for (int i = 0; i < nearestOreDeposits.Length; i++) { nearestOreDeposits[i] = null; nearestDistancesSquared[i] = float.MaxValue; } foreach (MyEntityOreDeposit oreMarker in oreMarkers) { for (int i = 0; i < oreMarker.Materials.Count; i++) { MyEntityOreDeposit.Data depositData = oreMarker.Materials[i]; var oreMaterial = depositData.Material; Vector3D oreWorldPosition; var voxelMap = oreMarker.VoxelMap; MyVoxelCoordSystems.LocalPositionToWorldPosition( (voxelMap.PositionComp.GetPosition() - (Vector3D)voxelMap.StorageMin), ref depositData.AverageLocalPosition, out oreWorldPosition); //ProfilerShort.BeginNextBlock("Distance"); Vector3D diff = (controlledEntityPosition - oreWorldPosition); float distanceSquared = (float)diff.LengthSquared(); float nearestDistanceSquared = nearestDistancesSquared[oreMaterial.Index]; if (distanceSquared < nearestDistanceSquared) { MyVoxelMaterialDefinition voxelMaterial = MyDefinitionManager.Static.GetVoxelMaterialDefinition(oreMaterial.Index); nearestOreDeposits[oreMaterial.Index] = new PositionedOreMarker() { Position = oreWorldPosition, OreDeposit = oreMarker, Name = oreMarkers.GetOreName(voxelMaterial), Distance = diff.Length(), }; nearestDistancesSquared[oreMaterial.Index] = distanceSquared; } } } return(nearestOreDeposits.Where(nod => nod?.OreDeposit?.VoxelMap != null && !nod.OreDeposit.VoxelMap.Closed)); }
public override void AddRenderObjects() { var minCorner = m_planet.PositionLeftBottomCorner; m_renderObjectIDs = new uint[] { MyRenderProxy.RENDER_ID_UNASSIGNED, MyRenderProxy.RENDER_ID_UNASSIGNED, MyRenderProxy.RENDER_ID_UNASSIGNED }; Debug.Assert((m_planet.Size % MyVoxelCoordSystems.RenderCellSizeInLodVoxels(0)) == Vector3I.Zero); var clipmapSizeLod0 = m_planet.Size / MyVoxelCoordSystems.RenderCellSizeInLodVoxels(0); Vector3 atmosphereWavelengths = new Vector3(); atmosphereWavelengths.X = 1.0f / (float)Math.Pow(m_planet.AtmosphereWavelengths.X, 4.0); atmosphereWavelengths.Y = 1.0f / (float)Math.Pow(m_planet.AtmosphereWavelengths.Y, 4.0); atmosphereWavelengths.Z = 1.0f / (float)Math.Pow(m_planet.AtmosphereWavelengths.Z, 4.0); SetRenderObjectID(0, MyRenderProxy.CreateClipmap( MatrixD.CreateTranslation(minCorner), clipmapSizeLod0, m_planet.ScaleGroup, m_planet.PositionComp.GetPosition(), m_planet.AtmosphereRadius, m_planet.AveragePlanetRadius, m_planet.HasAtmosphere, atmosphereWavelengths)); if (m_planet.HasAtmosphere) { MatrixD matrix = MatrixD.Identity * m_planet.AtmosphereRadius; matrix.M44 = 1; matrix.Translation = Entity.PositionComp.GetPosition(); SetRenderObjectID(1, VRageRender.MyRenderProxy.CreateRenderEntityAtmosphere(this.Entity.GetFriendlyName() + " " + this.Entity.EntityId.ToString(), "Models\\Environment\\Atmosphere_sphere.mwm", matrix, MyMeshDrawTechnique.ATMOSPHERE, RenderFlags.Visible, GetRenderCullingOptions(), m_planet.AtmosphereRadius, m_planet.AveragePlanetRadius, atmosphereWavelengths)); SetRenderObjectID(2, VRageRender.MyRenderProxy.CreateRenderEntityAtmosphere(this.Entity.GetFriendlyName() + " " + this.Entity.EntityId.ToString(), "Models\\Environment\\Atmosphere_sphere.mwm", matrix, MyMeshDrawTechnique.PLANET_SURFACE, RenderFlags.Visible, GetRenderCullingOptions(), m_planet.AtmosphereRadius, m_planet.AveragePlanetRadius, atmosphereWavelengths)); } if (m_renderEnabled == false) { VRageRender.MyRenderProxy.EnableRenderModule((uint)VRageRender.MyRenderModuleEnum.Atmosphere, true); m_renderEnabled = true; } }
public override bool IsOverlapOverThreshold(BoundingBoxD worldAabb, float thresholdPercentage) { //Debug.Assert( // worldAabb.Size.X > MyVoxelConstants.VOXEL_SIZE_IN_METRES && // worldAabb.Size.Y > MyVoxelConstants.VOXEL_SIZE_IN_METRES && // worldAabb.Size.Z > MyVoxelConstants.VOXEL_SIZE_IN_METRES, // "One of the sides of queried AABB is too small compared to voxel size. Results will be unreliable."); Vector3I minCorner, maxCorner; MyVoxelCoordSystems.WorldPositionToVoxelCoord(PositionLeftBottomCorner, ref worldAabb.Min, out minCorner); MyVoxelCoordSystems.WorldPositionToVoxelCoord(PositionLeftBottomCorner, ref worldAabb.Max, out maxCorner); minCorner += StorageMin; maxCorner += StorageMin; Storage.ClampVoxelCoord(ref minCorner); Storage.ClampVoxelCoord(ref maxCorner); m_storageCache.Resize(minCorner, maxCorner); Storage.ReadRange(m_storageCache, MyStorageDataTypeFlags.Content, 0, ref minCorner, ref maxCorner); BoundingBoxD voxelBox; //MyRenderProxy.DebugDrawAABB(worldAabb, Color.White, 1f, 1f, true); var invFullVoxel = 1.0 / (double)MyVoxelConstants.VOXEL_CONTENT_FULL_FLOAT; var voxelVolume = 1.0 / (double)MyVoxelConstants.VOXEL_VOLUME_IN_METERS; double overlapContentVolume = 0.0; var queryVolume = worldAabb.Volume; //using (var batch = MyRenderProxy.DebugDrawBatchAABB(Matrix.Identity, new Color(Color.Green, 0.1f), true, true)) { Vector3I coord, cache; for (coord.Z = minCorner.Z, cache.Z = 0; coord.Z <= maxCorner.Z; coord.Z++, cache.Z++) { for (coord.Y = minCorner.Y, cache.Y = 0; coord.Y <= maxCorner.Y; coord.Y++, cache.Y++) { for (coord.X = minCorner.X, cache.X = 0; coord.X <= maxCorner.X; coord.X++, cache.X++) { MyVoxelCoordSystems.VoxelCoordToWorldAABB(PositionLeftBottomCorner, ref coord, out voxelBox); if (worldAabb.Intersects(voxelBox)) { var contentVolume = m_storageCache.Content(ref cache) * invFullVoxel * voxelVolume; var overlapVolume = worldAabb.Intersect(voxelBox).Volume; overlapContentVolume += contentVolume * overlapVolume; //batch.Add(ref voxelBox); } } } } } var overlapVolumePercentage = overlapContentVolume / queryVolume; //MyRenderProxy.DebugDrawText3D(worldAabb.Center, overlapVolumePercentage.ToString("0.000"), Color.White, 1f, false); return(overlapVolumePercentage >= thresholdPercentage); }
//collisions //sphere vs voxel volumetric test public override bool DoOverlapSphereTest(float sphereRadius, Vector3D spherePos) { ProfilerShort.Begin("MyVoxelMap.DoOverlapSphereTest"); Vector3D body0Pos = spherePos; // sphere pos BoundingSphereD newSphere; newSphere.Center = body0Pos; newSphere.Radius = sphereRadius; // We will iterate only voxels contained in the bounding box of new sphere, so here we get min/max corned in voxel units Vector3I minCorner, maxCorner; { Vector3D sphereMin = newSphere.Center - newSphere.Radius - MyVoxelConstants.VOXEL_SIZE_IN_METRES; Vector3D sphereMax = newSphere.Center + newSphere.Radius + MyVoxelConstants.VOXEL_SIZE_IN_METRES; MyVoxelCoordSystems.WorldPositionToVoxelCoord(PositionLeftBottomCorner, ref sphereMin, out minCorner); MyVoxelCoordSystems.WorldPositionToVoxelCoord(PositionLeftBottomCorner, ref sphereMax, out maxCorner); } Storage.ClampVoxelCoord(ref minCorner); Storage.ClampVoxelCoord(ref maxCorner); m_storageCache.Resize(minCorner, maxCorner); Storage.ReadRange(m_storageCache, MyStorageDataTypeFlags.Content, 0, ref minCorner, ref maxCorner); Vector3I tempVoxelCoord, cache; for (tempVoxelCoord.Z = minCorner.Z, cache.Z = 0; tempVoxelCoord.Z <= maxCorner.Z; tempVoxelCoord.Z++, cache.Z++) { for (tempVoxelCoord.Y = minCorner.Y, cache.Y = 0; tempVoxelCoord.Y <= maxCorner.Y; tempVoxelCoord.Y++, cache.Y++) { for (tempVoxelCoord.X = minCorner.X, cache.X = 0; tempVoxelCoord.X <= maxCorner.X; tempVoxelCoord.X++, cache.X++) { byte voxelContent = m_storageCache.Content(ref cache); // Ignore voxels bellow the ISO value (empty, partialy empty...) if (voxelContent < MyVoxelConstants.VOXEL_ISO_LEVEL) { continue; } Vector3D voxelPosition; MyVoxelCoordSystems.VoxelCoordToWorldPosition(PositionLeftBottomCorner, ref tempVoxelCoord, out voxelPosition); float voxelSize = (voxelContent / MyVoxelConstants.VOXEL_CONTENT_FULL_FLOAT) * MyVoxelConstants.VOXEL_RADIUS; // If distance to voxel border is less than sphere radius, we have a collision // So now we calculate normal vector and penetration depth but on OLD sphere float newDistanceToVoxel = Vector3.Distance(voxelPosition, newSphere.Center) - voxelSize; if (newDistanceToVoxel < (newSphere.Radius)) { ProfilerShort.End(); return(true); } } } } ProfilerShort.End(); return(false); }
private int GetDivideIndex(ref Vector3D translation) { Vector3I renderCellCoord; BoundingBoxD lodAabb = m_boundingBoxes.GetAabb(m_boundingBoxes.GetRoot()); Vector3D relativeTranslation = Vector3D.Max(translation - lodAabb.Min, Vector3D.Zero); MyVoxelCoordSystems.LocalPositionToRenderCellCoord(m_lod, ref relativeTranslation, out renderCellCoord); return(GetDivideIndex(ref renderCellCoord)); }