internal MyVoxelPhysicsBody(MyVoxelBase voxelMap, float phantomExtend, float predictionSize = 3.0f, bool lazyPhysics = false)
            : base(voxelMap, RigidBodyFlag.RBF_STATIC)
        {
            ProfilerShort.Begin("MyVoxelPhysicsBody(");

            InvalidCells = new HashSet<Vector3I>[2];

            InvalidCells[0] = new HashSet<Vector3I>();
            InvalidCells[1] = new HashSet<Vector3I>();

            m_predictionSize = predictionSize;
            m_phantomExtend = phantomExtend;
            m_voxelMap = voxelMap;
            Vector3I storageSize = m_voxelMap.Size;
            Vector3I numCels = storageSize >> MyVoxelConstants.GEOMETRY_CELL_SIZE_IN_VOXELS_BITS;
            m_cellsOffset = m_voxelMap.StorageMin >> MyVoxelConstants.GEOMETRY_CELL_SIZE_IN_VOXELS_BITS;

            if (!MyFakes.ENABLE_LAZY_VOXEL_PHYSICS || !lazyPhysics || !ENABLE_AABB_PHANTOM)
            {
                CreateRigidBodies();
            }

            ProfilerShort.End();

            MaterialType = MyMaterialType.ROCK;
        }
        internal MyVoxelPhysicsBody(MyVoxelBase voxelMap,float phantomExtend): base(voxelMap, RigidBodyFlag.RBF_STATIC)
        {
            m_phantomExtend = phantomExtend;
            m_voxelMap = voxelMap;
            Vector3I storageSize = m_voxelMap.Size;
            Vector3I numCels = storageSize >> MyVoxelConstants.GEOMETRY_CELL_SIZE_IN_VOXELS_BITS;
            m_cellsOffset = m_voxelMap.StorageMin >> MyVoxelConstants.GEOMETRY_CELL_SIZE_IN_VOXELS_BITS;

            HkUniformGridShape shape = new HkUniformGridShape(
                new HkUniformGridShapeArgs()
                {
                    CellsCount = numCels,
                    CellSize = MyVoxelConstants.GEOMETRY_CELL_SIZE_IN_METRES,
                    CellOffset = MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF,
                    CellExpand = MyVoxelConstants.VOXEL_SIZE_IN_METRES,
                });
            shape.SetShapeRequestHandler(RequestShapeBlocking);

            CreateFromCollisionObject(shape, -m_voxelMap.SizeInMetresHalf, m_voxelMap.WorldMatrix, collisionFilter: MyPhysics.VoxelCollisionLayer);
            shape.Base.RemoveReference();

            if (ENABLE_AABB_PHANTOM)
            {
                m_aabbPhantom = new Havok.HkpAabbPhantom(new BoundingBox(Vector3.Zero, m_voxelMap.SizeInMetres), 0);
                m_aabbPhantom.CollidableAdded = AabbPhantom_CollidableAdded;
                m_aabbPhantom.CollidableRemoved = AabbPhantom_CollidableRemoved;
            }

            if (MyFakes.ENABLE_PHYSICS_HIGH_FRICTION)
                Friction = 0.65f;

            MaterialType = Sandbox.Common.MyMaterialType.ROCK;
        }
示例#3
0
 public void RemoveVoxelMap(MyVoxelBase voxelMap)
 {
     if (m_voxelMapsByEntityId.Remove(voxelMap.EntityId))
     {
         var render = voxelMap.Render;
         if (render is MyRenderComponentVoxelMap)
         {
             var clipMapId = (render as MyRenderComponentVoxelMap).ClipmapId;
             m_renderComponentsByClipmapId.Remove(clipMapId);
         }
     }
 }
示例#4
0
        //  Blends-out triangles affected by explosion (radius + some safe delta). Triangles there have zero alpha are flaged to not-draw at all.
        public static void HideTrianglesAfterExplosion(MyVoxelBase voxelMap, ref BoundingSphereD explosionSphere)
        {
            VRageRender.MyRenderProxy.GetRenderProfiler().StartProfilingBlock("MyDecals::HideTrianglesAfterExplosion");
            //MyMwcVector3Int renderCellCoord = voxelMap.GetVoxelRenderCellCoordinateFromMeters(ref explosionSphere.Center);
            //m_decalsForVoxels.HideTrianglesAfterExplosion(voxelMap.VoxelMapId, ref renderCellCoord, ref explosionSphere);

            foreach (uint id in voxelMap.Render.RenderObjectIDs)
            {
                VRageRender.MyRenderProxy.HideDecals(id, explosionSphere.Center, (float)explosionSphere.Radius);
            }

            VRageRender.MyRenderProxy.GetRenderProfiler().EndProfilingBlock();
        }
示例#5
0
        public void Add(MyVoxelBase voxelMap)
        {
            if (!Exist(voxelMap))
            {
                m_voxelMapsByEntityId.Add(voxelMap.EntityId, voxelMap);

                // On dedicated servers, ClipmapIDs are all 0, but it's fine since there is no rendering anyway.
                var render = voxelMap.Render;
                if (render is MyRenderComponentVoxelMap)
                {
                   var clipMapId= (render as MyRenderComponentVoxelMap).ClipmapId;
                   m_renderComponentsByClipmapId[clipMapId] = render as MyRenderComponentVoxelMap;
                }
            }
        }
            public void Add(MatrixD worldMatrix, BoundingBox box, Vector4I id, MyVoxelBase voxel)
            {
                if (m_list.Count > 1900)
                    m_list.ClearList();

                voxel = voxel.RootVoxel;
                box.Translate(-voxel.SizeInMetresHalf);
                //box.Translate(voxel.StorageMin);


                m_list.Add(new PredictionInfo
                {
                    Id = id,
                    Bounds = MyOrientedBoundingBoxD.Create((BoundingBoxD)box, voxel.WorldMatrix),
                    Body = voxel
                });
            }
        public MyVoxelNavigationMesh(MyVoxelBase voxelMap, MyNavmeshCoordinator coordinator, Func<long> timestampFunction)
            : base(coordinator.Links, 16, timestampFunction)
        {
            m_voxelMap = voxelMap;
            m_cellSize = m_voxelMap.SizeInMetres / m_voxelMap.Storage.Geometry.CellsCount * (1 << NAVMESH_LOD);

            m_processedCells = new MyVector3ISet();
            m_markedForAddition = new MyVector3ISet();
            m_toAdd = new MyBinaryStructHeap<float, Vector3I>(128);

            m_connectionHelper = new MyVoxelConnectionHelper();
            m_navmeshCoordinator = coordinator;
            m_higherLevel = new MyHighLevelGroup(this, coordinator.HighLevelLinks, timestampFunction);
            m_higherLevelHelper = new MyVoxelHighLevelHelper(this);

            m_debugCellEdges = new Dictionary<ulong, List<DebugDrawEdge>>();

            voxelMap.Storage.RangeChanged += OnStorageChanged;
        }
示例#8
0
 private static void VoxelOperationElipsoid_Implementation(long entityId, Vector3 radius, MatrixD Transformation, byte material, OperationType Type)
 {
     m_ellipsoidShape.Transformation = Transformation;
     m_ellipsoidShape.Radius         = radius;
     if (CanPlaceInArea(Type, m_ellipsoidShape))
     {
         MyEntity entity;
         MyEntities.TryGetEntityById(entityId, out entity);
         MyVoxelBase voxel = entity as MyVoxelBase;
         if (voxel != null)
         {
             voxel.BeforeContentChanged = true;
             MyMultiplayer.RaiseEvent(voxel.RootVoxel, x => x.PerformVoxelOperationElipsoid_Implementation, radius, Transformation, material, Type);
             var amountChanged = voxel.UpdateVoxelShape(Type, m_ellipsoidShape, material);
             if (Type == OperationType.Cut || Type == OperationType.Fill)
             {
                 MySession.Static.VoxelHandVolumeChanged += amountChanged;
             }
         }
     }
 }
示例#9
0
        static void VoxelOperationSphere_Implementation(long entityId, Vector3D center, float radius, byte material, OperationType Type)
        {
            m_sphereShape.Center = center;
            m_sphereShape.Radius = radius;

            if (CanPlaceInArea(Type, m_sphereShape))
            {
                MyEntity entity;
                MyEntities.TryGetEntityById(entityId, out entity);
                MyVoxelBase voxel = entity as MyVoxelBase;
                if (voxel != null)
                {
                    voxel.BeforeContentChanged = true;
                    MyMultiplayer.RaiseEvent(voxel, x => x.PerformVoxelOperationSphere_Implementation, center, radius, material, Type);
                    var amountChanged = voxel.UpdateVoxelShape(Type, m_sphereShape, material);
                    if (Type == OperationType.Cut || Type == OperationType.Fill)
                    {
                        MySession.Static.VoxelHandVolumeChanged += amountChanged;
                    }
                }
            }
        }
示例#10
0
        private static void VoxelOperationBox_Implementation(long entityId, BoundingBoxD box, MatrixD Transformation, byte material, OperationType Type)
        {
            m_boxShape.Transformation = Transformation;
            m_boxShape.Boundaries.Max = box.Max;
            m_boxShape.Boundaries.Min = box.Min;

            if (CanPlaceInArea(Type, m_boxShape))
            {
                MyEntity entity;
                MyEntities.TryGetEntityById(entityId, out entity);
                MyVoxelBase voxel = entity as MyVoxelBase;
                if (voxel != null)
                {
                    voxel.BeforeContentChanged = true;
                    MyMultiplayer.RaiseEvent(voxel.RootVoxel, x => x.PerformVoxelOperationBox_Implementation, box, Transformation, material, Type);
                    var amountChanged = voxel.UpdateVoxelShape(Type, m_boxShape, material);
                    if (Type == OperationType.Cut || Type == OperationType.Fill)
                    {
                        MySession.Static.VoxelHandVolumeChanged += amountChanged;
                    }
                }
            }
        }
示例#11
0
        private static void VoxelOperationCapsule_Implementation(long entityId, MyCapsuleShapeParams capsuleParams, OperationType Type)
        {
            m_capsuleShape.Transformation = capsuleParams.Transformation;
            m_capsuleShape.A      = capsuleParams.A;
            m_capsuleShape.B      = capsuleParams.B;
            m_capsuleShape.Radius = capsuleParams.Radius;

            if (CanPlaceInArea(Type, m_capsuleShape))
            {
                MyEntity entity;
                MyEntities.TryGetEntityById(entityId, out entity);
                MyVoxelBase voxel = entity as MyVoxelBase;
                if (voxel != null)
                {
                    voxel.BeforeContentChanged = true;
                    MyMultiplayer.RaiseEvent(voxel.RootVoxel, x => x.PerformVoxelOperationCapsule_Implementation, capsuleParams, Type);
                    var amountChanged = voxel.UpdateVoxelShape(Type, m_capsuleShape, capsuleParams.Material);
                    if (Type == OperationType.Cut || Type == OperationType.Fill)
                    {
                        MySession.Static.VoxelHandVolumeChanged += amountChanged;
                    }
                }
            }
        }
示例#12
0
 public abstract void SendFillRequest(MyVoxelBase voxel, byte newMaterialIndex);
示例#13
0
 public virtual void SendDrillCutOutRequest(MyVoxelBase voxel, bool damage = false) { }
示例#14
0
 public abstract void SendCutOutRequest(MyVoxelBase voxelbool);
        private static bool TestVoxelOverlap(ref MyGridPlacementSettings settings, ref BoundingBoxD localAabb, ref MatrixD worldMatrix, ref BoundingBoxD worldAabb, ref MyVoxelBase overlappedVoxelMap, bool touchingStaticGrid)
        {
            ProfilerShort.Begin("VoxelOverlap");
            try
            {
                if (MyFakes.GRID_IGNORE_VOXEL_OVERLAP) return true;

                if (MyFakes.ENABLE_VOXEL_MAP_AABB_CORNER_TEST)
                {
                    return TestPlacementVoxelMapOverlap(overlappedVoxelMap, ref settings, ref localAabb, ref worldMatrix, touchingStaticGrid: touchingStaticGrid);
                }
                else
                {
                    if (overlappedVoxelMap == null)
                    { // Havok only detects overlap with voxel map surface. This test will detect a voxel map even if we're fully inside it.

                        overlappedVoxelMap = MySession.Static.VoxelMaps.GetVoxelMapWhoseBoundingBoxIntersectsBox(ref worldAabb, null);
                        if (overlappedVoxelMap != null)
                        {
                            //We have just test, if aabb is not completelly inside voxelmap
                            if (!overlappedVoxelMap.IsOverlapOverThreshold(worldAabb))
                                overlappedVoxelMap = null;
                        }
                    }
                    return TestPlacementVoxelMapPenetration(overlappedVoxelMap, ref settings, ref localAabb, ref worldMatrix, touchingStaticGrid: touchingStaticGrid);
                }
            }
            finally
            {
                ProfilerShort.End();
            }
        }
		private MySoundPair SelectSound()
		{
            MySoundPair soundPair = EmptySoundPair;
            MyCharacterDefinition myCharDefinition = m_character.Definition;
            MyStringHash physMaterial = MyStringHash.GetOrCompute(myCharDefinition.PhysicalMaterial);
            m_isWalking = false;

            bool updateEmitterSounds = false;
            MyCharacterMovementEnum movementState = m_character.GetCurrentMovementState();
            switch (movementState)
			{
				case MyCharacterMovementEnum.Walking:
				case MyCharacterMovementEnum.BackWalking:
				case MyCharacterMovementEnum.WalkingLeftFront:
				case MyCharacterMovementEnum.WalkingRightFront:
				case MyCharacterMovementEnum.WalkingLeftBack:
				case MyCharacterMovementEnum.WalkingRightBack:
				case MyCharacterMovementEnum.WalkStrafingLeft:
				case MyCharacterMovementEnum.WalkStrafingRight:
					{
                        if (m_character.Breath != null)
						    m_character.Breath.CurrentState = MyCharacterBreath.State.Calm;
                        soundPair = MyMaterialPropertiesHelper.Static.GetCollisionCue(MovementSoundType.Walk, physMaterial, RayCastGround());
                        m_isWalking = true;
					}
					break;
				case MyCharacterMovementEnum.Running:
				case MyCharacterMovementEnum.Backrunning:
				case MyCharacterMovementEnum.RunStrafingLeft:
				case MyCharacterMovementEnum.RunStrafingRight:
				case MyCharacterMovementEnum.RunningRightFront:
				case MyCharacterMovementEnum.RunningRightBack:
				case MyCharacterMovementEnum.RunningLeftFront:
				case MyCharacterMovementEnum.RunningLeftBack:
                    {
                        if (m_character.Breath != null)
						    m_character.Breath.CurrentState = MyCharacterBreath.State.Heated;
                        soundPair = MyMaterialPropertiesHelper.Static.GetCollisionCue(MovementSoundType.Run, physMaterial, RayCastGround());
                        m_isWalking = true;
					}
					break;
				case MyCharacterMovementEnum.CrouchWalking:
				case MyCharacterMovementEnum.CrouchBackWalking:
				case MyCharacterMovementEnum.CrouchWalkingLeftFront:
				case MyCharacterMovementEnum.CrouchWalkingRightFront:
				case MyCharacterMovementEnum.CrouchWalkingLeftBack:
				case MyCharacterMovementEnum.CrouchWalkingRightBack:
				case MyCharacterMovementEnum.CrouchStrafingLeft:
				case MyCharacterMovementEnum.CrouchStrafingRight:
                    {
                        if (m_character.Breath != null)
						    m_character.Breath.CurrentState = MyCharacterBreath.State.Calm;
                        soundPair = MyMaterialPropertiesHelper.Static.GetCollisionCue(MovementSoundType.CrouchWalk, physMaterial, RayCastGround());
                        m_isWalking = true;
					}
					break;
                case MyCharacterMovementEnum.Crouching:
                case MyCharacterMovementEnum.Standing:
                    {
                        if (m_character.Breath != null)
                            m_character.Breath.CurrentState = MyCharacterBreath.State.Calm;
                        var previousMovementState = m_character.GetPreviousMovementState();
                        var currentMovementState = m_character.GetCurrentMovementState();
                        if (previousMovementState != currentMovementState
                            && (previousMovementState == MyCharacterMovementEnum.Standing || previousMovementState == MyCharacterMovementEnum.Crouching))
                            soundPair = (currentMovementState == MyCharacterMovementEnum.Standing) ? CharacterSounds[(int)CharacterSoundsEnum.CROUCH_UP_SOUND] : CharacterSounds[(int)CharacterSoundsEnum.CROUCH_DOWN_SOUND];
                    }
                    break;
				case MyCharacterMovementEnum.Sprinting:
                    {
                        if (m_character.Breath != null)
                            m_character.Breath.CurrentState = MyCharacterBreath.State.VeryHeated;
                        soundPair = MyMaterialPropertiesHelper.Static.GetCollisionCue(MovementSoundType.Sprint, physMaterial, RayCastGround());
                        m_isWalking = true;
					}
					break;
				case MyCharacterMovementEnum.Jump:
					{
                        if (!m_jumpReady)
							break;
                        m_jumpReady = false;
						m_character.SetPreviousMovementState(m_character.GetCurrentMovementState());
						var emitter = MyAudioComponent.TryGetSoundEmitter(); // We need to use another emitter otherwise the sound would be cut by silence next frame
						if (emitter != null)
						{
							emitter.Entity = m_character;
							emitter.PlaySingleSound(CharacterSounds[(int)CharacterSoundsEnum.JUMP_SOUND]);
						}

                        if ((m_standingOnGrid != null || m_standingOnVoxel != null) && ShouldUpdateSoundEmitters)
                            updateEmitterSounds = true;
                        m_standingOnGrid = null;
                        m_standingOnVoxel = null;
					}
					break;
				case MyCharacterMovementEnum.Flying:
                    {
                        if (m_character.Breath != null)
						    m_character.Breath.CurrentState = MyCharacterBreath.State.Calm;
                        if (m_character.JetpackComp != null && m_jetpackMinIdleTime <= 0f && m_character.JetpackComp.FinalThrust.LengthSquared() >= 50000f)
                        {
                            soundPair = CharacterSounds[(int)CharacterSoundsEnum.JETPACK_RUN_SOUND];
                            m_jetpackSustainTimer = Math.Min(JETPACK_TIME_BETWEEN_SOUNDS, m_jetpackSustainTimer + MyEngineConstants.UPDATE_STEP_SIZE_IN_SECONDS);
                        }
                        else
                        {
                            soundPair = CharacterSounds[(int)CharacterSoundsEnum.JETPACK_IDLE_SOUND];
                            m_jetpackSustainTimer = Math.Max(0f, m_jetpackSustainTimer - MyEngineConstants.UPDATE_STEP_SIZE_IN_SECONDS);
                        }
                        m_jetpackMinIdleTime -= MyEngineConstants.UPDATE_STEP_SIZE_IN_SECONDS;

                        if ((m_standingOnGrid != null || m_standingOnVoxel != null) && ShouldUpdateSoundEmitters)
                            updateEmitterSounds = true;
                        m_standingOnGrid = null;
                        m_standingOnVoxel = null;
					}
					break;
				case MyCharacterMovementEnum.Falling:
                    {
                        if (m_character.Breath != null)
						    m_character.Breath.CurrentState = MyCharacterBreath.State.Calm;

                        if ((m_standingOnGrid != null || m_standingOnVoxel != null) && ShouldUpdateSoundEmitters)
                            updateEmitterSounds = true;
                        m_standingOnGrid = null;
                        m_standingOnVoxel = null;
					}
					break;
				default:
					{
					}
					break;
			}

            //MyRenderProxy.DebugDrawText2D(Vector2.Zero, movementState.ToString(), Color.Red, 1.0f);

            if (movementState != MyCharacterMovementEnum.Flying)
            {
                m_jetpackSustainTimer = 0f;
                m_jetpackMinIdleTime = 0.5f;
            }
            if(updateEmitterSounds)
                MyEntity3DSoundEmitter.UpdateEntityEmitters(true, true, false);
			return soundPair;
		}
        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();
        }
        private static bool TestPlacementVoxelMapPenetration(
            MyVoxelBase voxelMap, 
            ref MyGridPlacementSettings settings,
            ref BoundingBoxD localAabb,
            ref MatrixD worldMatrix,
            bool touchingStaticGrid = false)
        {
            ProfilerShort.Begin("TestPlacementVoxelMapPenetration");
            var worldAabb = localAabb.Transform(ref worldMatrix);

            float penetrationAmountNormalized = 0f;
            float penetrationRatio = 0f;
            float penetrationVolume = 0f;
            if (voxelMap != null)
            {
                float unused;
                penetrationAmountNormalized = voxelMap.GetVoxelContentInBoundingBox_Obsolete(worldAabb, out unused);
                penetrationVolume = penetrationAmountNormalized * MyVoxelConstants.VOXEL_VOLUME_IN_METERS;
                penetrationRatio = penetrationVolume / (float)worldAabb.Volume;
            }

            bool penetrationTestPassed = true;
            switch (settings.Penetration.Unit)
            {
                case MyGridPlacementSettings.PenetrationUnitEnum.Absolute:
                    penetrationTestPassed = penetrationVolume <= settings.Penetration.MaxAllowed &&
                        (penetrationVolume >= settings.Penetration.MinAllowed || (settings.CanAnchorToStaticGrid && touchingStaticGrid));
                    break;

                case MyGridPlacementSettings.PenetrationUnitEnum.Ratio:
                    penetrationTestPassed = penetrationRatio <= settings.Penetration.MaxAllowed &&
                        (penetrationRatio >= settings.Penetration.MinAllowed || (settings.CanAnchorToStaticGrid && touchingStaticGrid));
                    break;

                default:
                    Debug.Fail("Invalid branch.");
                    break;
            }

            ProfilerShort.End();

            return penetrationTestPassed;
        }
示例#19
0
 private void MakeTransparent(MyVoxelBase voxelMap)
 {
     voxelMap.Render.Transparency = MyGridConstants.BUILDER_TRANSPARENCY;
 }
示例#20
0
 private void MakeVisible(MyVoxelBase voxelMap)
 {
     voxelMap.Render.Transparency = 0f;
 }
示例#21
0
 public bool Exist(MyVoxelBase voxelMap)
 {
     return(m_voxelMapsByEntityId.ContainsKey(voxelMap.EntityId));
 }
示例#22
0
        /// <summary>
        /// Return reference to voxel map that intersects the box. If not voxel map found, null is returned.
        /// </summary>
        public MyVoxelBase GetVoxelMapWhoseBoundingBoxIntersectsBox(ref BoundingBoxD boundingBox, MyVoxelBase ignoreVoxelMap)
        {
            foreach (var voxelMap in m_voxelMapsByEntityId.Values)
            {
                if (voxelMap == ignoreVoxelMap)
                {
                    continue;
                }
                if (voxelMap is MyVoxelBase)
                {
                    if (voxelMap.IsBoxIntersectingBoundingBoxOfThisVoxelMap(ref boundingBox))
                    {
                        return(voxelMap);
                    }
                }
            }

            //  If we get here, no intersection was found
            return(null);
        }
示例#23
0
        private static void ComputeShapeBounds(MyVoxelBase voxelMap,
            ref BoundingBoxD shapeAabb, Vector3D voxelMapMinCorner, Vector3I storageSize,
            out Vector3I voxelMin, out Vector3I voxelMax)
        {
            MyVoxelCoordSystems.WorldPositionToVoxelCoord(voxelMapMinCorner, ref shapeAabb.Min, out voxelMin);
            MyVoxelCoordSystems.WorldPositionToVoxelCoord(voxelMapMinCorner, ref shapeAabb.Max, out voxelMax);
            voxelMin += voxelMap.StorageMin;
            voxelMax += voxelMap.StorageMin;

            voxelMax += 1; //what? why? Another hack of MK?

            storageSize -= 1;
            Vector3I.Clamp(ref voxelMin, ref Vector3I.Zero, ref storageSize, out voxelMin);
            Vector3I.Clamp(ref voxelMax, ref Vector3I.Zero, ref storageSize, out voxelMax);
        }
        private void AddVoxelMesh(MyVoxelBase voxelBase, IMyStorage storage, Dictionary<Vector3I, MyIsoMesh> cache, float border, Vector3D originPosition, MyOrientedBoundingBoxD obb, List<BoundingBoxD> bbList)
        {
            bool useCache = cache != null;
            if (useCache)
                CheckCacheValidity();

            obb.HalfExtent += new Vector3D(border, 0, border);
            BoundingBoxD bb = obb.GetAABB();            
            int aabbSideSide = (int)Math.Round(bb.HalfExtents.Max() * 2);
            bb = new BoundingBoxD(bb.Min, bb.Min + aabbSideSide);
            bb.Translate(obb.Center - bb.Center);

            // For debug
            bbList.Add(new BoundingBoxD(bb.Min, bb.Max));

            bb = (BoundingBoxD)bb.TransformFast(voxelBase.PositionComp.WorldMatrixInvScaled);
            bb.Translate(voxelBase.SizeInMetresHalf);

            Vector3I min = Vector3I.Round(bb.Min);
            Vector3I max = min + aabbSideSide;
            Vector3I geomMin, geomMax;
            MyVoxelCoordSystems.VoxelCoordToGeometryCellCoord(ref min, out geomMin);
            MyVoxelCoordSystems.VoxelCoordToGeometryCellCoord(ref max, out geomMax);

            var cullBox = obb;
            cullBox.Transform(voxelBase.PositionComp.WorldMatrixInvScaled);
            cullBox.Center += voxelBase.SizeInMetresHalf;
            ProfilerShort.Begin("WOOOORK");

            Vector3I_RangeIterator it = new Vector3I_RangeIterator(ref geomMin, ref geomMax);
            MyCellCoord coord = new MyCellCoord();
            BoundingBox localAabb;
            coord.Lod = NAVMESH_LOD;
            int hits = 0;
            MyIsoMesh gMesh;
            Vector3 offset = originPosition - voxelBase.PositionLeftBottomCorner;

            // Calculate rotation
            Vector3 gravityVector = -Vector3.Normalize(GameSystems.MyGravityProviderSystem.CalculateTotalGravityInPoint(originPosition));
            Vector3 forwardVector = Vector3.CalculatePerpendicularVector(gravityVector);
            Quaternion quaternion = Quaternion.CreateFromForwardUp(forwardVector, gravityVector);
            Matrix rotation = Matrix.CreateFromQuaternion(Quaternion.Inverse(quaternion));

            Matrix ownRotation = voxelBase.PositionComp.WorldMatrix.GetOrientation();

            while (it.IsValid())
            {
                ProfilerShort.Begin("ITERATOR");

                if (useCache && cache.TryGetValue(it.Current, out gMesh))
                {
                    if (gMesh != null)
                    {
                        AddMeshTriangles(gMesh, offset, rotation, ownRotation);
                    }
                    it.MoveNext();
                    ProfilerShort.End();
                    continue;
                }
                    
                coord.CoordInLod = it.Current;
                MyVoxelCoordSystems.GeometryCellCoordToLocalAABB(ref coord.CoordInLod, out localAabb);
                
                if (!cullBox.Intersects(ref localAabb))
                {
                    hits++;
                    it.MoveNext();
                    ProfilerShort.End();
                    continue;
                }
                ProfilerShort.End();

                var debugBB = new BoundingBoxD(localAabb.Min, localAabb.Max).Translate(-voxelBase.SizeInMetresHalf);
                bbList.Add(debugBB);

                ProfilerShort.Begin("Mesh Calc");
                var voxelStart = coord.CoordInLod * MyVoxelConstants.GEOMETRY_CELL_SIZE_IN_VOXELS - 1;
                var voxelEnd = voxelStart + MyVoxelConstants.GEOMETRY_CELL_SIZE_IN_VOXELS //- 1
                    + 1 // overlap to neighbor so geometry is stitched together within same LOD
                    + 1; // for eg. 9 vertices in row we need 9 + 1 samples (voxels)

                var generatedMesh = MyPrecalcComponent.IsoMesher.Precalc(storage, NAVMESH_LOD, voxelStart, voxelEnd, false, false, true);
                ProfilerShort.End();

                if (useCache)
                    cache[it.Current] = generatedMesh;

                if (generatedMesh != null)
                {
                    ProfilerShort.Begin("Mesh NOT NULL");
                    AddMeshTriangles(generatedMesh, offset, rotation, ownRotation);
                    ProfilerShort.End();
                }
                it.MoveNext();
            }
            ProfilerShort.End();
        }
        public static void PaintInShape(MyVoxelBase voxelMap, MyShape shape, byte materialIdx)
        {
            Vector3I minCorner, maxCorner, numCells;
            GetVoxelShapeDimensions(voxelMap, shape, out minCorner, out maxCorner, out numCells);

            for (var itCells = new Vector3I.RangeIterator(ref Vector3I.Zero, ref numCells); itCells.IsValid(); itCells.MoveNext())
            {
                Vector3I cellMinCorner, cellMaxCorner;
                GetCellCorners(ref minCorner, ref maxCorner, ref itCells, out cellMinCorner, out cellMaxCorner);

                m_cache.Resize(cellMinCorner, cellMaxCorner);
                voxelMap.Storage.ReadRange(m_cache, MyStorageDataTypeFlags.Material, 0, ref cellMinCorner, ref cellMaxCorner);

                for (var it = new Vector3I.RangeIterator(ref cellMinCorner, ref cellMaxCorner); it.IsValid(); it.MoveNext())
                {
                    var relPos = it.Current - cellMinCorner;

                    Vector3D vpos;
                    MyVoxelCoordSystems.VoxelCoordToWorldPosition(voxelMap.PositionLeftBottomCorner, ref it.Current, out vpos);
                    float volume = shape.GetVolume(ref vpos);
                    if (volume > 0.5f)
                        m_cache.Material(ref relPos, materialIdx); // set material
                }

                voxelMap.Storage.WriteRange(m_cache, MyStorageDataTypeFlags.Material, ref cellMinCorner, ref cellMaxCorner);
            }
        }
        private MyStringHash RayCastGround()
		{
            MyStringHash walkSurfaceMaterial = new MyStringHash();

            float maxDistValue = MyConstants.DEFAULT_GROUND_SEARCH_DISTANCE;
            var from = m_character.PositionComp.GetPosition() + m_character.PositionComp.WorldMatrix.Up * 0.5; //(needs some small distance from the bottom or the following call to HavokWorld.CastRay will find no hits)
            var to = from + m_character.PositionComp.WorldMatrix.Down * maxDistValue;

			MyPhysics.CastRay(from, to, m_hits, MyPhysics.CollisionLayers.CharacterCollisionLayer);

			// Skips invalid hits (null body, self character)
			int index = 0;
			while ((index < m_hits.Count) && ((m_hits[index].HkHitInfo.Body == null) || (m_hits[index].HkHitInfo.GetHitEntity() == Entity.Components)))
			{
				index++;
			}

            if (m_hits.Count == 0)
            {
                if ((m_standingOnGrid != null || m_standingOnVoxel != null) && ShouldUpdateSoundEmitters)
                {
                m_standingOnGrid = null;
                m_standingOnVoxel = null;
                    MyEntity3DSoundEmitter.UpdateEntityEmitters(true, true, false);
            }
                else
                {
                    m_standingOnGrid = null;
                    m_standingOnVoxel = null;
                }
            }

			if (index < m_hits.Count)
			{
				// We must take only closest hit (others are hidden behind)
				var h = m_hits[index];
				var entity = h.HkHitInfo.GetHitEntity();

				var sqDist = Vector3D.DistanceSquared((Vector3D)h.Position, from);
                if (sqDist < maxDistValue * maxDistValue)
				{
					var cubeGrid = entity as MyCubeGrid;
					var voxelBase = entity as MyVoxelBase;

                    if (((cubeGrid != null && m_standingOnGrid != cubeGrid) || (voxelBase != null && m_standingOnVoxel != voxelBase)) && ShouldUpdateSoundEmitters)
                    {
                    m_standingOnGrid = cubeGrid;
                    m_standingOnVoxel = voxelBase;
                        MyEntity3DSoundEmitter.UpdateEntityEmitters(true, true, true);
                    }
                    else
                    {
                        m_standingOnGrid = cubeGrid;
                        m_standingOnVoxel = voxelBase;
                    }
                    if(cubeGrid != null || voxelBase != null)
                        m_jumpReady = true;

                    if (cubeGrid != null)
                        walkSurfaceMaterial = cubeGrid.Physics.GetMaterialAt(h.Position + m_character.PositionComp.WorldMatrix.Down * 0.1f);
                    else if (voxelBase != null && voxelBase.Storage != null && voxelBase.Storage.DataProvider != null)
                    {
                        var materialDefinition = voxelBase.GetMaterialAt(ref h.Position);
                        if (materialDefinition != null)
                            walkSurfaceMaterial = MyStringHash.GetOrCompute(materialDefinition.MaterialTypeName);
                    }
					if (walkSurfaceMaterial.ToString().Length == 0)
						walkSurfaceMaterial = MyMaterialType.ROCK;
				}
			}

			m_hits.Clear();

			return walkSurfaceMaterial;
		}
 private static void GetVoxelShapeDimensions(MyVoxelBase voxelMap, MyShape shape, out Vector3I minCorner, out Vector3I maxCorner, out Vector3I numCells, float extent = 0.0f)
 {
     {
         var bbox = shape.GetWorldBoundaries();
         ComputeShapeBounds(ref bbox, voxelMap.PositionLeftBottomCorner, voxelMap.Storage.Size, out minCorner, out maxCorner);
     }
     minCorner += voxelMap.StorageMin;
     maxCorner += voxelMap.StorageMin;
     numCells = new Vector3I((maxCorner.X - minCorner.X) / CELL_SIZE, (maxCorner.Y - minCorner.Y) / CELL_SIZE, (maxCorner.Z - minCorner.Z) / CELL_SIZE);
 }
        public static bool TestPlacementVoxelMapOverlap(
            MyVoxelBase voxelMap,
            ref MyGridPlacementSettings settings,
            ref BoundingBoxD localAabb,
            ref MatrixD worldMatrix,
            bool touchingStaticGrid = false)
        {
            ProfilerShort.Begin("TestPlacementVoxelMapOverlap");

            var worldAabb = localAabb.Transform(ref worldMatrix);

            const int IntersectsOrInside = 1;
            const int Outside = 2;

            int overlapState = Outside;

            if (voxelMap == null)
                voxelMap = MySession.Static.VoxelMaps.GetVoxelMapWhoseBoundingBoxIntersectsBox(ref worldAabb, null);

            if (voxelMap != null && voxelMap.IsAnyAabbCornerInside(ref worldMatrix, localAabb))
            {
                overlapState = IntersectsOrInside;
            }

            bool testPassed = true;

            switch (overlapState)
            {
                case IntersectsOrInside:
                    testPassed = settings.Penetration.MaxAllowed > 0;
                    break;
                case Outside:
                    testPassed = settings.Penetration.MinAllowed <= 0 || (settings.CanAnchorToStaticGrid && touchingStaticGrid);
                    break;
                default:
                    Debug.Fail("Invalid branch.");
                    break;
            }

            ProfilerShort.End();

            return testPassed;
        }
示例#29
0
 private void CreateCrater(MyPhysics.MyContactPointEvent value, MyVoxelBase voxel)
 {
     if (Math.Abs(Vector3.Normalize(-Entity.WorldMatrix.Forward).Dot(value.ContactPointEvent.ContactPoint.Normal)) < 0.1)
     {
         MyParticleEffect impactParticle1;
         if (InParticleVisibleRange && MyParticlesManager.TryCreateParticleEffect((int)MyParticleEffectsIDEnum.MeteorAsteroidCollision, out impactParticle1))
         {
             impactParticle1.WorldMatrix = Entity.WorldMatrix;
             impactParticle1.UserScale = (float)Entity.PositionComp.WorldVolume.Radius * 2;
         }
         m_particleVectorUp = Vector3.Zero;
         return;
     }
     if (Sync.IsServer)
     {
         BoundingSphereD sphere = new BoundingSphere(value.Position, Entity.PositionComp.Scale.Value / 3);
         Vector3 direction;
         // if contact was send after reflection we need to get former direction
         if (value.ContactPointEvent.SeparatingVelocity < 0)
             direction = Vector3.Normalize(Entity.Physics.LinearVelocity);
         else
             direction = Vector3.Normalize(Vector3.Reflect(Entity.Physics.LinearVelocity, value.ContactPointEvent.ContactPoint.Normal));
         var material = VoxelMaterial;
         int tries = MyDefinitionManager.Static.GetVoxelMaterialDefinitions().Count() * 2; // max amount of tries
         while (!material.IsRare || !material.SpawnsFromMeteorites || material.MinVersion > MySession.Static.Settings.VoxelGeneratorVersion)
         {
             if (--tries < 0) // to prevent infinite loops in case all materials are disabled just use the meteorites' initial material
             {
                 material = VoxelMaterial;
                 break;
             }
             material = MyDefinitionManager.Static.GetVoxelMaterialDefinitions().ElementAt(MyUtils.GetRandomInt(MyDefinitionManager.Static.GetVoxelMaterialDefinitions().Count() - 1));
         }
         voxel.CreateVoxelMeteorCrater(sphere.Center, (float)sphere.Radius, -direction, material);
         MyVoxelGenerator.MakeCrater(voxel, sphere, -direction, material);
     }
     m_closeAfterSimulation = Sync.IsServer;
 }
        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();
        }
示例#31
0
 public override void SendFillRequest(MyVoxelBase voxel, byte newMaterialIndex)
 {
     voxel.RequestVoxelOperationRamp(Boundaries, RampNormal, RampNormalW, Transformation, newMaterialIndex, OperationType.Fill);
 }
        public static ulong FillInShape(MyVoxelBase voxelMap, MyShape shape, byte materialIdx)
        {
            Vector3I minCorner, maxCorner, numCells;
            ulong retValue = 0;
            GetVoxelShapeDimensions(voxelMap, shape, out minCorner, out maxCorner, out numCells);

            for (var itCells = new Vector3I.RangeIterator(ref Vector3I.Zero, ref numCells); itCells.IsValid(); itCells.MoveNext())
            {
                Vector3I cellMinCorner, cellMaxCorner;
                GetCellCorners(ref minCorner, ref maxCorner, ref itCells, out cellMinCorner, out cellMaxCorner);

                Vector3I originalMinCorner = cellMinCorner;
                Vector3I originalMaxCorner = cellMaxCorner;

                voxelMap.Storage.ClampVoxelCoord(ref cellMinCorner, VOXEL_CLAMP_BORDER_DISTANCE);
                voxelMap.Storage.ClampVoxelCoord(ref cellMaxCorner, VOXEL_CLAMP_BORDER_DISTANCE);

                ClampingInfo minCornerClamping = CheckForClamping(originalMinCorner, cellMinCorner);
                ClampingInfo maxCornerClamping = CheckForClamping(originalMaxCorner, cellMaxCorner);

                m_cache.Resize(cellMinCorner, cellMaxCorner);
                voxelMap.Storage.ReadRange(m_cache, MyStorageDataTypeFlags.ContentAndMaterial, 0, ref cellMinCorner, ref cellMaxCorner);

                ulong filledSum = 0;

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

                    if (original == MyVoxelConstants.VOXEL_CONTENT_FULL) // if there is nothing to add
                        continue;

                    //if there was some claping, fill the clamp region with material 
                    if ((it.Current.X == cellMinCorner.X && minCornerClamping.X) || (it.Current.X == cellMaxCorner.X && maxCornerClamping.X) ||
                        (it.Current.Y == cellMinCorner.Y && minCornerClamping.Y) || (it.Current.Y == cellMaxCorner.Y && maxCornerClamping.Y) ||
                        (it.Current.Z == cellMinCorner.Z && minCornerClamping.Z) || (it.Current.Z == cellMaxCorner.Z && maxCornerClamping.Z))
                    {
                        m_cache.Material(ref relPos, materialIdx);
                        continue;
                    }

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


                    if (volume <= 0f) // there is nothing to fill
                        continue;

                    m_cache.Material(ref relPos, materialIdx); // set material

                    var toFill = (int)(volume * MyVoxelConstants.VOXEL_CONTENT_FULL);
                    long newVal = MathHelper.Clamp(original + toFill, 0, Math.Max(original, toFill));

                    m_cache.Content(ref relPos, (byte)newVal);
                    filledSum += (ulong)(newVal - original);
                }
                if (filledSum > 0)
                {
                    RemoveSmallVoxelsUsingChachedVoxels();
                    voxelMap.Storage.WriteRange(m_cache, MyStorageDataTypeFlags.ContentAndMaterial, ref cellMinCorner, ref cellMaxCorner);
                }

                retValue += filledSum;
            }

            return retValue;
        }
示例#33
0
 public override void SendCutOutRequest(MyVoxelBase voxel)
 {
     voxel.RequestVoxelOperationCapsule(A, B, Radius, Transformation, 0, OperationType.Cut);
 }
        public static ulong CutOutShape(MyVoxelBase voxelMap, MyShape shape)
        {
            Vector3I minCorner, maxCorner, numCells;
            GetVoxelShapeDimensions(voxelMap, shape, out minCorner, out maxCorner, out numCells);
            ulong changedVolumeAmount = 0;

            for (var itCells = new Vector3I.RangeIterator(ref Vector3I.Zero, ref numCells); itCells.IsValid(); itCells.MoveNext())
            {
                Vector3I cellMinCorner, cellMaxCorner;
                GetCellCorners(ref minCorner, ref maxCorner, ref itCells, out cellMinCorner, out cellMaxCorner);

                var cacheMin = cellMinCorner - 1;
                var cacheMax = cellMaxCorner + 1;
                voxelMap.Storage.ClampVoxelCoord(ref cacheMin);
                voxelMap.Storage.ClampVoxelCoord(ref cacheMax);

                ulong removedSum = 0;
                m_cache.Resize(cacheMin, cacheMax);
                voxelMap.Storage.ReadRange(m_cache, MyStorageDataTypeFlags.Content, 0, ref cacheMin, ref cacheMax);

                for (var it = new Vector3I.RangeIterator(ref cellMinCorner, ref cellMaxCorner); 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 toRemove = (int)(MyVoxelConstants.VOXEL_CONTENT_FULL - (volume * MyVoxelConstants.VOXEL_CONTENT_FULL));
                    var newVal = Math.Min(toRemove, original);
                    ulong removed = (ulong)Math.Abs(original - newVal);

                    m_cache.Content(ref relPos, (byte)newVal);
                    removedSum += removed;
                }

                if (removedSum > 0)
                {
                    RemoveSmallVoxelsUsingChachedVoxels(); // must stay because of the around when filling voxels
                    voxelMap.Storage.WriteRange(m_cache, MyStorageDataTypeFlags.Content, ref cacheMin, ref cacheMax);
                }

                changedVolumeAmount += removedSum;
            }

            return changedVolumeAmount;
        }
示例#35
0
 public override void SendFillRequest(MyVoxelBase voxel, byte newMaterialIndex)
 {
     voxel.RequestVoxelOperationCapsule(A, B, Radius, Transformation, newMaterialIndex, OperationType.Fill);
 }
        private void CreatePlanetMenu()
        {
            m_currentVoxel = null;
            MyGuiControlList list = new MyGuiControlList(size: new Vector2(SCREEN_SIZE.X,1.0f));

            Vector2 controlPadding = new Vector2(0.02f, 0.02f); // X: Left & Right, Y: Bottom & Top

            float textScale = 0.8f;
            float usableWidth = SCREEN_SIZE.X - HIDDEN_PART_RIGHT - controlPadding.X * 2;

            m_currentPosition = Vector2.Zero;/* -m_size.Value / 2.0f;
            m_currentPosition += controlPadding;*/
            m_scale = textScale;

            var label = AddLabel(MyTexts.GetString(MySpaceTexts.ScreenDebugSpawnMenu_SelectAsteroidType), Vector4.One, m_scale);
            Controls.Remove(label);
            list.Controls.Add(label);

            var combo = AddCombo();
            combo.AddItem(1, MySpaceTexts.ScreenDebugSpawnMenu_PredefinedAsteroids);
            combo.AddItem(2, MySpaceTexts.ScreenDebugSpawnMenu_ProceduralAsteroids);
            combo.AddItem(3, MySpaceTexts.ScreenDebugSpawnMenu_Planets);

            combo.SelectItemByKey(m_asteroid_showPlanet ? 3 : m_asteroid_showPredefinedOrProcedural ? 1 : 2);
            combo.ItemSelected += () => { m_asteroid_showPredefinedOrProcedural = combo.GetSelectedKey() == 1; m_asteroid_showPlanet = combo.GetSelectedKey() == 3; RecreateControls(false); };

            Controls.Remove(combo);
            list.Controls.Add(combo);

            CreatePlanetControls(list, usableWidth);

            AddSeparator(list);
  
            var button = CreateDebugButton(usableWidth, MySpaceTexts.ScreenDebugSpawnMenu_SpawnAsteroid, OnSpawnProceduralAsteroid); 
            Controls.Remove(button);
            list.Controls.Add(button);

            Controls.Add(list);
        }
示例#37
0
        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();
        }
        private void DebugDrawVertexNames()
        {
            //VRageRender.MyRenderProxy.DebugDrawText2D(new Vector2(10, 0), "Voxel names searching", Color.Yellow, 0.5f);
            LineD line = new LineD(IntersectionStart, IntersectionStart + IntersectionDirection * 500);
            MyIntersectionResultLineTriangleEx?intersection =
                MyEntities.GetIntersectionWithLine(ref line, MySession.Static.LocalCharacter, null, false, true, true,
                                                   VRage.Game.Components.IntersectionFlags.ALL_TRIANGLES, 0, false);


            if (intersection.HasValue)
            {
                if (intersection.Value.Entity is MyVoxelBase)
                {
                    MyVoxelBase voxels = (MyVoxelBase)intersection.Value.Entity;
                    Vector3D    point  = intersection.Value.IntersectionPointInWorldSpace;
                    if (intersection.Value.Entity is MyPlanet)
                    {
                        MyRenderProxy.DebugDrawText2D(new Vector2(20, 20), "Type: planet/moon", Color.Yellow,
                                                      DEBUG_SCALE);
                        MyRenderProxy.DebugDrawText2D(new Vector2(20, 30),
                                                      "Terrain: " + voxels.GetMaterialAt(ref point), Color.Yellow, DEBUG_SCALE);
                    }
                    else
                    {
                        MyRenderProxy.DebugDrawText2D(new Vector2(20, 20), "Type: asteroid", Color.Yellow,
                                                      DEBUG_SCALE);
                        MyRenderProxy.DebugDrawText2D(new Vector2(20, 30),
                                                      "Terrain: " + voxels.GetMaterialAt(ref point), Color.Yellow, DEBUG_SCALE);
                    }
                    MyRenderProxy.DebugDrawText2D(new Vector2(20, 40),
                                                  "Object size: " + voxels.SizeInMetres, Color.Yellow, DEBUG_SCALE);

                    //location

                    /*
                     * VRageRender.MyRenderProxy.DebugDrawText2D(new Vector2(20, 50), "Location:", Color.Yellow, 0.5f);
                     * VRageRender.MyRenderProxy.DebugDrawText2D(new Vector2(30, 60), "x " + Math.Round(point.X, 3).ToString(), Color.Yellow, 0.5f);
                     * VRageRender.MyRenderProxy.DebugDrawText2D(new Vector2(30, 70), "y " + Math.Round(point.Y, 3).ToString(), Color.Yellow, 0.5f);
                     * VRageRender.MyRenderProxy.DebugDrawText2D(new Vector2(30, 80), "z " + Math.Round(point.Z, 3).ToString(), Color.Yellow, 0.5f);*/
                }
                else if (intersection.Value.Entity is MyCubeGrid)
                {
                    MyCubeGrid grid = (MyCubeGrid)intersection.Value.Entity;
                    MyRenderProxy.DebugDrawText2D(new Vector2(20, 20), "Detected grid object", Color.Yellow, DEBUG_SCALE);
                    MyRenderProxy.DebugDrawText2D(new Vector2(20, 30), String.Format("Grid name: {0}", grid.DisplayName), Color.Yellow,
                                                  DEBUG_SCALE);
                    int row = 4;

                    MyIntersectionResultLineTriangleEx?t;
                    MySlimBlock block;
                    if (grid.GetIntersectionWithLine(ref line, out t, out block) && t.HasValue && block != null)
                    {
                        if (block.FatBlock != null)
                        {
                            DebugDrawModelTextures(block.FatBlock, ref row);
                        }
                        else
                        {
                            DebugDrawBareBlockInfo(block, ref row);
                        }
                    }
                }
                else
                {
                    MyRenderProxy.DebugDrawText2D(new Vector2(20, 20), "Unknown object detected", Color.Yellow,
                                                  DEBUG_SCALE);
                }
            }
            else
            {
                MyRenderProxy.DebugDrawText2D(new Vector2(20, 20), "Nothing detected nearby", Color.Yellow, DEBUG_SCALE);
            }
        }
示例#39
0
        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();
        }