public MyMaterialLayer()
 {
     StartHeight = 0;
     EndHeight = 0;
     MaterialName = null;
     MaterialDefinition = null;
 }
 public MyMaterialLayer(float start, float end, string name)
 {
     StartHeight = start;
     EndHeight = end;
     MaterialName = name;
     MaterialDefinition = null;
 }
            public void Start(Vector3D position, Vector3D initialVelocity, float scale, MyVoxelMaterialDefinition mat)
            {
                Components.MyRenderComponentDebrisVoxel voxelDebrisRender = Container.Entity.Render as Components.MyRenderComponentDebrisVoxel;

                voxelDebrisRender.TexCoordOffset = MyUtils.GetRandomFloat(5, 15);
                voxelDebrisRender.TexCoordScale = MyUtils.GetRandomFloat(8, 12);
                voxelDebrisRender.VoxelMaterialIndex = mat.Index;
                base.Start(position, initialVelocity, scale);
                Container.Entity.Render.NeedsResolveCastShadow = true;
                Container.Entity.Render.FastCastShadowResolve = true;
            }
        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();
        }
 public MyCompositeShapeOreDeposit(MyCsgShapeBase shape, MyVoxelMaterialDefinition material)
 {
     System.Diagnostics.Debug.Assert(material != null, "Shape must have material");
     Shape = shape;
     m_material = material;
 }
        private void InitInternal()
        {
            // TODO: This will be fixed and made much more simple once ore models are done
            // https://app.asana.com/0/6594565324126/10473934569658

            var physicalItem = MyDefinitionManager.Static.GetPhysicalItemDefinition(Item.Content);

            string model = physicalItem.Model;

            VoxelMaterial = null;
            float scale = 1.0f;

            if (Item.Content is MyObjectBuilder_Ore)
            {
                string oreSubTypeId = physicalItem.Id.SubtypeId.ToString();
                foreach (var mat in MyDefinitionManager.Static.GetVoxelMaterialDefinitions())
                {
                    if (oreSubTypeId == mat.MinedOre)
                    {
                        VoxelMaterial = mat;
                        model = MyDebris.GetRandomDebrisVoxel();
                        scale = (float)Math.Pow((float)Item.Amount * physicalItem.Volume / MyDebris.VoxelDebrisModelVolume, 0.333f);
                        break;
                    }
                }

                scale = (float)Math.Pow((float)Item.Amount * physicalItem.Volume / MyDebris.VoxelDebrisModelVolume, 0.333f);
            }

            if (scale < 0.05f)
                Close();
            else if (scale < 0.15f)
                scale = 0.15f;

            FormatDisplayName(m_displayedText, Item);
            Init(m_displayedText, model, null, null, null);

            PositionComp.Scale = scale; // Must be set after init


            var massProperties = new HkMassProperties();
            HkShape shape = GetPhysicsShape(physicalItem.Mass * (float)Item.Amount, scale, out massProperties);
            var scaleMatrix = Matrix.CreateScale(scale);

            if (Physics != null)
                Physics.Close();
            Physics = new MyPhysicsBody(this, RigidBodyFlag.RBF_DEBRIS);

            if (VoxelMaterial != null)
            {
                HkConvexTransformShape transform = new HkConvexTransformShape((HkConvexShape)shape, ref scaleMatrix, HkReferencePolicy.None);
        
                Physics.CreateFromCollisionObject(transform, Vector3.Zero, MatrixD.Identity, massProperties, MyPhysics.FloatingObjectCollisionLayer);
               
                Physics.Enabled = true;
                transform.Base.RemoveReference();
            }
            else
            {
                Physics.CreateFromCollisionObject(shape, Vector3.Zero, MatrixD.Identity, massProperties, MyPhysics.FloatingObjectCollisionLayer);
                Physics.Enabled = true;
            }

            Physics.MaterialType = VoxelMaterial != null ? MyMaterialType.ROCK : MyMaterialType.METAL;
            Physics.PlayCollisionCueEnabled = true;

            NeedsUpdate = MyEntityUpdateEnum.EACH_FRAME;
        }
Exemple #7
0
        public void CreateVoxelMeteorCrater(Vector3D center, float radius, Vector3 normal, MyVoxelMaterialDefinition material)
        {
            var msg = new MeteorCraterMsg();
            msg.EntityId = Entity.EntityId;
            msg.Center = center;
            msg.Radius = radius;
            msg.Normal = normal;
            msg.Material = material.Index;

            MySession.Static.SyncLayer.SendMessageToAll(ref msg, MyTransportMessageEnum.Success);
        }
 private bool HasMaterial(MyVoxelMaterialDefinition material)
 {
     if(material == Material0 || material == Material1 || material == Material2)
     {
         return true;
     }
     return false;
 }
 protected abstract void OverwriteAllMaterialsInternal(MyVoxelMaterialDefinition material);
Exemple #10
0
 public void CreateVoxelMeteorCrater(Vector3D center, float radius, Vector3 normal, MyVoxelMaterialDefinition material)
 {
     BeforeContentChanged = true;
     MyMultiplayer.RaiseEvent(RootVoxel, x => x.CreateVoxelMeteorCrater_Implementation, center, radius, normal, material.Index);
 }
 void IMyStorage.MergeVoxelMaterials(MyMwcVoxelFilesEnum voxelFile, Vector3I voxelPosition, MyVoxelMaterialDefinition materialToSet)
 {
     EnsureMutable();
     m_trueStorage.MergeVoxelMaterials(voxelFile, voxelPosition, materialToSet);
 }
        public static void MakeCrater(MyVoxelBase voxelMap, BoundingSphereD sphere, Vector3 direction, MyVoxelMaterialDefinition material)
        {
            ProfilerShort.Begin("MakeCrater");

            Vector3 normal = Vector3.Normalize(sphere.Center - voxelMap.RootVoxel.WorldMatrix.Translation);

            Vector3I minCorner, maxCorner;
            {
                Vector3D sphereMin = sphere.Center - (sphere.Radius - MyVoxelConstants.VOXEL_SIZE_IN_METRES) * 1.3f;
                Vector3D sphereMax = sphere.Center + (sphere.Radius + MyVoxelConstants.VOXEL_SIZE_IN_METRES) * 1.3f;
                MyVoxelCoordSystems.WorldPositionToVoxelCoord(voxelMap.PositionLeftBottomCorner, ref sphereMin, out minCorner);
                MyVoxelCoordSystems.WorldPositionToVoxelCoord(voxelMap.PositionLeftBottomCorner, ref sphereMax, out maxCorner);
            }

            voxelMap.Storage.ClampVoxelCoord(ref minCorner);
            voxelMap.Storage.ClampVoxelCoord(ref maxCorner);

            Vector3I worldMinCorner = minCorner + voxelMap.StorageMin;
            Vector3I worldMaxCorner = maxCorner + voxelMap.StorageMin;

            //  We are tracking which voxels were changed, so we can invalidate only needed cells in the cache
            bool changed = false;
            ProfilerShort.Begin("Reading cache");
            m_cache.Resize(minCorner, maxCorner);

            voxelMap.Storage.ReadRange(m_cache, MyStorageDataTypeFlags.ContentAndMaterial, 0, ref worldMinCorner, ref worldMaxCorner);

            ProfilerShort.End();

            ProfilerShort.Begin("Changing cache");
            int removedVoxelContent = 0;
            Vector3I tempVoxelCoord;
            Vector3I cachePos = (maxCorner - minCorner) / 2;

            byte oldMaterial = m_cache.Material(ref cachePos);

            float digRatio = 1 - Vector3.Dot(normal, direction);

            Vector3 newCenter = sphere.Center - normal * (float)sphere.Radius * 1.1f;//0.9f;
            float sphRadA = (float)(sphere.Radius * 1.5f);
            float sphRadSqA = (float)(sphRadA * sphRadA);
            float voxelSizeHalfTransformedPosA = MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF * (2 * sphRadA + MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF);
            float voxelSizeHalfTransformedNegA = MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF * (-2 * sphRadA + MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF);

            Vector3 newDelCenter = newCenter + normal * (float)sphere.Radius * (0.7f + digRatio) + direction * (float)sphere.Radius * 0.65f;
            float sphRadD = (float)(sphere.Radius);
            float sphRadSqD = (float)(sphRadD * sphRadD);
            float voxelSizeHalfTransformedPosD = MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF * (2 * sphRadD + MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF);
            float voxelSizeHalfTransformedNegD = MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF * (-2 * sphRadD + MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF);

            Vector3 newSetCenter = newCenter + normal * (float)sphere.Radius * (digRatio) + direction * (float)sphere.Radius * 0.3f;
            float sphRadS = (float)(sphere.Radius * 0.1f);
            float sphRadSqS = (float)(sphRadS * sphRadS);
            float voxelSizeHalfTransformedPosS = MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF * (2 * sphRadS + MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF);

            for (tempVoxelCoord.Z = minCorner.Z, cachePos.Z = 0; tempVoxelCoord.Z <= maxCorner.Z; tempVoxelCoord.Z++, ++cachePos.Z)
            {
                for (tempVoxelCoord.Y = minCorner.Y, cachePos.Y = 0; tempVoxelCoord.Y <= maxCorner.Y; tempVoxelCoord.Y++, ++cachePos.Y)
                {
                    for (tempVoxelCoord.X = minCorner.X, cachePos.X = 0; tempVoxelCoord.X <= maxCorner.X; tempVoxelCoord.X++, ++cachePos.X)
                    {
                        Vector3D voxelPosition;
                        MyVoxelCoordSystems.VoxelCoordToWorldPosition(voxelMap.PositionLeftBottomCorner, ref tempVoxelCoord, out voxelPosition);

                        byte originalContent = m_cache.Content(ref cachePos);

                        //Add sphere
                        if (originalContent != MyVoxelConstants.VOXEL_CONTENT_FULL)
                        {

                            float addDist = (float)(voxelPosition - newCenter).LengthSquared();
                            float addDiff = (float)(addDist - sphRadSqA);

                        byte newContent;
                            if (addDiff > voxelSizeHalfTransformedPosA)
                        {
                            newContent = MyVoxelConstants.VOXEL_CONTENT_EMPTY;
                        }
                            else if (addDiff < voxelSizeHalfTransformedNegA)
                        {
                            newContent = MyVoxelConstants.VOXEL_CONTENT_FULL;
                        }
                        else
                        {
                                float value = (float)Math.Sqrt(addDist + sphRadSqA - 2 * sphRadA * Math.Sqrt(addDist));
                                if (addDiff < 0) { value = -value; }
                            //  This formula will work even if diff is positive or negative
                                newContent = (byte)(MyVoxelConstants.VOXEL_ISO_LEVEL - value / MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF * MyVoxelConstants.VOXEL_ISO_LEVEL);
                        }

                            if (newContent > originalContent)
                        {
                            if (material != null)
                            {
                                    m_cache.Material(ref cachePos, oldMaterial);
                            }

                            changed = true;
                            m_cache.Content(ref cachePos, newContent);
                        }
                        }

                        //Delete sphere
                        float delDist = (float)(voxelPosition - newDelCenter).LengthSquared();
                        float delDiff = (float)(delDist - sphRadSqD);

                        byte contentToRemove;
                        if (delDiff > voxelSizeHalfTransformedPosD)
                        {
                            contentToRemove = MyVoxelConstants.VOXEL_CONTENT_EMPTY;
                        }
                        else if (delDiff < voxelSizeHalfTransformedNegD)
                        {
                            contentToRemove = MyVoxelConstants.VOXEL_CONTENT_FULL;
                        }
                        else
                        {
                            float value = (float)Math.Sqrt(delDist + sphRadSqD - 2 * sphRadD * Math.Sqrt(delDist));
                            if (delDiff < 0) { value = -value; }
                            //  This formula will work even if diff is positive or negative
                            contentToRemove = (byte)(MyVoxelConstants.VOXEL_ISO_LEVEL - value / MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF * MyVoxelConstants.VOXEL_ISO_LEVEL);
                        }

                        originalContent = m_cache.Content(ref cachePos);

                        if (originalContent > MyVoxelConstants.VOXEL_CONTENT_EMPTY && contentToRemove > MyVoxelConstants.VOXEL_CONTENT_EMPTY)
                        {
                            changed = true;

                            int newVal = originalContent - contentToRemove;
                            if (newVal < MyVoxelConstants.VOXEL_CONTENT_EMPTY)
                                newVal = MyVoxelConstants.VOXEL_CONTENT_EMPTY;
                            m_cache.Content(ref cachePos, (byte)newVal);

                            removedVoxelContent += originalContent - newVal;
                        }

                        //Set material

                        float setDist = (float)(voxelPosition - newSetCenter).LengthSquared();
                        float setDiff = (float)(setDist - sphRadSqS);

                        if (setDiff <= MyVoxelConstants.VOXEL_SIZE_IN_METRES * 1.5f)  // could be VOXEL_SIZE_IN_METRES_HALF, but we want to set material in empty cells correctly
                        {

                            MyVoxelMaterialDefinition originalMaterial = MyDefinitionManager.Static.GetVoxelMaterialDefinition(m_cache.Material(ref cachePos));

                            // Change the material:
                            // - always on boundaries between material and nothing
                            // - smoothly on inner boundaries
                            MyVoxelMaterialDefinition newMaterial = material;
                            if (setDiff > 0)
                            {
                                byte content = m_cache.Content(ref cachePos);
                                if (content == MyVoxelConstants.VOXEL_CONTENT_FULL)
                                    newMaterial = originalMaterial;
                                if (setDiff >= voxelSizeHalfTransformedPosS && content != MyVoxelConstants.VOXEL_CONTENT_EMPTY)  // set material behind boundary only for empty voxels
                                    newMaterial = originalMaterial;
                            }

                            if (originalMaterial == newMaterial)
                            {
                                continue;
                            }

                            m_cache.Material(ref cachePos, newMaterial.Index);
                            changed = true;
                        }

                        float dist = (float)(voxelPosition - newCenter).LengthSquared();
                        float diff = (float)(dist - sphRadSqA);

                        if (diff <= 0f)
                        {
                            originalContent = m_cache.Content(ref cachePos);
                            if (originalContent > MyVoxelConstants.VOXEL_CONTENT_EMPTY)
                            {
                                bool wrinkled = m_cache.WrinkleVoxelContent(ref cachePos, MyVoxelConstants.DEFAULT_WRINKLE_WEIGHT_ADD, MyVoxelConstants.DEFAULT_WRINKLE_WEIGHT_REMOVE);
                                if (wrinkled)
                                    changed = true;
                            }
                        }
                    }
                }
            }
            ProfilerShort.End();

            if (changed)
            {
                ProfilerShort.Begin("RemoveSmallVoxelsUsingChachedVoxels");
                RemoveSmallVoxelsUsingChachedVoxels();
                ProfilerShort.BeginNextBlock("Writing cache");
                minCorner += voxelMap.StorageMin;
                maxCorner += voxelMap.StorageMin;
                voxelMap.Storage.WriteRange(m_cache, MyStorageDataTypeFlags.ContentAndMaterial, ref minCorner, ref maxCorner);
                MyShapeSphere sphereShape = new MyShapeSphere();
                sphereShape.Center = sphere.Center;
                sphereShape.Radius = (float)(sphere.Radius*1.5);
                OnVoxelChanged(OperationType.Cut, voxelMap, sphereShape);
                ProfilerShort.End();
            }

            ProfilerShort.End();
        }
        public static void MakeCrater(MyVoxelBase voxelMap, BoundingSphereD sphere, Vector3 normal, MyVoxelMaterialDefinition material)
        {
            ProfilerShort.Begin("MakeCrater");

            Vector3I minCorner, maxCorner;
            {
                Vector3D sphereMin = sphere.Center - (sphere.Radius - MyVoxelConstants.VOXEL_SIZE_IN_METRES);
                Vector3D sphereMax = sphere.Center + (sphere.Radius + MyVoxelConstants.VOXEL_SIZE_IN_METRES);
                MyVoxelCoordSystems.WorldPositionToVoxelCoord(voxelMap.PositionLeftBottomCorner, ref sphereMin, out minCorner);
                MyVoxelCoordSystems.WorldPositionToVoxelCoord(voxelMap.PositionLeftBottomCorner, ref sphereMax, out maxCorner);
            }


            voxelMap.Storage.ClampVoxelCoord(ref minCorner);
            voxelMap.Storage.ClampVoxelCoord(ref maxCorner);

            //  We are tracking which voxels were changed, so we can invalidate only needed cells in the cache
            bool changed = false;
            ProfilerShort.Begin("Reading cache");
            m_cache.Resize(minCorner, maxCorner);
            voxelMap.Storage.ReadRange(m_cache, MyStorageDataTypeFlags.ContentAndMaterial, 0, ref minCorner, ref maxCorner);
            ProfilerShort.End();

            ProfilerShort.Begin("Changing cache");
            int removedVoxelContent = 0;
            Vector3I tempVoxelCoord;
            Vector3I cachePos;
            for (tempVoxelCoord.Z = minCorner.Z, cachePos.Z = 0; tempVoxelCoord.Z <= maxCorner.Z; tempVoxelCoord.Z++, ++cachePos.Z)
            {
                for (tempVoxelCoord.Y = minCorner.Y, cachePos.Y = 0; tempVoxelCoord.Y <= maxCorner.Y; tempVoxelCoord.Y++, ++cachePos.Y)
                {
                    for (tempVoxelCoord.X = minCorner.X, cachePos.X = 0; tempVoxelCoord.X <= maxCorner.X; tempVoxelCoord.X++, ++cachePos.X)
                    {
                        Vector3D voxelPosition;
                        MyVoxelCoordSystems.VoxelCoordToWorldPosition(voxelMap.PositionLeftBottomCorner, ref tempVoxelCoord, out voxelPosition);

                        float addDist = (float)(voxelPosition - sphere.Center).Length();
                        float addDiff = (float)(addDist - sphere.Radius);

                        byte newContent;
                        if (addDiff > MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF)
                        {
                            newContent = MyVoxelConstants.VOXEL_CONTENT_EMPTY;
                        }
                        else if (addDiff < -MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF)
                        {
                            newContent = MyVoxelConstants.VOXEL_CONTENT_FULL;
                        }
                        else
                        {
                            //  This formula will work even if diff is positive or negative
                            newContent = (byte)(MyVoxelConstants.VOXEL_ISO_LEVEL - addDiff / MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF * MyVoxelConstants.VOXEL_ISO_LEVEL);
                        }

                        byte originalContent = m_cache.Content(ref cachePos);

                        if (newContent > originalContent && originalContent > 0)
                        {
                            if (material != null)
                            {
                                m_cache.Material(ref cachePos, material.Index);
                            }

                            changed = true;
                            m_cache.Content(ref cachePos, newContent);
                        }

                        float delDist = (float)(voxelPosition - (sphere.Center + (float)sphere.Radius * 0.7f * normal)).Length();
                        float delDiff = (float)(delDist - sphere.Radius);

                        byte contentToRemove;
                        if (delDiff > MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF)
                        {
                            contentToRemove = MyVoxelConstants.VOXEL_CONTENT_EMPTY;
                        }
                        else if (delDiff < -MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF)
                        {
                            contentToRemove = MyVoxelConstants.VOXEL_CONTENT_FULL;
                        }
                        else
                        {
                            //  This formula will work even if diff is positive or negative
                            contentToRemove = (byte)(MyVoxelConstants.VOXEL_ISO_LEVEL - delDiff / MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF * MyVoxelConstants.VOXEL_ISO_LEVEL);
                        }

                        originalContent = m_cache.Content(ref cachePos);

                        if (originalContent > MyVoxelConstants.VOXEL_CONTENT_EMPTY && contentToRemove > MyVoxelConstants.VOXEL_CONTENT_EMPTY)
                        {
                            changed = true;

                            int newVal = originalContent - contentToRemove;
                            if (newVal < MyVoxelConstants.VOXEL_CONTENT_EMPTY)
                                newVal = MyVoxelConstants.VOXEL_CONTENT_EMPTY;
                            m_cache.Content(ref cachePos, (byte)newVal);

                            removedVoxelContent += originalContent - newVal;
                        }

                        float setDist = (float)(voxelPosition - (sphere.Center - (float)sphere.Radius * 0.5f * normal)).Length();
                        float setDiff = (float)(setDist - sphere.Radius / 4f);

                        if (setDiff <= MyVoxelConstants.VOXEL_SIZE_IN_METRES * 1.5f)  // could be VOXEL_SIZE_IN_METRES_HALF, but we want to set material in empty cells correctly
                        {
                            byte indestructibleContentToSet = MyVoxelConstants.VOXEL_CONTENT_FULL;
                            if (setDiff >= MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF)  // outside
                            {
                                indestructibleContentToSet = MyVoxelConstants.VOXEL_CONTENT_EMPTY;
                            }
                            else if (setDiff >= -MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF)  // boundary
                            {
                                indestructibleContentToSet = (byte)(MyVoxelConstants.VOXEL_ISO_LEVEL - setDiff / MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF * MyVoxelConstants.VOXEL_ISO_LEVEL);
                            }

                            MyVoxelMaterialDefinition originalMaterial = MyDefinitionManager.Static.GetVoxelMaterialDefinition(m_cache.Material(ref cachePos));

                            // Change the material:
                            // - always on boundaries between material and nothing
                            // - smoothly on inner boundaries
                            MyVoxelMaterialDefinition newMaterial = material;
                            if (setDiff > 0)
                            {
                                byte content = m_cache.Content(ref cachePos);
                                if (content == MyVoxelConstants.VOXEL_CONTENT_FULL)
                                    newMaterial = originalMaterial;
                                if (setDiff >= MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF && content != MyVoxelConstants.VOXEL_CONTENT_EMPTY)  // set material behind boundary only for empty voxels
                                    newMaterial = originalMaterial;
                            }

                            if (originalMaterial == newMaterial)
                            {
                                continue;
                            }

                            m_cache.Material(ref cachePos, newMaterial.Index);
                            changed = true;
                        }

                        float dist = (float)(voxelPosition - sphere.Center).Length();
                        float diff = (float)(dist - sphere.Radius);

                        if (diff <= 0f)
                        {
                            originalContent = m_cache.Content(ref cachePos);
                            if (originalContent > MyVoxelConstants.VOXEL_CONTENT_EMPTY)
                            {
                                bool wrinkled = m_cache.WrinkleVoxelContent(ref cachePos, MyVoxelConstants.DEFAULT_WRINKLE_WEIGHT_ADD, MyVoxelConstants.DEFAULT_WRINKLE_WEIGHT_REMOVE);
                                if (wrinkled)
                                    changed = true;
                            }
                        }
                    }
                }
            }
            ProfilerShort.End();

            if (changed)
            {
                ProfilerShort.Begin("RemoveSmallVoxelsUsingChachedVoxels");
                RemoveSmallVoxelsUsingChachedVoxels();
                ProfilerShort.BeginNextBlock("Writing cache");
                voxelMap.Storage.WriteRange(m_cache, MyStorageDataTypeFlags.ContentAndMaterial, ref minCorner, ref maxCorner);
                ProfilerShort.End();
            }

            ProfilerShort.End();
        }
 protected override void OverwriteAllMaterialsInternal(MyVoxelMaterialDefinition material)
 {
     Debug.Fail("Not implemented.");
 }
        /// <summary>
        /// Converts voxel material to ore material and puts it into the inventory. If there is no
        /// corresponding ore for given voxel type, nothing happens.
        /// </summary>
        private bool TryHarvestOreMaterial(MyVoxelMaterialDefinition material, Vector3 hitPosition, int removedAmount, bool onlyCheck)
        {
            if (string.IsNullOrEmpty(material.MinedOre))
                return false;

            //Do one frame heatup only in singleplayer, lag will solve it in multiplayer
            if (InitialHeatup())
                return true;

            if (!onlyCheck)
            {
                ProfilerShort.Begin("TryHarvestOreMaterial");
                var oreObjBuilder = MyObjectBuilderSerializer.CreateNewObject<MyObjectBuilder_Ore>(material.MinedOre);
                float amountCubicMeters = (float)(((float)removedAmount / (float)MyVoxelConstants.VOXEL_CONTENT_FULL) * MyVoxelConstants.VOXEL_VOLUME_IN_METERS * VoxelHarvestRatio);
                amountCubicMeters *= (float)material.MinedOreRatio;

                if (!MySession.Static.AmountMined.ContainsKey(material.MinedOre))
                    MySession.Static.AmountMined[material.MinedOre] = 0;
                MySession.Static.AmountMined[material.MinedOre] += (MyFixedPoint)amountCubicMeters;

                float maxDropCubicMeters = 0.150f;

                var physItem = MyDefinitionManager.Static.GetPhysicalItemDefinition(oreObjBuilder);
                MyFixedPoint amountInItemCount = (MyFixedPoint)(amountCubicMeters / physItem.Volume);
                MyFixedPoint maxAmountPerDrop = (MyFixedPoint)(maxDropCubicMeters / physItem.Volume);

                if (OutputInventory != null)
                {
                    MyFixedPoint amountDropped = amountInItemCount * (1 - m_inventoryCollectionRatio);
                    amountDropped = MyFixedPoint.Min(maxAmountPerDrop * 10 - (MyFixedPoint)0.001, amountDropped);
                    MyFixedPoint inventoryAmount = (amountInItemCount * m_inventoryCollectionRatio) - amountDropped;
                    OutputInventory.AddItems(inventoryAmount, oreObjBuilder);
                    SpawnOrePieces(amountDropped, maxAmountPerDrop, hitPosition, oreObjBuilder, material);
                }
                else
                {
                    SpawnOrePieces(amountInItemCount, maxAmountPerDrop, hitPosition, oreObjBuilder, material);
                }
                ProfilerShort.End();
            }

            return true;
        }
        public void CreateExplosionDebris(ref BoundingSphereD explosionSphere, float voxelsCountInPercent, MyVoxelMaterialDefinition voxelMaterial, MyVoxelBase voxelMap)
        {
            MyDebug.AssertDebug((voxelsCountInPercent >= 0.0f) && (voxelsCountInPercent <= 1.0f));
            MyDebug.AssertDebug(explosionSphere.Radius > 0);

            ProfilerShort.Begin("CreateExplosionDebris");

            ProfilerShort.Begin("Matrices");
            //  This matrix will rotate all newly created debrises, so they won't apper as alligned with coordinate system
            MatrixD randomRotationMatrix = MatrixD.CreateRotationX(MyUtils.GetRandomRadian()) *
                                          MatrixD.CreateRotationY(MyUtils.GetRandomRadian());

            float highScale = MathHelper.Clamp((float)explosionSphere.Radius * m_debrisScaleUpper, 0, m_debrisScaleClamp);
            float lowScale = highScale * (m_debrisScaleLower / m_debrisScaleUpper);

            int objectsToGenerate = (int)(m_voxelDebrisOffsets.Count * voxelsCountInPercent);
            ProfilerShort.End();

            ProfilerShort.Begin("m_positionOffsets");
            const float SPHERE_FIT_CUBE_SCALE = 1 / 1.73f; // Resize sphere to fit inside cube
            int debrisCount = m_voxelDebrisOffsets.Count;
            //float debrisScale = Math.Max(explosionSphere.Radius / debrisCount, 0.2f);
            float debrisScale = Math.Max((float)explosionSphere.Radius, 0.2f);
            for (int i = 0; i < debrisCount; i++)
            {
                MyDebrisVoxel newObj = CreateVoxelDebris();
                if (newObj == null)
                {
                    break; // no point in continuing
                }

                Vector3D position = m_voxelDebrisOffsets[i] * (float)explosionSphere.Radius * SPHERE_FIT_CUBE_SCALE;
                Vector3D.Transform(ref position, ref randomRotationMatrix, out position);
                position += explosionSphere.Center;

                var initialVelocity = MyUtils.GetRandomVector3Normalized();
                if (initialVelocity == Vector3.Zero)
                    continue;
                initialVelocity *= MyUtils.GetRandomFloat(MyDebrisConstants.EXPLOSION_DEBRIS_INITIAL_SPEED_MIN,
                                                               MyDebrisConstants.EXPLOSION_DEBRIS_INITIAL_SPEED_MAX);
                (newObj.Debris as MyDebrisVoxel.MyDebrisVoxelLogic).Start(position, initialVelocity, debrisScale, voxelMaterial);

            }
            ProfilerShort.End();

            ProfilerShort.End();
        }
        public void CreateDirectedDebris(Vector3 sourceWorldPosition,
                                         Vector3 offsetDirection,
                                         float minSourceDistance,
                                         float maxSourceDistance,
                                         float minDeviationAngle,
                                         float maxDeviationAngle,
                                         int debrisPieces,
                                         float initialSpeed,
                                         float scale,
                                         MyVoxelMaterialDefinition material)
        {
            ProfilerShort.Begin("Create directed debris");
            MyDebug.AssertDebug(debrisPieces > 0);
            for (int i = 0; i < debrisPieces; ++i)
            {
                var newObj = CreateVoxelDebris();
                if (newObj == null)
                {
                    break; // no point in continuing
                }

                float dist = MyUtils.GetRandomFloat(minSourceDistance, maxSourceDistance);
                float angleX = MyUtils.GetRandomFloat(minDeviationAngle, maxDeviationAngle);
                float angleY = MyUtils.GetRandomFloat(minDeviationAngle, maxDeviationAngle);
                var rotation = Matrix.CreateRotationX(angleX) * Matrix.CreateRotationY(angleY);
                var deviatedDir = Vector3.Transform(offsetDirection, rotation);
                var startPos = sourceWorldPosition + deviatedDir * dist;
                var initialVelocity = deviatedDir * initialSpeed;
                (newObj.Debris as MyDebrisVoxel.MyDebrisVoxelLogic).Start(startPos, initialVelocity, scale, material);
            }
            ProfilerShort.End();
        }
 public MyBoxOreDeposit(MyCsgShapeBase baseShape, MyVoxelMaterialDefinition material) :
     base(baseShape, material)
 {
     m_boxShape = (MyCsgBox)baseShape;
 }
 public bool MatchMaterials(MyVoxelMaterialDefinition material0, MyVoxelMaterialDefinition material1, MyVoxelMaterialDefinition material2)
 {
     return HasMaterial(material0) && HasMaterial(material1) && HasMaterial(material2);
 }
 void IMyStorage.OverwriteAllMaterials(MyVoxelMaterialDefinition material)
 {
     EnsureMutable();
     m_trueStorage.OverwriteAllMaterials(material);
 }
        private void SpawnOrePieces(MyFixedPoint amountItems, MyFixedPoint maxAmountPerDrop, Vector3 hitPosition, MyObjectBuilder_PhysicalObject oreObjBuilder, MyVoxelMaterialDefinition voxelMaterial)
        {
            ProfilerShort.Begin("SpawnOrePieces");
            var forward = Vector3.Normalize(m_sensor.FrontPoint - m_sensor.Center);
            //var pos = m_sensor.CutOutSphere.Center + forward * m_floatingObjectSpawnOffset;
            var pos = hitPosition - forward * m_floatingObjectSpawnRadius;
            BoundingSphere bsphere = new BoundingSphere(pos, m_floatingObjectSpawnRadius);

            while (amountItems > 0)
            {
                MyFixedPoint dropAmount = MyFixedPoint.Min(amountItems, maxAmountPerDrop);
                amountItems -= dropAmount;
                var inventoryItem = new MyPhysicalInventoryItem(dropAmount, oreObjBuilder);
                var item = MyFloatingObjects.Spawn(inventoryItem, bsphere, null, voxelMaterial);
                item.Physics.LinearVelocity = MyUtils.GetRandomVector3HemisphereNormalized(forward) * MyUtils.GetRandomFloat(5, 8);
                item.Physics.AngularVelocity = MyUtils.GetRandomVector3Normalized() * MyUtils.GetRandomFloat(4, 8);
            }
            ProfilerShort.End();
        }
        private void InitInternal()
        {
            // TODO: This will be fixed and made much more simple once ore models are done
            // https://app.asana.com/0/6594565324126/10473934569658

            var itemDefinition = MyDefinitionManager.Static.GetPhysicalItemDefinition(Item.Content);

            m_health = itemDefinition.Health;

            // Setting voxel material (if applicable)
            VoxelMaterial = null;
            if (itemDefinition.VoxelMaterial != MyStringHash.NullOrEmpty)
            {
                VoxelMaterial = MyDefinitionManager.Static.GetVoxelMaterialDefinition(itemDefinition.VoxelMaterial.String);
            }
            else if (Item.Content is MyObjectBuilder_Ore)
            {
                string oreSubTypeId = itemDefinition.Id.SubtypeName;
                string materialName = (Item.Content as MyObjectBuilder_Ore).GetMaterialName();
                bool hasMaterialName = (Item.Content as MyObjectBuilder_Ore).HasMaterialName();

                foreach (var mat in MyDefinitionManager.Static.GetVoxelMaterialDefinitions())
                {
                    if ((hasMaterialName && materialName == mat.Id.SubtypeName) || (hasMaterialName == false && oreSubTypeId == mat.MinedOre))
                    {
                        VoxelMaterial = mat;
                        break;
                    }
                }
            }

            // Setting the item's model
            string model = itemDefinition.Model;
            if (itemDefinition.HasModelVariants)
            {
                int modelNum = itemDefinition.Models.Length;
                Debug.Assert(m_modelVariant >= 0 && m_modelVariant < modelNum, "Model variant overflow. This can happen if model variants changed");
                m_modelVariant = m_modelVariant % modelNum;

                model = itemDefinition.Models[m_modelVariant];
            }
            else if (Item.Content is MyObjectBuilder_Ore && VoxelMaterial != null)
            {
                // Only ores without found voxel material use the defined model (otherwise, the scrap metal does not work)
                model = MyDebris.GetRandomDebrisVoxel();
            }

            // Setting the scale
            float scale = this.Item.Scale;
            if (Item.Content is MyObjectBuilder_Ore)
            {
                scale *= (float)Math.Pow((float)Item.Amount * itemDefinition.Volume / MyDebris.VoxelDebrisModelVolume, 0.333f);
            }
            else
            {
                scale *= (float)Math.Pow(itemDefinition.Volume / itemDefinition.ModelVolume, 0.333f);
            }
            if (scale < 0.05f)
                Close();
            else if (scale < 0.15f)
                scale = 0.15f;

            FormatDisplayName(m_displayedText, Item);
            Debug.Assert(model != null, "Floating object model is null");
            Init(m_displayedText, model, null, null, null);

            PositionComp.Scale = scale; // Must be set after init

            var massProperties = new HkMassProperties();
            var mass = MyPerGameSettings.Destruction ? MyDestructionHelper.MassToHavok(itemDefinition.Mass) : itemDefinition.Mass;
            mass = mass * (float)Item.Amount;

            HkShape shape = GetPhysicsShape(mass, scale, out massProperties);
            var scaleMatrix = Matrix.CreateScale(scale);

            if (Physics != null)
                Physics.Close();
            Physics = new MyPhysicsBody(this, RigidBodyFlag.RBF_DEBRIS);

            int layer = mass > MyPerGameSettings.MinimumLargeShipCollidableMass ? MyPhysics.CollisionLayers.FloatingObjectCollisionLayer : MyPhysics.CollisionLayers.LightFloatingObjectCollisionLayer;

            if (VoxelMaterial != null || (shape.IsConvex && scale != 1f))
            {
                HkConvexTransformShape transform = new HkConvexTransformShape((HkConvexShape)shape, ref scaleMatrix, HkReferencePolicy.None);

                Physics.CreateFromCollisionObject(transform, Vector3.Zero, MatrixD.Identity, massProperties, layer);

                Physics.Enabled = true;
                transform.Base.RemoveReference();
            }
            else
            {
                Physics.CreateFromCollisionObject(shape, Vector3.Zero, MatrixD.Identity, massProperties, layer);
                Physics.Enabled = true;
            }

            Physics.MaterialType = this.EvaluatePhysicsMaterial(itemDefinition.PhysicalMaterial);
            Physics.PlayCollisionCueEnabled = true;
            Physics.RigidBody.ContactSoundCallbackEnabled = true;
            m_easeCollisionForce = new HkEasePenetrationAction(Physics.RigidBody, 2f);
            m_massChangeForCollisions = 0.010f;

            NeedsUpdate = MyEntityUpdateEnum.EACH_FRAME;
        }
        public static void CutOutShapeWithProperties(
            MyVoxelBase voxelMap,
            MyShape shape,
            out float voxelsCountInPercent,
            out MyVoxelMaterialDefinition voxelMaterial,
            Dictionary<MyVoxelMaterialDefinition, int> exactCutOutMaterials = null,
            bool updateSync = false,
            bool onlyCheck = false,
            bool applyDamageMaterial = false,
            bool onlyApplyMaterial = false)
        {
            if (MySession.Static.EnableVoxelDestruction == false)
            {
                voxelsCountInPercent = 0;
                voxelMaterial = null;
                return;
            }

            ProfilerShort.Begin("MyVoxelGenerator::CutOutShapeWithProperties()");

            int originalSum = 0;
            int removedSum = 0;
            bool materials = exactCutOutMaterials != null;

            // Bring the shape into voxel space.
            var oldTranmsform = shape.Transformation;
            var newTransf = oldTranmsform * voxelMap.PositionComp.WorldMatrixInvScaled;
            newTransf.Translation += voxelMap.SizeInMetresHalf;
            shape.Transformation = newTransf;

            // This boundary should now be in our local space
            var bbox = shape.GetWorldBoundaries();

            Vector3I minCorner, maxCorner;
            ComputeShapeBounds(voxelMap, ref bbox, Vector3.Zero, voxelMap.Storage.Size, out minCorner, out maxCorner);

            bool readMaterial = exactCutOutMaterials != null || applyDamageMaterial;

            var cacheMin = minCorner - 1;
            var cacheMax = maxCorner + 1;

            //try on making the read/write cell alligned see MyOctreeStorage.WriteRange - Micro octree leaf
            /*const int SHIFT = 4;
            const int REM = (1 << SHIFT) - 1;
            const int MASK = ~REM;
            cacheMin &= MASK;
            cacheMax = (cacheMax + REM) & MASK;*/

            voxelMap.Storage.ClampVoxelCoord(ref cacheMin);
            voxelMap.Storage.ClampVoxelCoord(ref cacheMax);
            m_cache.Resize(cacheMin, cacheMax);
            m_cache.ClearMaterials(0);

            // Advise that the read content shall be cached
            MyVoxelRequestFlags flags = MyVoxelRequestFlags.AdviseCache;
            voxelMap.Storage.ReadRange(m_cache, readMaterial ? MyStorageDataTypeFlags.ContentAndMaterial : MyStorageDataTypeFlags.Content, 0, ref cacheMin, ref cacheMax, ref flags);

            Vector3I center;
            if (materials)
            {
                center = m_cache.Size3D / 2;
                voxelMaterial = MyDefinitionManager.Static.GetVoxelMaterialDefinition(m_cache.Material(ref center));
            }
            else
            {
                center = (cacheMin + cacheMax) / 2;
                voxelMaterial = voxelMap.Storage.GetMaterialAt(ref center);
            }

            MyVoxelMaterialDefinition voxelMat = null;

            ProfilerShort.Begin("Main loop");
            Vector3I pos;
            for (pos.X = minCorner.X; pos.X <= maxCorner.X; ++pos.X)
                for (pos.Y = minCorner.Y; pos.Y <= maxCorner.Y; ++pos.Y)
                    for (pos.Z = minCorner.Z; pos.Z <= maxCorner.Z; ++pos.Z)
            {
                // get original amount
                var relPos = pos - cacheMin;
                var lin = m_cache.ComputeLinear(ref relPos);
                var original = m_cache.Content(lin);

                if (original == MyVoxelConstants.VOXEL_CONTENT_EMPTY) // if there is nothing to remove
                    continue;

                Vector3D spos = (Vector3D)(pos - voxelMap.StorageMin) * MyVoxelConstants.VOXEL_SIZE_IN_METRES;
                var volume = shape.GetVolume(ref spos);

                if (volume == 0f) // if there is no intersection
                    continue;

                var maxRemove = (int)(volume * MyVoxelConstants.VOXEL_CONTENT_FULL);
                var toRemove = maxRemove;// (int)(maxRemove * voxelMat.DamageRatio);
                var newVal = Math.Max(original - toRemove, 0);//MathHelper.Clamp(original - toRemove, 0, original-maxRemove);
                var removed  = original - newVal;

                if (!onlyCheck && !onlyApplyMaterial)
                    m_cache.Content(lin, (byte)newVal);

                originalSum += original;
                removedSum += removed;

                if (readMaterial)
                    voxelMat = MyDefinitionManager.Static.GetVoxelMaterialDefinition(m_cache.Material(lin));

                if (exactCutOutMaterials != null)
                {
                    int value = 0;
                    exactCutOutMaterials.TryGetValue(voxelMat, out value);
                    value += (MyFakes.ENABLE_REMOVED_VOXEL_CONTENT_HACK ? (int)(removed * 3.9f) : removed);
                    exactCutOutMaterials[voxelMat] = value;
                }

                if (applyDamageMaterial && voxelMat.HasDamageMaterial && !onlyCheck)
                    m_cache.Material(lin, voxelMat.DamagedMaterialId);
            }

            if (removedSum > 0 && updateSync && Sync.IsServer)
            {
                shape.SendDrillCutOutRequest(voxelMap, applyDamageMaterial);
            }

            ProfilerShort.BeginNextBlock("Write");

            if (removedSum > 0 && !onlyCheck)
            {
                //  Clear all small voxel that may have been created during explosion. They can be created even outside the range of
                //  explosion sphere, e.g. if you have three voxels in a row A, B, C, where A is 255, B is 60, and C is 255. During the
                //  explosion you change C to 0, so now we have 255, 60, 0. Than another explosion that will change A to 0, so we
                //  will have 0, 60, 0. But B was always outside the range of the explosion. So this is why we need to do -1/+1 and remove
                //  B voxels too.
                //!! TODO AR & MK : check if this is needed !!
                //RemoveSmallVoxelsUsingChachedVoxels();

                var dataTypeFlags = applyDamageMaterial ? MyStorageDataTypeFlags.ContentAndMaterial : MyStorageDataTypeFlags.Content;
                if (MyFakes.LOG_NAVMESH_GENERATION) MyAIComponent.Static.Pathfinding.VoxelPathfinding.DebugLog.LogStorageWrite(voxelMap, m_cache, dataTypeFlags, cacheMin, cacheMax);
                voxelMap.Storage.WriteRange(m_cache, dataTypeFlags, ref cacheMin, ref cacheMax);
            }
            ProfilerShort.End();


            voxelsCountInPercent = (originalSum > 0f) ? (float)removedSum / (float)originalSum : 0f;

            shape.Transformation = oldTranmsform;

            if (removedSum > 0)
                OnVoxelChanged(OperationType.Cut, voxelMap, shape);

            ProfilerShort.End();
        }
 //  Use when you want to change whole cell to one single material
 public void Reset(MyVoxelMaterialDefinition defaultMaterial)
 {
     IsSingleMaterial             = true;
     m_singleMaterial             = defaultMaterial.Index;
     m_averageCellMaterial        = m_singleMaterial;
     m_averageNonRareCellMaterial = m_singleMaterial; // might be rare, but we have no way of knowing what non-rare material to use
     m_materials                  = null;
 }
        public static void CutOutShapeWithProperties(
            MyVoxelBase voxelMap,
            MyShape shape,
            out float voxelsCountInPercent,
            out MyVoxelMaterialDefinition voxelMaterial,
            Dictionary<MyVoxelMaterialDefinition, int> exactCutOutMaterials = null,
            bool updateSync = false,
            bool onlyCheck = false)
        {
            ProfilerShort.Begin("MyVoxelGenerator::CutOutShapeWithProperties()");

            int originalSum = 0;
            int removedSum = 0;

            var bbox = shape.GetWorldBoundaries();
            Vector3I minCorner, maxCorner;
            ComputeShapeBounds(ref bbox, voxelMap.PositionLeftBottomCorner, voxelMap.Storage.Size, out minCorner, out maxCorner);

            var cacheMin = minCorner - 1;
            var cacheMax = maxCorner + 1;
            voxelMap.Storage.ClampVoxelCoord(ref cacheMin);
            voxelMap.Storage.ClampVoxelCoord(ref cacheMax);
            m_cache.Resize(cacheMin, cacheMax);
            voxelMap.Storage.ReadRange(m_cache, MyStorageDataTypeFlags.ContentAndMaterial, 0, ref cacheMin, ref cacheMax);

            {
                var shapeCenter = bbox.Center;
                Vector3I exactCenter;
                MyVoxelCoordSystems.WorldPositionToVoxelCoord(voxelMap.PositionLeftBottomCorner, ref shapeCenter, out exactCenter);
                exactCenter -= cacheMin;
                exactCenter = Vector3I.Clamp(exactCenter, Vector3I.Zero, m_cache.Size3D - 1);
                voxelMaterial = MyDefinitionManager.Static.GetVoxelMaterialDefinition(m_cache.Material(ref exactCenter));
            }

            for (var it = new Vector3I.RangeIterator(ref minCorner, ref maxCorner); it.IsValid(); it.MoveNext())
            {
                var relPos   = it.Current - cacheMin; // get original amount
                var original = m_cache.Content(ref relPos);

                if (original == MyVoxelConstants.VOXEL_CONTENT_EMPTY) // if there is nothing to remove
                    continue;

                Vector3D vpos;
                MyVoxelCoordSystems.VoxelCoordToWorldPosition(voxelMap.PositionLeftBottomCorner, ref it.Current, out vpos);
                var volume = shape.GetVolume(ref vpos);

                if (volume == 0f) // if there is no intersection
                    continue;

                var maxRemove = (int)(volume * MyVoxelConstants.VOXEL_CONTENT_FULL);
                var voxelMat  = MyDefinitionManager.Static.GetVoxelMaterialDefinition(m_cache.Material(ref relPos));
                var toRemove  = (int)(maxRemove * voxelMat.DamageRatio);
                var newVal    = MathHelper.Clamp(original - toRemove, 0, maxRemove);
                var removed   = Math.Abs(original - newVal);

                if (!onlyCheck)
                    m_cache.Content(ref relPos, (byte)newVal);

                originalSum += original;
                removedSum  += removed;

                if (exactCutOutMaterials != null)
                {
                    int value = 0;
                    exactCutOutMaterials.TryGetValue(voxelMat, out value);
                    value += (MyFakes.ENABLE_REMOVED_VOXEL_CONTENT_HACK ? (int)(removed * 3.9f) : removed);
                    exactCutOutMaterials[voxelMat] = value;
                }
            }

            if (removedSum > 0 && !onlyCheck)
            {
                //  Clear all small voxel that may have been created during explosion. They can be created even outside the range of
                //  explosion sphere, e.g. if you have three voxels in a row A, B, C, where A is 255, B is 60, and C is 255. During the
                //  explosion you change C to 0, so now we have 255, 60, 0. Than another explosion that will change A to 0, so we
                //  will have 0, 60, 0. But B was always outside the range of the explosion. So this is why we need to do -1/+1 and remove
                //  B voxels too.
                //!! TODO AR & MK : check if this is needed !!
                RemoveSmallVoxelsUsingChachedVoxels();

                voxelMap.Storage.WriteRange(m_cache, MyStorageDataTypeFlags.Content, ref cacheMin, ref cacheMax);
            }

            if (removedSum > 0 && updateSync && Sync.IsServer)
            {
                shape.SendDrillCutOutRequest(voxelMap.SyncObject);
            }

            voxelsCountInPercent = (originalSum > 0f) ? (float)removedSum / (float)originalSum : 0f;
            ProfilerShort.End();
        }
 //  Change material for specified voxel
 //  If this material is single material for whole cell, we do nothing. Otherwise we allocate 3D arrays and start using them.
 public void SetMaterial(MyVoxelMaterialDefinition material, ref Vector3I voxelCoordInCell)
 {
     SetMaterial(material.Index, ref voxelCoordInCell);
 }
 void IMyStorage.SetSurfaceMaterial(MyVoxelMaterialDefinition material, int cellThickness)
 {
     EnsureMutable();
     m_trueStorage.SetSurfaceMaterial(material, cellThickness);
 }
 public MaterialCell(MyVoxelMaterialDefinition defaultMaterial)
 {
     //  By default cell contains only one single material
     Reset(defaultMaterial);
 }
 public MyCompositeShapeOreDeposit(MyCsgShapeBase shape, MyVoxelMaterialDefinition material)
 {
     Shape = shape;
     m_material = material;
 }
Exemple #30
0
        public void OverwriteAllMaterials(MyVoxelMaterialDefinition material)
        {
            MyPrecalcComponent.AssertUpdateThread();

            using (m_storageLock.AcquireExclusiveUsing())
            {
                m_compressedData = null;
                OverwriteAllMaterialsInternal(material);
            }
            OnRangeChanged(Vector3I.Zero, Size - 1, MyStorageDataTypeFlags.Material);
        }