/// <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);
            }
        }
Exemplo n.º 2
0
        /// <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);
        }
Exemplo n.º 3
0
        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();
        }
Exemplo n.º 4
0
        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);
        }
Exemplo n.º 5
0
        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);
                    }
                }
            }
        }
Exemplo n.º 6
0
        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);
        }
Exemplo n.º 10
0
        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);
        }
Exemplo n.º 11
0
        /**
         * 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);
        }
Exemplo n.º 12
0
        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);
        }
Exemplo n.º 13
0
        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);
            }
        }
Exemplo n.º 14
0
        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;
        }
Exemplo n.º 16
0
        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;
        }
Exemplo n.º 17
0
        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);
        }
Exemplo n.º 19
0
        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;
        }
Exemplo n.º 20
0
        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);
        }
Exemplo n.º 21
0
        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);
        }
Exemplo n.º 23
0
        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;
        }
Exemplo n.º 24
0
        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);
        }
Exemplo n.º 25
0
        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;
                        }
                    }
                }
            }
        }
Exemplo n.º 27
0
        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);
        }
Exemplo n.º 28
0
        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);
        }