Exemple #1
0
        public static void GetExistingCubes(MyCubeGrid grid, Vector3I min, Vector3I max, BoundingSphere localSphere, bool checkDestroyed, List <IMySlimBlock> resultSet)
        {
            resultSet.Clear();
            Vector3I result1 = Vector3I.Floor((min - Vector3I.One) / 2f);
            Vector3I result2 = Vector3I.Ceiling((max - Vector3I.One) / 2f);
            var      gridMin = grid.Min;
            var      gridMax = grid.Max;

            Vector3I.Max(ref result1, ref gridMin, out result1);
            Vector3I.Min(ref result2, ref gridMax, out result2);
            Vector3I key;

            for (key.X = result1.X; key.X <= result2.X; ++key.X)
            {
                for (key.Y = result1.Y; key.Y <= result2.Y; ++key.Y)
                {
                    for (key.Z = result1.Z; key.Z <= result2.Z; ++key.Z)
                    {
                        MyCube myCube;
                        if (grid.TryGetCube(key, out myCube))
                        {
                            var block = (IMySlimBlock)myCube.CubeBlock;
                            if (checkDestroyed && block.IsDestroyed || !new BoundingBox(block.Min * grid.GridSize - grid.GridSizeHalf, block.Max * grid.GridSize + grid.GridSizeHalf).Intersects(localSphere))
                            {
                                continue;
                            }

                            resultSet.Add(block);
                        }
                    }
                }
            }
        }
Exemple #2
0
        public static void GetExistingCubes(MyCubeGrid grid, Vector3I min, Vector3I max, List <IMySlimBlock> resultSet)
        {
            resultSet.Clear();
            Vector3I result1 = Vector3I.Floor((min - Vector3I.One) / 2f);
            Vector3I result2 = Vector3I.Ceiling((max - Vector3I.One) / 2f);
            var      gridMin = grid.Min;
            var      gridMax = grid.Max;

            Vector3I.Max(ref result1, ref gridMin, out result1);
            Vector3I.Min(ref result2, ref gridMax, out result2);
            Vector3I key;

            for (key.X = result1.X; key.X <= result2.X; ++key.X)
            {
                for (key.Y = result1.Y; key.Y <= result2.Y; ++key.Y)
                {
                    for (key.Z = result1.Z; key.Z <= result2.Z; ++key.Z)
                    {
                        MyCube myCube;
                        if (grid.TryGetCube(key, out myCube))
                        {
                            resultSet.Add(myCube.CubeBlock);
                        }
                    }
                }
            }
        }
Exemple #3
0
        private static bool IntersectsVoxelSurface(OrientedBoundingBoxD box)
        {
            var data = VoxelData;

            using (PoolManager.Get(out List <MyEntity> entities))
            {
                MyGamePruningStructure.GetTopmostEntitiesInBox(box.GetAABB(), entities, MyEntityQueryType.Static);
                foreach (var ent in entities)
                {
                    if (ent is MyVoxelBase voxel && !(ent is MyVoxelPhysics))
                    {
                        var invWorld      = voxel.PositionComp.WorldMatrixInvScaled;
                        var storageBounds = BoundingBoxD.CreateInvalid();
                        var voxelOffset   = (voxel.Size >> 1) + voxel.StorageMin;
                        var storageObb    = box;
                        storageObb.Transform(invWorld);
                        storageObb.HalfExtent /= voxel.VoxelSize;
                        storageObb.Center      = storageObb.Center / voxel.VoxelSize + voxelOffset;
                        storageBounds.Include(storageObb.GetAABB());

                        var storageMin = Vector3I.Max(Vector3I.Floor(storageBounds.Min), voxel.StorageMin);
                        var storageMax = Vector3I.Min(Vector3I.Ceiling(storageBounds.Max), voxel.StorageMax);
                        var localBox   = new BoundingBoxI(storageMin, storageMax);
                        localBox.Inflate(1);
                        var floatBox = new BoundingBox(localBox);
                        if (voxel.IntersectStorage(ref floatBox) == ContainmentType.Disjoint)
                        {
                            continue;
                        }
                        data.Resize(storageMin, storageMax);
                        voxel.Storage.ReadRange(data, MyStorageDataTypeFlags.Content, 0, storageMin, storageMax);
                        foreach (var pt in new BoundingBoxI(Vector3I.Zero, storageMax - storageMin).EnumeratePoints())
                        {
                            var voxelBox    = new BoundingBoxD(storageMin + pt, storageMin + pt + 1);
                            var containment = storageObb.Contains(ref voxelBox);
                            if (containment == ContainmentType.Disjoint)
                            {
                                continue;
                            }
                            var tmpPt   = pt;
                            var index   = data.ComputeLinear(ref tmpPt);
                            var content = data.Content(index);
                            if (containment == ContainmentType.Intersects && content >= 127)
                            {
                                return(true);
                            }
                            if (containment == ContainmentType.Contains && content > 0)
                            {
                                return(true);
                            }
                        }
                    }
                }
            }

            return(false);
        }
        public override MyVoxelMaterialDefinition GetMaterialForPosition(ref Vector3 pos, float lodSize)
        {
            Vector3I cellPos = Vector3I.Ceiling(pos / DEPOSIT_MAX_SIZE);
            MyCompositeShapeOreDeposit deposit;

            if (m_deposits.TryGetValue(cellPos, out deposit) == true)
            {
                if (deposit.Shape.SignedDistance(ref pos, lodSize, null, null) == -1)
                {
                    return(deposit.GetMaterialForPosition(ref pos, lodSize));
                }
            }

            return(null);
        }
        public MyCompositeOrePlanetDeposit(MyCsgShapeBase baseShape, int seed, float minDepth, float maxDepth, MyOreProbability[] oreProbabilties, MyVoxelMaterialDefinition material) :
            base(baseShape, material)
        {
            m_minDepth = minDepth;
            double outherSphereVolume = (4.0 * MathHelper.Pi * Math.Pow(minDepth, 3.0f)) / 3.0;
            double innerSphereVolume  = (4.0 * MathHelper.Pi * Math.Pow(maxDepth, 3.0f)) / 3.0;

            double depositVolume = (4.0 * MathHelper.Pi * Math.Pow(DEPOSIT_MAX_SIZE, 3.0f)) / 3.0;
            double volume        = outherSphereVolume - innerSphereVolume;

            m_numDeposits = oreProbabilties.Length > 0 ? (int)Math.Floor((volume * 0.4f) / depositVolume) : 0;

            int numSectors = (int)(minDepth / DEPOSIT_MAX_SIZE);

            MyRandom random = MyRandom.Instance;

            FillMaterialCollections();
            Vector3D offset = -new Vector3D(DEPOSIT_MAX_SIZE / 2.0);

            using (var stateToken = random.PushSeed(seed))
            {
                for (int i = 0; i < m_numDeposits; ++i)
                {
                    Vector3D direction          = MyProceduralWorldGenerator.GetRandomDirection(random);
                    float    distanceFromCenter = random.NextFloat(maxDepth, minDepth);
                    Vector3D position           = direction * distanceFromCenter;

                    Vector3I cellPos = Vector3I.Ceiling((Shape.Center() + position) / DEPOSIT_MAX_SIZE);

                    MyCompositeShapeOreDeposit deposit;
                    if (m_deposits.TryGetValue(cellPos, out deposit) == false)
                    {
                        var oreDefinition      = GetOre(random.NextFloat(0, 1), oreProbabilties);
                        var materialDefinition = m_materialsByOreType[oreDefinition.OreName][random.Next() % m_materialsByOreType[oreDefinition.OreName].Count];
                        deposit             = new MyCompositeShapeOreDeposit(new MyCsgSimpleSphere(cellPos * DEPOSIT_MAX_SIZE + offset, random.NextFloat(64, DEPOSIT_MAX_SIZE / 2.0f)), materialDefinition);
                        m_deposits[cellPos] = deposit;
                    }
                }
            }

            m_materialsByOreType.Clear();
        }
Exemple #6
0
        /// <summary>
        /// Calculates amount of volume of a bounding box in voxels.
        /// </summary>
        /// <param name="localAabb">Local bounding box to query for.</param>
        /// <param name="worldMatrix">World matrix of the bounding box.</param>
        /// <returns>Pair of floats where 1st value is Volume amount and 2nd value is ratio of Volume amount to Whole volume.</returns>
        public MyTuple <float, float> GetVoxelContentInBoundingBox_Fast(BoundingBoxD localAabb, MatrixD worldMatrix)
        {
            MatrixD toVoxel = worldMatrix * PositionComp.WorldMatrixNormalizedInv;
            MatrixD toGrid; MatrixD.Invert(ref toVoxel, out toGrid);

            BoundingBoxD transAABB = localAabb.Transform(toVoxel);

            transAABB.Translate(SizeInMetresHalf + StorageMin);
            Vector3I minI = Vector3I.Floor(transAABB.Min);
            Vector3I maxI = Vector3I.Ceiling(transAABB.Max);

            double vol              = localAabb.Volume / MyVoxelConstants.VOXEL_VOLUME_IN_METERS;
            int    K                = Math.Max((MathHelper.Log2Ceiling((int)vol) - MathHelper.Log2Ceiling(100)) / 3, 0);
            float  voxelSizeAtLod   = MyVoxelConstants.VOXEL_SIZE_IN_METRES * (1 << K);
            float  voxelVolumeAtLod = voxelSizeAtLod * voxelSizeAtLod * voxelSizeAtLod;

            minI >>= K;
            maxI >>= K;

            // localAabb.Inflate(1 * voxelSizeAtLod);

            var offset = ((Size >> 1) + StorageMin) >> K;

            m_tempStorage.Resize(maxI - minI + 1);
            Storage.ReadRange(m_tempStorage, MyStorageDataTypeFlags.Content, K, minI, maxI);

            float resultVolume   = 0;
            float resultPercent  = 0;
            int   hitVolumeBoxes = 0;

            MyOrientedBoundingBoxD worldbbox = new MyOrientedBoundingBoxD(localAabb, worldMatrix);

            Vector3I coord, cache;

            for (coord.Z = minI.Z, cache.Z = 0; coord.Z <= maxI.Z; coord.Z++, cache.Z++)
            {
                for (coord.Y = minI.Y, cache.Y = 0; coord.Y <= maxI.Y; coord.Y++, cache.Y++)
                {
                    for (coord.X = minI.X, cache.X = 0; coord.X <= maxI.X; coord.X++, cache.X++)
                    {
                        Vector3D voxelPos = (coord - offset) * voxelSizeAtLod;

                        Vector3D gridPoint;
                        Vector3D.Transform(ref voxelPos, ref toGrid, out gridPoint);

                        ContainmentType cont;
                        //localAabb.Contains(ref gridPoint, out cont);

                        var voxelToWorld = WorldMatrix;
                        voxelToWorld.Translation -= (Vector3D)StorageMin + SizeInMetresHalf;

                        BoundingBoxD voxelBox = new BoundingBoxD();
                        voxelBox.Min = ((Vector3D)(coord) - .5) * voxelSizeAtLod;
                        voxelBox.Max = ((Vector3D)(coord) + .5) * voxelSizeAtLod;

                        MyOrientedBoundingBoxD voxelBbox = new MyOrientedBoundingBoxD(voxelBox, voxelToWorld);

                        cont = worldbbox.Contains(ref voxelBbox);

                        if (cont == ContainmentType.Disjoint)
                        {
                            //VRageRender.MyRenderProxy.DebugDrawOBB(
                            //new MyOrientedBoundingBoxD(voxelBox, voxelToWorld), Color.Red, 0.1f,
                            //true, false);
                            continue;
                        }

                        float content = m_tempStorage.Content(ref cache) / MyVoxelConstants.VOXEL_CONTENT_FULL_FLOAT;



                        //VRageRender.MyRenderProxy.DebugDrawOBB(voxelBbox, Color.Aqua, content,
                        //   true, false);

                        resultVolume  += content * voxelVolumeAtLod;
                        resultPercent += content;
                        hitVolumeBoxes++;
                    }
                }
            }

            resultPercent /= hitVolumeBoxes;
            //float localAABBVol = (float)localAabb.Volume;
            //if (localAABBVol < resultVolume)
            //    resultPercent *= (float)localAabb.Volume / resultVolume;


            //VRageRender.MyRenderProxy.DebugDrawOBB(worldbbox, Color.Yellow, 0,
            //                true, false);
            //VRageRender.MyRenderProxy.DebugWaitForFrameFinish();


            return(new MyTuple <float, float>(resultVolume, resultPercent));
        }
        public void Apply(IReadOnlyList <IMyCubeGrid> group)
        {
            var totalAABB = BoundingBoxD.CreateInvalid();

            // ReSharper disable once LoopCanBeConvertedToQuery
            foreach (var grid in group)
            {
                totalAABB = totalAABB.Include(grid.WorldAABB);
            }
            var totalSphere = new BoundingSphereD(totalAABB.Center, totalAABB.HalfExtents.Length());

            foreach (var impact in m_impactDirectionRadius)
            {
                var      speed = impact.Velocity.Length();
                var      direction = (Vector3D)impact.Velocity / speed;
                Vector3D start, end;
                {
                    var rayOffset = totalAABB.HalfExtents * 0.8 * (Vector3D)impact.Shift;
                    // mag2(rayOffset + l*direction) == radius*radius
                    // (rayOffset + l*direction)*(rayOffset + l*direction)
                    // mag2(rayOffset) + 2*l*dot(direction, rayOffset) + l*l*mag2(direction)
                    // mag2(rayOffset) - (radius*radius) + 2*l*dot(direction, rayOffset) + l*l == 0
                    var         c   = rayOffset.LengthSquared() - totalSphere.Radius * totalSphere.Radius;
                    var         b   = 2 * Vector3D.Dot(direction, rayOffset);
                    const float a   = 1;
                    var         rad = b * b - 4 * a * c;
                    if (rad <= double.Epsilon)
                    {
                        continue;
                    }
                    var lLow  = (-b - Math.Sqrt(rad)) / (2 * a);
                    var lHigh = (-b + Math.Sqrt(rad)) / (2 * a);
                    start = totalSphere.Center + rayOffset + lLow * direction;
                    end   = totalSphere.Center + rayOffset + lHigh * direction;
                }
                var ray = new RayD(start, direction);

                var bestHitLocation        = default(Vector3D);
                var bestHitDistanceSquared = double.MaxValue;
                foreach (var grid in group)
                {
                    if (!grid.WorldAABB.Intersects(ray).HasValue)
                    {
                        continue;
                    }
                    var block = grid.RayCastBlocks(start, end);
                    if (!block.HasValue)
                    {
                        continue;
                    }
                    var world    = Vector3D.Transform(block.Value * grid.GridSize, grid.WorldMatrix);
                    var distance = Vector3D.DistanceSquared(world, start);
                    if (distance > bestHitDistanceSquared)
                    {
                        continue;
                    }
                    bestHitDistanceSquared = distance;
                    bestHitLocation        = world;
                }
                if (bestHitDistanceSquared > double.MaxValue / 2)
                {
                    continue;
                }
                var impactSphere = new BoundingSphereD(bestHitLocation, impact.Radius);
                var localSphere  = new BoundingSphereD();
                var damageAmount = impact.Mass * speed * speed * (4.0 / 3.0) * Math.PI;
                var damageTotals = new Dictionary <IMySlimBlock, double>();
                foreach (var grid in group)
                {
                    if (grid.WorldAABB.Intersects(impactSphere))
                    {
                        // compute local sphere.
                        localSphere.Center = Vector3D.Transform(impactSphere.Center, grid.WorldMatrixNormalizedInv) / grid.GridSize;
                        localSphere.Radius = impactSphere.Radius / grid.GridSize;
                        var min = Vector3I.Max(Vector3I.Floor(localSphere.Center - localSphere.Radius), grid.Min);
                        var max = Vector3I.Min(Vector3I.Ceiling(localSphere.Center + localSphere.Radius), grid.Max);
                        for (var itr = new Vector3I_RangeIterator(ref min, ref max); itr.IsValid(); itr.MoveNext())
                        {
                            if (localSphere.Contains(itr.Current) == ContainmentType.Disjoint)
                            {
                                continue;
                            }
                            var block = grid.GetCubeBlock(itr.Current);
                            if (block == null)
                            {
                                continue;
                            }
                            var distanceFactor = 1 - ((Vector3D)itr.Current - localSphere.Center).LengthSquared() / (localSphere.Radius * localSphere.Radius);
                            var blockDamage    = damageAmount * distanceFactor * ((block.BlockDefinition as MyCubeBlockDefinition)?.DeformationRatio ?? 1);
                            damageTotals.AddValue(block, blockDamage);
                        }
                    }
                }
                // No idea what shape key should be.
                Logger.Debug("Apply damage to {0} blocks", damageTotals.Count);
                var hitInfo = new MyHitInfo()
                {
                    Normal = direction, Position = impactSphere.Center, Velocity = impact.Velocity, ShapeKey = 0
                };
                foreach (var kv in damageTotals)
                {
                    kv.Key.DoDamage((float)kv.Value, MyDamageType.Explosion, true, hitInfo);
                }
            }
        }
        private static bool IntersectsInternalExpensive(ref PartFromPrefab partA, ref MatrixI transformA, ref MatrixI invTransformA, ref PartFromPrefab partB, ref MatrixI transformB, ref MatrixI invTransformB, bool testOptional)
        {
            using (partA.LockSharedUsing())
                using (partB.LockSharedUsing())
                {
                    var reservedAAll = Utilities.TransformBoundingBox(partA.ReservedSpace, ref transformA);
                    var reservedBAll = Utilities.TransformBoundingBox(partB.ReservedSpace, ref transformB);

                    var reservedA = new List <MyTuple <ReservedSpace, BoundingBox> >(partA.m_reservedSpaces.Count);
                    // ReSharper disable once LoopCanBeConvertedToQuery (preserve ref)
                    foreach (var aabb in partA.m_reservedSpaces)
                    {
                        if (!aabb.IsOptional || testOptional)
                        {
                            reservedA.Add(MyTuple.Create(aabb, Utilities.TransformBoundingBox(aabb.Box, ref transformA)));
                        }
                    }

                    var reservedB = new List <MyTuple <ReservedSpace, BoundingBox> >(partB.m_reservedSpaces.Count);
                    // ReSharper disable once LoopCanBeConvertedToQuery (preserve ref)
                    foreach (var aabb in partB.m_reservedSpaces)
                    {
                        if (!aabb.IsOptional || testOptional)
                        {
                            reservedB.Add(MyTuple.Create(aabb, Utilities.TransformBoundingBox(aabb.Box, ref transformB)));
                        }
                    }

                    // Reserved spaces intersect?
                    if (partA.m_reservedSpaces.Count > 0 && partB.m_reservedSpaces.Count > 0 && reservedAAll.Intersects(reservedBAll))
                    {
                        if (reservedA.Any(x => reservedB.Any(y => !y.Item1.IsShared && !x.Item1.IsShared && x.Item2.Intersects(y.Item2))))
                        {
                            return(true);
                        }
                    }

                    var blockAAll = Utilities.TransformBoundingBox(partA.BoundingBox, ref transformA);
                    var blockBAll = Utilities.TransformBoundingBox(partB.BoundingBox, ref transformB);

                    // Block spaces intersect with reserved space?
                    if (partA.m_reservedSpaces.Count > 0 && reservedAAll.Intersects(blockBAll))
                    {
                        foreach (var aabb in reservedA)
                        {
                            var min = Vector3I.Floor(Vector3.Max(aabb.Item2.Min, blockBAll.Min));
                            var max = Vector3I.Ceiling(Vector3.Min(aabb.Item2.Max, blockBAll.Max));
                            for (var vi = new Vector3I_RangeIterator(ref min, ref max); vi.IsValid(); vi.MoveNext())
                            {
                                if (partB.CubeExists(Vector3I.Transform(vi.Current, invTransformB)))
                                {
                                    return(true);
                                }
                            }
                        }
                    }
                    if (partB.m_reservedSpaces.Count > 0 && reservedBAll.Intersects(blockAAll))
                    {
                        foreach (var aabb in reservedB)
                        {
                            var min = Vector3I.Floor(Vector3.Max(aabb.Item2.Min, blockAAll.Min));
                            var max = Vector3I.Ceiling(Vector3.Min(aabb.Item2.Max, blockAAll.Max));
                            for (var vi = new Vector3I_RangeIterator(ref min, ref max); vi.IsValid(); vi.MoveNext())
                            {
                                if (partA.CubeExists(Vector3I.Transform(vi.Current, invTransformA)))
                                {
                                    return(true);
                                }
                            }
                        }
                    }

                    // Block space intersects with block space?
                    if (!blockAAll.Intersects(blockBAll))
                    {
                        return(false);
                    }
                    if (partA.m_blocks.Count < partB.m_blocks.Count)
                    {
                        foreach (var pos in partA.m_blocks.Keys)
                        {
                            if (partB.CubeExists(Vector3I.Transform(Vector3I.Transform(pos, ref transformA), ref invTransformB)))
                            {
                                return(true);
                            }
                        }
                    }
                    else
                    {
                        foreach (var pos in partB.m_blocks.Keys)
                        {
                            if (partA.CubeExists(Vector3I.Transform(Vector3I.Transform(pos, ref transformB), ref invTransformA)))
                            {
                                return(true);
                            }
                        }
                    }
                    return(false);
                }
        }
Exemple #9
0
 private bool ApplyDelegate(MyObjectBuilder_CubeGrid grid, MyObjectBuilder_CubeBlock source, string srcName, MyObjectBuilder_CubeBlock dest, Base6Directions.Direction destDir)
 {
     if (srcName.StartsWithICase(MountDelegated))
     {
         var     lTransOrig = new MatrixI(source.BlockOrientation);
         var     lTrans     = new MatrixI(dest.BlockOrientation);
         MatrixI iTrans;
         MatrixI.Invert(ref lTrans, out iTrans);
         var arguments = PartDummyUtils.ConfigArguments(srcName.Substring(MountDelegated.Length).Trim()).Select(
             (arg) =>
         {
             if (arg.StartsWithICase(PartDummyUtils.ArgumentBiasDirection))
             {
                 Base6Directions.Direction dir;
                 if (Enum.TryParse(arg.Substring(PartDummyUtils.ArgumentBiasDirection.Length), out dir))
                 {
                     return(PartDummyUtils.ArgumentBiasDirection +
                            iTrans.GetDirection(lTransOrig.GetDirection(dir)));
                 }
                 else
                 {
                     this.Error("Failed to parse bias argument \"{0}\"", arg);
                 }
             }
             else if (arg.StartsWithICase(PartDummyUtils.ArgumentSecondBiasDirection))
             {
                 Base6Directions.Direction dir;
                 if (Enum.TryParse(arg.Substring(PartDummyUtils.ArgumentSecondBiasDirection.Length), out dir))
                 {
                     return(PartDummyUtils.ArgumentSecondBiasDirection +
                            iTrans.GetDirection(lTransOrig.GetDirection(dir)));
                 }
                 else
                 {
                     this.Error("Failed to parse second bias argument \"{0}\"", arg);
                 }
             }
             return(arg);
         }).ToList();
         arguments.Add(PartDummyUtils.ArgumentMountDirection + iTrans.GetDirection(Base6Directions.GetOppositeDirection(destDir)));
         var anchorPoint = source.Min + Base6Directions.GetIntVector(destDir);
         var del         = anchorPoint - dest.Min;
         if (del != Vector3I.Zero)
         {
             arguments.Add(PartDummyUtils.ArgumentAnchorPoint + del.X + ":" + del.Y + ":" + del.Z);
         }
         var outName = PartMetadata.MountPrefix + " " + string.Join(" ", arguments);
         if (string.IsNullOrWhiteSpace(dest.Name))
         {
             dest.Name = outName;
         }
         else
         {
             dest.Name = dest.Name + PartMetadata.MultiUseSentinel + outName;
         }
         return(true);
     }
     if (srcName.StartsWithICase(ReservedSpaceDelegated))
     {
         var baseName = srcName.Substring(ReservedSpaceDelegated.Length).Trim();
         var args     = baseName.Split(' ').Select(x => x.Trim()).Where(x => x.Length > 0).ToArray();
         var box      = PartDummyUtils.ParseReservedSpace(MyDefinitionManager.Static.GetCubeSize(grid.GridSizeEnum), source, args, this.Error);
         var del      = source.Min - (Vector3I)dest.Min;
         box.Box.Max += del;
         box.Box.Min += del;
         var boxLocalFloat = Utilities.TransformBoundingBox(box.Box, Matrix.Invert(new MatrixI(dest.BlockOrientation).GetFloatMatrix()));
         var boxLocal      = new BoundingBoxI(Vector3I.Floor(boxLocalFloat.Min), Vector3I.Ceiling(boxLocalFloat.Max));
         var outName       = $"{PartMetadata.ReservedSpacePrefix} NE:{boxLocal.Min.X}:{boxLocal.Min.Y}:{boxLocal.Min.Z} PE:{boxLocal.Max.X}:{boxLocal.Max.Y}:{boxLocal.Max.Z}";
         if (box.IsShared)
         {
             outName += " shared";
         }
         if (box.IsOptional)
         {
             outName += " optional";
         }
         if (string.IsNullOrWhiteSpace(dest.Name))
         {
             dest.Name = outName;
         }
         else
         {
             dest.Name = dest.Name + PartMetadata.MultiUseSentinel + outName;
         }
         return(true);
     }
     return(false);
 }
Exemple #10
0
        private void Process(CommandFeedback feedback, IMyCubeGrid grid)
        {
            if (grid.CustomName == null || !grid.CustomName.StartsWithICase("EqProcBuild"))
            {
                return;
            }
            var ob = grid.GetObjectBuilder(true) as MyObjectBuilder_CubeGrid;

            if (ob == null)
            {
                return;
            }
            this.Info("Begin processing {0}", grid.CustomName);
            feedback?.Invoke("Processing {0}", grid.CustomName);
            try
            {
                var dummyDel  = new List <MyTuple <MyObjectBuilder_CubeBlock, string> >();
                var blockKeep = new List <MyObjectBuilder_CubeBlock>();
                var blockMap  = new Dictionary <Vector3I, MyObjectBuilder_CubeBlock>(Vector3I.Comparer);
                foreach (var block in ob.CubeBlocks)
                {
                    var mount = false;
                    foreach (var name in block.ConfigNames())
                    {
                        if (!name.StartsWithICase(MountDelegated) && !name.StartsWithICase(ReservedSpaceDelegated))
                        {
                            continue;
                        }
                        dummyDel.Add(MyTuple.Create(block, name));
                        mount = true;
                        break;
                    }
                    if (mount)
                    {
                        continue;
                    }

                    var      blockMin = (Vector3I)block.Min;
                    Vector3I blockMax;
                    BlockTransformations.ComputeBlockMax(block, out blockMax);
                    for (var rangeItr = new Vector3I_RangeIterator(ref blockMin, ref blockMax); rangeItr.IsValid(); rangeItr.MoveNext())
                    {
                        blockMap[rangeItr.Current] = block;
                    }
                    blockKeep.Add(block);
                }
                this.Info("Found {0} blocks to keep, {1} block mounts to remap", blockKeep.Count, dummyDel.Count);
                foreach (var pair in dummyDel)
                {
                    var block   = pair.Item1;
                    var useName = pair.Item2;

                    IEnumerable <Base6Directions.Direction> dirs = Base6Directions.EnumDirections;
                    var def       = MyDefinitionManager.Static.GetCubeBlockDefinition(pair.Item1);
                    var transform = new MatrixI(block.BlockOrientation);
                    if (def?.MountPoints != null)
                    {
                        var mountDirs = new HashSet <Base6Directions.Direction>();
                        foreach (var mount in def.MountPoints)
                        {
                            mountDirs.Add(Base6Directions.GetDirection(Vector3I.TransformNormal(mount.Normal, ref transform)));
                        }
                    }

                    var args     = useName.Split(' ');
                    var keepArgs = new List <string>(args.Length);
                    foreach (var arg in args)
                    {
                        if (arg.StartsWithICase(PartDummyUtils.ArgumentMountDirection))
                        {
                            Base6Directions.Direction dir;
                            if (Enum.TryParse(arg.Substring(2), out dir))
                            {
                                dirs = new[] { transform.GetDirection(Base6Directions.GetOppositeDirection(dir)) }
                            }
                            ;
                            else
                            {
                                this.Error("Failed to parse direction argument \"{0}\"", arg);
                                feedback?.Invoke("Error: Failed to parse direction argument \"{0}\"", arg);
                            }
                        }
                        else
                        {
                            keepArgs.Add(arg);
                        }
                    }
                    useName = string.Join(" ", keepArgs);

                    MyObjectBuilder_CubeBlock outputBlock = null;
                    var outputDir = Base6Directions.Direction.Forward;
                    foreach (var dir in dirs)
                    {
                        MyObjectBuilder_CubeBlock tmp;
                        if (!blockMap.TryGetValue(block.Min + Base6Directions.GetIntVector(dir), out tmp))
                        {
                            continue;
                        }
                        if (tmp.ConfigNames().Any(x => x.StartsWithICase(MountDelegated)))
                        {
                            continue;
                        }
                        if (outputBlock != null)
                        {
                            this.Error("Multiple directions found for {0}", pair.Item2);
                            feedback?.Invoke("Error: Multiple directions found for {0}", pair.Item2);
                        }
                        outputBlock = tmp;
                        outputDir   = dir;
                    }
                    if (outputBlock == null || !ApplyDelegate(ob, block, useName, outputBlock, outputDir))
                    {
                        this.Error("Failed to find delegated mount point for {0}", pair.Item2);
                        feedback?.Invoke("Error: Failed to find delegated mount point for {0}", pair.Item2);
                    }
                }
                ob.CubeBlocks = blockKeep;

                // Grab related grids!
                var relatedGrids = new HashSet <IMyCubeGrid> {
                    grid
                };
                var scanRelated           = new Queue <IMyCubeGrid>();
                var relatedGridController = new Dictionary <IMyCubeGrid, IMyCubeBlock>();
                scanRelated.Enqueue(grid);
                while (scanRelated.Count > 0)
                {
                    var          subGrid = scanRelated.Dequeue();
                    IMyCubeBlock controllerForThisGrid = null;
                    relatedGridController.TryGetValue(subGrid, out controllerForThisGrid);

                    subGrid.GetBlocks(null, (y) =>
                    {
                        var x = y?.FatBlock;
                        if (x == null)
                        {
                            return(false);
                        }
                        var childGrid = (x as IMyMechanicalConnectionBlock)?.TopGrid;
                        if (childGrid != null && relatedGrids.Add(childGrid))
                        {
                            scanRelated.Enqueue(childGrid);
                            relatedGridController[childGrid] = x.CubeGrid == grid ? x : controllerForThisGrid;
                        }
                        var parentGrid = (x as IMyAttachableTopBlock)?.Base?.CubeGrid;
                        // ReSharper disable once InvertIf
                        if (parentGrid != null && relatedGrids.Add(parentGrid))
                        {
                            scanRelated.Enqueue(parentGrid);
                            relatedGridController[parentGrid] = x.CubeGrid == grid ? x : controllerForThisGrid;
                        }
                        return(false);
                    });
                }
                relatedGrids.Remove(grid);
                var removedNoController = relatedGrids.RemoveWhere(x => !relatedGridController.ContainsKey(x));
                if (removedNoController > 0)
                {
                    this.Error("Failed to find the mechanical connection block for all subgrids.  {0} will be excluded",
                               removedNoController);
                    feedback?.Invoke("Error: Failed to find the mechanical connection block for all subgrids.  {0} will be excluded",
                                     removedNoController);
                }
                // Need to add reserved space for subgrids so they don't overlap.  So compute that.  Yay!
                foreach (var rel in relatedGrids)
                {
                    IMyCubeBlock root;
                    if (!relatedGridController.TryGetValue(rel, out root))
                    {
                        this.Error("Unable to find the mechanical connection for grid {0}", rel.CustomName);
                        feedback?.Invoke("Error: Unable to find the mechanical connection for grid {0}",
                                         rel.CustomName);
                        continue;
                    }
                    MyObjectBuilder_CubeBlock blockDest;
                    if (blockMap.TryGetValue(root.Min, out blockDest))
                    {
                        var blockLocal = (MatrixD) new MatrixI(blockDest.BlockOrientation).GetFloatMatrix();
                        blockLocal.Translation = (Vector3I)blockDest.Min * grid.GridSize;
                        var blockWorld = MatrixD.Multiply(blockLocal, grid.WorldMatrix);

                        var worldAABB = rel.WorldAABB;
                        worldAABB = Utilities.TransformBoundingBox(worldAABB, MatrixD.Invert(blockWorld));
                        var gridAABB = new BoundingBoxI(Vector3I.Floor(worldAABB.Min / grid.GridSize), Vector3I.Ceiling(worldAABB.Max / grid.GridSize));
                        var code     = $"{PartMetadata.ReservedSpacePrefix} NE:{gridAABB.Min.X}:{gridAABB.Min.Y}:{gridAABB.Min.Z} PE:{gridAABB.Max.X}:{gridAABB.Max.Y}:{gridAABB.Max.Z}";
                        this.Info("Added reserved space for subgrid {0}: Spec is \"{1}\"", rel.CustomName, code);
                        if (blockDest.Name == null || blockDest.Name.Trim().Length == 0)
                        {
                            blockDest.Name = code;
                        }
                        else
                        {
                            blockDest.Name += PartMetadata.MultiUseSentinel + code;
                        }
                    }
                    else
                    {
                        this.Error("Unable to find the OB for grid block {0} ({1}, {2}, {3}).  Is it a delegate?", (root as IMyTerminalBlock)?.CustomName ?? root.Name, root.Min.X, root.Min.Y, root.Min.Z);
                        feedback?.Invoke("Unable to the find OB for grid block {0} ({1}, {2}, {3}).  Was it a delegate?", (root as IMyTerminalBlock)?.CustomName ?? root.Name, root.Min.X, root.Min.Y, root.Min.Z);
                    }
                }

                var allGrids = new List <MyObjectBuilder_CubeGrid>(relatedGrids.Count + 1)
                {
                    ob
                };
                allGrids.AddRange(relatedGrids.Select(relGrid => relGrid.GetObjectBuilder(false)).OfType <MyObjectBuilder_CubeGrid>());

                // Compose description: TODO I'd love if this actually worked :/
                // var storage = new MyPartMetadata();
                // storage.InitFromGrids(ob, allGrids);
                // var data = Convert.ToBase64String(MyAPIGateway.Utilities.SerializeToBinary(storage.GetObjectBuilder()));

                var defOut = new MyObjectBuilder_PrefabDefinition()
                {
                    Id        = new SerializableDefinitionId(typeof(MyObjectBuilder_PrefabDefinition), grid.CustomName),
                    CubeGrids = allGrids.ToArray()
                };

                var fileName = grid.CustomName + ".sbc";
                this.Info("Saving {1} grids as {0}", fileName, defOut.CubeGrids.Length);
                feedback?.Invoke("Saving {1} grids as {0}", fileName, defOut.CubeGrids.Length);

                var mishMash = new MyObjectBuilder_Definitions()
                {
                    Prefabs = new MyObjectBuilder_PrefabDefinition[] { defOut }
                };
                var writer = MyAPIGateway.Utilities.WriteBinaryFileInLocalStorage(fileName, typeof(DesignTools));
                var obCode = MyAPIGateway.Utilities.SerializeToXML(mishMash);
                obCode = obCode.Replace("encoding=\"utf-16\"", "encoding=\"utf-8\"");
                writer.Write(Encoding.UTF8.GetBytes(obCode));
                writer.Close();
            }
            catch (Exception e)
            {
                this.Error("Failed to parse.  Error:\n{0}", e.ToString());
            }
        }
Exemple #11
0
        private static int PerformVoxelOpInternal(
            List <MyVoxelBase> voxels,
            List <OrientedBoundingBoxD> boxes,
            byte replacementMaterial,
            int materialLimit,
            VoxelMiningBuffer miningBuffer,
            bool disableFarmingItems)
        {
            var data         = VoxelData;
            var usedMaterial = 0;

            using (PoolManager.Get(out List <OrientedBoundingBoxD> storageBoxes))
                foreach (var voxel in voxels)
                {
                    if (materialLimit < usedMaterial)
                    {
                        break;
                    }
                    var invWorld      = voxel.PositionComp.WorldMatrixInvScaled;
                    var storageBounds = BoundingBoxD.CreateInvalid();
                    storageBoxes.Clear();
                    var voxelOffset = (voxel.Size >> 1) + voxel.StorageMin;
                    foreach (var obb in boxes)
                    {
                        var storageObb = obb;
                        storageObb.Transform(invWorld);
                        storageObb.HalfExtent /= voxel.VoxelSize;
                        storageObb.Center      = storageObb.Center / voxel.VoxelSize + voxelOffset;
                        storageBoxes.Add(storageObb);
                        storageBounds.Include(storageObb.GetAABB());
                    }

                    var storageMin = Vector3I.Max(Vector3I.Floor(storageBounds.Min), voxel.StorageMin);
                    var storageMax = Vector3I.Min(Vector3I.Ceiling(storageBounds.Max), voxel.StorageMax);
                    var localBox   = new BoundingBox(storageMin, storageMax);
                    localBox.Translate(-voxel.SizeInMetresHalf - voxel.StorageMin);
                    if (voxel.IntersectStorage(ref localBox, false) == ContainmentType.Disjoint)
                    {
                        continue;
                    }
                    data.Resize(storageMin, storageMax);
                    voxel.Storage.ReadRange(data, MyStorageDataTypeFlags.ContentAndMaterial, 0, storageMin, storageMax);
                    var modified       = false;
                    var modifiedVoxels = BoundingBoxD.CreateInvalid();
                    foreach (var pt in new BoundingBoxI(Vector3I.Zero, storageMax - storageMin).EnumeratePoints())
                    {
                        if (materialLimit < usedMaterial)
                        {
                            break;
                        }
                        var contained = false;
                        var voxelBox  = new BoundingBoxD(storageMin + pt, storageMin + pt + 1);
                        foreach (var storageBox in storageBoxes)
                        {
                            if (storageBox.Intersects(ref voxelBox))
                            {
                                contained = true;
                                break;
                            }
                        }

                        if (!contained)
                        {
                            continue;
                        }
                        var tmpPt   = pt;
                        var index   = data.ComputeLinear(ref tmpPt);
                        var content = data.Content(index);
                        if (content <= 0)
                        {
                            continue;
                        }
                        var material = data.Material(index);
                        if (material == replacementMaterial)
                        {
                            continue;
                        }

                        usedMaterial += content;
                        miningBuffer?.Add(material, content);
                        data.Material(index, replacementMaterial);
                        modified = true;
                        modifiedVoxels.Include(voxelBox);
                    }

                    if (!modified)
                    {
                        continue;
                    }
                    voxel.Storage.WriteRange(data, MyStorageDataTypeFlags.Material, storageMin, storageMax);
                    if (!disableFarmingItems)
                    {
                        continue;
                    }
                    modifiedVoxels.Min = (modifiedVoxels.Min - voxelOffset) * voxel.VoxelSize;
                    modifiedVoxels.Max = (modifiedVoxels.Max - voxelOffset) * voxel.VoxelSize;
                    voxel.DisableFarmingItemsIn(OrientedBoundingBoxD.Create(modifiedVoxels, voxel.WorldMatrix));
                }

            return(usedMaterial);
        }
        public override IEnumerable <ProceduralObject> Generate(BoundingSphereD include, BoundingSphereD?exclude)
        {
            var root        = Vector3D.Transform(include.Center, m_invTransform);
            var excludeRoot = exclude.HasValue
                ? Vector3D.Transform(exclude.Value.Center, m_invTransform)
                : default(Vector3D);

            var minLocal = root - include.Radius;
            var maxLocal = root + include.Radius;

            minLocal = Vector3D.Max(minLocal, Shape.RelevantArea.Min);
            maxLocal = Vector3D.Min(maxLocal, Shape.RelevantArea.Max);
            for (var i = 0; i < m_layers.Length; i++)
            {
                var layer = m_layers[i];
                var includePaddedSquared = include.Radius + layer.AsteroidSpacing * 2;
                includePaddedSquared *= includePaddedSquared;
                var excludePaddedSquared = exclude.HasValue ? exclude.Value.Radius - layer.AsteroidSpacing * 2 : 0;
                excludePaddedSquared *= excludePaddedSquared;

                var minPos = Vector3I.Floor(minLocal / layer.AsteroidSpacing);
                var maxPos = Vector3I.Ceiling(maxLocal / layer.AsteroidSpacing);
                for (var itr = new Vector3I_RangeIterator(ref minPos, ref maxPos); itr.IsValid(); itr.MoveNext())
                {
                    var seed     = new Vector4I(itr.Current.X, itr.Current.Y, itr.Current.Z, i);
                    var localPos = ((Vector3D)itr.Current + 0.5) * layer.AsteroidSpacing;

                    // Very quick, include/exclude.
                    if (Vector3D.DistanceSquared(root, localPos) > includePaddedSquared)
                    {
                        continue;
                    }
                    if (exclude.HasValue && Vector3D.DistanceSquared(excludeRoot, localPos) < excludePaddedSquared)
                    {
                        continue;
                    }
                    var localWeight = Shape.Weight(localPos) + layer.UsableRegion - 1;
                    if (1 - layer.AsteroidDensity > localWeight)
                    {
                        continue;
                    }

                    var densityNoise = Math.Abs(m_noise.GetValue(localPos + Math.PI)) * localWeight;
                    if (1 - layer.AsteroidDensity > densityNoise)
                    {
                        continue;
                    }

                    localPos.X += 0.45 * m_noise.GetValue(localPos) * layer.AsteroidSpacing;
                    localPos.Y += 0.45 * m_noise.GetValue(localPos) * layer.AsteroidSpacing;
                    localPos.Z += 0.45 * m_noise.GetValue(localPos) * layer.AsteroidSpacing;

                    localPos.X += 0.35 * Shape.WarpSize.X * m_noiseWarp.GetValue(localPos);
                    localPos.Y += 0.35 * Shape.WarpSize.Y * m_noiseWarp.GetValue(localPos);
                    localPos.Z += 0.05 * Shape.WarpSize.Z * m_noiseWarp.GetValue(localPos);

                    var worldPos = Vector3D.Transform(localPos, m_transform);
                    ProceduralAsteroid procAst;
                    if (!m_asteroids.TryGetValue(seed, out procAst))
                    {
                        var size = m_noise.GetValue(worldPos) * (layer.AsteroidMaxSize - layer.AsteroidMinSize) +
                                   layer.AsteroidMinSize;
                        m_asteroids[seed] = procAst = new ProceduralAsteroid(this, seed, worldPos, size, m_layers[i]);
                    }

                    procAst.SpawnIfNeeded((procAst.m_boundingBox.Center - include.Center).LengthSquared());
                    yield return(procAst);
                }
            }
        }