/// <summary> /// Returns small block add direction (returns large block add normal). /// Assumes that smallBlockWorldAabb intersects largeBlockWorldAabb and smallBlockWorldAabbReduced does not intersects largeBlockWorldAabb. /// </summary> private Vector3I GetSmallBlockAddDirection(ref BoundingBoxD smallBlockWorldAabb, ref BoundingBoxD smallBlockWorldAabbReduced, ref BoundingBoxD largeBlockWorldAabb) { Debug.Assert(largeBlockWorldAabb.Intersects(smallBlockWorldAabb)); Debug.Assert(!largeBlockWorldAabb.Intersects(smallBlockWorldAabbReduced)); if (smallBlockWorldAabbReduced.Min.X > largeBlockWorldAabb.Max.X && smallBlockWorldAabb.Min.X <= largeBlockWorldAabb.Max.X) { return(Vector3I.UnitX); } else if (smallBlockWorldAabbReduced.Max.X < largeBlockWorldAabb.Min.X && smallBlockWorldAabb.Max.X >= largeBlockWorldAabb.Min.X) { return(-Vector3I.UnitX); } if (smallBlockWorldAabbReduced.Min.Y > largeBlockWorldAabb.Max.Y && smallBlockWorldAabb.Min.Y <= largeBlockWorldAabb.Max.Y) { return(Vector3I.UnitY); } else if (smallBlockWorldAabbReduced.Max.Y < largeBlockWorldAabb.Min.Y && smallBlockWorldAabb.Max.Y >= largeBlockWorldAabb.Min.Y) { return(-Vector3I.UnitY); } if (smallBlockWorldAabbReduced.Min.Z > largeBlockWorldAabb.Max.Z && smallBlockWorldAabb.Min.Z <= largeBlockWorldAabb.Max.Z) { return(Vector3I.UnitZ); } else { Debug.Assert(smallBlockWorldAabbReduced.Max.Z < largeBlockWorldAabb.Min.Z && smallBlockWorldAabb.Max.Z >= largeBlockWorldAabb.Min.Z); return(-Vector3I.UnitZ); } }
/// <summary> /// <para>Uses IMyEntities.GetEntities to get entities in AABB</para> /// <para>Always use over GetEntitiesInAABB_Safe() when blocks are not needed, much faster.</para> /// </summary> /// <param name="preCollect">applied before intersection test</param> public static void GetEntitiesInAABB_Safe_NoBlock(this IMyEntities entitiesObject, BoundingBoxD boundingBox, HashSet <IMyEntity> entities, Func <IMyEntity, bool> preCollect = null) { Func <IMyEntity, bool> collector; if (preCollect == null) { collector = (entity) => boundingBox.Intersects(entity.WorldAABB); } else { collector = (entity) => { return(preCollect(entity) && boundingBox.Intersects(entity.WorldAABB)); } }; entitiesObject.GetEntities_Safe(entities, collector); }
private void CheckAndDamagePlayer() { var character = MyAPIGateway.Session.Player?.Controller?.ControlledEntity?.Entity as IMyCharacter; if (character == null) { return; } var damageBlock = Profiler.Start("0.ShipyardMod.ShipyardCore", nameof(CheckAndDamagePlayer)); BoundingBoxD charbox = character.WorldAABB; MyAPIGateway.Parallel.ForEach(Communication.LineDict.Values.ToArray(), lineList => { foreach (LineItem line in lineList) { var ray = new Ray(line.Start, line.End - line.Start); double?intersection = charbox.Intersects(ray); if (intersection.HasValue) { if (Vector3D.DistanceSquared(charbox.Center, line.Start) < Vector3D.DistanceSquared(line.Start, line.End)) { Utilities.Invoke(() => character.DoDamage(5, MyStringHash.GetOrCompute("ShipyardLaser"), true)); } } } }); damageBlock.End(); }
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); }
private IEnumerable <MyTuple <Vector4I, Vector4D> > GetSpawnsIn(Vector4I cell, BoundingBoxD aabbGlobal, Func <BoundingBoxD, bool> test) { var aabb = GetNodeAABB(cell); if (!aabbGlobal.Intersects(aabb)) { yield break; } if (test != null && !test.Invoke(aabb)) { yield break; } var densityNoise = m_densityNoise.GetValue(aabb.Center) * m_depth; var depthDensity = (int)MyMath.Clamp((float)Math.Floor(densityNoise), 0, m_depth - 1); if (depthDensity <= cell.W) { var localDensity = densityNoise - depthDensity; // When local density is zero we just came from a subdivision which means there is a (1/8) chance. When it is one we want 100% chance. var probability = (1 + localDensity * 7) / 8.0; var placementRoll = MyMath.Clamp((float)(m_probabilityModule.GetValue(aabb.Center) + 1) / 2, 0, 1); if (placementRoll <= probability) { yield break; } // Try to spawn in this cell. var placement = new Vector3(SampleNoiseNorm(m_placementNoise[0], aabb.Center), SampleNoiseNorm(m_placementNoise[1], aabb.Center), SampleNoiseNorm(m_placementNoise[2], aabb.Center)); var warp = new Vector3(SampleNoiseNorm(m_warpNoise[0], aabb.Center), SampleNoiseNorm(m_warpNoise[1], aabb.Center), SampleNoiseNorm(m_warpNoise[2], aabb.Center)); var localPos = Vector3.Clamp((warp * 0.25f) + (placement * 0.75f), Vector3.MinusOne, Vector3.One); var worldPos = aabb.Center + aabb.HalfExtents * localPos; yield return(MyTuple.Create(cell, new Vector4D(worldPos, densityNoise / m_depth))); } else { // Subdivide. for (var i = 0; i < 8; i++) { var x = (cell.X << 1) | (i & 1); var y = (cell.Y << 1) | ((i >> 1) & 1); var z = (cell.Z << 1) | ((i >> 2) & 1); foreach (var k in GetSpawnsIn(new Vector4I(x, y, z, cell.W + 1), aabbGlobal, test)) { yield return(k); } } } }
public void SubtractBB(ref BoundingBoxD bb) { if (m_bBox.Intersects(ref bb) == false) { return; } BoundingBoxD intersected = m_bBox.Intersect(bb); m_sampler.Subtract(ref m_bBox, ref intersected); }
public static bool IntersectPoints(this BoundingBoxD boundingBox, Vector3D position, Vector3D target, out Vector3D?hitIngoing, out Vector3D?hitOutgoing) { //if (!Sandbox.Game.Entities.MyEntities.IsRaycastBlocked(position, target)) //{ // hitIngoing = null; // hitOutgoing = null; // return false; //} // big enough for planets double outbound = 200000; var direction = Vector3D.Normalize(target - position); var ray = new RayD(position + direction * -outbound, Vector3D.Normalize(direction * outbound)); var interset = boundingBox.Intersects(ray); if (interset.HasValue) { hitIngoing = position + direction * -outbound + (direction * interset.Value); } else { hitIngoing = null; } direction = Vector3D.Normalize(position - target); ray = new RayD(target + direction * -outbound, Vector3D.Normalize(direction * outbound)); interset = boundingBox.Intersects(ray); if (interset.HasValue) { hitOutgoing = target + direction * -outbound + (direction * interset.Value); } else { hitOutgoing = null; } return(hitIngoing.HasValue && hitOutgoing.HasValue); }
public bool Contains(IMyEntity entity) { switch (Shape) { case ProtectionAreaShape.Cube: var boundingBox = new BoundingBoxD(new Vector3D(Center.X - Size, Center.Y - Size, Center.Z - Size), new Vector3D(Center.X + Size, Center.Y + Size, Center.Z + Size)); return boundingBox.Intersects(entity.WorldAABB); case ProtectionAreaShape.Sphere: var boundingSphere = new BoundingSphereD(Center, Size); return boundingSphere.Intersects(entity.WorldAABB); } return false; }
public bool Contains(BoundingBoxD boundingbox) { switch (Shape) { case ProtectionAreaShape.Cube: var boundingBox = new BoundingBoxD(Center - Size, Center + Size); return(boundingBox.Intersects(boundingbox)); case ProtectionAreaShape.Sphere: var boundingSphere = new BoundingSphereD(Center, Size); return(boundingSphere.Intersects(boundingbox)); } return(false); }
public bool Contains(IMyEntity entity) { switch (Shape) { case ProtectionAreaShape.Cube: var boundingBox = new BoundingBoxD(new Vector3D(Center.X - Size, Center.Y - Size, Center.Z - Size), new Vector3D(Center.X + Size, Center.Y + Size, Center.Z + Size)); return(boundingBox.Intersects(entity.WorldAABB)); case ProtectionAreaShape.Sphere: var boundingSphere = new BoundingSphereD(Center, Size); return(boundingSphere.Intersects(entity.WorldAABB)); } return(false); }
/** * Project a position to a face of the (-1, -1, -1)(1, 1, 1) cube. */ public static void ProjectToNearestFace(ref Vector3D localPos, out Vector3 faceCoords) { Vector3D gravity; Vector3D.Normalize(ref localPos, out gravity); gravity = -gravity; RayD r = new RayD(localPos, gravity); double?travel = s_unitsBox.Intersects(r); Debug.Assert(travel.HasValue, "Ray does not intersect with planet!"); faceCoords = localPos + (Vector3D)(gravity * travel); }
public float GetVoxelContentInBoundingBox_Obsolete(BoundingBoxD worldAabb, out float cellCount) { MyPrecalcComponent.AssertUpdateThread(); cellCount = 0; float result = 0; 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_tempStorage.Resize(minCorner, maxCorner); Storage.ReadRange(m_tempStorage, MyStorageDataTypeFlags.Content, 0, ref minCorner, ref maxCorner); BoundingBoxD voxelBox; 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 - StorageMin * MyVoxelConstants.VOXEL_SIZE_IN_METRES, ref coord, out voxelBox); if (worldAabb.Intersects(voxelBox)) { float content = m_tempStorage.Content(ref cache) / MyVoxelConstants.VOXEL_CONTENT_FULL_FLOAT; float containPercent = (float)(worldAabb.Intersect(voxelBox).Volume / MyVoxelConstants.VOXEL_VOLUME_IN_METERS); result += content * containPercent; cellCount += containPercent; } } } } return(result); }
protected bool GetCubeAddAndRemovePositions(Vector3I intersectedCube, bool placingSmallGridOnLargeStatic, out Vector3I addPos, out Vector3I addDir, out Vector3I removePos) { bool flag = false; addPos = new Vector3I(); addDir = new Vector3I(); removePos = new Vector3I(); MatrixD worldMatrixInvScaled = this.CurrentGrid.PositionComp.WorldMatrixInvScaled; addPos = intersectedCube; addDir = Vector3I.Forward; Vector3D position = Vector3D.Transform(IntersectionStart, worldMatrixInvScaled); Vector3D direction = Vector3D.Normalize(Vector3D.TransformNormal(IntersectionDirection, worldMatrixInvScaled)); RayD ray = new RayD(position, direction); int num = 0; while (true) { if (num < 100) { BoundingBoxD cubeBoundingBox = this.GetCubeBoundingBox(addPos); if (placingSmallGridOnLargeStatic || (cubeBoundingBox.Contains(position) != ContainmentType.Contains)) { double?nullable = cubeBoundingBox.Intersects(ray); if (nullable != null) { removePos = addPos; Vector3I vectori = Vector3I.Sign(Vector3.DominantAxisProjection((Vector3)((position + (direction * nullable.Value)) - (removePos * this.CurrentGrid.GridSize)))); addPos = (Vector3I)(removePos + vectori); addDir = vectori; if (this.CurrentGrid.CubeExists(addPos)) { num++; continue; } flag = true; } } } return(flag); } }
private void GeneratePhysicalShapeForBox(ref Vector3I increment, ref BoundingBoxD shapeBox) { if (!shapeBox.Intersects(PositionComp.WorldAABB)) { return; } Vector3I minCorner, maxCorner; MyVoxelCoordSystems.WorldPositionToVoxelCoord(PositionLeftBottomCorner, ref shapeBox.Min, out minCorner); MyVoxelCoordSystems.WorldPositionToVoxelCoord(PositionLeftBottomCorner, ref shapeBox.Max, out maxCorner); minCorner /= PHYSICS_SECTOR_SIZE_METERS; maxCorner /= PHYSICS_SECTOR_SIZE_METERS; for (var it = new Vector3I_RangeIterator(ref minCorner, ref maxCorner); it.IsValid(); it.MoveNext()) { ProfilerShort.Begin("Myplanet::create physics shape"); CreateVoxelPhysics(ref increment, ref it); ProfilerShort.End(); } }
public bool SpawnInventoryContainer(bool spawnAboveEntity = true) { //TODO: this should not be here but we have to know if session is being closed if so then no new entity will be created. // Entity closing method and event should have parameter with sessionIsClosing. if (Sandbox.Game.World.MySession.Static == null || !Sandbox.Game.World.MySession.Static.Ready) return false; var ownerEntity = Entity as MyEntity; for (int i = 0; i < ownerEntity.InventoryCount; ++i) { var inventory = ownerEntity.GetInventory(i); if (inventory != null && inventory.GetItemsCount() > 0) { MyEntity inventoryOwner = Entity as MyEntity; var worldMatrix = inventoryOwner.WorldMatrix; if (spawnAboveEntity) { Vector3 upDir = -Sandbox.Game.GameSystems.MyGravityProviderSystem.CalculateNaturalGravityInPoint(inventoryOwner.PositionComp.GetPosition()); if (upDir == Vector3.Zero) upDir = Vector3.Up; upDir.Normalize(); Vector3 forwardDir = Vector3.CalculatePerpendicularVector(upDir); var ownerPosition = worldMatrix.Translation; var ownerAabb = inventoryOwner.PositionComp.WorldAABB; for (int moveIter = 0; moveIter < 20; ++moveIter) { var newPosition = ownerPosition + 0.1f * moveIter * upDir + 0.1f * moveIter * forwardDir; var aabb = new BoundingBoxD(newPosition - 0.25 * Vector3D.One, newPosition + 0.25 * Vector3D.One); if (!aabb.Intersects(ref ownerAabb)) { // Move newPosition a little to avoid collision with fractured pieces. worldMatrix.Translation = newPosition + 0.25f * upDir; break; } } if (worldMatrix.Translation == ownerPosition) worldMatrix.Translation += upDir + forwardDir; } else { var model = (inventoryOwner.Render.ModelStorage as MyModel); if (model != null) { Vector3 modelCenter = model.BoundingBox.Center; Vector3 translationToCenter = Vector3.Transform(modelCenter, worldMatrix); worldMatrix.Translation = translationToCenter; } } MyContainerDefinition entityDefinition; if (!MyComponentContainerExtension.TryGetContainerDefinition(m_containerDefinition.TypeId, m_containerDefinition.SubtypeId, out entityDefinition)) { System.Diagnostics.Debug.Fail("Container Definition: " + m_containerDefinition.ToString() + " was not found!"); return false; } MyEntity entity = MyEntities.CreateFromComponentContainerDefinitionAndAdd(entityDefinition.Id); System.Diagnostics.Debug.Assert(entity != null); if (entity == null) return false; entity.PositionComp.SetWorldMatrix(worldMatrix); System.Diagnostics.Debug.Assert(inventoryOwner != null, "Owner is not set!"); if (inventoryOwner.InventoryCount == 1) { inventoryOwner.Components.Remove<MyInventoryBase>(); } else { var aggregate = inventoryOwner.GetInventoryBase() as MyInventoryAggregate; if (aggregate != null) { aggregate.RemoveComponent(inventory); } else { System.Diagnostics.Debug.Fail("Inventory owners indicates that it owns more inventories, but doesn't have aggregate?"); return false; } } // Replaces bag default inventory with existing one. entity.Components.Add<MyInventoryBase>(inventory); inventory.RemoveEntityOnEmpty = true; entity.Physics.LinearVelocity = Vector3.Zero; entity.Physics.AngularVelocity = Vector3.Zero; if (ownerEntity.Physics != null) { entity.Physics.LinearVelocity = ownerEntity.Physics.LinearVelocity; entity.Physics.AngularVelocity = ownerEntity.Physics.AngularVelocity; } else if (ownerEntity is MyCubeBlock) { var grid = (ownerEntity as MyCubeBlock).CubeGrid; if (grid.Physics != null) { entity.Physics.LinearVelocity = grid.Physics.LinearVelocity; entity.Physics.AngularVelocity = grid.Physics.AngularVelocity; } } return true; } } return false; }
public float GetVoxelContentInBoundingBox_Obsolete(BoundingBoxD worldAabb, out float cellCount) { MyPrecalcComponent.AssertUpdateThread(); cellCount = 0; float result = 0; 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; 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 - StorageMin * MyVoxelConstants.VOXEL_SIZE_IN_METRES, ref coord, out voxelBox); if (worldAabb.Intersects(voxelBox)) { float content = m_storageCache.Content(ref cache) / MyVoxelConstants.VOXEL_CONTENT_FULL_FLOAT; float containPercent = (float)(worldAabb.Intersect(voxelBox).Volume / MyVoxelConstants.VOXEL_VOLUME_IN_METERS); result += content * containPercent; cellCount += containPercent; } } } } return result; }
private bool ExtractStationIntersect(bool tightIntersection) { // Make a shortlist of station Entities in the bounding box of the asteroid. var asteroidWorldAABB = new BoundingBoxD(DataModel.ContentBounds.Min + DataModel.PositionAndOrientation.Value.Position, DataModel.ContentBounds.Max + DataModel.PositionAndOrientation.Value.Position); var stations = MainViewModel.GetIntersectingEntities(asteroidWorldAABB).Where(e => e.ClassType == ClassType.Station).Cast <StructureCubeGridModel>().ToList(); if (stations.Count == 0) { return(false); } var modified = false; var sourceFile = DataModel.SourceVoxelFilepath ?? DataModel.VoxelFilepath; var asteroid = new MyVoxelMap(); asteroid.Load(sourceFile, SpaceEngineersCore.Resources.GetDefaultMaterialName(), true); var total = stations.Sum(s => s.CubeGrid.CubeBlocks.Count); MainViewModel.ResetProgress(0, total); // Search through station entities cubes for intersection with this voxel. foreach (var station in stations) { var quaternion = station.PositionAndOrientation.Value.ToQuaternion(); foreach (var cube in station.CubeGrid.CubeBlocks) { MainViewModel.IncrementProgress(); var definition = SpaceEngineersApi.GetCubeDefinition(cube.TypeId, station.CubeGrid.GridSizeEnum, cube.SubtypeName); var orientSize = definition.Size.Transform(cube.BlockOrientation).Abs(); var min = cube.Min.ToVector3() * station.CubeGrid.GridSizeEnum.ToLength(); var max = (cube.Min + orientSize) * station.CubeGrid.GridSizeEnum.ToLength(); var p1 = Vector3D.Transform(min, quaternion) + station.PositionAndOrientation.Value.Position - (station.CubeGrid.GridSizeEnum.ToLength() / 2); var p2 = Vector3D.Transform(max, quaternion) + station.PositionAndOrientation.Value.Position - (station.CubeGrid.GridSizeEnum.ToLength() / 2); var cubeWorldAABB = new BoundingBoxD(Vector3.Min(p1, p2), Vector3.Max(p1, p2)); // find worldAABB of block. if (asteroidWorldAABB.Intersects(cubeWorldAABB)) { var pointMin = new Vector3I(cubeWorldAABB.Min - DataModel.PositionAndOrientation.Value.Position); var pointMax = new Vector3I(cubeWorldAABB.Max - DataModel.PositionAndOrientation.Value.Position); Vector3I coords; for (coords.Z = pointMin.Z; coords.Z <= pointMax.Z; coords.Z++) { for (coords.Y = pointMin.Y; coords.Y <= pointMax.Y; coords.Y++) { for (coords.X = pointMin.X; coords.X <= pointMax.X; coords.X++) { if (coords.X >= 0 && coords.Y >= 0 && coords.Z >= 0 && coords.X < asteroid.Size.X && coords.Y < asteroid.Size.Y && coords.Z < asteroid.Size.Z) { asteroid.SetVoxelContent(0, ref coords); } } } } modified = true; } } } MainViewModel.ClearProgress(); if (modified) { var tempfilename = TempfileUtil.NewFilename(MyVoxelMap.V2FileExtension); asteroid.Save(tempfilename); // replaces the existing asteroid file, as it is still the same size and dimentions. DataModel.SourceVoxelFilepath = tempfilename; } return(modified); }
/// <summary> /// Adds small/large block static connections and creates links. Returns true if the block connects to any other block. /// </summary> internal bool AddBlockSmallToLargeConnection(MySlimBlock block) { if (!Sync.IsServer) { return(false); } if (!m_smallToLargeCheckEnabled) { return(true); } if (!block.CubeGrid.IsStatic || block.FatBlock == null) { return(false); } bool retval = false; if (block.FatBlock is MyCompoundCubeBlock) { MyCompoundCubeBlock compoundBlock = block.FatBlock as MyCompoundCubeBlock; foreach (var blockInCompound in compoundBlock.GetBlocks()) { bool localRetVal = AddBlockSmallToLargeConnection(blockInCompound); retval = retval || localRetVal; } return(retval); } MyCubeSize searchCubeSize = block.BlockDefinition.CubeSize == MyCubeSize.Large ? MyCubeSize.Small : MyCubeSize.Large; GetSurroundingBlocksFromStaticGrids(block, searchCubeSize, m_tmpBlocks); if (m_tmpBlocks.Count == 0) { return(false); } float smallGridSize = MyDefinitionManager.Static.GetCubeSize(MyCubeSize.Small); BoundingBoxD blockAabb; block.GetWorldBoundingBox(out blockAabb); blockAabb.Inflate(0.05); if (block.BlockDefinition.CubeSize == MyCubeSize.Large) { foreach (var smallBlock in m_tmpBlocks) { Debug.Assert(smallBlock.CubeGrid.GridSizeEnum == MyCubeSize.Small); BoundingBoxD smallAabb = smallBlock.PositionComp.WorldAABB; if (!smallAabb.Intersects(blockAabb)) { continue; } if (SmallBlockConnectsToLarge(smallBlock.SlimBlock, ref smallAabb, block, ref blockAabb)) { ConnectSmallToLargeBlock(smallBlock.SlimBlock, block); retval = true; } } } else { Debug.Assert(block.BlockDefinition.CubeSize == MyCubeSize.Small); foreach (var largeBlock in m_tmpBlocks) { Debug.Assert(largeBlock.BlockDefinition.CubeSize == MyCubeSize.Large); BoundingBoxD largeAabb = largeBlock.PositionComp.WorldAABB; if (!largeAabb.Intersects(blockAabb)) { continue; } if (SmallBlockConnectsToLarge(block, ref blockAabb, largeBlock.SlimBlock, ref largeAabb)) { ConnectSmallToLargeBlock(block, largeBlock.SlimBlock); retval = true; } } } return(retval); }
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; }
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 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. One of the given AABB's is inflated with 0.05 to reduce inaccuracies. /// </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(GetCubeSize(smallBlock) == MyCubeSize.Small); Debug.Assert(GetCubeSize(largeBlock) == 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.Intersects(smallBlockWorldAabbReduced); if (!penetratesAabbs) { Vector3I addDir = GetSmallBlockAddDirection(ref smallBlockWorldAabb, ref smallBlockWorldAabbReduced, ref largeBlockWorldAabb); // 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); }
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; }
public bool ExtractStationIntersect(IMainView mainViewModel, bool tightIntersection) { // Make a shortlist of station Entities in the bounding box of the asteroid. var asteroidWorldAABB = new BoundingBoxD((Vector3D)ContentBounds.Min + PositionAndOrientation.Value.Position, (Vector3D)ContentBounds.Max + PositionAndOrientation.Value.Position); var stations = mainViewModel.GetIntersectingEntities(asteroidWorldAABB).Where(e => e.ClassType == ClassType.LargeStation).Cast <StructureCubeGridModel>().ToList(); if (stations.Count == 0) { return(false); } var modified = false; var sourceFile = SourceVoxelFilepath ?? VoxelFilepath; var asteroid = new MyVoxelMap(); asteroid.Load(sourceFile); var total = stations.Sum(s => s.CubeGrid.CubeBlocks.Count); mainViewModel.ResetProgress(0, total); // Search through station entities cubes for intersection with this voxel. foreach (var station in stations) { var quaternion = station.PositionAndOrientation.Value.ToQuaternion(); foreach (var cube in station.CubeGrid.CubeBlocks) { mainViewModel.IncrementProgress(); var definition = SpaceEngineersApi.GetCubeDefinition(cube.TypeId, station.CubeGrid.GridSizeEnum, cube.SubtypeName); var orientSize = definition.Size.Transform(cube.BlockOrientation).Abs(); var min = cube.Min.ToVector3() * station.CubeGrid.GridSizeEnum.ToLength(); var max = (cube.Min + orientSize) * station.CubeGrid.GridSizeEnum.ToLength(); var p1 = Vector3D.Transform(min, quaternion) + station.PositionAndOrientation.Value.Position - (station.CubeGrid.GridSizeEnum.ToLength() / 2); var p2 = Vector3D.Transform(max, quaternion) + station.PositionAndOrientation.Value.Position - (station.CubeGrid.GridSizeEnum.ToLength() / 2); var cubeWorldAABB = new BoundingBoxD(Vector3.Min(p1, p2), Vector3.Max(p1, p2)); // find worldAABB of block. if (asteroidWorldAABB.Intersects(cubeWorldAABB)) { Vector3I block; var cacheSize = new Vector3I(64); Vector3D position = PositionAndOrientation.Value.Position; // read the asteroid in chunks of 64 to avoid the Arithmetic overflow issue. for (block.Z = 0; block.Z < asteroid.Storage.Size.Z; block.Z += 64) { for (block.Y = 0; block.Y < asteroid.Storage.Size.Y; block.Y += 64) { for (block.X = 0; block.X < asteroid.Storage.Size.X; block.X += 64) { var cache = new MyStorageData(); cache.Resize(cacheSize); // LOD1 is not detailed enough for content information on asteroids. Vector3I maxRange = block + cacheSize - 1; asteroid.Storage.ReadRange(cache, MyStorageDataTypeFlags.Content, 0, block, maxRange); bool changed = false; Vector3I p; for (p.Z = 0; p.Z < cacheSize.Z; ++p.Z) { for (p.Y = 0; p.Y < cacheSize.Y; ++p.Y) { for (p.X = 0; p.X < cacheSize.X; ++p.X) { BoundingBoxD voxelCellBox = new BoundingBoxD(position + p + block, position + p + block + 1); ContainmentType contains = cubeWorldAABB.Contains(voxelCellBox); // TODO: finish tightIntersection. Will require high interpretation of voxel content volumes. if (contains == ContainmentType.Contains || contains == ContainmentType.Intersects) { cache.Content(ref p, 0); changed = true; } } } } if (changed) { asteroid.Storage.WriteRange(cache, MyStorageDataTypeFlags.Content, block, maxRange); modified = true; } } } } } } } mainViewModel.ClearProgress(); if (modified) { var tempfilename = TempfileUtil.NewFilename(MyVoxelMap.V2FileExtension); asteroid.Save(tempfilename); // replaces the existing asteroid file, as it is still the same size and dimentions. UpdateNewSource(asteroid, tempfilename); MaterialAssets = null; InitializeAsync(); } return(modified); }
private void GeneratePhysicalShapeForBox(ref Vector3I increment, ref BoundingBoxD shapeBox) { if (!shapeBox.Intersects(PositionComp.WorldAABB)) return; Vector3I minCorner, maxCorner; MyVoxelCoordSystems.WorldPositionToVoxelCoord(PositionLeftBottomCorner, ref shapeBox.Min, out minCorner); MyVoxelCoordSystems.WorldPositionToVoxelCoord(PositionLeftBottomCorner, ref shapeBox.Max, out maxCorner); minCorner /= PHYSICS_SECTOR_SIZE_METERS; maxCorner /= PHYSICS_SECTOR_SIZE_METERS; for (var it = new Vector3I.RangeIterator(ref minCorner, ref maxCorner); it.IsValid(); it.MoveNext()) { ProfilerShort.Begin("Myplanet::create physics shape"); CreatePhysicsShape(ref increment, ref it); ProfilerShort.End(); } }
/// <summary> /// Override this function to set custom update behaviour. /// Call base at first because it queries objects if DoQuery is set. /// </summary> protected virtual void UpdateInternal() { if (DoQuery) { m_queryResult.Clear(); switch (m_triggerType) { case TriggerType.AABB: MyGamePruningStructure.GetTopMostEntitiesInBox(ref m_AABB, m_queryResult); break; case TriggerType.Sphere: MyGamePruningStructure.GetAllTopMostEntitiesInSphere(ref m_boundingSphere, m_queryResult); break; default: throw new ArgumentOutOfRangeException(); } for (int index = 0; index < m_queryResult.Count;) { var result = m_queryResult[index]; if (!QueryEvaluator(result)) { m_queryResult.RemoveAtFast(index); } else { switch (m_triggerType) { case TriggerType.AABB: if (!m_AABB.Intersects(m_queryResult[index].PositionComp.WorldAABB)) { m_queryResult.RemoveAtFast(index); } else { index++; } break; case TriggerType.Sphere: if (!m_boundingSphere.Intersects(m_queryResult[index].PositionComp.WorldAABB)) { m_queryResult.RemoveAtFast(index); } else { index++; } break; default: index++; break; } } } } }
public bool SpawnInventoryContainer(bool spawnAboveEntity = true) { //TODO: this should not be here but we have to know if session is being closed if so then no new entity will be created. // Entity closing method and event should have parameter with sessionIsClosing. if (Sandbox.Game.World.MySession.Static == null || !Sandbox.Game.World.MySession.Static.Ready) { return(false); } var ownerEntity = Entity as MyEntity; for (int i = 0; i < ownerEntity.InventoryCount; ++i) { var inventory = ownerEntity.GetInventory(i); if (inventory != null && inventory.GetItemsCount() > 0) { MyEntity inventoryOwner = Entity as MyEntity; var worldMatrix = inventoryOwner.WorldMatrix; if (spawnAboveEntity) { Vector3 upDir = -Sandbox.Game.GameSystems.MyGravityProviderSystem.CalculateNaturalGravityInPoint(inventoryOwner.PositionComp.GetPosition()); if (upDir == Vector3.Zero) { upDir = Vector3.Up; } upDir.Normalize(); Vector3 forwardDir = Vector3.CalculatePerpendicularVector(upDir); var ownerPosition = worldMatrix.Translation; var ownerAabb = inventoryOwner.PositionComp.WorldAABB; for (int moveIter = 0; moveIter < 20; ++moveIter) { var newPosition = ownerPosition + 0.1f * moveIter * upDir + 0.1f * moveIter * forwardDir; var aabb = new BoundingBoxD(newPosition - 0.25 * Vector3D.One, newPosition + 0.25 * Vector3D.One); if (!aabb.Intersects(ref ownerAabb)) { // Move newPosition a little to avoid collision with fractured pieces. worldMatrix.Translation = newPosition + 0.25f * upDir; break; } } if (worldMatrix.Translation == ownerPosition) { worldMatrix.Translation += upDir + forwardDir; } } else { var model = (inventoryOwner.Render.ModelStorage as MyModel); if (model != null) { Vector3 modelCenter = model.BoundingBox.Center; Vector3 translationToCenter = Vector3.Transform(modelCenter, worldMatrix); worldMatrix.Translation = translationToCenter; } } MyContainerDefinition entityDefinition; if (!MyComponentContainerExtension.TryGetContainerDefinition(m_containerDefinition.TypeId, m_containerDefinition.SubtypeId, out entityDefinition)) { System.Diagnostics.Debug.Fail("Container Definition: " + m_containerDefinition.ToString() + " was not found!"); return(false); } MyEntity entity = MyEntities.CreateFromComponentContainerDefinitionAndAdd(entityDefinition.Id); System.Diagnostics.Debug.Assert(entity != null); if (entity == null) { return(false); } entity.PositionComp.SetWorldMatrix(worldMatrix); System.Diagnostics.Debug.Assert(inventoryOwner != null, "Owner is not set!"); if (inventoryOwner.InventoryCount == 1) { inventoryOwner.Components.Remove <MyInventoryBase>(); } else { var aggregate = inventoryOwner.GetInventoryBase() as MyInventoryAggregate; if (aggregate != null) { aggregate.RemoveComponent(inventory); } else { System.Diagnostics.Debug.Fail("Inventory owners indicates that it owns more inventories, but doesn't have aggregate?"); return(false); } } // Replaces bag default inventory with existing one. entity.Components.Add <MyInventoryBase>(inventory); inventory.RemoveEntityOnEmpty = true; entity.Physics.LinearVelocity = Vector3.Zero; entity.Physics.AngularVelocity = Vector3.Zero; if (ownerEntity.Physics != null) { entity.Physics.LinearVelocity = ownerEntity.Physics.LinearVelocity; entity.Physics.AngularVelocity = ownerEntity.Physics.AngularVelocity; } else if (ownerEntity is MyCubeBlock) { var grid = (ownerEntity as MyCubeBlock).CubeGrid; if (grid.Physics != null) { entity.Physics.LinearVelocity = grid.Physics.LinearVelocity; entity.Physics.AngularVelocity = grid.Physics.AngularVelocity; } } return(true); } } return(false); }
public void CalculateLines() { DsWatch.Start("CLines"); try { if (closestPlanet != null) { var planetAtmosphereAltitude = closestPlanet.AtmosphereAltitude; var cameraUp = new Vector3D(Camera.Position - planetCentre); var cameraForward = Vector3D.CalculatePerpendicularVector(cameraUp); frustumMatrix = MatrixD.CreateWorld(Camera.Position, cameraForward, cameraUp); var offset = Vector3.Zero; var frustum = new BoundingFrustumD(Camera.ViewMatrix * customProjectionMatrix); frustumBBox = BoundingBoxD.CreateInvalid(); frustumBBox.Include(ref frustum); if (cameraAltitude < (planetAtmosphereAltitude / 2)) { var lineAmount = 100; for (int i = 0; i < lineAmount; i++) // Line calculation LOOP { lineThickness = MyUtils.GetRandomFloat(0.01f, 0.05f); offset.Y = (float)frustumBBox.Extents.Y; offset.X = MyUtils.GetRandomInt(-60, 60); offset.Z = MyUtils.GetRandomInt(-60, 60); if (offset.X >= 0 && offset.X < 1) { offset.X = offset.X + 1; } if (offset.Z >= 0 && offset.Z < 1) { offset.Z = offset.Z + 1; } Vector3D lineStartPoint = Vector3D.Transform(offset, frustumMatrix); Vector3D lineEndPoint = planetCentre; var length = frustumBBox.HalfExtents.Y * 0.25; // Shorten line length by 1/4 LineD lineCheck = new LineD(lineStartPoint, lineEndPoint, length); Vector3D finalHitPos = lineEndPoint; Vector3D hitPos = lineEndPoint; double? hitDist = double.MaxValue; double finalHitDistSq = double.MaxValue; var checkVoxel = true; var isVoxel = false; lineIntersectedGrids.Clear(); lineIntersectedVoxels.Clear(); if (frustumBBox.Intersects(ref lineCheck)) { for (int j = 0; j < rainImpactEntities.Count; j++) // Line calculation LOOP { var rainedOnEnt = rainImpactEntities[j]; var grid = rainedOnEnt as IMyCubeGrid; if (grid != null && grid.Physics != null) { lineIntersectedGrids.Add(rainedOnEnt); } else if (rainedOnEnt is MyVoxelBase) { lineIntersectedVoxels.Add(rainedOnEnt); } } for (int k = 0; k < lineIntersectedGrids.Count; k++) { var intersectedGrid = lineIntersectedGrids[k]; var cubeGrid = intersectedGrid as IMyCubeGrid; if (cubeGrid != null && cubeGrid.Physics != null) { MyOrientedBoundingBoxD gridOBB = new MyOrientedBoundingBoxD(cubeGrid.LocalAABB, cubeGrid.WorldMatrix); //DrawOBB(gridOBB, whiteColor, MySimpleObjectRasterizer.Wireframe, 0.01f); // If we don't intersect a grid continue. if (!gridOBB.Intersects(ref lineCheck).HasValue) { continue; } hitDist = GridHitCheck(cubeGrid, lineCheck, lineStartPoint, lineEndPoint); if (hitDist != null) { hitPos = lineStartPoint + (lineCheck.Direction * hitDist.Value); if (finalHitDistSq > hitDist.Value) { finalHitPos = hitPos; finalHitDistSq = hitDist.Value; checkVoxel = false; } } //LogGridBlockHits(finalHitDistSq, finalHitPos, cubeGrid, blk, lineColor); } } /* * if (checkVoxel) * { * for (int l = 0; l < lineIntersectedVoxels.Count; l++) * { * var intersectedVoxel = lineIntersectedVoxels[l]; * var voxelHitName = intersectedVoxel as MyVoxelBase; * if (voxelHitName != null) * { * var voxelCheck = VoxelHitCheck(voxelHitName, closestPlanet, lineStartPoint, lineEndPoint, lineCheck); * if (voxelCheck != Vector3D.Zero && voxelCheck != null) * { * finalHitPos = voxelCheck; * hitDist = Vector3D.Distance(lineStartPoint, finalHitPos); * //LogVoxelHits(hitDist, voxelHitName, finalHitPos, lineCheck.Length); * isVoxel = true; * } * } * } * } */ /* * // Log Loop sizes * if (_updateCount % 100 == 0) * { * Logging.Instance.WriteLine(rainImpactEntities.Count.ToString() + " " + * lineIntersectedGrids.Count.ToString() + " " + * lineIntersectedVoxels.Count.ToString()); * } */ //Logging.Instance.WriteLine(isVoxel.ToString()); float distanceTotal = 0f; var rainDropSize = MyUtils.GetRandomFloat(0.8f, 1.5f); var randSkip = MyUtils.GetRandomInt(8); var hasHit = hitDist.Value > 0.001 && (hitDist.Value < lineCheck.Length || isVoxel); var dropsInDistance = hasHit ? hitDist.Value / rainDropSize : lineCheck.Length / rainDropSize; //var nextStart = hasHit ? finalHitPos : lineStartPoint; //var dir = hasHit ? -lineCheck.Direction : lineCheck.Direction; var nextStart = hasHit ? finalHitPos : finalHitPos; var dir = hasHit ? -lineCheck.Direction : -lineCheck.Direction; //var nextStart = hasHit && !checkVoxel ? finalHitPos : finalHitPos; //var dir = hasHit && !checkVoxel ? -lineCheck.Direction : -lineCheck.Direction; lineColor = checkVoxel ? Color.Green : Color.White; if (checkVoxel && voxelHitName != null && _updateCount % 300 == 0) { //LogVoxelHits(hitDist, voxelHitName, finalHitPos, lineCheck.Length); } while (distanceTotal < dropsInDistance) { if (randSkip-- <= 0) { Droplet droplet; Droplets.AllocateOrCreate(out droplet); droplet.StartPoint = nextStart; droplet.Direction = dir; droplet.DrawLength = rainDropSize; droplet.LineColor = lineColor; randSkip = MyUtils.GetRandomInt(8); } distanceTotal += rainDropSize; nextStart += (dir * rainDropSize); } } } } } } catch (Exception e) { Logging.Instance.WriteLine(e.ToString()); } DsWatch.Complete(true); }