protected void UpdateRenderObject() { m_actualWorldAABB = BoundingBoxD.CreateInvalid(); if (AnimationController.CharacterBones != null) { for (int i = 1; i < Model.Bones.Length; i++) { Vector3D p1 = Vector3D.Transform(AnimationController.CharacterBones[i].Parent.AbsoluteTransform.Translation, WorldMatrix); Vector3D p2 = Vector3D.Transform(AnimationController.CharacterBones[i].AbsoluteTransform.Translation, WorldMatrix); m_actualWorldAABB.Include(ref p1); m_actualWorldAABB.Include(ref p2); } } ContainmentType containmentType; m_aabb.Contains(ref m_actualWorldAABB, out containmentType); if (containmentType != ContainmentType.Contains) { m_actualWorldAABB.Inflate(0.5f); MatrixD worldMatrix = WorldMatrix; VRageRender.MyRenderProxy.UpdateRenderObject(Render.RenderObjectIDs[0], ref worldMatrix, false, m_actualWorldAABB); m_aabb = m_actualWorldAABB; } }
public void PrepareVoxelTriangleTests(BoundingBoxD cellBoundingBox, List<MyCubeGrid> gridsToTestOutput) { ProfilerShort.Begin("PrepareVoxelTriangleTests"); m_tmpEntityList.Clear(); // Each triangle will be tested with grids up to one largest cube further away from them, so we have to reflect this in the bounding box. float largeCubeSize = MyDefinitionManager.Static.GetCubeSize(MyCubeSize.Large); cellBoundingBox.Inflate(largeCubeSize); // Furthermore, a triangle cannot lie in a cube under existing block, so we have to extend the bbox even further if (MyPerGameSettings.NavmeshPresumesDownwardGravity) { var min = cellBoundingBox.Min; min.Y -= largeCubeSize; cellBoundingBox.Min = min; } MyGamePruningStructure.GetAllEntitiesInBox(ref cellBoundingBox, m_tmpEntityList); foreach (var entity in m_tmpEntityList) { var grid = entity as MyCubeGrid; if (grid == null) continue; if (!MyGridPathfinding.GridCanHaveNavmesh(grid)) continue; gridsToTestOutput.Add(grid); } m_tmpEntityList.Clear(); ProfilerShort.End(); }
/// <summary> /// How far away is the closest entity to myCubeGrid? /// </summary> /// <returns>Distance to closest Entity, may be negative</returns> public double ClosestEntity() { BoundingBoxD NearbyBox = myCubeGrid.WorldAABB; NearbyBox.Inflate(NearbyRange); HashSet <IMyEntity> offenders = new HashSet <IMyEntity>(); // = MyAPIGateway.Entities.GetEntitiesInAABB_Safe(ref NearbyBox); MyAPIGateway.Entities.GetEntitiesInAABB_Safe_NoBlock(NearbyBox, offenders, collect_Entities); if (offenders.Count == 0) { myLogger.debugLog("AABB is empty", "ClosestEntity()"); return(NearbyRange); } myLogger.debugLog("collected entities to test: " + offenders.Count, "ClosestEntity()"); double distClosest = NearbyRange; foreach (IMyEntity entity in offenders) { double distance = myCubeGrid.Distance_ShorterBounds(entity); if (distance < distClosest) { distClosest = distance; } } return(distClosest); }
private static void CheckNeighbourStaticGridsAfterVoxelChanged(MyVoxelBase.OperationType type, MyVoxelBase voxelMap, MyShape shape) { // Check static grids around (possible change to dynamic) if (Sync.IsServer && MyFakes.ENABLE_BLOCK_PLACEMENT_ON_VOXEL && MyFakes.ENABLE_BLOCKS_IN_VOXELS_TEST && MyStructuralIntegrity.Enabled) { BoundingBoxD cutOutBox = shape.GetWorldBoundaries(); cutOutBox.Inflate(0.25); List <MyEntity> boxOverlapList = new List <MyEntity>(); MyEntities.GetElementsInBox(ref cutOutBox, boxOverlapList); foreach (var entity in boxOverlapList) { var grid = entity as MyCubeGrid; if (grid != null && grid.IsStatic) { if (grid.Physics != null && grid.Physics.Shape != null) { grid.Physics.Shape.RecalculateConnectionsToWorld(grid.GetBlocks()); } if (type == MyVoxelBase.OperationType.Cut) { grid.TestDynamic = true; } } } boxOverlapList.Clear(); } }
/// <summary> /// Writes all surrounding blocks around the given one with the given size. /// </summary> private void GetSurroundingBlocksFromStaticGrids(MySlimBlock block, MyCubeSize cubeSizeEnum, HashSet <MyCubeBlock> outBlocks) { outBlocks.Clear(); BoundingBoxD aabb = new BoundingBoxD(block.Min * block.CubeGrid.GridSize - block.CubeGrid.GridSize / 2, block.Max * block.CubeGrid.GridSize + block.CubeGrid.GridSize / 2); if (block.FatBlock != null) { aabb = (BoundingBoxD)block.FatBlock.Model.BoundingBox; aabb.Translate(block.Position * block.CubeGrid.GridSize); } aabb = aabb.Transform(block.CubeGrid.WorldMatrix); aabb.Inflate(0.125); List <MyEntity> boxOverlapList = new List <MyEntity>(); MyEntities.GetElementsInBox(ref aabb, boxOverlapList); for (int i = 0; i < boxOverlapList.Count; i++) { var otherBlock = boxOverlapList[i] as MyCubeBlock; if (otherBlock != null && otherBlock.CubeGrid.IsStatic && otherBlock.CubeGrid.EnableSmallToLargeConnections && otherBlock.SlimBlock != block && otherBlock.CubeGrid != block.CubeGrid && otherBlock.CubeGrid.GridSizeEnum == cubeSizeEnum && !(otherBlock is MyCompoundCubeBlock) && !(otherBlock is MyFracturedBlock)) { outBlocks.Add(otherBlock); } } boxOverlapList.Clear(); }
public unsafe void PrepareVoxelTriangleTests(BoundingBoxD cellBoundingBox, List <MyCubeGrid> gridsToTestOutput) { m_tmpEntityList.Clear(); float cubeSize = MyDefinitionManager.Static.GetCubeSize(MyCubeSize.Large); cellBoundingBox.Inflate((double)cubeSize); if (MyPerGameSettings.NavmeshPresumesDownwardGravity) { Vector3D min = cellBoundingBox.Min; double * numPtr1 = (double *)ref min.Y; numPtr1[0] -= cubeSize; cellBoundingBox.Min = min; } MyGamePruningStructure.GetAllEntitiesInBox(ref cellBoundingBox, m_tmpEntityList, MyEntityQueryType.Both); foreach (MyCubeGrid grid in m_tmpEntityList) { if (grid == null) { continue; } if (MyGridPathfinding.GridCanHaveNavmesh(grid)) { gridsToTestOutput.Add(grid); } } m_tmpEntityList.Clear(); }
public void CreateSingleCluster() { BoundingBoxD bb = SingleCluster.Value; bb.Inflate(200); //inflate 200m so objects near world border have AABB inside => physics created CreateCluster(ref bb); }
private void GetSurroundingBlocksFromStaticGrids(MySlimBlock block, MyCubeSize cubeSizeEnum, HashSet <MyCubeBlock> outBlocks) { outBlocks.Clear(); BoundingBoxD boundingBox = new BoundingBoxD((Vector3D)((block.Min * block.CubeGrid.GridSize) - (block.CubeGrid.GridSize / 2f)), (block.Max * block.CubeGrid.GridSize) + (block.CubeGrid.GridSize / 2f)); if (block.FatBlock != null) { Matrix matrix; boundingBox = block.FatBlock.Model.BoundingBox; block.FatBlock.Orientation.GetMatrix(out matrix); boundingBox = boundingBox.TransformFast(matrix); boundingBox.Translate(boundingBox.Center); } boundingBox = boundingBox.TransformFast(block.CubeGrid.WorldMatrix); boundingBox.Inflate((double)0.125); List <VRage.Game.Entity.MyEntity> foundElements = new List <VRage.Game.Entity.MyEntity>(); Sandbox.Game.Entities.MyEntities.GetElementsInBox(ref boundingBox, foundElements); int num = 0; while (true) { while (true) { if (num >= foundElements.Count) { foundElements.Clear(); return; } MyCubeBlock item = foundElements[num] as MyCubeBlock; if (((item != null) && (!ReferenceEquals(item.SlimBlock, block) && (item.CubeGrid.IsStatic && (item.CubeGrid.EnableSmallToLargeConnections && (item.CubeGrid.SmallToLargeConnectionsInitialized && (!ReferenceEquals(item.CubeGrid, block.CubeGrid) && ((item.CubeGrid.GridSizeEnum == cubeSizeEnum) && !(item is MyFracturedBlock)))))))) && !item.Components.Has <MyFractureComponentBase>()) { MyCompoundCubeBlock block3 = item as MyCompoundCubeBlock; if (block3 != null) { foreach (MySlimBlock block4 in block3.GetBlocks()) { if (ReferenceEquals(block4, block)) { continue; } if (!block4.FatBlock.Components.Has <MyFractureComponentBase>()) { outBlocks.Add(block4.FatBlock); } } break; } outBlocks.Add(item); } break; } num++; } }
private void GetSurroundingBlocksFromStaticGrids(MySlimBlock block, MyCubeSize cubeSizeEnum, HashSet <MySlimBlock> outBlocks) { outBlocks.Clear(); BoundingBoxD aabbForNeighbors = new BoundingBoxD((Vector3D)(block.Min * block.CubeGrid.GridSize), (Vector3D)(block.Max * block.CubeGrid.GridSize)); BoundingBoxD box = new BoundingBoxD((Vector3D)((block.Min * block.CubeGrid.GridSize) - (block.CubeGrid.GridSize / 2f)), (block.Max * block.CubeGrid.GridSize) + (block.CubeGrid.GridSize / 2f)); if (block.FatBlock != null) { Matrix matrix; box = block.FatBlock.Model.BoundingBox; block.FatBlock.Orientation.GetMatrix(out matrix); box = box.TransformFast(matrix); box.Translate(box.Center); } box.Inflate((double)0.125); BoundingBoxD boundingBox = box.TransformFast(block.CubeGrid.WorldMatrix); List <VRage.Game.Entity.MyEntity> foundElements = new List <VRage.Game.Entity.MyEntity>(); Sandbox.Game.Entities.MyEntities.GetElementsInBox(ref boundingBox, foundElements); for (int i = 0; i < foundElements.Count; i++) { MyCubeGrid objA = foundElements[i] as MyCubeGrid; if (((objA != null) && (objA.IsStatic && (!ReferenceEquals(objA, block.CubeGrid) && (objA.EnableSmallToLargeConnections && objA.SmallToLargeConnectionsInitialized)))) && (objA.GridSizeEnum == cubeSizeEnum)) { m_tmpSlimBlocksList.Clear(); objA.GetBlocksIntersectingOBB(box, block.CubeGrid.WorldMatrix, m_tmpSlimBlocksList); CheckNeighborBlocks(block, aabbForNeighbors, objA, m_tmpSlimBlocksList); foreach (MySlimBlock block2 in m_tmpSlimBlocksList) { if (block2.FatBlock == null) { outBlocks.Add(block2); continue; } if (!(block2.FatBlock is MyFracturedBlock) && !block2.FatBlock.Components.Has <MyFractureComponentBase>()) { if (block2.FatBlock is MyCompoundCubeBlock) { foreach (MySlimBlock block3 in (block2.FatBlock as MyCompoundCubeBlock).GetBlocks()) { if (!block3.FatBlock.Components.Has <MyFractureComponentBase>()) { outBlocks.Add(block3); } } continue; } outBlocks.Add(block2); } } m_tmpSlimBlocksList.Clear(); } } foundElements.Clear(); }
public static BoundingBoxD AdjustAABBByVelocity(BoundingBoxD aabb, Vector3 velocity, float inflate = 1.1f) { if (velocity.LengthSquared() > 0.001f) { velocity.Normalize(); } aabb.Inflate((double)inflate); BoundingBoxD box = aabb; box += (BoundingBoxD)((velocity * 2000f) * inflate); aabb.Include(box); return(aabb); }
/// <summary> /// Writes all surrounding blocks around the given one with the given size. /// </summary> private void GetSurroundingBlocksFromStaticGrids(MySlimBlock block, MyCubeSize cubeSizeEnum, HashSet <MyCubeBlock> outBlocks) { outBlocks.Clear(); BoundingBoxD aabb = new BoundingBoxD(block.Min * block.CubeGrid.GridSize - block.CubeGrid.GridSize / 2, block.Max * block.CubeGrid.GridSize + block.CubeGrid.GridSize / 2); if (block.FatBlock != null) { var aabbCenter = aabb.Center; aabb = (BoundingBoxD)block.FatBlock.Model.BoundingBox; Matrix m; block.FatBlock.Orientation.GetMatrix(out m); aabb = aabb.TransformFast(m); aabb.Translate(aabbCenter); } aabb = aabb.TransformFast(block.CubeGrid.WorldMatrix); aabb.Inflate(0.125); List <MyEntity> boxOverlapList = new List <MyEntity>(); MyEntities.GetElementsInBox(ref aabb, boxOverlapList); for (int i = 0; i < boxOverlapList.Count; i++) { var otherBlock = boxOverlapList[i] as MyCubeBlock; if (otherBlock != null && otherBlock.SlimBlock != block && otherBlock.CubeGrid.IsStatic && otherBlock.CubeGrid.EnableSmallToLargeConnections && otherBlock.CubeGrid.SmallToLargeConnectionsInitialized && otherBlock.CubeGrid != block.CubeGrid && otherBlock.CubeGrid.GridSizeEnum == cubeSizeEnum && !(otherBlock is MyFracturedBlock) && !(otherBlock.Components.Has <MyFractureComponentBase>())) { var compound = otherBlock as MyCompoundCubeBlock; if (compound != null) { foreach (var blockInCompound in compound.GetBlocks()) { if (blockInCompound != block && !(blockInCompound.FatBlock.Components.Has <MyFractureComponentBase>())) { outBlocks.Add(blockInCompound.FatBlock); } } } else { outBlocks.Add(otherBlock); } } } boxOverlapList.Clear(); }
/// <summary> /// Writes all surrounding blocks around the given one with the given size. /// </summary> private void GetSurroundingBlocksFromStaticGrids(MySlimBlock block, MyCubeSize cubeSizeEnum, HashSet <MyCubeBlock> outBlocks) { outBlocks.Clear(); BoundingBoxD aabb = new BoundingBoxD(block.Min * block.CubeGrid.GridSize - block.CubeGrid.GridSize / 2, block.Max * block.CubeGrid.GridSize + block.CubeGrid.GridSize / 2); if (block.FatBlock != null) { aabb = (BoundingBoxD)block.FatBlock.Model.BoundingBox; aabb.Translate(block.Position * block.CubeGrid.GridSize); } aabb = aabb.Transform(block.CubeGrid.WorldMatrix); aabb.Inflate(0.125); List <MyEntity> boxOverlapList = new List <MyEntity>(); MyEntities.GetElementsInBox(ref aabb, boxOverlapList); for (int i = 0; i < boxOverlapList.Count; i++) { var otherGrid = boxOverlapList[i] as MyCubeGrid; if (otherGrid != null) { foreach (var gridBlock in otherGrid.CubeBlocks) { if (IsValidForConnection(gridBlock.FatBlock, block, cubeSizeEnum)) { if (!IsCompoundAndProcessed(gridBlock.FatBlock, block, outBlocks)) { outBlocks.Add(gridBlock.FatBlock); } } } } else { var otherBlock = boxOverlapList[i] as MyCubeBlock; if (IsValidForConnection(otherBlock, block, cubeSizeEnum)) { if (!IsCompoundAndProcessed(otherBlock, block, outBlocks)) { outBlocks.Add(otherBlock); } } } } boxOverlapList.Clear(); }
private static void OnVoxelChanged(MyVoxelBase.OperationType type, MyVoxelBase voxelMap, MyShape shape) { if (Sync.IsServer) { BoundingBoxD cutOutBox = shape.GetWorldBoundaries(); cutOutBox.Inflate(0.25); MyEntities.GetElementsInBox(ref cutOutBox, m_overlapList); // Check static grids around (possible change to dynamic) if (/*MyFakes.ENABLE_BLOCK_PLACEMENT_ON_VOXEL &&*/ MyFakes.ENABLE_BLOCKS_IN_VOXELS_TEST && MyStructuralIntegrity.Enabled) { foreach (var entity in m_overlapList) { var grid = entity as MyCubeGrid; if (grid != null && grid.IsStatic) { if (grid.Physics != null && grid.Physics.Shape != null) { grid.Physics.Shape.RecalculateConnectionsToWorld(grid.GetBlocks()); } if (type == MyVoxelBase.OperationType.Cut) { grid.TestDynamic = true; } } } } } var voxelPhysics = voxelMap as MyVoxelPhysics; MyPlanet planet = voxelPhysics != null ? voxelPhysics.Parent : voxelMap as MyPlanet; if (planet != null) { var planetEnvironment = planet.Components.Get <MyPlanetEnvironmentComponent>(); if (planetEnvironment != null) { var sectors = planetEnvironment.GetSectorsInRange(shape); if (sectors != null) { foreach (var sector in sectors) { sector.DisableItemsInShape(shape); } } } } m_overlapList.Clear(); }
public static void NotifyVoxelChanged(MyVoxelBase.OperationType type, MyVoxelBase voxelMap, ref BoundingBoxD cutOutBox) { cutOutBox.Inflate((double)0.25); MyGamePruningStructure.GetTopmostEntitiesInBox(ref cutOutBox, m_overlapList, MyEntityQueryType.Both); if (MyFakes.ENABLE_BLOCKS_IN_VOXELS_TEST) { foreach (MyEntity entity in m_overlapList) { if (Sync.IsServer) { MyCubeGrid grid = entity as MyCubeGrid; if ((grid != null) && grid.IsStatic) { if ((grid.Physics != null) && (grid.Physics.Shape != null)) { grid.Physics.Shape.RecalculateConnectionsToWorld(grid.GetBlocks()); } if (type == MyVoxelBase.OperationType.Cut) { grid.TestDynamic = MyCubeGrid.MyTestDynamicReason.GridSplit; } } } MyPhysicsBody physics = entity.Physics as MyPhysicsBody; if (((physics != null) && !physics.IsStatic) && (physics.RigidBody != null)) { physics.RigidBody.Activate(); } } } m_overlapList.Clear(); if (Sync.IsServer) { MyPlanetEnvironmentComponent component = voxelMap.Components.Get <MyPlanetEnvironmentComponent>(); if (component != null) { component.GetSectorsInRange(ref cutOutBox, m_overlapList); using (List <MyEntity> .Enumerator enumerator = m_overlapList.GetEnumerator()) { while (enumerator.MoveNext()) { ((MyEnvironmentSector)enumerator.Current).DisableItemsInBox(ref cutOutBox); } } m_overlapList.Clear(); } } }
private static void OnVoxelChanged(MyVoxelBase.OperationType type, MyVoxelBase voxelMap, MyShape shape) { if (!Sync.IsServer) { return; } BoundingBoxD cutOutBox = shape.GetWorldBoundaries(); cutOutBox.Inflate(0.25); MyEntities.GetElementsInBox(ref cutOutBox, m_overlapList); // Check static grids around (possible change to dynamic) if (MyFakes.ENABLE_BLOCK_PLACEMENT_ON_VOXEL && MyFakes.ENABLE_BLOCKS_IN_VOXELS_TEST && MyStructuralIntegrity.Enabled) { foreach (var entity in m_overlapList) { var grid = entity as MyCubeGrid; if (grid != null && grid.IsStatic) { if (grid.Physics != null && grid.Physics.Shape != null) { grid.Physics.Shape.RecalculateConnectionsToWorld(grid.GetBlocks()); } if (type == MyVoxelBase.OperationType.Cut) { grid.TestDynamic = true; } } } } var voxelPhysics = voxelMap as MyVoxelPhysics; MyPlanet planet = voxelPhysics != null ? voxelPhysics.Parent : voxelMap as MyPlanet; if (planet != null) { var center = cutOutBox.Center; foreach (var environment in planet.GetEnvironmentItemsAtPosition(ref center)) { environment.RemoveItemsAroundPoint(cutOutBox.Center, cutOutBox.HalfExtents.Max()); } } m_overlapList.Clear(); }
public static MyEntity FindSupportForCharacterAABB(MyEntity entity) { if (entity == null) { return(null); } BoundingBoxD characterBox = entity.PositionComp.WorldAABB; characterBox.Inflate(1.0); m_entities.Clear(); MyEntities.GetTopMostEntitiesInBox(ref characterBox, m_entities); float maxRadius = 0; MyCubeGrid biggestGrid = null; foreach (var parent in m_entities) { MyCubeGrid grid = parent as MyCubeGrid; if (grid != null) { if (grid.Physics == null || grid.Physics.IsStatic || grid.GridSizeEnum == MyCubeSize.Small) { continue; } grid = MyGridPhysicsStateGroup.GetMasterGrid(grid); var rad = grid.PositionComp.LocalVolume.Radius; if (rad > maxRadius || (rad == maxRadius && (biggestGrid == null || grid.EntityId > biggestGrid.EntityId))) { maxRadius = rad; biggestGrid = grid; } } } if (biggestGrid != null && biggestGrid.CubeBlocks.Count > 10) { return(biggestGrid); } return(null); }
public void EnsureClusterSpace(BoundingBoxD aabb) { if (SingleCluster.HasValue) { return; } aabb.Inflate(3000); m_clusterTree.OverlapAllBoundingBox(ref aabb, m_returnedClusters); bool needReorder = true; if (m_returnedClusters.Count == 1) { if (m_returnedClusters[0].AABB.Contains(aabb) == ContainmentType.Contains) { needReorder = false; } } if (needReorder) { ulong objectId = m_clusterObjectCounter++; int staticObjectId = MyDynamicAABBTreeD.NullNode; m_objectsData[objectId] = new MyObjectData() { Id = objectId, Cluster = null, ActivationHandler = null, AABB = aabb, StaticId = staticObjectId }; ReorderClusters(aabb, objectId); RemoveObjectFromCluster(m_objectsData[objectId], false); m_objectsData.Remove(objectId); } }
// DigVoxels will dig voxels around the grids if necessary. // // Grids built inside dug out voxel (e.g. underground bases) have the problem that once saved // in hangar, voxels are likely to regenerate, and the grids cannot be loaded again without // exploding, requiring either admin assistance to dig it out, or give up on the grids. // // However it is not desirable to dig out all voxels around the grids unconditionally, grids placed // on voxels (e.g. surface bases) can load just fine and voxels under them should remain intact. // // Therefore the criteria is: if the grids center is inside voxels then dig voxels around, otherwise not. // The current digging strategy is simply a bounding box around it, aligned on the biggest grid and as // large as necessary for the whole grid to fit, plus an arbitrary 2 meters to fit a character standing. // // The grids center and the bounding box are determined by FindGridBounds. // // It is worth noting that this behavior can be used to dig out voxels for free, e.g. a long line of // blocks in each direction would result in a large cube dug out; or, in gravity a station grid that was // previously held by voxels would now appear to float in the air. These are definitely quirks but // not game breaking, as players can achieve the same result themselves. // // Needs to run in the game thread. private void DigVoxels() { var center = new BoundingBoxD(SphereD.Center - 0.1f, SphereD.Center + 0.1f); foreach (MyVoxelBase voxel in MySession.Static.VoxelMaps.Instances) { if (voxel.StorageName == null) { continue; // invalid voxel } // ignore ghost asteroids: planets don't have physics linked directly to entity and // asteroids do have physics and they're disabled when in ghost placement mode, but not null if (!(voxel is MyPlanet) && (voxel.Physics == null || !voxel.Physics.Enabled)) { continue; } // before we check if it's inside voxel material (complex), there's a fast check // we can do: if it's not near the voxel map, then bail out if (!voxel.IsBoxIntersectingBoundingBoxOfThisVoxelMap(ref center)) { continue; } // dig only if the grids center is inside voxel material // this allows to leave untouched grids that are partially in voxels on purpose if (!voxel.IsAnyAabbCornerInside(ref MatrixD.Identity, center)) { continue; } // in practice, this is reached only once because voxel material cannot overlap var box = new BoundingBoxD(BoxAAB.Min, BoxAAB.Max); box.Inflate(2f); // just enough for one character height var shape = MyAPIGateway.Session.VoxelMaps.GetBoxVoxelHand(); shape.Boundaries = box; shape.Transform = _BiggestGrid.PositionAndOrientation.Value.GetMatrix(); MyAPIGateway.Session.VoxelMaps.CutOutShape(voxel, shape); } }
public void PrepareVoxelTriangleTests(BoundingBoxD cellBoundingBox, List <MyCubeGrid> gridsToTestOutput) { ProfilerShort.Begin("PrepareVoxelTriangleTests"); m_tmpEntityList.Clear(); // Each triangle will be tested with grids up to one largest cube further away from them, so we have to reflect this in the bounding box. float largeCubeSize = MyDefinitionManager.Static.GetCubeSize(MyCubeSize.Large); cellBoundingBox.Inflate(largeCubeSize); // Furthermore, a triangle cannot lie in a cube under existing block, so we have to extend the bbox even further if (MyPerGameSettings.NavmeshPresumesDownwardGravity) { var min = cellBoundingBox.Min; min.Y -= largeCubeSize; cellBoundingBox.Min = min; } MyGamePruningStructure.GetAllEntitiesInBox(ref cellBoundingBox, m_tmpEntityList); foreach (var entity in m_tmpEntityList) { var grid = entity as MyCubeGrid; if (grid == null) { continue; } if (!MyGridPathfinding.GridCanHaveNavmesh(grid)) { continue; } gridsToTestOutput.Add(grid); } m_tmpEntityList.Clear(); ProfilerShort.End(); }
public static MyEntity FindSupportForCharacterAABB(MyEntity entity) { BoundingBoxD characterBox = entity.PositionComp.WorldAABB; characterBox.Inflate(1.0); m_entities.Clear(); MyEntities.GetTopMostEntitiesInBox(ref characterBox, m_entities); float maxRadius = 0; MyCubeGrid biggestGrid = null; MyEntity voxel = null; foreach (var parent in m_entities) { MyCubeGrid grid = parent as MyCubeGrid; if (parent is MyVoxelBase) { voxel = (parent as MyVoxelBase).RootVoxel; } if (grid != null) { var rad = grid.PositionComp.LocalVolume.Radius; if (rad > maxRadius || (rad == maxRadius && (biggestGrid == null || grid.EntityId > biggestGrid.EntityId))) { maxRadius = rad; biggestGrid = grid; } } } if (biggestGrid == null) { return(voxel); } return(biggestGrid); }
// ReSharper restore InconsistentNaming public void DebugDraw(bool force = false) { force |= ForceDebugDraw; if (!force && !Settings.DebugDraw) { return; } var transform = Grid.WorldMatrix; var gridSize = Grid.GridSize; foreach (var room in Construction.Rooms) { if (force || Settings.DebugDrawBlocks) { var localAABB = new BoundingBoxD((room.BoundingBox.Min - 0.5f) * gridSize, (room.BoundingBox.Max + 0.5f) * gridSize); MySimpleObjectDraw.DrawTransparentBox(ref transform, ref localAABB, ref DebugColorBlocksTotal, MySimpleObjectRasterizer.Wireframe, 1, .02f); } if (force || Settings.DebugDrawReservedTotal && room.Part.ReservedSpaces.Any()) { var temp = Utilities.TransformBoundingBox(room.Part.ReservedSpace, room.Transform); var tmpAABB = new BoundingBoxD((temp.Min - 0.5f) * gridSize, (temp.Max + 0.5f) * gridSize); MySimpleObjectDraw.DrawTransparentBox(ref transform, ref tmpAABB, ref DebugColorReservedSpaceTotal, MySimpleObjectRasterizer.Wireframe, 1, .02f); } if (force || Settings.DebugDrawReserved) { foreach (var rs in room.Part.ReservedSpaces) { var temp = Utilities.TransformBoundingBox(rs.Box, room.Transform); var tmpAABB = new BoundingBoxD(temp.Min * gridSize, (temp.Max + 1) * gridSize); tmpAABB = tmpAABB.Inflate(-0.02); Color color; if (rs.IsShared && rs.IsOptional) { color = DebugColorReservedSpaceBoth; } else if (rs.IsShared) { color = DebugColorReservedSpaceShared; } else if (rs.IsOptional) { color = DebugColorReservedSpaceOptional; } else { color = DebugColorReservedSpace; } MySimpleObjectDraw.DrawTransparentBox(ref transform, ref tmpAABB, ref color, MySimpleObjectRasterizer.Wireframe, 1, .005f); } } // ReSharper disable once InvertIf if (force || Settings.DebugDrawMountPoints) { foreach (var mount in room.MountPoints) { foreach (var block in mount.MountPoint.Blocks) { var anchorLoc = (Vector3)block.AnchorLocation; var opposeLoc = (Vector3)(block.AnchorLocation + (block.MountDirection * 2)); opposeLoc += 0.5f * Vector3.Abs(Vector3I.One - Vector3I.Abs(block.MountDirection)); // hacky way to get perp. components anchorLoc -= 0.5f * Vector3.Abs(Vector3I.One - Vector3I.Abs(block.MountDirection)); var anchor = gridSize * Vector3.Transform(anchorLoc, room.Transform.GetFloatMatrix()); var oppose = gridSize * Vector3.Transform(opposeLoc, room.Transform.GetFloatMatrix()); var tmpAABB = new BoundingBoxD(Vector3.Min(anchor, oppose), Vector3.Max(anchor, oppose)); MySimpleObjectDraw.DrawTransparentBox(ref transform, ref tmpAABB, ref DebugColorMountPoint, MySimpleObjectRasterizer.Solid, 1, .02f); } } } } }
public static bool DefaultGizmoCloseEnough(ref MatrixD invGridWorldMatrix, BoundingBoxD gizmoBox, float gridSize, float intersectionDistance) { //MyRenderProxy.DebugDrawText2D(new Vector2(0.0f, 0.0f), "Intersection distance = " + intersectionDistance, Color.Red, 1.0f); var m = invGridWorldMatrix; MyCharacter character = MySession.LocalCharacter; if (character == null) return false; // Character head for measuring distance to intesection. Vector3D originHead = character.GetHeadMatrix(true).Translation; // Camera position adn direction. Used for ray cast to cube block box. Vector3D originCamera = MySector.MainCamera.Position; Vector3 direction = MySector.MainCamera.ForwardVector; Vector3 localHead = Vector3D.Transform(originHead, m); Vector3 localStart = Vector3D.Transform(originCamera, m); Vector3 localEnd = Vector3D.Transform(originCamera + direction * intersectionDistance, m); LineD line = new LineD(localStart, localEnd); // AABB of added block float inflate = 0.025f * gridSize; gizmoBox.Inflate(inflate); /*{ Vector4 blue = Color.Blue.ToVector4(); Matrix mtx = Matrix.Invert(invGridWorldMatrix); MySimpleObjectDraw.DrawTransparentBox(ref mtx, ref gizmoBox, ref blue, MySimpleObjectRasterizer.Wireframe, 1, 0.04f); }*/ double distance = double.MaxValue; if (gizmoBox.Intersects(line, out distance)) { // Distance from the player's head to the gizmo box. double distanceToPlayer = gizmoBox.Distance(localHead); return distanceToPlayer <= 5.0; } return false; }
public static bool DefaultGizmoCloseEnough(ref MatrixD invGridWorldMatrix, BoundingBoxD gizmoBox, float gridSize, float intersectionDistance) { //MyRenderProxy.DebugDrawText2D(new Vector2(0.0f, 0.0f), "Intersection distance = " + intersectionDistance, Color.Red, 1.0f); var m = invGridWorldMatrix; MyCharacter character = MySession.Static.LocalCharacter; if (character == null) return false; // Character head for measuring distance to intesection. Vector3D originHead = character.GetHeadMatrix(true).Translation; // Camera position adn direction. Used for ray cast to cube block box. Vector3D originCamera = MySector.MainCamera.Position; Vector3 direction = MySector.MainCamera.ForwardVector; double cameraHeadDist = (originHead - MySector.MainCamera.Position).Length(); Vector3 localHead = Vector3D.Transform(originHead, m); Vector3 localStart = Vector3D.Transform(originCamera, m); Vector3 localEnd = Vector3D.Transform(originCamera + direction * (intersectionDistance + (float)cameraHeadDist), m); LineD line = new LineD(localStart, localEnd); // AABB of added block float inflate = 0.025f * gridSize; gizmoBox.Inflate(inflate); //{ // Color blue = Color.Blue; // MatrixD mtx = MatrixD.Invert(invGridWorldMatrix); // MySimpleObjectDraw.DrawTransparentBox(ref mtx, ref gizmoBox, ref blue, MySimpleObjectRasterizer.Wireframe, 1, 0.04f); // MyRenderProxy.DebugDrawLine3D(originCamera, originCamera + direction * (intersectionDistance + (float)cameraHeadDist), Color.Red, Color.Red, false); //} double distance = double.MaxValue; if (gizmoBox.Intersects(ref line, out distance)) { // Distance from the player's head to the gizmo box. double distanceToPlayer = gizmoBox.Distance(localHead); if (MySession.Static.ControlledEntity is MyShipController) { if (MyCubeBuilder.Static.CubeBuilderState.CurrentBlockDefinition.CubeSize == MyCubeSize.Large) return distanceToPlayer <= MyCubeBuilder.CubeBuilderDefinition.BuildingDistLargeSurvivalShip; else return distanceToPlayer <= MyCubeBuilder.CubeBuilderDefinition.BuildingDistSmallSurvivalShip; } else { if (MyCubeBuilder.Static.CubeBuilderState.CurrentBlockDefinition.CubeSize == MyCubeSize.Large) return distanceToPlayer <= MyCubeBuilder.CubeBuilderDefinition.BuildingDistLargeSurvivalCharacter; else return distanceToPlayer <= MyCubeBuilder.CubeBuilderDefinition.BuildingDistSmallSurvivalCharacter; } } return false; }
/// <summary> /// Returns true if the given small block connects to large one. /// </summary> /// <param name="smallBlock">small block</param> /// <param name="smallBlockWorldAabb">small block world AABB</param> /// <param name="largeBlock">large block</param> /// <param name="largeBlockWorldAabb">large block wotld AABB</param> /// <returns>true when connected</returns> private bool SmallBlockConnectsToLarge(MySlimBlock smallBlock, ref BoundingBoxD smallBlockWorldAabb, MySlimBlock largeBlock, ref BoundingBoxD largeBlockWorldAabb) { Debug.Assert(smallBlock.BlockDefinition.CubeSize == MyCubeSize.Small); Debug.Assert(largeBlock.BlockDefinition.CubeSize == MyCubeSize.Large); Debug.Assert(!(smallBlock.FatBlock is MyCompoundCubeBlock)); Debug.Assert(!(largeBlock.FatBlock is MyCompoundCubeBlock)); BoundingBoxD smallBlockWorldAabbReduced = smallBlockWorldAabb; smallBlockWorldAabbReduced.Inflate(-smallBlock.CubeGrid.GridSize / 4); // Small block aabb penetrates large block aabb (large timbers). bool penetratesAabbs = largeBlockWorldAabb.Contains(smallBlockWorldAabbReduced) == ContainmentType.Intersects; if (!penetratesAabbs) { Vector3D centerToCenter = smallBlockWorldAabb.Center - largeBlockWorldAabb.Center; Vector3I addDir = Base6Directions.GetIntVector(Base6Directions.GetClosestDirection(centerToCenter)); // Check small grid mount points Quaternion smallBlockRotation; smallBlock.Orientation.GetQuaternion(out smallBlockRotation); smallBlockRotation = Quaternion.CreateFromRotationMatrix(smallBlock.CubeGrid.WorldMatrix) * smallBlockRotation; if (!MyCubeGrid.CheckConnectivitySmallBlockToLargeGrid(largeBlock.CubeGrid, smallBlock.BlockDefinition, ref smallBlockRotation, ref addDir)) { return(false); } } BoundingBoxD smallBlockWorldAabbInflated = smallBlockWorldAabb; smallBlockWorldAabbInflated.Inflate(2 * smallBlock.CubeGrid.GridSize / 3); // Trim small block aabb with large block aabb. BoundingBoxD intersectedBox = smallBlockWorldAabbInflated.Intersect(largeBlockWorldAabb); Vector3D intersectedBoxCenter = intersectedBox.Center; HkShape shape = new HkBoxShape((Vector3)intersectedBox.HalfExtents); Quaternion largeRotation; largeBlock.Orientation.GetQuaternion(out largeRotation); largeRotation = Quaternion.CreateFromRotationMatrix(largeBlock.CubeGrid.WorldMatrix) * largeRotation; Vector3D largeTranslation; largeBlock.ComputeWorldCenter(out largeTranslation); bool result = false; try { if (largeBlock.FatBlock != null) { MyModel model = largeBlock.FatBlock.Model; if (model != null) { HkShape[] shapes = model.HavokCollisionShapes; if (shapes == null || shapes.Length == 0) { return(false); } for (int i = 0; i < shapes.Length; ++i) { result = MyPhysics.IsPenetratingShapeShape(shape, ref intersectedBoxCenter, ref Quaternion.Identity, shapes[i], ref largeTranslation, ref largeRotation); if (result) { break; } } } else { HkShape shapeLarge = new HkBoxShape(largeBlock.BlockDefinition.Size * largeBlock.CubeGrid.GridSize / 2); result = MyPhysics.IsPenetratingShapeShape(shape, ref intersectedBoxCenter, ref Quaternion.Identity, shapeLarge, ref largeTranslation, ref largeRotation); shapeLarge.RemoveReference(); } } else { HkShape shapeLarge = new HkBoxShape(largeBlock.BlockDefinition.Size * largeBlock.CubeGrid.GridSize / 2); result = MyPhysics.IsPenetratingShapeShape(shape, ref intersectedBoxCenter, ref Quaternion.Identity, shapeLarge, ref largeTranslation, ref largeRotation); shapeLarge.RemoveReference(); } } finally { shape.RemoveReference(); } return(result); }
private unsafe void RasterSectorsForCollision(MyEntity entity) { if (!(entity is MyCubeGrid)) { return; } BoundingBoxD range = entity.PositionComp.WorldAABB; range.Inflate(8); range.Translate(-PlanetTranslation); Vector2I top = new Vector2I(1 << m_clipmaps[0].Depth) - 1; Vector3D *pos = stackalloc Vector3D[8]; range.GetCornersUnsafe(pos); // bitmask for faces, 7th bit is simple bit int markedFaces = 0; int firstFace = 0; for (var i = 0; i < 8; ++i) { Vector3D copy = pos[i]; int index = MyPlanetCubemapHelper.FindCubeFace(ref copy); firstFace = index; index = 1 << index; if ((markedFaces & ~index) != 0) { markedFaces |= 0x40; } markedFaces |= index; } // This way we can ensure a single code path. int startFace = 0; int endFace = 5; // If we only encounter one face we narrow it down. if ((markedFaces & 0x40) == 0) { startFace = endFace = firstFace; } for (int face = startFace; face <= endFace; ++face) { if (((1 << face) & markedFaces) == 0) { continue; } // Offset var offset = 1 << m_clipmaps[face].Depth - 1; BoundingBox2D bounds = BoundingBox2D.CreateInvalid(); for (int i = 0; i < 8; ++i) { Vector3D copy = pos[i]; Vector2D normCoords; MyPlanetCubemapHelper.ProjectForFace(ref copy, face, out normCoords); bounds.Include(normCoords); } bounds.Min += 1; bounds.Min *= offset; bounds.Max += 1; bounds.Max *= offset; // Calculate bounds in sectors. var start = new Vector2I((int)bounds.Min.X, (int)bounds.Min.Y); var end = new Vector2I((int)bounds.Max.X, (int)bounds.Max.Y); Vector2I.Max(ref start, ref Vector2I.Zero, out start); Vector2I.Min(ref end, ref top, out end); for (int x = start.X; x <= end.X; ++x) { for (int y = start.Y; y <= end.Y; ++y) { long sect = MyPlanetSectorId.MakeSectorId(x, y, face); List <MyOrientedBoundingBoxD> boxes; if (!m_obstructorsPerSector.TryGetValue(sect, out boxes)) { boxes = new List <MyOrientedBoundingBoxD>(); m_obstructorsPerSector.Add(sect, boxes); } var bb = entity.PositionComp.LocalAABB; bb.Inflate(8); // inflate by 8m to increase the likellyhood of overlap with trees' roots. boxes.Add(new MyOrientedBoundingBoxD((BoundingBoxD)bb, entity.PositionComp.WorldMatrix)); } } } }
private bool SmallBlockConnectsToLarge(MySlimBlock smallBlock, ref BoundingBoxD smallBlockWorldAabb, MySlimBlock largeBlock, ref BoundingBoxD largeBlockWorldAabb) { Quaternion quaternion; Vector3D vectord2; BoundingBoxD box = smallBlockWorldAabb; box.Inflate((double)(-smallBlock.CubeGrid.GridSize / 4f)); if (!largeBlockWorldAabb.Intersects(box)) { Quaternion quaternion2; Vector3I addNormal = this.GetSmallBlockAddDirection(ref smallBlockWorldAabb, ref box, ref largeBlockWorldAabb); smallBlock.Orientation.GetQuaternion(out quaternion2); quaternion2 = Quaternion.CreateFromRotationMatrix(smallBlock.CubeGrid.WorldMatrix) * quaternion2; if (!MyCubeGrid.CheckConnectivitySmallBlockToLargeGrid(largeBlock.CubeGrid, smallBlock.BlockDefinition, ref quaternion2, ref addNormal)) { return(false); } } BoundingBoxD xd2 = smallBlockWorldAabb; xd2.Inflate((double)((2f * smallBlock.CubeGrid.GridSize) / 3f)); BoundingBoxD xd3 = xd2.Intersect(largeBlockWorldAabb); Vector3D center = xd3.Center; HkShape shape = (HkShape) new HkBoxShape((Vector3)xd3.HalfExtents); largeBlock.Orientation.GetQuaternion(out quaternion); quaternion = Quaternion.CreateFromRotationMatrix(largeBlock.CubeGrid.WorldMatrix) * quaternion; largeBlock.ComputeWorldCenter(out vectord2); bool flag = false; try { if (largeBlock.FatBlock == null) { HkShape shape3 = (HkShape) new HkBoxShape((largeBlock.BlockDefinition.Size * largeBlock.CubeGrid.GridSize) / 2f); flag = MyPhysics.IsPenetratingShapeShape(shape, ref center, ref Quaternion.Identity, shape3, ref vectord2, ref quaternion); shape3.RemoveReference(); } else { MyModel model = largeBlock.FatBlock.Model; if ((model == null) || (model.HavokCollisionShapes == null)) { HkShape shape2 = (HkShape) new HkBoxShape((largeBlock.BlockDefinition.Size * largeBlock.CubeGrid.GridSize) / 2f); flag = MyPhysics.IsPenetratingShapeShape(shape, ref center, ref Quaternion.Identity, shape2, ref vectord2, ref quaternion); shape2.RemoveReference(); } else { HkShape[] havokCollisionShapes = model.HavokCollisionShapes; for (int i = 0; i < havokCollisionShapes.Length; i++) { flag = MyPhysics.IsPenetratingShapeShape(shape, ref center, ref Quaternion.Identity, havokCollisionShapes[i], ref vectord2, ref quaternion); if (flag) { break; } } } } } finally { shape.RemoveReference(); } return(flag); }
public ulong AddObject(BoundingBoxD bbox, Vector3 velocity, IMyActivationHandler activationHandler, ulong?customId) { if (SingleCluster.HasValue && m_clusters.Count == 0) { BoundingBoxD bb = SingleCluster.Value; bb.Inflate(200); //inflate 200m so objects near world border have AABB inside => physics created CreateCluster(ref bb); } BoundingBoxD inflatedBBox; if (SingleCluster.HasValue) { inflatedBBox = bbox; } else { inflatedBBox = bbox.GetInflated(MinimumDistanceFromBorder); } m_clusterTree.OverlapAllBoundingBox(ref inflatedBBox, m_returnedClusters); MyCluster cluster = null; bool needReorder = false; if (m_returnedClusters.Count == 1) { if (m_returnedClusters[0].AABB.Contains(inflatedBBox) == ContainmentType.Contains) { cluster = m_returnedClusters[0]; } else if (m_returnedClusters[0].AABB.Contains(inflatedBBox) == ContainmentType.Intersects && activationHandler.IsStaticForCluster) { if (m_returnedClusters[0].AABB.Contains(bbox) == ContainmentType.Disjoint) { //completely out } else { cluster = m_returnedClusters[0]; } } else { needReorder = true; } } else if (m_returnedClusters.Count > 1) { needReorder = true; } else if (m_returnedClusters.Count == 0) { if (!activationHandler.IsStaticForCluster) { var clusterBB = new BoundingBoxD(bbox.Center - IdealClusterSize / 2, bbox.Center + IdealClusterSize / 2); m_clusterTree.OverlapAllBoundingBox(ref clusterBB, m_returnedClusters); if (m_returnedClusters.Count == 0) { //Space is empty, create new cluster m_staticTree.OverlapAllBoundingBox(ref clusterBB, m_objectDataResultList); cluster = CreateCluster(ref clusterBB); foreach (var ob in m_objectDataResultList) { System.Diagnostics.Debug.Assert(m_objectsData[ob].Cluster == null, "Found object must not be in cluster!"); AddObjectToCluster(cluster, ob, false); } } else //There is still some blocking cluster { needReorder = true; } } } ulong objectId = customId.HasValue ? customId.Value : m_clusterObjectCounter++; int staticObjectId = MyDynamicAABBTreeD.NullNode; m_objectsData[objectId] = new MyObjectData() { Id = objectId, Cluster = cluster, ActivationHandler = activationHandler, AABB = bbox, StaticId = staticObjectId }; System.Diagnostics.Debug.Assert(!needReorder || (!SingleCluster.HasValue && needReorder), "Object cannot be added outside borders of a single cluster"); if (needReorder && !SingleCluster.HasValue) { System.Diagnostics.Debug.Assert(cluster == null, "Error in cluster logic"); ReorderClusters(bbox, objectId); if (!m_objectsData[objectId].ActivationHandler.IsStaticForCluster) { System.Diagnostics.Debug.Assert(m_objectsData[objectId].Cluster != null, "Object not added"); } #if DEBUG m_clusterTree.OverlapAllBoundingBox(ref bbox, m_returnedClusters); System.Diagnostics.Debug.Assert(m_returnedClusters.Count <= 1, "Clusters overlap!"); if (m_returnedClusters.Count != 0) { System.Diagnostics.Debug.Assert(activationHandler.IsStaticForCluster ? m_returnedClusters[0].AABB.Contains(inflatedBBox) != ContainmentType.Disjoint : m_returnedClusters[0].AABB.Contains(inflatedBBox) == ContainmentType.Contains, "Clusters reorder failure!"); } #endif } if (activationHandler.IsStaticForCluster) { staticObjectId = m_staticTree.AddProxy(ref bbox, objectId, 0); m_objectsData[objectId].StaticId = staticObjectId; } if (cluster != null) { return(AddObjectToCluster(cluster, objectId, false)); } else { return(objectId); } }
/// <summary> /// Casts preview grids aabbs and get shortest distance. Returns shortest intersection or null. /// </summary> protected Vector3D?GetFreeSpacePlacementPositionGridAabbs(bool copyPaste, out bool buildAllowed) { Vector3D?freePlacementIntersectionPoint = null; buildAllowed = true; float gridSize = PreviewGrids[0].GridSize; double shortestDistance = double.MaxValue; double?currentRayInts = MyCubeBuilder.GetCurrentRayIntersection(); if (currentRayInts.HasValue) { shortestDistance = currentRayInts.Value; } Vector3D worldRefPointOffset = Vector3D.Zero; if (copyPaste) { Matrix firstGridOrientation = GetFirstGridOrientationMatrix(); worldRefPointOffset = Vector3.TransformNormal(m_dragPointToPositionLocal, firstGridOrientation); } Vector3D worldRefPoint = PreviewGrids[0].GridIntegerToWorld(Vector3I.Zero); foreach (var grid in PreviewGrids) { Vector3 halfExt = grid.PositionComp.LocalAABB.HalfExtents; Vector3 minLocal = grid.Min * grid.GridSize - Vector3.Half * grid.GridSize; Vector3 maxLocal = grid.Max * grid.GridSize + Vector3.Half * grid.GridSize; MatrixD gridWorlTransform = MatrixD.Identity; gridWorlTransform.Translation = 0.5f * (minLocal + maxLocal); gridWorlTransform = gridWorlTransform * grid.WorldMatrix; Vector3I size = grid.Max - grid.Min + Vector3I.One; Vector3 sizeOffset = Vector3I.Abs((size % 2) - Vector3I.One) * 0.5 * grid.GridSize; sizeOffset = Vector3.TransformNormal(sizeOffset, grid.WorldMatrix); Vector3D offset = gridWorlTransform.Translation + worldRefPointOffset - worldRefPoint /*- sizeOffset*/;// Vector3.Zero;// gridWorlTransform.Translation + worldRefPointOffset - worldRefPoint; HkShape shape = new HkBoxShape(halfExt); Vector3D rayStart = MyCubeBuilder.IntersectionStart + offset; double castPlaneDistanceToRayStart = DistanceFromCharacterPlane(ref rayStart); rayStart -= castPlaneDistanceToRayStart * MyCubeBuilder.IntersectionDirection; Vector3D rayEnd = MyCubeBuilder.IntersectionStart + (m_dragDistance - castPlaneDistanceToRayStart) * MyCubeBuilder.IntersectionDirection + offset; MatrixD matrix = gridWorlTransform; matrix.Translation = rayStart; try { float?dist = MyPhysics.CastShape(rayEnd, shape, ref matrix, MyPhysics.CollisionLayers.CollisionLayerWithoutCharacter); if (dist.HasValue && dist.Value != 0f) { Vector3D intersectionPoint = rayStart + dist.Value * (rayEnd - rayStart); const bool debugDraw = true; if (debugDraw) { Color green = Color.Green; BoundingBoxD localAABB = new BoundingBoxD(-halfExt, halfExt); localAABB.Inflate(0.03f); MatrixD drawMatrix = matrix; drawMatrix.Translation = intersectionPoint; MySimpleObjectDraw.DrawTransparentBox(ref drawMatrix, ref localAABB, ref green, MySimpleObjectRasterizer.Wireframe, 1, 0.04f); } double fixedDistance = DistanceFromCharacterPlane(ref intersectionPoint) - castPlaneDistanceToRayStart; if (fixedDistance <= 0) { fixedDistance = 0; shortestDistance = 0; buildAllowed = false; break; } if (fixedDistance < shortestDistance) { shortestDistance = fixedDistance; } } else { buildAllowed = false; } } finally { shape.RemoveReference(); } } if (shortestDistance != 0 && shortestDistance < m_dragDistance) { freePlacementIntersectionPoint = MyCubeBuilder.IntersectionStart + shortestDistance * MyCubeBuilder.IntersectionDirection; } else { buildAllowed = false; } return(freePlacementIntersectionPoint); }
/// <summary> /// Casts preview grids aabbs and get shortest distance. Returns shortest intersection or null. /// </summary> protected Vector3D? GetFreeSpacePlacementPositionGridAabbs(bool copyPaste, out bool buildAllowed) { Vector3D? freePlacementIntersectionPoint = null; buildAllowed = true; float gridSize = PreviewGrids[0].GridSize; double shortestDistance = double.MaxValue; double? currentRayInts = GetCurrentRayIntersection(); if (currentRayInts.HasValue) shortestDistance = currentRayInts.Value; Vector3D worldRefPointOffset = Vector3D.Zero; if (copyPaste) { Matrix firstGridOrientation = GetFirstGridOrientationMatrix(); worldRefPointOffset = Vector3.TransformNormal(m_dragPointToPositionLocal, firstGridOrientation); } Vector3D worldRefPoint = PreviewGrids[0].GridIntegerToWorld(Vector3I.Zero); foreach (var grid in PreviewGrids) { Vector3 halfExt = grid.PositionComp.LocalAABB.HalfExtents; Vector3 minLocal = grid.Min * grid.GridSize - Vector3.Half * grid.GridSize; Vector3 maxLocal = grid.Max * grid.GridSize + Vector3.Half * grid.GridSize; MatrixD gridWorlTransform = MatrixD.Identity; gridWorlTransform.Translation = 0.5f * (minLocal + maxLocal); gridWorlTransform = gridWorlTransform * grid.WorldMatrix; Vector3I size = grid.Max - grid.Min + Vector3I.One; Vector3 sizeOffset = Vector3I.Abs((size % 2) - Vector3I.One) * 0.5 * grid.GridSize; sizeOffset = Vector3.TransformNormal(sizeOffset, grid.WorldMatrix); Vector3D offset = gridWorlTransform.Translation + worldRefPointOffset - worldRefPoint /*- sizeOffset*/;// Vector3.Zero;// gridWorlTransform.Translation + worldRefPointOffset - worldRefPoint; HkShape shape = new HkBoxShape(halfExt); Vector3D rayStart = MyCubeBuilder.IntersectionStart + offset; double castPlaneDistanceToRayStart = DistanceFromCharacterPlane(ref rayStart); rayStart -= castPlaneDistanceToRayStart * MyCubeBuilder.IntersectionDirection; Vector3D rayEnd = MyCubeBuilder.IntersectionStart + (m_dragDistance - castPlaneDistanceToRayStart) * MyCubeBuilder.IntersectionDirection + offset; MatrixD matrix = gridWorlTransform; matrix.Translation = rayStart; try { float? dist = MyPhysics.CastShape(rayEnd, shape, ref matrix, MyPhysics.CollisionLayerWithoutCharacter); if (dist.HasValue && dist.Value != 0f) { Vector3D intersectionPoint = rayStart + dist.Value * (rayEnd - rayStart); const bool debugDraw = true; if (debugDraw) { Color green = Color.Green; BoundingBoxD localAABB = new BoundingBoxD(-halfExt, halfExt); localAABB.Inflate(0.03f); MatrixD drawMatrix = matrix; drawMatrix.Translation = intersectionPoint; MySimpleObjectDraw.DrawTransparentBox(ref drawMatrix, ref localAABB, ref green, MySimpleObjectRasterizer.Wireframe, 1, 0.04f); } double fixedDistance = DistanceFromCharacterPlane(ref intersectionPoint) - castPlaneDistanceToRayStart; if (fixedDistance <= 0) { fixedDistance = 0; shortestDistance = 0; buildAllowed = false; break; } if (fixedDistance < shortestDistance) shortestDistance = fixedDistance; } else { buildAllowed = false; } } finally { shape.RemoveReference(); } } if (shortestDistance != 0 && shortestDistance < m_dragDistance) freePlacementIntersectionPoint = MyCubeBuilder.IntersectionStart + shortestDistance * MyCubeBuilder.IntersectionDirection; else buildAllowed = false; return freePlacementIntersectionPoint; }
protected void UpdateRenderObject() { m_actualWorldAABB = BoundingBoxD.CreateInvalid(); if (AnimationController.CharacterBones != null) for (int i = 1; i < Model.Bones.Length; i++) { Vector3D p1 = Vector3D.Transform(AnimationController.CharacterBones[i].Parent.AbsoluteTransform.Translation, WorldMatrix); Vector3D p2 = Vector3D.Transform(AnimationController.CharacterBones[i].AbsoluteTransform.Translation, WorldMatrix); m_actualWorldAABB.Include(ref p1); m_actualWorldAABB.Include(ref p2); } ContainmentType containmentType; m_aabb.Contains(ref m_actualWorldAABB, out containmentType); if (containmentType != ContainmentType.Contains) { m_actualWorldAABB.Inflate(0.5f); MatrixD worldMatrix = WorldMatrix; VRageRender.MyRenderProxy.UpdateRenderObject(Render.RenderObjectIDs[0], ref worldMatrix, false, m_actualWorldAABB); m_aabb = m_actualWorldAABB; } }
/// <summary> /// Writes all surrounding blocks around the given one with the given size. /// </summary> private void GetSurroundingBlocksFromStaticGrids(MySlimBlock block, MyCubeSize cubeSizeEnum, HashSet <MySlimBlock> outBlocks) { outBlocks.Clear(); BoundingBoxD aabbForNeighbors = new BoundingBoxD(block.Min * block.CubeGrid.GridSize, block.Max * block.CubeGrid.GridSize); BoundingBoxD aabb = new BoundingBoxD(block.Min * block.CubeGrid.GridSize - block.CubeGrid.GridSize / 2, block.Max * block.CubeGrid.GridSize + block.CubeGrid.GridSize / 2); if (block.FatBlock != null) { var aabbCenter = aabb.Center; aabb = (BoundingBoxD)block.FatBlock.Model.BoundingBox; Matrix m; block.FatBlock.Orientation.GetMatrix(out m); aabb = aabb.TransformFast(m); aabb.Translate(aabbCenter); } aabb.Inflate(0.125); var aabbWorld = aabb.TransformFast(block.CubeGrid.WorldMatrix); List <MyEntity> boxOverlapList = new List <MyEntity>(); MyEntities.GetElementsInBox(ref aabbWorld, boxOverlapList); for (int i = 0; i < boxOverlapList.Count; i++) { var cubeGrid = boxOverlapList[i] as MyCubeGrid; if (cubeGrid != null) { if (cubeGrid.IsStatic && cubeGrid != block.CubeGrid && cubeGrid.EnableSmallToLargeConnections && cubeGrid.SmallToLargeConnectionsInitialized && cubeGrid.GridSizeEnum == cubeSizeEnum) { Debug.Assert(m_tmpSlimBlocksList.Count == 0); m_tmpSlimBlocksList.Clear(); cubeGrid.GetBlocksIntersectingOBB(aabb, block.CubeGrid.WorldMatrix, m_tmpSlimBlocksList); CheckNeighborBlocks(block, aabbForNeighbors, cubeGrid, m_tmpSlimBlocksList); foreach (var slimBlock in m_tmpSlimBlocksList) { if (slimBlock.FatBlock != null) { if (slimBlock.FatBlock is MyFracturedBlock) { continue; } if (slimBlock.FatBlock.Components.Has <MyFractureComponentBase>()) { continue; } if (slimBlock.FatBlock is MyCompoundCubeBlock) { foreach (var blockInCompound in (slimBlock.FatBlock as MyCompoundCubeBlock).GetBlocks()) { if (!(blockInCompound.FatBlock.Components.Has <MyFractureComponentBase>())) { outBlocks.Add(blockInCompound); } } } else { outBlocks.Add(slimBlock); } } else { outBlocks.Add(slimBlock); } } m_tmpSlimBlocksList.Clear(); } } } boxOverlapList.Clear(); }
private bool TryFindLocationOutsideForestInternal(Vector3D? desiredLocationSize, out Vector3D location, Predicate<AreaData> predicate = null) { Vector3D desiredHalfSize = desiredLocationSize.HasValue ? desiredLocationSize.Value * 0.5f : Vector3D.Zero; desiredHalfSize.Y = 0; if (m_highLevelBoxes.Count == 0) { // no forest on the map, generate starting point bool valid = false; while (m_initialForestLocations.Count > 0 && !valid) { var potentialTreePosition = m_initialForestLocations.Dequeue(); valid = true; BoundingBoxD itemBox = new BoundingBoxD(potentialTreePosition, potentialTreePosition); itemBox.Inflate(desiredHalfSize); var entities = MyEntities.GetEntitiesInAABB(ref itemBox); foreach (var entity in entities) { if (entity is MyEnvironmentItems) continue; if (entity is MyVoxelBase) continue; var entityBox = entity.PositionComp.WorldAABB; var containment = entityBox.Intersects(itemBox); if (containment) { valid = false; break; } } entities.Clear(); if (valid) { Vector3D end = potentialTreePosition; end.Y -= 20; if (RaycastForExactPosition(potentialTreePosition, end, out location)) { d_foundEnlargingPoints.Add(location); return true; } else { valid = false; } } } location = Vector3D.Zero; return false; } else { if (!TryGetRandomAreas(m_tmpAreas)) { location = Vector3D.Zero; return false; } int areaIdx = 0; int randomStartIdx = MyUtils.GetRandomInt(m_tmpAreas.Count); while (areaIdx < m_tmpAreas.Count) { var spawnArea = m_tmpAreas[randomStartIdx]; randomStartIdx = (randomStartIdx + 1) % m_tmpAreas.Count; areaIdx++; if (!spawnArea.IsValid || spawnArea.IsFull) continue; if (predicate != null && !predicate(spawnArea.GetAreaData())) { spawnArea.IsFull = true; continue; } var spawnBox = spawnArea.ForestBox; var forestBox = spawnArea.ForestBox; spawnBox = forestBox.Inflate(desiredHalfSize); spawnBox.Inflate(new Vector3D(0.2, 0, 0.2)); // inflate for some minimum size MyBBSetSampler setSampler = new MyBBSetSampler(spawnBox.Min, spawnBox.Max); setSampler.SubtractBB(ref forestBox); RefineSampler(spawnArea, ref spawnBox, ref desiredHalfSize, setSampler); if (!setSampler.Valid) continue; Vector3D exactLocation; Vector3D samplePosition = setSampler.Sample(); if (TryGetExactLocation(spawnArea, samplePosition, 40, out exactLocation)) { location = exactLocation; d_foundEnlargingPoints.Add(exactLocation); m_tmpAreas.Clear(); return true; } else { location = Vector3D.Zero; m_tmpAreas.Clear(); return false; } } } location = Vector3D.Zero; m_tmpAreas.Clear(); return false; }
public ulong AddObject(BoundingBoxD bbox, IMyActivationHandler activationHandler, ulong?customId, string tag, long entityId, bool batch) { using (this.m_clustersLock.AcquireExclusiveUsing()) { BoundingBoxD inflated; ulong num5; if (this.SingleCluster.HasValue && (this.m_clusters.Count == 0)) { BoundingBoxD clusterBB = this.SingleCluster.Value; clusterBB.Inflate((double)200.0); this.CreateCluster(ref clusterBB); } if (this.SingleCluster.HasValue || this.ForcedClusters) { inflated = bbox; } else { inflated = bbox.GetInflated(MinimumDistanceFromBorder); } this.m_clusterTree.OverlapAllBoundingBox <MyCluster>(ref inflated, this.m_returnedClusters, 0, true); MyCluster cluster = null; bool flag = false; if (this.m_returnedClusters.Count == 1) { if (this.m_returnedClusters[0].AABB.Contains(inflated) == ContainmentType.Contains) { cluster = this.m_returnedClusters[0]; } else if ((this.m_returnedClusters[0].AABB.Contains(inflated) == ContainmentType.Intersects) && activationHandler.IsStaticForCluster) { if (this.m_returnedClusters[0].AABB.Contains(bbox) != ContainmentType.Disjoint) { cluster = this.m_returnedClusters[0]; } } else { flag = true; } } else if (this.m_returnedClusters.Count > 1) { if (!activationHandler.IsStaticForCluster) { flag = true; } } else if (this.m_returnedClusters.Count == 0) { if (this.SingleCluster.HasValue) { return(ulong.MaxValue); } if (!activationHandler.IsStaticForCluster) { BoundingBoxD xd3 = new BoundingBoxD(bbox.Center - ((Vector3D)(IdealClusterSize / 2f)), bbox.Center + ((Vector3D)(IdealClusterSize / 2f))); this.m_clusterTree.OverlapAllBoundingBox <MyCluster>(ref xd3, this.m_returnedClusters, 0, true); if (this.m_returnedClusters.Count == 0) { this.m_staticTree.OverlapAllBoundingBox <ulong>(ref xd3, m_objectDataResultList, 0, true); cluster = this.CreateCluster(ref xd3); foreach (ulong num in m_objectDataResultList) { if (this.m_objectsData[num].Cluster == null) { this.AddObjectToCluster(cluster, num, false); } } } else { flag = true; } } } ulong objectId = customId.HasValue ? customId.Value : num5; int num3 = -1; MyObjectData data = new MyObjectData { Id = objectId, Cluster = cluster, ActivationHandler = activationHandler, AABB = bbox, StaticId = num3, Tag = tag, EntityId = entityId }; this.m_objectsData[objectId] = data; if ((flag && !this.SingleCluster.HasValue) && !this.ForcedClusters) { this.ReorderClusters(bbox, objectId); bool isStaticForCluster = this.m_objectsData[objectId].ActivationHandler.IsStaticForCluster; } if (activationHandler.IsStaticForCluster) { num3 = this.m_staticTree.AddProxy(ref bbox, objectId, 0, true); this.m_objectsData[objectId].StaticId = num3; } if (cluster != null) { return(this.AddObjectToCluster(cluster, objectId, batch)); } return(objectId); } }
private Vector3D?FindSuitableJumpLocation(Vector3D desiredLocation) { BoundingBoxD shipBBox = GetAggregateBBox(); // 1 Km distante to other objects to prevent spawning in bases shipBBox.Inflate(1000f); BoundingBoxD regionBBox = shipBBox.GetInflated(shipBBox.HalfExtents * 10); regionBBox.Translate(desiredLocation - regionBBox.Center); MyProceduralWorldGenerator.Static.OverlapAllPlanetSeedsInSphere(new BoundingSphereD(regionBBox.Center, regionBBox.HalfExtents.AbsMax()), m_objectsInRange); Vector3D currentSearchPosition = desiredLocation; foreach (var planet in m_objectsInRange) { if (planet.BoundingVolume.Contains(currentSearchPosition) != ContainmentType.Disjoint) { Vector3D v = currentSearchPosition - planet.BoundingVolume.Center; v.Normalize(); v *= planet.BoundingVolume.HalfExtents * 1.5; currentSearchPosition = planet.BoundingVolume.Center + v; break; } } m_objectsInRange.Clear(); MyProceduralWorldGenerator.Static.OverlapAllAsteroidSeedsInSphere(new BoundingSphereD(regionBBox.Center, regionBBox.HalfExtents.AbsMax()), m_objectsInRange); foreach (var asteroid in m_objectsInRange) { m_obstaclesInRange.Add(asteroid.BoundingVolume); } m_objectsInRange.Clear(); MyGamePruningStructure.GetTopMostEntitiesInBox(ref regionBBox, m_entitiesInRange); // Inflate the obstacles so we only need to check the center of the ship for collisions foreach (var entity in m_entitiesInRange) { if (!(entity is MyPlanet)) { m_obstaclesInRange.Add(entity.PositionComp.WorldAABB.GetInflated(shipBBox.HalfExtents)); } } int maxStepCount = 10; int stepCount = 0; // When we collide with an obsticle, we add it here BoundingBoxD?aggregateCollidedObstacles = null; bool obstructed = false; bool found = false; while (stepCount < maxStepCount) { stepCount++; obstructed = false; foreach (var obstacle in m_obstaclesInRange) { var contains = obstacle.Contains(currentSearchPosition); if (contains == ContainmentType.Contains || contains == ContainmentType.Intersects) { if (!aggregateCollidedObstacles.HasValue) { aggregateCollidedObstacles = obstacle; } aggregateCollidedObstacles = aggregateCollidedObstacles.Value.Include(obstacle); aggregateCollidedObstacles = aggregateCollidedObstacles.Value.Inflate(1.0); currentSearchPosition = ClosestPointOnBounds(aggregateCollidedObstacles.Value, currentSearchPosition); obstructed = true; break; } } if (!obstructed) { // No obstacle found, return current search position found = true; break; } } m_obstaclesInRange.Clear(); m_entitiesInRange.Clear(); m_objectsInRange.Clear(); if (found) { return(currentSearchPosition); } else { return(null); } }