public static void Draw()
        {
            if (m_Enabled && IsAnyEditorActive())
            {
                VoxelHandShape.Draw();
                if (MyVoxelConstants.VOXEL_HAND_DRAW_CONE && !MyFakes.MWBUILDER)
                {
                    VoxelHandShape.DrawCone(m_conePosition);
                }

                if (MyEditor.DisplayVoxelBounding)
                {
                    foreach (MyEntity voxelMapEntity in MyVoxelMaps.GetVoxelMaps())
                    {
                        MyVoxelMap voxelMap = voxelMapEntity as MyVoxelMap;
                        voxelMap.DrawBounding();
                    }
                }

                if (MyFakes.MWBUILDER)
                {
                    Matrix  wm  = VoxelHandShape.WorldMatrix;
                    Vector4 clr = Vector4.One;
                    MySimpleObjectDraw.DrawTransparentSphere(ref wm, 10, ref clr, false, 8);

                    MyDebugDraw.TextBatch.AddText(wm.Translation, new System.Text.StringBuilder(MyUtils.GetFormatedVector3(wm.Translation, 0)), Color.White, 0.8f);
                }
            }
        }
Esempio n. 2
0
        /// <summary>
        /// DrawSelectedBounding
        /// </summary>
        private void DrawSelectedBounding()
        {
            if (MyConfig.EditorDisplayUnselectedBounding)
            {
                Vector4 color = new Vector4(0.6f, 0.6f, 0.6f, 0.2f);
                foreach (MyEntity entity in MyEntities.GetEntities())
                {
                    entity.DebugDrawBox(color, false);
                }

                foreach (MyVoxelMap voxelMap in MyVoxelMaps.GetVoxelMaps())
                {
                    MyDebugDraw.DrawHiresBoxWireframe(Matrix.CreateScale(voxelMap.GetSize()) * voxelMap.WorldMatrix, new Vector3(0, 0.4f, 0), 0.3f);
                }
            }

            if (IsEditingPrefabContainer())
            {
                m_activePrefabContainer.DebugDrawBox(new Vector4(1, 1, 0, 0.4f));
            }

            foreach (MyEntity entity in MyEditorGizmo.SelectedEntities)
            {
                if (entity is MyPrefabContainer)
                {
                    MyPrefabContainer container = (MyPrefabContainer)entity;
                    container.DebugDrawBox(new Vector4(0, 1, 0, 0.4f));
                }
            }
        }
 /// <summary>
 /// Removes all entities - TODO - this will have to be unified in MyEntities.cs
 /// </summary>
 void RemoveAllEntities()
 {
     //MyEditor.Static.DeleteAllFromCollidingList();
     MyEditor.Static.CollidingElements.Clear();
     MyEntities.CollisionsElements.Clear();
     MyEditorGizmo.ClearSelection();
     MyEntities.CloseAll(false);
     MyVoxelMaps.RemoveAll();
 }
Esempio n. 4
0
        /// <summary>
        /// Starts the explosion.
        /// </summary>
        /// <param name="damage"></param>
        /// <param name="type"></param>
        /// <param name="explosionSphere"></param>
        /// <param name="lifespanInMiliseconds"></param>
        /// <param name="explosionForceDirection"></param>
        /// <param name="groupMask"></param>
        /// <param name="createExplosionDebris"></param>
        /// <param name="cascadeLevel"></param>
        /// <param name="hitEntity"></param>
        /// <param name="particleScale"></param>
        /// <param name="ownerEntity"></param>
        /// <param name="affectVoxels"></param>
        /// <param name="applyForceAndDamage"></param>
        /// <param name="createDecals"></param>
        /// <param name="direction">If applicable, gives the direction of the explosion, e.g. when it was caused by a missile (with its moving direction).</param>
        public void Start(ref MyExplosionInfo explosionInfo)
        {
            //MyCommonDebugUtils.AssertDebug(explosionInfo.ExplosionSphere.Radius <= MyExplosionsConstants.EXPLOSION_RADIUS_MAX);
            MyCommonDebugUtils.AssertDebug(explosionInfo.ExplosionSphere.Radius > 0);

            MyRender.GetRenderProfiler().StartProfilingBlock("MyExplosion.Start");

            m_explosionSphere       = explosionInfo.ExplosionSphere;
            m_elapsedMiliseconds    = 0;
            m_lifespanInMiliseconds = explosionInfo.LifespanMiliseconds;

            if (explosionInfo.PlaySound)
            {
                MyRender.GetRenderProfiler().StartProfilingBlock("Sound");
                //  Play explosion sound
                if (m_explosionCue != null && m_explosionCue.Value.IsPlaying)
                {
                    m_explosionCue.Value.Stop(SharpDX.XACT3.StopFlags.Immediate);
                }
                m_explosionCue = MyAudio.AddCue3D(GetCueEnumByExplosionType(explosionInfo.ExplosionType), m_explosionSphere.Center, Vector3.Zero, Vector3.Zero, Vector3.Zero);
                MyRender.GetRenderProfiler().EndProfilingBlock();
            }

            MyRender.GetRenderProfiler().StartProfilingBlock("Light");
            //  Light of explosion

            /*
             * m_light = MyLights.AddLight();
             * if (m_light != null)
             * {
             *  m_light.Start(MyLight.LightTypeEnum.PointLight, m_explosionSphere.Center, MyExplosionsConstants.EXPLOSION_LIGHT_COLOR, 1, Math.Min(m_explosionSphere.Radius * 8.0f, MyLightsConstants.MAX_POINTLIGHT_RADIUS));
             *  m_light.Intensity = 2.0f;
             * } */
            MyRender.GetRenderProfiler().EndProfilingBlock();

            // close explosion check
            bool close = IsExplosionClose(explosionInfo.ExplosionSphere);

            MyParticleEffectsIDEnum newParticlesType;

            switch (explosionInfo.ExplosionType)
            {
            case MyExplosionTypeEnum.SMALL_SHIP_EXPLOSION:
                //  Create metal debris objects thrown from the explosion
                //  This must be called before ApplyExplosionForceAndDamage (because there we apply impulses to the debris)
                //  Throw a lot of debrises, more than only if some metalic object is hit (because this is destruction of a ship)
                //MyPhysObjectExplosionDebrises.CreateExplosionDebris(m_explosionSphere.Center, 1);
                newParticlesType = MyParticleEffectsIDEnum.Explosion_Smallship;
                break;

            case MyExplosionTypeEnum.MISSILE_EXPLOSION:
                newParticlesType =
                    // ? MyParticleEffectsIDEnum.Explosion_Missile_Close
                    MyParticleEffectsIDEnum.Explosion_Missile;
                break;

            case MyExplosionTypeEnum.BOMB_EXPLOSION:
            case MyExplosionTypeEnum.GRAVITY_EXPLOSION:
                newParticlesType = MyParticleEffectsIDEnum.Explosion_Bomb;
                break;

            case MyExplosionTypeEnum.AMMO_EXPLOSION:
                newParticlesType = MyParticleEffectsIDEnum.Explosion_Ammo;
                break;

            case MyExplosionTypeEnum.BLASTER_EXPLOSION:
                newParticlesType = MyParticleEffectsIDEnum.Explosion_Blaster;
                break;

            case MyExplosionTypeEnum.BIOCHEM_EXPLOSION:
                newParticlesType = MyParticleEffectsIDEnum.Explosion_BioChem;
                break;

            case MyExplosionTypeEnum.EMP_EXPLOSION:
            case MyExplosionTypeEnum.FLASH_EXPLOSION:
                newParticlesType = MyParticleEffectsIDEnum.Explosion_EMP;
                break;

            case MyExplosionTypeEnum.METEOR_EXPLOSION:
                newParticlesType = MyParticleEffectsIDEnum.Explosion_Meteor;
                break;

            case MyExplosionTypeEnum.NUCLEAR_EXPLOSION:
                newParticlesType = MyParticleEffectsIDEnum.Explosion_Nuclear;
                break;

            case MyExplosionTypeEnum.PLASMA_EXPLOSION:
                newParticlesType = MyParticleEffectsIDEnum.Explosion_Plasma;
                break;

            case MyExplosionTypeEnum.SMALL_EXPLOSION:
                newParticlesType = MyParticleEffectsIDEnum.Explosion_SmallPrefab;
                break;

            case MyExplosionTypeEnum.LARGE_SHIP_EXPLOSION:
                newParticlesType = MyParticleEffectsIDEnum.Explosion_Huge;
                break;

            case MyExplosionTypeEnum.LARGE_PREFAB_EXPLOSION:
                newParticlesType = MyParticleEffectsIDEnum.Explosion_Large;
                break;

            case MyExplosionTypeEnum.MEDIUM_PREFAB_EXPLOSION:
                newParticlesType = MyParticleEffectsIDEnum.Explosion_Medium;
                break;

            case MyExplosionTypeEnum.ASTEROID_EXPLOSION:
                newParticlesType = MyParticleEffectsIDEnum.Explosion_Asteroid;
                break;

            default:
                throw new System.NotImplementedException();
                break;
            }


            if (explosionInfo.Damage > 0)
            {
                MyRender.GetRenderProfiler().StartProfilingBlock("Voxel or collision");

                //  If explosion sphere intersects a voxel map, we need to cut out a sphere, spawn debrises, etc
                MyVoxelMap voxelMap = explosionInfo.AffectVoxels && explosionInfo.EmpDamage == 0 ? MyVoxelMaps.GetOverlappingWithSphere(ref m_explosionSphere) : null;
                if (voxelMap != null)
                {
                    //  Dirty explosion with a lot of dust

                    MyMwcVoxelMaterialsEnum?voxelMaterial = null;
                    float voxelContentRemovedInPercent    = 0;

                    bool createDebris = true;            // We want to create debris

                    if (explosionInfo.HitEntity != null) // but not when we hit prefab
                    {
                        createDebris &= explosionInfo.HitEntity is MyVoxelMap;
                    }


                    //cut off
                    BoundingSphere voxelExpSphere = new BoundingSphere(explosionInfo.VoxelExplosionCenter, m_explosionSphere.Radius * explosionInfo.VoxelCutoutScale);
                    if (MyVoxelGenerator.CutOutSphereFast(voxelMap, voxelExpSphere, out voxelContentRemovedInPercent, out voxelMaterial, (explosionInfo.OwnerEntity is MySmallShip && explosionInfo.OwnerEntity == Managers.Session.MySession.PlayerShip), MyFakes.VOXELS_REMOVE_RATIO))
                    {
                        if (explosionInfo.HitEntity is MyVoxelMap)
                        {
                            HUD.MyHud.ShowIndestructableAsteroidNotification();
                        }
                        createDebris = false; // and no debris when voxel is indestructible
                    }

                    //  Only if at least something was removed from voxel map
                    //  If voxelContentRemovedInPercent is more than zero than also voxelMaterial shouldn't be null, but I rather check both of them.
                    if ((voxelContentRemovedInPercent > 0) && (voxelMaterial != null))
                    {
                        //remove decals
                        MyDecals.HideTrianglesAfterExplosion(voxelMap, ref voxelExpSphere);

                        MyRender.GetRenderProfiler().StartProfilingBlock("CreateDebris");

                        if (explosionInfo.CreateDebris && (createDebris || explosionInfo.ForceDebris) && MyRenderConstants.RenderQualityProfile.ExplosionDebrisCountMultiplier > 0)
                        {
                            //  Create debris rocks thrown from the explosion
                            //  This must be called before ApplyExplosionForceAndDamage (because there we apply impulses to the debris)
                            MyExplosionDebrisVoxel.CreateExplosionDebris(ref voxelExpSphere, voxelContentRemovedInPercent, voxelMaterial.Value, explosionInfo.GroupMask, voxelMap);
                        }

                        MyRender.GetRenderProfiler().EndProfilingBlock();

                        MyRender.GetRenderProfiler().StartProfilingBlock("CreateParticleEffect");

                        MyParticleEffect explosionEffect = MyParticlesManager.CreateParticleEffect((int)MyParticleEffectsIDEnum.MaterialExplosion_Destructible);
                        explosionEffect.WorldMatrix          = Matrix.CreateTranslation(voxelExpSphere.Center);
                        explosionEffect.UserRadiusMultiplier = voxelExpSphere.Radius;

                        MyRender.GetRenderProfiler().EndProfilingBlock();
                    }
                }
                MyRender.GetRenderProfiler().EndProfilingBlock();
            }

            if (explosionInfo.Damage > 0)
            {
                //  Create dirt decals in player's cockpit glass
                MyRender.GetRenderProfiler().StartProfilingBlock("Cockpit Decals");
                CreateDirtDecalOnCockpitGlass(ref m_explosionSphere);
                MyRender.GetRenderProfiler().EndProfilingBlock();
            }

            if (DEBUG_EXPLOSIONS)
            {
                MyRender.GetRenderProfiler().EndProfilingBlock();
                return;
            }

            if (explosionInfo.Damage > 0)
            {
                BoundingSphere influenceExplosionSphere = m_explosionSphere;
                influenceExplosionSphere.Radius *= MyExplosionsConstants.EXPLOSION_RADIUS_MULTPLIER_FOR_IMPULSE;
                for (int i = 0; i < explosionInfo.CascadeLevel; i++)
                {
                    influenceExplosionSphere.Radius *= MyExplosionsConstants.EXPLOSION_CASCADE_FALLOFF;
                }

                //  Throws surrounding objects away from centre of the explosion.
                if (explosionInfo.ApplyForceAndDamage)
                {
                    if (explosionInfo.ExplosionType == MyExplosionTypeEnum.LARGE_PREFAB_EXPLOSION ||
                        explosionInfo.ExplosionType == MyExplosionTypeEnum.LARGE_SHIP_EXPLOSION ||
                        explosionInfo.ExplosionType == MyExplosionTypeEnum.MEDIUM_PREFAB_EXPLOSION)
                    {
                        DisableContainedDummyParticles(ref explosionInfo);
                    }

                    explosionInfo.StrengthImpulse        = MyExplosionsConstants.EXPLOSION_STRENGTH_IMPULSE * m_explosionSphere.Radius / 20;
                    explosionInfo.StrengthAngularImpulse = MyExplosionsConstants.EXPLOSION_STRENGTH_ANGULAR_IMPULSE;
                    explosionInfo.HitEntity = explosionInfo.HitEntity != null?explosionInfo.HitEntity.GetBaseEntity() : null;

                    MyRender.GetRenderProfiler().StartProfilingBlock("ApplyExplosionForceAndDamage");
                    MyEntities.ApplyExplosionForceAndDamage(ref explosionInfo);
                    MyRender.GetRenderProfiler().EndProfilingBlock();
                }

                //  Look for objects in explosion radius
                BoundingBox boundingBox;
                BoundingBox.CreateFromSphere(ref influenceExplosionSphere, out boundingBox);

                //if (explosionInfo.CreateDecals && explosionInfo.Direction.HasValue && explosionInfo.EmpDamage == 0)
                //{
                //    CreateDecals(explosionInfo.Direction.Value);
                //}
            }

            if (explosionInfo.CreateParticleEffect)
            {
                MyRender.GetRenderProfiler().StartProfilingBlock("Particles");

                if (explosionInfo.CustomEffect != null)
                {
                    if (explosionInfo.CustomEffect.ParticleID == 0)
                    {
                        explosionInfo.CustomEffect.ParticleID = (int)newParticlesType;
                    }
                    //Reload effect
                    explosionInfo.CustomEffect.Enabled = false;
                    explosionInfo.CustomEffect.Enabled = true;
                }
                else
                {
                    //  Explosion particles
                    GenerateExplosionParticles(newParticlesType, m_explosionSphere, explosionInfo.ParticleScale);
                }

                MyRender.GetRenderProfiler().EndProfilingBlock();
            }

            MyRender.GetRenderProfiler().EndProfilingBlock();

            /*
             *  // When MyAmmoBase entity is closed to explosion it will explode
             *  if (entity is MyAmmoBase)
             *  {
             *      (entity as MyAmmoBase).ExplodeCascade(cascadeLevel + 1);
             *  }
             */

            //  Smut decals - must be called after the explosion, after voxels are cutted out

            /*if ((intersection.PhysObject is MyVoxelMap) == false)
             * {
             *  if (intersection.PhysObject is MyCockpitGlass)
             *  {
             *      //  Change phys object so rest of the code will think we hit the parent
             *      //  Same fix is in projectile too - because cockpit glass is only helper object, we don't use it for real rendering and stuff
             *      //  And if not changed, it can make problem in "phys object decals"
             *      intersection.PhysObject = intersection.PhysObject.Parent;
             *  }
             *
             *  //  Create explosion smut decal on model we hit by this missile
             *  MyDecals.Add(
             *      MyDecalTexturesEnum.ExplosionSmut,
             *      MyMwcUtils.GetRandomFloat(m_explosionSphere.Radius * 0.7f, m_explosionSphere.Radius * 1.3f),
             *      MyMwcUtils.GetRandomRadian(),
             *      GetSmutDecalRandomColor(),
             *      true,
             *      ref intersection);
             * }
             * else
             * {
             *  //  Creating explosion smut decal on voxel is more complicated than on voxel. We will project few lines
             *  //  from explosion epicentrum to the surounding world (random directions) and place decal where intersection detected.
             *  //if (knownMissileDirection != null)
             *  //{
             *  //    MyLine linePrologned = new MyLine(knownIntersection.Value.IntersectionPointInObjectSpace,
             *  //        knownIntersection.Value.IntersectionPointInObjectSpace + knownMissileDirection.Value * MyExplosionsConstants.EXPLOSION_RANDOM_RADIUS_MAX * 2,
             *  //        true);
             *  //    MyLineTriangleIntersectionResult intersectionForSmut = knownIntersection.Value.VoxelMap.GetIntersectionWithLine(ref linePrologned);
             *  //    if (intersectionForSmut.Found == true)
             *  //    {
             *  //        MyDecals.Add(
             *  //            MyDecalTexturesEnum.ExplosionSmut,
             *  //            MyMwcUtils.GetRandomFloat(m_explosionSphere.Radius * 0.5f, m_explosionSphere.Radius * 1.0f),
             *  //            MyMwcUtils.GetRandomRadian(),
             *  //            GetSmutDecalRandomColor(),
             *  //            false,
             *  //            ref intersectionForSmut);
             *  //    }
             *  //}
             * }*/

            //  Generate dust particles that will stay in place of the explosion
            //doesnt look good in final
            //GenerateStatisDustParticles(m_explosionSphere);
        }
        //public static event OnVoxelShapeSizeChanged OnVoxelShapeSize;
        //public static event OnVoxelShapeDistanceChanged OnVoxelShapeDistance;

        public static void HandleInput(MyGuiInput input)
        {
            // exit voxel hand using this key
            if (input.IsEditorControlNewPressed(MyEditorControlEnums.VOXEL_HAND))
            {
                SwitchEnabled();
            }

            if (m_Enabled == false || !IsAnyEditorActive())
            {
                return;
            }

            m_applyToVoxelMap = null;

            //here possible change
            if ((input.IsEditorControlNewPressed(MyEditorControlEnums.PRIMARY_ACTION_KEY) ||
                 input.IsAnyShiftKeyPressed() && input.IsEditorControlPressed(MyEditorControlEnums.PRIMARY_ACTION_KEY)) &&
                (m_timeFromLastShaping >= MyVoxelConstants.VOXEL_HAND_SHAPING_INTERVAL || MyFakes.RAPID_VOXEL_HAND_SHAPING_ENABLED || MyFakes.MWBUILDER))
            {
                m_timeFromLastShaping = 0;

                if (DetachedVoxelHand != null && !input.IsKeyPress(Keys.Space))
                {
                    return;
                }

                MyVoxelMap voxelMap = null;

                if (VoxelHandShape is MyVoxelHandSphere)
                {
                    MyVoxelHandSphere sphere = (MyVoxelHandSphere)VoxelHandShape;
                    BoundingSphere    vol    = sphere.WorldVolume;
                    voxelMap = MyVoxelMaps.GetIntersectionWithSphere(ref vol, SelectedVoxelMap);
                }
                else if (VoxelHandShape is MyVoxelHandBox)
                {
                    MyVoxelHandBox box = (MyVoxelHandBox)VoxelHandShape;
                    BoundingBox    localBoundingBox = box.GetLocalBoundingBox();
                    Vector3        boxWorldPosition = box.GetPosition();
                    voxelMap = MyVoxelMaps.GetIntersectionWithBox(ref localBoundingBox, ref boxWorldPosition, SelectedVoxelMap);
                }
                else if (VoxelHandShape is MyVoxelHandCuboid)
                {
                    MyVoxelHandCuboid cuboid           = (MyVoxelHandCuboid)VoxelHandShape;
                    BoundingBox       localBoundingBox = cuboid.GetLocalBoundingBox();
                    Vector3           boxWorldPosition = cuboid.GetPosition();
                    voxelMap = MyVoxelMaps.GetIntersectionWithBox(ref localBoundingBox, ref boxWorldPosition, SelectedVoxelMap);
                }
                else if (VoxelHandShape is MyVoxelHandCylinder)
                {
                    MyVoxelHandCylinder cylinder         = (MyVoxelHandCylinder)VoxelHandShape;
                    BoundingBox         localBoundingBox = cylinder.GetLocalBoundingBox();
                    Vector3             boxWorldPosition = cylinder.GetPosition();
                    voxelMap = MyVoxelMaps.GetIntersectionWithBox(ref localBoundingBox, ref boxWorldPosition, SelectedVoxelMap);
                }
                else
                {
                    System.Diagnostics.Debug.Assert(false);
                }

                if (voxelMap != null)
                {
                    m_applyToVoxelMap = voxelMap;
                }
            }

            ////////////////////////////////////////////////////////////////////////////////////////////////////////////
            // Change size of asteroid tool from camera
            ////////////////////////////////////////////////////////////////////////////////////////////////////////////

            /*
             * if (input.IsAnyShiftKeyPressed())
             * {
             * if (input.PreviousMouseScrollWheelValue() > input.MouseScrollWheelValue())
             * {
             * SetVoxelSize(MyEditorVoxelHand.VoxelHandShape.GetShapeSize() - MyVoxelConstants.VOXEL_HAND_SIZE_STEP);
             * }
             * else if (input.PreviousMouseScrollWheelValue() < input.MouseScrollWheelValue())
             * {
             * SetVoxelSize(MyEditorVoxelHand.VoxelHandShape.GetShapeSize() + MyVoxelConstants.VOXEL_HAND_SIZE_STEP);
             * }
             *
             * }
             *
             * ////////////////////////////////////////////////////////////////////////////////////////////////////////////
             * // Change distance of asteroid tool from camera
             * ////////////////////////////////////////////////////////////////////////////////////////////////////////////
             *
             * if (input.IsAnyControlPress())
             * {
             * if (input.PreviousMouseScrollWheelValue() > input.MouseScrollWheelValue())
             * {
             * SetShapeDistance(GetShapeDistance() - MyVoxelConstants.VOXEL_HAND_DISTANCE_STEP);
             *
             * }
             * else if (input.PreviousMouseScrollWheelValue() < input.MouseScrollWheelValue())
             * {
             * SetShapeDistance(GetShapeDistance() + MyVoxelConstants.VOXEL_HAND_DISTANCE_STEP);
             * }
             * } */
        }
Esempio n. 6
0
        protected override void Drill()
        {
            //  Sphere which is used to make tunnel to voxel and sphere for testing collision with voxel
            m_fakeCollisionSphere = new BoundingSphere(m_fakeSpherePositionTransformed, m_radius);
            //  Check for collision with drill and world
            //MyEntity collisionResult = MyEntities.GetIntersectionWithSphere(ref m_fakeCollisionSphere, this, Parent, false, true);
            // bSphere collision doesn't work - the sphere is tested against LOD0 model, but it is hidden inside the COL model and the bSphere is too small to reach it - so I use line instead

            MyEntity collisionResult = null;
            MyLine   line;

            if (MySession.Is25DSector)
            {
                line = new MyLine(m_positionMuzzleInWorldSpace - 10 * WorldMatrix.Forward, m_positionMuzzleInWorldSpace + 20 * WorldMatrix.Forward, true);
            }
            else
            {
                line = new MyLine(m_positionMuzzleInWorldSpace - 10 * WorldMatrix.Forward, m_positionMuzzleInWorldSpace + 5 * WorldMatrix.Forward, true);
            }

            MyIntersectionResultLineTriangleEx?intersection = MyEntities.GetIntersectionWithLine(ref line, Parent, this, true, true);

            if (intersection != null && intersection.Value.Entity.Physics != null)
            {
                collisionResult = intersection.Value.Entity;
            }

            if (!(collisionResult is MyVoxelMap))
            {
                m_lastTimeDrillNotCollidedWithVoxelMapInMiliseconds = MyMinerGame.TotalGamePlayTimeInMilliseconds;

                if (!MySession.Is25DSector)
                {
                    ((MySmallShip)Parent).IncreaseHeadShake(MyDrillDeviceConstants.SHAKE_DURING_ROTATION);
                }

                StopDustEffect();

                if (collisionResult != null)
                {
                    var effect = MyParticlesManager.CreateParticleEffect((int)MyParticleEffectsIDEnum.MaterialHit_Autocannon_Metal);
                    effect.WorldMatrix = Matrix.CreateTranslation(m_fakeCollisionSphere.Center);
                    collisionResult.DoDamage(0, m_damage * MyConstants.PHYSICS_STEP_SIZE_IN_SECONDS, 0, MyDamageType.Drill, MyAmmoType.Basic, Parent);
                }
            }
            //  Display particles when we are in contact with voxel
            else
            {
                if (m_dustEffect == null)
                {
                    m_dustEffect = MyParticlesManager.CreateParticleEffect((int)MyParticleEffectsIDEnum.Smoke_DrillDust);
                }
                m_dustEffect.WorldMatrix = Matrix.CreateTranslation(m_fakeSpherePositionTransformed);
                m_dustEffect.UserScale   = MySession.Is25DSector ? 3 : 1;
                ((MySmallShip)Parent).IncreaseHeadShake(MyDrillDeviceConstants.SHAKE_DURING_IN_VOXELS);
            }

            //  Play sound if there is collision with voxel
            if (collisionResult != null)
            {
                if (collisionResult is MyStaticAsteroid)
                {
                    if (!collisionResult.IsDestructible)
                    {
                        MinerWars.AppCode.Game.HUD.MyHud.ShowIndestructableAsteroidNotification();
                    }
                }
                StartDrillingCue(collisionResult is MyVoxelMap);
                StopMovingCue();
            }
            else
            {
                StartMovingCue();
                StopDrillingCue();
            }

            //  We found voxel so lets make tunel into it
            using (var voxelMapsFound = PoolList <MyVoxelMap> .Get())
            {
                bool drilled = false;
                bool drilledSomeDestructibleContent = false;
                MyVoxelMaps.GetListOfVoxelMapsWhoseBoundingSphereIntersectsSphere(ref m_fakeCollisionSphere, voxelMapsFound, null);

                int drillInterval        = MySession.Is25DSector ? 100 : (int)MyDrillDeviceConstants.DRILL_INTERVAL_IN_MILISECONDS;
                int timerToDrillInterval = MySession.Is25DSector ? 100 : (int)MyDrillDeviceConstants.TIME_TO_DRILL_VOXEL_IN_MILISECONDS;

                foreach (MyVoxelMap voxelMap in voxelMapsFound)
                {
                    if ((collisionResult is MyVoxelMap) && ((MyMinerGame.TotalGamePlayTimeInMilliseconds - m_lastTimeDrilled) > drillInterval) &&
                        (MyMinerGame.TotalGamePlayTimeInMilliseconds - m_lastTimeDrillNotCollidedWithVoxelMapInMiliseconds) > timerToDrillInterval)
                    {
                        drilled = true;
                        float          rangeStep          = 0;
                        float          radius             = GetRadiusNeededForTunel();
                        BoundingSphere bigSphereForTunnel = new BoundingSphere(m_fakeCollisionSphere.Center, radius);

                        while (rangeStep < m_range)
                        {
                            MyMwcVector3Int exactCenterOfDrilling = voxelMap.GetVoxelCoordinateFromMeters(bigSphereForTunnel.Center);

                            // we don't want to drill indestructible voxels or empty space
                            if (voxelMap.IsVoxelInVoxelMap(ref exactCenterOfDrilling) && voxelMap.GetVoxelMaterialIndestructibleContent(ref exactCenterOfDrilling) == MyVoxelConstants.VOXEL_CONTENT_FULL)
                            {
                                break;
                            }
                            else
                            {
                                drilledSomeDestructibleContent = true;
                            }

                            CutOutFromVoxel(voxelMap, ref bigSphereForTunnel);

                            bigSphereForTunnel.Center += 2 * WorldMatrix.Forward;

                            rangeStep += 1;
                        }
                    }
                }
                if (drilled)
                {
                    m_lastTimeDrilled = MyMinerGame.TotalGamePlayTimeInMilliseconds;
                    if (!drilledSomeDestructibleContent)
                    {
                        HUD.MyHud.ShowIndestructableAsteroidNotification();
                    }
                }
            }
        }
        protected override bool Interact(bool staticCollision)
        {
            if (staticCollision)
            {
                //MyCommonDebugUtils.AssertDebug(false, "Sphere-voxel static interaction called! And that's wrong.");
            }
            else
            {
                MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().StartProfilingBlock("SphereVoxelInteraction");

                MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().StartProfilingBlock("Transformations");

                if (RBElement1.GetElementType() != MyRBElementType.ET_SPHERE)
                {
                    SwapElements();
                }

                Matrix matrix0 = RBElement1.GetGlobalTransformation();
                Matrix matrix1 = RBElement2.GetGlobalTransformation();

                float sphereRadius = ((MyRBSphereElement)RBElement1).Radius;

                Vector3 body0Pos = matrix0.Translation; // sphere pos
                Vector3 body1Pos = matrix1.Translation;

                float dt      = MyPhysics.physicsSystem.GetRigidBodyModule().CurrentTimeStep;
                float epsylon = MyPhysics.physicsSystem.GetRigidBodyModule().CollisionEpsilon;

                Vector3 newBody0Pos = matrix0.Translation + GetRigidBody1().LinearVelocity *dt;

                float sphereTolR  = epsylon + sphereRadius;
                float sphereTolR2 = sphereTolR * sphereTolR;

                MySmallCollPointInfo[] collPtArray = MyContactInfoCache.SCPIStackAlloc();
                int numCollPts = 0;

                Vector3 collNormal = Vector3.Zero;

                //var colDetThroughVoxels = MyConstants.SPHERE_VOXELMAP_COLDET_THROUGH_VOXELS;
                var colDetThroughVoxels = !GetRigidBody1().ReadFlag(RigidBodyFlag.RBF_COLDET_THROUGH_VOXEL_TRIANGLES);

                MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().EndProfilingBlock();

                if (colDetThroughVoxels)
                {
                    MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().StartProfilingBlock("colDetThroughVoxels");

                    BoundingSphere newSphere;
                    newSphere.Center = newBody0Pos;
                    newSphere.Radius = sphereRadius;

                    MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().StartProfilingBlock("PoolList.Get");
                    using (var voxelMapsFounded = PoolList <MyVoxelMap> .Get())
                    {
                        MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().StartNextBlock("GetListOfVoxelMapsWhoseBoundingSphereIntersectsSphere");

                        MyVoxelMaps.GetListOfVoxelMapsWhoseBoundingSphereIntersectsSphere(ref newSphere, voxelMapsFounded, null);

                        MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().StartNextBlock("foreach (MyVoxelMap voxelMap in voxelMapsFounded)");
                        foreach (MyVoxelMap voxelMap in voxelMapsFounded)
                        {
                            if (voxelMap != null)
                            {
                                //  We will iterate only voxels contained in the bounding box of new sphere, so here we get min/max corned in voxel units
                                MyMwcVector3Int minCorner = voxelMap.GetVoxelCoordinateFromMeters(new Vector3(
                                                                                                      newSphere.Center.X - newSphere.Radius,
                                                                                                      newSphere.Center.Y - newSphere.Radius,
                                                                                                      newSphere.Center.Z - newSphere.Radius));
                                MyMwcVector3Int maxCorner = voxelMap.GetVoxelCoordinateFromMeters(new Vector3(
                                                                                                      newSphere.Center.X + newSphere.Radius,
                                                                                                      newSphere.Center.Y + newSphere.Radius,
                                                                                                      newSphere.Center.Z + newSphere.Radius));
                                voxelMap.FixVoxelCoord(ref minCorner);
                                voxelMap.FixVoxelCoord(ref maxCorner);

                                MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().StartProfilingBlock("for loop");

                                MyMwcVector3Int tempVoxelCoord;
                                for (tempVoxelCoord.X = minCorner.X; tempVoxelCoord.X <= maxCorner.X; tempVoxelCoord.X++)
                                {
                                    for (tempVoxelCoord.Y = minCorner.Y; tempVoxelCoord.Y <= maxCorner.Y; tempVoxelCoord.Y++)
                                    {
                                        for (tempVoxelCoord.Z = minCorner.Z; tempVoxelCoord.Z <= maxCorner.Z; tempVoxelCoord.Z++)
                                        {
                                            byte voxelContent = voxelMap.GetVoxelContent(ref tempVoxelCoord);

                                            //  Ignore voxels bellow the ISO value (empty, partialy empty...)
                                            if (voxelContent < MyVoxelConstants.VOXEL_ISO_LEVEL)
                                            {
                                                continue;
                                            }

                                            Vector3 voxelPosition = voxelMap.GetVoxelCenterPositionAbsolute(ref tempVoxelCoord);

                                            //float voxelSize = MyVoxelMaps.GetVoxelContentAsFloat(voxelContent) * MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF;
                                            float voxelSize = MyVoxelMaps.GetVoxelContentAsFloat(voxelContent) * MyVoxelConstants.VOXEL_RADIUS;

                                            //  If distance to voxel border is less than sphere radius, we have a collision
                                            //  So now we calculate normal vector and penetration depth but on OLD sphere
                                            float newDistanceToVoxel = Vector3.Distance(voxelPosition, newSphere.Center) - voxelSize;
                                            if (newDistanceToVoxel < (epsylon + newSphere.Radius))
                                            {
                                                Vector3 collisionN = MyMwcUtils.Normalize(voxelPosition - body0Pos);

                                                if (numCollPts < MyPhysicsConfig.MaxContactPoints)
                                                {
                                                    //  Calculate penetration depth, but from old sphere (not new)
                                                    float oldDistanceToVoxel  = Vector3.Distance(voxelPosition, newSphere.Center) - voxelSize;
                                                    float oldPenetrationDepth = oldDistanceToVoxel - sphereRadius;

                                                    // Vector3 pt = body0Pos + sphereRadius * collisionN;
                                                    Vector3 pt = voxelPosition - collisionN * (voxelSize - epsylon);

                                                    collPtArray[numCollPts++] = new MySmallCollPointInfo(pt - body0Pos, pt - body1Pos, GetRigidBody1().LinearVelocity, GetRigidBody2().LinearVelocity, collisionN, oldPenetrationDepth, pt);
                                                }

                                                collNormal -= collisionN;
                                            }
                                        }
                                    }
                                }

                                MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().EndProfilingBlock();
                            }
                        }

                        MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().EndProfilingBlock();
                    }

                    MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().EndProfilingBlock();
                }
                else //if (colDetThroughVoxels)
                {
                    MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().StartProfilingBlock("ColDet triangles");

                    int optimalIterationCount = (int)(GetRigidBody1().LinearVelocity.Length() * dt / sphereRadius);
                    int maxIndex = (int)MathHelper.Min(MathHelper.Max(optimalIterationCount, 1), 16);

                    for (int i = 0; i < maxIndex; i++)
                    {
                        float velocityAdd = GetRigidBody1().LinearVelocity.Length() * dt / (float)maxIndex;

                        Vector3 interpolatedPosition = body0Pos + GetRigidBody1().LinearVelocity *dt *i / (float)maxIndex;

                        BoundingSphere newSphere;
                        newSphere.Center = interpolatedPosition;
                        newSphere.Radius = sphereRadius;

                        int numTriangles;

                        BoundingBox bb = BoundingBox.CreateFromSphere(newSphere);
                        MyVoxelMaps.GetPotentialTrianglesForColDet(out numTriangles, ref bb);

                        for (int iTriangle = 0; iTriangle < numTriangles; ++iTriangle)
                        {
                            MyColDetVoxelTriangle meshTriangle = MyVoxelMaps.PotentialColDetTriangles[iTriangle]; // mesh.GetTriangle(potentialTriangles[iTriangle]);


                            MyTriangle_Vertex_Normal triangle = new MyTriangle_Vertex_Normal();
                            triangle.Vertexes.Vertex0 = meshTriangle.Vertex0;
                            triangle.Vertexes.Vertex1 = meshTriangle.Vertex1;
                            triangle.Vertexes.Vertex2 = meshTriangle.Vertex2;


                            // skip too narrow triangles causing instability
                            if ((triangle.Vertexes.Vertex0 - triangle.Vertexes.Vertex1).LengthSquared() < MyPhysicsConfig.TriangleEpsilon)
                            {
                                continue;
                            }

                            if ((triangle.Vertexes.Vertex1 - triangle.Vertexes.Vertex2).LengthSquared() < MyPhysicsConfig.TriangleEpsilon)
                            {
                                continue;
                            }

                            if ((triangle.Vertexes.Vertex0 - triangle.Vertexes.Vertex2).LengthSquared() < MyPhysicsConfig.TriangleEpsilon)
                            {
                                continue;
                            }

                            MyPlane plane = new MyPlane(ref triangle.Vertexes);

                            Vector3?pt = MyUtils.GetSphereTriangleIntersection(ref newSphere, ref plane, ref triangle.Vertexes);
                            if (pt == null)
                            {
                                continue;
                            }


                            Vector3 collisionN = plane.Normal;

                            // skip triangle in case the normal is in wrong dir (narrow walls)
                            Vector3 tempV = (newBody0Pos - pt.Value);
                            if (Vector3.Dot(collisionN, tempV) >= 0.8f * tempV.Length())  // equivalent to dot(collisionN, normalize(tempV)) > 0.8f, but works for zero vectors
                            {
                                continue;
                            }

                            float depth = Vector3.Distance(pt.Value, body0Pos) - sphereRadius;

                            if (numCollPts < MyPhysicsConfig.MaxContactPoints)
                            {
                                // since impulse get applied at the old position
                                Vector3 p2 = pt.Value;

                                collPtArray[numCollPts++] = new MySmallCollPointInfo(p2 - body0Pos, p2 - body1Pos, GetRigidBody1().LinearVelocity, GetRigidBody2().LinearVelocity, collisionN, depth, p2);
                            }

                            collNormal += collisionN;
                        }
                    }

                    MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().EndProfilingBlock();
                }

                if (numCollPts > 0)
                {
                    MyPhysics.physicsSystem.GetContactConstraintModule().AddContactConstraint(this, collPtArray, numCollPts);
                }
                MyContactInfoCache.FreeStackAlloc(collPtArray);

                MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().EndProfilingBlock();
            }

            return(false);
        }
Esempio n. 8
0
        protected override bool Interact(bool staticCollision)
        {
            if (RBElement1.GetElementType() != MyRBElementType.ET_BOX)
            {
                SwapElements();
            }

            if (!staticCollision)
            {
                MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().StartProfilingBlock("BoxVoxelInteraction");
            }

            MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().StartProfilingBlock("Transformations");

            MyRBBoxElement rbbox0 = (MyRBBoxElement)RBElement1;

            Matrix matrix0 = RBElement1.GetGlobalTransformation();

            MyBox box = tempBox;

            box.Transform.Orientation             = matrix0;
            box.Transform.Orientation.Translation = Vector3.Zero;
            box.Transform.Position = matrix0.Translation - Vector3.TransformNormal(rbbox0.Size * 0.5f, matrix0);

            box.SideLengths = rbbox0.Size;

            float boxRadius = box.GetBoundingRadiusAroundCentre();

            #region boxCentre
            Vector3 boxCentre;
            box.GetCentre(out boxCentre);
            // Deano need to trasnform the box center into mesh space
            //Matrix invTransformMatrix = mesh.InverseTransformMatrix;
            //Vector3.Transform(ref boxCentre, ref invTransformMatrix, out boxCentre);
            #endregion

            BoundingBox bb = RBElement1.GetWorldSpaceAABB();

            MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().EndProfilingBlock();

            MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().StartProfilingBlock("GetPotentialTrianglesForColDet");
            // extent bb for the movement
            int numTriangles;
            MyVoxelMaps.GetPotentialTrianglesForColDet(out numTriangles, ref bb);

            MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().EndProfilingBlock();

            if (staticCollision)
            {
                for (int iTriangle = 0; iTriangle < numTriangles; ++iTriangle)
                {
                    MyColDetVoxelTriangle triangle = MyVoxelMaps.PotentialColDetTriangles[iTriangle];

                    // quick early test is done in mesh space
                    float dist = triangle.Plane.DotCoordinate(boxCentre);

                    if (dist > boxRadius)
                    {
                        continue;
                    }

                    // skip too narrow triangles causing destability
                    if ((triangle.Vertex0 - triangle.Vertex1).LengthSquared() < MyPhysicsConfig.TriangleEpsilon ||
                        (triangle.Vertex1 - triangle.Vertex2).LengthSquared() < MyPhysicsConfig.TriangleEpsilon ||
                        (triangle.Vertex0 - triangle.Vertex2).LengthSquared() < MyPhysicsConfig.TriangleEpsilon
                        )
                    {
                        continue;
                    }

                    if (DoOverlapBoxTriangleStaticTest(box, ref triangle))
                    {
                        return(true);
                    }
                }
            }
            else
            {
                MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().StartProfilingBlock("for DoOverlapBoxTriangleTest");

                for (int iTriangle = 0; iTriangle < numTriangles; ++iTriangle)
                {
                    MyColDetVoxelTriangle triangle = MyVoxelMaps.PotentialColDetTriangles[iTriangle];

                    // skip too narrow triangles causing destability
                    if ((triangle.Vertex0 - triangle.Vertex1).LengthSquared() < MyPhysicsConfig.TriangleEpsilon ||
                        (triangle.Vertex1 - triangle.Vertex2).LengthSquared() < MyPhysicsConfig.TriangleEpsilon ||
                        (triangle.Vertex0 - triangle.Vertex2).LengthSquared() < MyPhysicsConfig.TriangleEpsilon
                        )
                    {
                        continue;
                    }

                    DoOverlapBoxTriangleTest(box, ref triangle);
                }

                MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().EndProfilingBlock();
            }

            if (!staticCollision)
            {
                MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().EndProfilingBlock();
            }
            return(false);
        }