public static void DebugDrawOBB(MyOrientedBoundingBoxD obb, Color color, float alpha, bool depthRead, bool smooth)
        {
            MatrixD obbMatrix = MatrixD.CreateFromQuaternion(obb.Orientation);
            obbMatrix.Right *= obb.HalfExtent.X * 2;
            obbMatrix.Up *= obb.HalfExtent.Y * 2;
            obbMatrix.Forward *= obb.HalfExtent.Z * 2;
            obbMatrix.Translation = obb.Center;

            VRageRender.MyRenderProxy.DebugDrawOBB(obbMatrix, color, alpha, depthRead, smooth);
        }
        public static void DebugDrawClusters()
        {
            if (Clusters == null)
                return;

            double previewScale = 2000;
            MatrixD previewMatrix = MatrixD.CreateWorld(DebugDrawClustersMatrix.Translation + previewScale * DebugDrawClustersMatrix.Forward, Vector3D.Forward, Vector3D.Up);

            m_resultWorlds.Clear();

            Clusters.GetAll(m_resultWorlds);

            BoundingBoxD totalBox = BoundingBoxD.CreateInvalid();

            foreach (var res in m_resultWorlds)
            {
                totalBox = totalBox.Include(res.AABB);
            }

            double maxAxis = totalBox.Size.AbsMax();
            //double scaleAxis = 0.057142857142857141;
            double scaleAxis = previewScale / maxAxis;

            //Vector3D scale = new Vector3D(totalBox.Size.X * scaleAxis, totalBox.Size.Y * scaleAxis, totalBox.Size.Z * scaleAxis);

            Vector3D center = totalBox.Center;
            totalBox.Min -= center;
            totalBox.Max -= center;

            {
                BoundingBoxD scaledBox = new BoundingBoxD(totalBox.Min * scaleAxis * 1.02f, totalBox.Max * scaleAxis * 1.02f);
                MyOrientedBoundingBoxD oriented = new MyOrientedBoundingBoxD(scaledBox, previewMatrix);
                MyRenderProxy.DebugDrawOBB(oriented, Color.Green, .2f, false, false);

                MyRenderProxy.DebugDrawAxis(previewMatrix, 50, false);

                if (MySession.Static != null)
                {
                    foreach (var player in Sandbox.Game.Multiplayer.Sync.Players.GetOnlinePlayers())
                    {
                        if (player.Character != null)
                        {
                            var playerPos = Vector3D.Transform((player.Character.PositionComp.GetPosition() - center) * scaleAxis, previewMatrix);
                            MyRenderProxy.DebugDrawSphere(playerPos, 10, Vector3.One, 1, false);
                        }
                    }
                }
            }

            Clusters.GetAllStaticObjects(m_clusterStaticObjects);
            foreach (var staticBB in m_clusterStaticObjects)
            {
                BoundingBoxD scaledBox = new BoundingBoxD((staticBB.Min - center) * scaleAxis, (staticBB.Max - center) * scaleAxis);

                MyOrientedBoundingBoxD oriented = new MyOrientedBoundingBoxD(scaledBox, previewMatrix);

                MyRenderProxy.DebugDrawOBB(oriented, Color.Blue, .2f, false, false);
            }

            foreach (var res in m_resultWorlds)
            {
                BoundingBoxD scaledBox = new BoundingBoxD((res.AABB.Min - center) * scaleAxis, (res.AABB.Max - center) * scaleAxis);

                MyOrientedBoundingBoxD oriented = new MyOrientedBoundingBoxD(scaledBox, previewMatrix);

                MyRenderProxy.DebugDrawOBB(oriented, Color.White, .2f, false, false);

                foreach (var rb in ((HkWorld)res.UserData).CharacterRigidBodies)
                {
                    Vector3D rbCenter = res.AABB.Center + rb.Position;
                    rbCenter = (rbCenter - center) * scaleAxis;
                    rbCenter = Vector3D.Transform(rbCenter, previewMatrix);

                    Vector3D velocity = rb.LinearVelocity;
                    velocity = Vector3D.TransformNormal(velocity, previewMatrix) * 10;
                    MyRenderProxy.DebugDrawLine3D(rbCenter, rbCenter + velocity, Color.Blue, Color.White, false);
                }

                foreach (var rb in ((HkWorld)res.UserData).RigidBodies)
                {
                    //jn: TODO fix debug draw
                    //MyOrientedBoundingBoxD rbbb = new MyOrientedBoundingBoxD((BoundingBoxD)rb.GetEntity().LocalAABB, rb.GetEntity().WorldMatrix);
                    //rbbb.Center = (rbbb.Center - center) * scaleAxis;
                    //rbbb.HalfExtent *= scaleAxis;
                    //rbbb.Transform(previewMatrix);
                    //MyRenderProxy.DebugDrawOBB(rbbb, Color.Yellow, 1, false, false);

                    ////BoundingBoxD rbaa = rb.GetEntity().WorldAABB;
                    ////rbaa.Min = (rbaa.Min - center) * scaleAxis;
                    ////rbaa.Max = (rbaa.Max - center) * scaleAxis;
                    ////MyRenderProxy.DebugDrawAABB(rbaa, new Vector3(0.8f, 0.8f, 0.8f), 1, 1, false);

                    //Vector3D velocity = rb.LinearVelocity;
                    //velocity = Vector3D.TransformNormal(velocity, previewMatrix) * 10;
                    //MyRenderProxy.DebugDrawLine3D(rbbb.Center, rbbb.Center + velocity, Color.Red, Color.White, false);

                    //if (velocity.Length() > 1)
                    //{
                    //    BoundingBoxD ideal = new BoundingBoxD(rb.GetEntity().WorldAABB.Center - MyHavokCluster.IdealClusterSize / 2, rb.GetEntity().WorldAABB.Center + MyHavokCluster.IdealClusterSize / 2);
                    //    MyOrientedBoundingBoxD idealObb = new MyOrientedBoundingBoxD(ideal, MatrixD.Identity);
                    //    idealObb.Center = (ideal.Center - center) * scaleAxis;
                    //    idealObb.HalfExtent *= scaleAxis;
                    //    idealObb.Transform(previewMatrix);
                    //    MyRenderProxy.DebugDrawOBB(idealObb, new Vector3(0, 0, 1), 1, false, false);
                    //}
                }
            }
        }
Exemple #3
0
        /// <summary>
        /// Calculates amount of volume of a bounding box in voxels.
        /// </summary>
        /// <param name="localAabb">Local bounding box to query for.</param>
        /// <param name="worldMatrix">World matrix of the bounding box.</param>
        /// <returns>Pair of floats where 1st value is Volume amount and 2nd value is ratio of Volume amount to Whole volume.</returns>
        public MyTuple<float,float> GetVoxelContentInBoundingBox_Fast(BoundingBoxD localAabb, MatrixD worldMatrix)
        {
            MatrixD toVoxel = worldMatrix * PositionComp.WorldMatrixNormalizedInv;
            MatrixD toGrid; MatrixD.Invert(ref toVoxel, out toGrid);

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

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

           // localAabb.Inflate(1 * voxelSizeAtLod);

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

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

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

            MyOrientedBoundingBoxD worldbbox = new MyOrientedBoundingBoxD(localAabb, worldMatrix);

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

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

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

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

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

                        MyOrientedBoundingBoxD voxelBbox = new MyOrientedBoundingBoxD(voxelBox, voxelToWorld);

                        cont = worldbbox.Contains(ref voxelBbox);

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

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



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

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

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


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


            return new MyTuple<float, float>(resultVolume, resultPercent);
        }
        public override bool HandleInput()
        {
            if (base.HandleInput())
                return true;

            bool handled = false;

          
            //foreach (var ent in MyEntities.GetEntities())
            //{
            //    if (ent is MyCubeGrid)
            //    {
            //        if (ent.PositionComp.WorldAABB.Contains(MySector.MainCamera.Position) == ContainmentType.Disjoint)
            //        {
            //            ent.Close();
            //        }
            //    }
            //}

            //var measureStart = new VRage.Library.Utils.MyTimeSpan(System.Diagnostics.Stopwatch.GetTimestamp());

            var list = MyDefinitionManager.Static.GetAnimationDefinitions();

            foreach (var skin in m_skins)
            {                
                skin.UpdateAnimation(Vector3.Distance(MySector.MainCamera.Position,skin.PositionComp.GetPosition()));

                if (MyRandom.Instance.NextFloat() > 0.95f)
                {
                    var randomAnim = list.ItemAt(MyRandom.Instance.Next(0, list.Count));
                    var command = new MyAnimationCommand()
                    {
                        AnimationSubtypeName = randomAnim.Id.SubtypeName,
                        FrameOption = MyFrameOption.Loop,
                        TimeScale = 1,
                        BlendTime = 0.3f
                    };
                    skin.AddCommand(command);
                }
            }


//            var measureEnd = new VRage.Library.Utils.MyTimeSpan(System.Diagnostics.Stopwatch.GetTimestamp());
 //           var total = measureEnd - measureStart;
   //         m_skins.Clear();

            if (m_voxelMap != null && m_voxelMap.PositionComp != null)
            {
                Vector3D center = m_voxelMap.PositionComp.WorldAABB.Center;
                Vector3D centerDelta = m_voxelMap.PositionComp.WorldMatrix.Translation - center;



                MatrixD worldMatrix = m_voxelMap.PositionComp.WorldMatrix;

                var rotationMatrix = Matrix.CreateRotationZ(0.01f);
                worldMatrix *= rotationMatrix;
                centerDelta = Vector3.TransformNormal(centerDelta, rotationMatrix);

                worldMatrix.Translation = center + centerDelta;

                //m_voxelMap.PositionComp.WorldMatrix = worldMatrix;


                SI_DYNAMICS_MULTIPLIER += 0.01f;

                //var tr = worldMatrix.Translation;
                //worldMatrix.Translation = new Vector3D(tr.X += (double)MyMath.FastSin(SI_DYNAMICS_MULTIPLIER), tr.Y, tr.Z);
                //worldMatrix.Translation = new Vector3D(tr.X + 100, tr.Y, tr.Z);

                //m_voxelMap.PositionComp.WorldMatrix = worldMatrix;

                var localBB = m_voxelMap.PositionComp.LocalAABB;
                MyOrientedBoundingBoxD orb = new MyOrientedBoundingBoxD((BoundingBoxD)localBB, m_voxelMap.PositionComp.WorldMatrix);
                VRageRender.MyRenderProxy.DebugDrawOBB(orb, Color.White, 0, false, false);
            }

            return handled;
        }
        /// <summary>
        /// Changes the given OBB so it is Y bounded by the range where surface may exist
        /// </summary>
        private bool SetTerrainLimits(ref MyOrientedBoundingBoxD obb)
        {
            float minHeight, maxHeight;
            int pointCount = 4;
            unsafe
            {
                Vector3* points = stackalloc Vector3[4];
                GetMiddleOBBLocalPoints(obb, ref points);
                m_planet.Provider.Shape.GetBounds(points, pointCount, out minHeight, out maxHeight);
            }

            if (minHeight.IsValid() && maxHeight.IsValid())
            {
                Vector3 minPoint = obb.Orientation.Up * minHeight + m_planet.PositionComp.GetPosition();
                Vector3 maxPoint = obb.Orientation.Up * maxHeight + m_planet.PositionComp.GetPosition();

                obb.Center = (minPoint + maxPoint) * 0.5f;
                // maxHeight and minHeight may be the same
                float heightDiff = Math.Max(maxHeight - minHeight, 1);
                obb.HalfExtent.Y = heightDiff * 0.5f;

                return true;
            }

            return false;
        }
Exemple #6
0
        internal static bool BresenhamGridIntersection(MyCubeGrid grid, ref Vector3D worldStart, ref Vector3D worldEnd, out Vector3D?hitPos, MyCubeBlock weapon = null, GridAi ai = null)
        {
            var      start = grid.WorldToGridInteger(worldStart);
            var      end   = grid.WorldToGridInteger(worldEnd);
            Vector3I delta = end - start;
            Vector3I step  = Vector3I.Sign(delta);

            delta *= step;
            int max = delta.AbsMax();

            hitPos = null;

            var gMinX = grid.Min.X;
            var gMinY = grid.Min.Y;
            var gMinZ = grid.Min.Z;
            var gMaxX = grid.Max.X;
            var gMaxY = grid.Max.Y;
            var gMaxZ = grid.Max.Z;

            if (ai != null)
            {
                var dir = (worldEnd - worldStart);
                var ray = new RayD(ref worldStart, ref dir);
                foreach (var sub in ai.SubGrids)
                {
                    if (sub == grid)
                    {
                        continue;
                    }
                    var subDist = sub.PositionComp.WorldVolume.Intersects(ray);
                    if (subDist.HasValue)
                    {
                        var      rotMatrix = Quaternion.CreateFromRotationMatrix(ai.MyGrid.WorldMatrix);
                        var      obb       = new MyOrientedBoundingBoxD(ai.MyGrid.PositionComp.WorldAABB.Center, ai.MyGrid.PositionComp.LocalAABB.HalfExtents, rotMatrix);
                        Vector3D?ignoreHit;
                        if (obb.Intersects(ref ray) != null && BresenhamGridIntersection(sub, ref worldStart, ref worldEnd, out ignoreHit, weapon))
                        {
                            return(true);
                        }
                    }
                }
            }

            if (max == delta.X)
            {
                int p1 = 2 * delta.Y - delta.X;
                int p2 = 2 * delta.Z - delta.X;
                while (start.X != end.X)
                {
                    start.X += step.X;
                    if (p1 >= 0)
                    {
                        start.Y += step.Y;
                        p1      -= 2 * delta.X;
                    }

                    if (p2 >= 0)
                    {
                        start.Z += step.Z;
                        p2      -= 2 * delta.X;
                    }
                    p1 += 2 * delta.Y;
                    p2 += 2 * delta.Z;
                    var contained = gMinX <= start.X && start.X <= gMaxX && (gMinY <= start.Y && start.Y <= gMaxY) && (gMinZ <= start.Z && start.Z <= gMaxZ);
                    if (!contained)
                    {
                        return(false);
                    }

                    MyCube cube;
                    if (grid.TryGetCube(start, out cube) && cube.CubeBlock != weapon?.SlimBlock)
                    {
                        return(true);
                    }
                }
            }
            else if (max == delta.Y)
            {
                int p1 = 2 * delta.X - delta.Y;
                int p2 = 2 * delta.Z - delta.Y;
                while (start.Y != end.Y)
                {
                    start.Y += step.Y;
                    if (p1 >= 0)
                    {
                        start.X += step.X;
                        p1      -= 2 * delta.Y;
                    }

                    if (p2 >= 0)
                    {
                        start.Z += step.Z;
                        p2      -= 2 * delta.Y;
                    }
                    p1 += 2 * delta.X;
                    p2 += 2 * delta.Z;

                    var contained = gMinX <= start.X && start.X <= gMaxX && (gMinY <= start.Y && start.Y <= gMaxY) && (gMinZ <= start.Z && start.Z <= gMaxZ);
                    if (!contained)
                    {
                        return(false);
                    }

                    MyCube cube;
                    if (grid.TryGetCube(start, out cube) && cube.CubeBlock != weapon?.SlimBlock)
                    {
                        return(true);
                    }
                }
            }
            else
            {
                int p1 = 2 * delta.X - delta.Z;
                int p2 = 2 * delta.Y - delta.Z;
                while (start.Z != end.Z)
                {
                    start.Z += step.Z;
                    if (p1 >= 0)
                    {
                        start.X += step.X;
                        p1      -= 2 * delta.Z;
                    }

                    if (p2 >= 0)
                    {
                        start.Y += step.Y;
                        p2      -= 2 * delta.Z;
                    }
                    p1 += 2 * delta.X;
                    p2 += 2 * delta.Y;

                    var contained = gMinX <= start.X && start.X <= gMaxX && (gMinY <= start.Y && start.Y <= gMaxY) && (gMinZ <= start.Z && start.Z <= gMaxZ);
                    if (!contained)
                    {
                        return(false);
                    }

                    MyCube cube;
                    if (grid.TryGetCube(start, out cube) && cube.CubeBlock != weapon?.SlimBlock)
                    {
                        return(true);
                    }
                }
            }
            return(false);
        }
Exemple #7
0
        public bool IsWeaponAreaRestricted(MyStringHash subtype, MyOrientedBoundingBoxD cubeBoundingBox, MyCubeGrid myGrid, long ignoredEntity, GridAi gridAi, out MyOrientedBoundingBoxD restrictedBox, out BoundingSphereD restrictedSphere)
        {
            _tmpNearByBlocks.Clear();
            GridAi ai;

            if (gridAi == null)
            {
                if (!GridToMasterAi.ContainsKey(myGrid))
                {
                    restrictedSphere = new BoundingSphereD();
                    restrictedBox    = new MyOrientedBoundingBoxD();
                    return(false);
                }
                ai = GridToMasterAi[myGrid];
            }
            else
            {
                ai = gridAi;
            }

            CalculateRestrictedShapes(subtype, cubeBoundingBox, out restrictedBox, out restrictedSphere);
            var queryRadius = Math.Max(restrictedBox.HalfExtent.AbsMax(), restrictedSphere.Radius);

            if (queryRadius < 0.01)
            {
                return(false);
            }

            var restriction = WeaponAreaRestrictions[subtype];
            var checkBox    = restriction.RestrictionBoxInflation > 0;
            var checkSphere = restriction.RestrictionRadius > 0;
            var querySphere = new BoundingSphereD(cubeBoundingBox.Center, queryRadius);

            myGrid.Hierarchy.QuerySphere(ref querySphere, _tmpNearByBlocks);

            foreach (var grid in ai.SubGrids)
            {
                if (grid == myGrid || !GridTargetingAIs.ContainsKey(grid))
                {
                    continue;
                }
                grid.Hierarchy.QuerySphere(ref querySphere, _tmpNearByBlocks);
            }

            for (int l = 0; l < _tmpNearByBlocks.Count; l++)
            {
                var cube = _tmpNearByBlocks[l] as MyCubeBlock;
                if (cube == null || cube.EntityId == ignoredEntity || !WeaponCoreBlockDefs.ContainsKey(cube.BlockDefinition.Id.SubtypeId.String))
                {
                    continue;
                }

                if (!restriction.CheckForAnyWeapon && cube.BlockDefinition.Id.SubtypeId != subtype)
                {
                    continue;
                }

                if (checkBox)
                {
                    var cubeBox = new MyOrientedBoundingBoxD(cube.PositionComp.LocalAABB, cube.PositionComp.WorldMatrixRef);
                    if (restrictedBox.Contains(ref cubeBox) != ContainmentType.Disjoint)
                    {
                        return(true);
                    }
                }

                if (checkSphere && restrictedSphere.Contains(cube.PositionComp.WorldAABB) != ContainmentType.Disjoint)
                {
                    return(true);
                }
            }
            return(false);
        }
        private void AddEntities(float border, Vector3D originPosition, MyOrientedBoundingBoxD obb, List<BoundingBoxD> boundingBoxes, List<MyVoxelMap> trackedEntities)
        {
            obb.HalfExtent += new Vector3D(border, 0, border);
            var aabb = obb.GetAABB();

            List<MyEntity> entities = new List<MyEntity>();
            MyGamePruningStructure.GetAllEntitiesInBox(ref aabb, entities);

            //TODO: remove this? Just for Debug...
            if (entities.Count(e => e is MyCubeGrid) > 0)
            {
                m_lastGridsInfo.Clear();
                m_lastIntersectedGridsInfoCubes.Clear();
            }

            foreach (var entity in entities)
            {
                var grid = entity as MyCubeGrid;
                //TODO: let the static be here?
                if (grid != null && grid.IsStatic)
                {
                    ProfilerShort.Begin("AddEntities.AddGridVerticesInsideOBB");
                    AddGridVerticesInsideOBB(grid, obb);
                    ProfilerShort.End();
                    return;
                }

                var voxelMap = entity as MyVoxelMap;
                if (voxelMap != null)
                {
                    trackedEntities.Add(voxelMap);

                    ProfilerShort.Begin("AddEntities.AddVoxelVertices");
                    AddVoxelVertices(voxelMap, border, originPosition, obb, boundingBoxes);
                    ProfilerShort.End();
                    return;
                }

            }
        }
Exemple #9
0
        void DrawBlockSelection(IMySlimBlock block, SelectionState state, bool primarySelection = false)
        {
            IMyCubeGrid           grid = block.CubeGrid;
            MyCubeBlockDefinition def  = (MyCubeBlockDefinition)block.BlockDefinition;

            Color color = (state == SelectionState.InvalidButMirrorValid ? Color.Yellow : (state == SelectionState.Valid ? Color.Green : Color.Red));

            MatrixD      worldMatrix;
            BoundingBoxD localBB;

            #region Compute box
            MyCubeBlock fatBlock = block.FatBlock as MyCubeBlock;
            if (fatBlock != null)
            {
                worldMatrix = fatBlock.PositionComp.WorldMatrixRef;

                if (Main.Tick % (Constants.TICKS_PER_SECOND / 4) == 0 || !LocalBBCache.TryGetValue(block, out localBB))
                {
                    BoundingBox localAABB = fatBlock.PositionComp.LocalAABB;
                    localBB = new BoundingBoxD(localAABB.Min, localAABB.Max);

                    #region Subpart localBB inclusion
                    if (fatBlock.Subparts != null)
                    {
                        MatrixD transformToBlockLocal = fatBlock.PositionComp.WorldMatrixInvScaled;

                        foreach (VRage.Game.Entity.MyEntitySubpart s1 in fatBlock.Subparts.Values)
                        {
                            MyOrientedBoundingBoxD obbS1 = new MyOrientedBoundingBoxD(s1.PositionComp.LocalAABB, s1.PositionComp.WorldMatrixRef);
                            obbS1.GetCorners(Corners, 0);

                            for (int i = 0; i < Corners.Length; i++)
                            {
                                Vector3D corner = Corners[i];
                                localBB.Include(Vector3D.Transform(corner, transformToBlockLocal));
                            }

                            if (s1.Subparts != null)
                            {
                                foreach (VRage.Game.Entity.MyEntitySubpart s2 in s1.Subparts.Values)
                                {
                                    MyOrientedBoundingBoxD obbS2 = new MyOrientedBoundingBoxD(s2.PositionComp.LocalAABB, s2.PositionComp.WorldMatrixRef);
                                    obbS2.GetCorners(Corners, 0);

                                    for (int i = 0; i < Corners.Length; i++)
                                    {
                                        Vector3D corner = Corners[i];
                                        localBB.Include(Vector3D.Transform(corner, transformToBlockLocal));
                                    }

                                    if (s2.Subparts != null)
                                    {
                                        foreach (VRage.Game.Entity.MyEntitySubpart s3 in s2.Subparts.Values)
                                        {
                                            MyOrientedBoundingBoxD obbS3 = new MyOrientedBoundingBoxD(s3.PositionComp.LocalAABB, s3.PositionComp.WorldMatrixRef);
                                            obbS3.GetCorners(Corners, 0);

                                            for (int i = 0; i < Corners.Length; i++)
                                            {
                                                Vector3D corner = Corners[i];
                                                localBB.Include(Vector3D.Transform(corner, transformToBlockLocal));
                                            }

                                            if (s3.Subparts != null)
                                            {
                                                foreach (VRage.Game.Entity.MyEntitySubpart s4 in s3.Subparts.Values)
                                                {
                                                    MyOrientedBoundingBoxD obbS4 = new MyOrientedBoundingBoxD(s4.PositionComp.LocalAABB, s4.PositionComp.WorldMatrixRef);
                                                    obbS4.GetCorners(Corners, 0);

                                                    for (int i = 0; i < Corners.Length; i++)
                                                    {
                                                        Vector3D corner = Corners[i];
                                                        localBB.Include(Vector3D.Transform(corner, transformToBlockLocal));
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                    #endregion

                    LocalBBCache[block] = localBB;
                }
            }
            else
            {
                Matrix localMatrix;
                block.Orientation.GetMatrix(out localMatrix);
                localMatrix.Translation = new Vector3(block.Position) * grid.GridSize;
                worldMatrix             = localMatrix * grid.WorldMatrix;

                Vector3 halfSize = def.Size * (grid.GridSize * 0.5f);
                localBB = new BoundingBoxD(-halfSize, halfSize);
            }
            #endregion

            localBB.Inflate((grid.GridSizeEnum == MyCubeSize.Large ? 0.1 : 0.03));
            float lineWidth;

            if (primarySelection)
            {
                lineWidth = (grid.GridSizeEnum == MyCubeSize.Large ? 0.02f : 0.016f);
            }
            else
            {
                lineWidth = (grid.GridSizeEnum == MyCubeSize.Large ? 0.25f : 0.1f); // thicker mirrored selections to see better in distance
            }
            DrawSelectionLines(ref worldMatrix, ref localBB, color, lineWidth);
        }
Exemple #10
0
        public void CalculateRestrictedShapes(MyStringHash subtype, MyOrientedBoundingBoxD cubeBoundingBox, out MyOrientedBoundingBoxD restrictedBox, out BoundingSphereD restrictedSphere)
        {
            restrictedSphere = new BoundingSphereD();
            restrictedBox    = new MyOrientedBoundingBoxD();

            if (!WeaponAreaRestrictions.ContainsKey(subtype))
            {
                return;
            }

            WeaponAreaRestriction restriction = WeaponAreaRestrictions[subtype];

            if (restriction.RestrictionBoxInflation < 0.1 && restriction.RestrictionRadius < 0.1)
            {
                return;
            }

            bool checkBox    = restriction.RestrictionBoxInflation > 0;
            bool checkSphere = restriction.RestrictionRadius > 0;

            if (checkBox)
            {
                restrictedBox            = new MyOrientedBoundingBoxD(cubeBoundingBox.Center, cubeBoundingBox.HalfExtent, cubeBoundingBox.Orientation);
                restrictedBox.HalfExtent = restrictedBox.HalfExtent + new Vector3D(Math.Sign(restrictedBox.HalfExtent.X) * restriction.RestrictionBoxInflation, Math.Sign(restrictedBox.HalfExtent.Y) * restriction.RestrictionBoxInflation, Math.Sign(restrictedBox.HalfExtent.Z) * restriction.RestrictionBoxInflation);
            }
            if (checkSphere)
            {
                restrictedSphere = new BoundingSphereD(cubeBoundingBox.Center, restriction.RestrictionRadius);
            }
        }
Exemple #11
0
        public void CalculateLines()
        {
            DsWatch.Start("CLines");
            try
            {
                if (closestPlanet != null)
                {
                    var planetAtmosphereAltitude = closestPlanet.AtmosphereAltitude;

                    var cameraUp      = new Vector3D(Camera.Position - planetCentre);
                    var cameraForward = Vector3D.CalculatePerpendicularVector(cameraUp);
                    frustumMatrix = MatrixD.CreateWorld(Camera.Position, cameraForward, cameraUp);
                    var offset = Vector3.Zero;

                    var frustum = new BoundingFrustumD(Camera.ViewMatrix * customProjectionMatrix);
                    frustumBBox = BoundingBoxD.CreateInvalid();
                    frustumBBox.Include(ref frustum);

                    if (cameraAltitude < (planetAtmosphereAltitude / 2))
                    {
                        var lineAmount = 100;
                        for (int i = 0; i < lineAmount; i++) // Line calculation LOOP
                        {
                            lineThickness = MyUtils.GetRandomFloat(0.01f, 0.05f);

                            offset.Y = (float)frustumBBox.Extents.Y;
                            offset.X = MyUtils.GetRandomInt(-60, 60);
                            offset.Z = MyUtils.GetRandomInt(-60, 60);

                            if (offset.X >= 0 && offset.X < 1)
                            {
                                offset.X = offset.X + 1;
                            }

                            if (offset.Z >= 0 && offset.Z < 1)
                            {
                                offset.Z = offset.Z + 1;
                            }

                            Vector3D lineStartPoint = Vector3D.Transform(offset, frustumMatrix);
                            Vector3D lineEndPoint   = planetCentre;

                            var   length    = frustumBBox.HalfExtents.Y * 0.25; // Shorten line length by 1/4
                            LineD lineCheck = new LineD(lineStartPoint, lineEndPoint, length);

                            Vector3D finalHitPos    = lineEndPoint;
                            Vector3D hitPos         = lineEndPoint;
                            double?  hitDist        = double.MaxValue;
                            double   finalHitDistSq = double.MaxValue;
                            var      checkVoxel     = true;
                            var      isVoxel        = false;

                            lineIntersectedGrids.Clear();
                            lineIntersectedVoxels.Clear();

                            if (frustumBBox.Intersects(ref lineCheck))
                            {
                                for (int j = 0; j < rainImpactEntities.Count; j++) // Line calculation LOOP
                                {
                                    var rainedOnEnt = rainImpactEntities[j];
                                    var grid        = rainedOnEnt as IMyCubeGrid;
                                    if (grid != null && grid.Physics != null)
                                    {
                                        lineIntersectedGrids.Add(rainedOnEnt);
                                    }
                                    else if (rainedOnEnt is MyVoxelBase)
                                    {
                                        lineIntersectedVoxels.Add(rainedOnEnt);
                                    }
                                }

                                for (int k = 0; k < lineIntersectedGrids.Count; k++)
                                {
                                    var intersectedGrid = lineIntersectedGrids[k];
                                    var cubeGrid        = intersectedGrid as IMyCubeGrid;
                                    if (cubeGrid != null && cubeGrid.Physics != null)
                                    {
                                        MyOrientedBoundingBoxD gridOBB = new MyOrientedBoundingBoxD(cubeGrid.LocalAABB, cubeGrid.WorldMatrix);
                                        //DrawOBB(gridOBB, whiteColor, MySimpleObjectRasterizer.Wireframe, 0.01f);

                                        // If we don't intersect a grid continue.
                                        if (!gridOBB.Intersects(ref lineCheck).HasValue)
                                        {
                                            continue;
                                        }

                                        hitDist = GridHitCheck(cubeGrid, lineCheck, lineStartPoint, lineEndPoint);

                                        if (hitDist != null)
                                        {
                                            hitPos = lineStartPoint + (lineCheck.Direction * hitDist.Value);
                                            if (finalHitDistSq > hitDist.Value)
                                            {
                                                finalHitPos    = hitPos;
                                                finalHitDistSq = hitDist.Value;
                                                checkVoxel     = false;
                                            }
                                        }

                                        //LogGridBlockHits(finalHitDistSq, finalHitPos, cubeGrid, blk, lineColor);
                                    }
                                }

                                /*
                                 * if (checkVoxel)
                                 * {
                                 *  for (int l = 0; l < lineIntersectedVoxels.Count; l++)
                                 *  {
                                 *      var intersectedVoxel = lineIntersectedVoxels[l];
                                 *      var voxelHitName = intersectedVoxel as MyVoxelBase;
                                 *      if (voxelHitName != null)
                                 *      {
                                 *          var voxelCheck = VoxelHitCheck(voxelHitName, closestPlanet, lineStartPoint, lineEndPoint, lineCheck);
                                 *          if (voxelCheck != Vector3D.Zero && voxelCheck != null)
                                 *          {
                                 *              finalHitPos = voxelCheck;
                                 *              hitDist = Vector3D.Distance(lineStartPoint, finalHitPos);
                                 *              //LogVoxelHits(hitDist, voxelHitName, finalHitPos, lineCheck.Length);
                                 *              isVoxel = true;
                                 *          }
                                 *      }
                                 *  }
                                 * }
                                 */

                                /*
                                 * // Log Loop sizes
                                 * if (_updateCount % 100 == 0)
                                 * {
                                 *  Logging.Instance.WriteLine(rainImpactEntities.Count.ToString() + " " +
                                 *                             lineIntersectedGrids.Count.ToString() + " " +
                                 *                             lineIntersectedVoxels.Count.ToString());
                                 * }
                                 */


                                //Logging.Instance.WriteLine(isVoxel.ToString());
                                float distanceTotal   = 0f;
                                var   rainDropSize    = MyUtils.GetRandomFloat(0.8f, 1.5f);
                                var   randSkip        = MyUtils.GetRandomInt(8);
                                var   hasHit          = hitDist.Value > 0.001 && (hitDist.Value < lineCheck.Length || isVoxel);
                                var   dropsInDistance = hasHit ? hitDist.Value / rainDropSize : lineCheck.Length / rainDropSize;

                                //var nextStart = hasHit ? finalHitPos : lineStartPoint;
                                //var dir = hasHit ? -lineCheck.Direction : lineCheck.Direction;

                                var nextStart = hasHit ? finalHitPos : finalHitPos;
                                var dir       = hasHit ? -lineCheck.Direction : -lineCheck.Direction;

                                //var nextStart = hasHit && !checkVoxel ? finalHitPos : finalHitPos;
                                //var dir = hasHit && !checkVoxel ? -lineCheck.Direction : -lineCheck.Direction;

                                lineColor = checkVoxel ? Color.Green : Color.White;

                                if (checkVoxel && voxelHitName != null && _updateCount % 300 == 0)
                                {
                                    //LogVoxelHits(hitDist, voxelHitName, finalHitPos, lineCheck.Length);
                                }

                                while (distanceTotal < dropsInDistance)
                                {
                                    if (randSkip-- <= 0)
                                    {
                                        Droplet droplet;
                                        Droplets.AllocateOrCreate(out droplet);

                                        droplet.StartPoint = nextStart;
                                        droplet.Direction  = dir;
                                        droplet.DrawLength = rainDropSize;
                                        droplet.LineColor  = lineColor;
                                        randSkip           = MyUtils.GetRandomInt(8);
                                    }

                                    distanceTotal += rainDropSize;
                                    nextStart     += (dir * rainDropSize);
                                }
                            }
                        }
                    }
                }
            }
            catch (Exception e)
            {
                Logging.Instance.WriteLine(e.ToString());
            }
            DsWatch.Complete(true);
        }
Exemple #12
0
        /// <summary>
        /// Handles camera collisions with environment
        /// </summary>
        /// <param name="controlledEntity"></param>
        /// <param name="shakeActive"></param>
        /// <param name="headPosition"></param>
        /// <param name="headDirection"></param>
        /// <returns>False if no correct position was found</returns>
        private bool HandleIntersection(MyEntity controlledEntity, MyOrientedBoundingBoxD safeOBB, bool requireRaycast, bool shakeActive, Vector3D headPosition, Vector3 headDirection)
        {
            var line = new LineD(m_target, m_position);

            var      safeOBBLine = new LineD(line.From, line.From + line.Direction * 2 * safeOBB.HalfExtent.Length());
            Vector3D castStartSafe;

            {
                MyOrientedBoundingBoxD safeObbWithCollisionExtents = new MyOrientedBoundingBoxD(safeOBB.Center, safeOBB.HalfExtent + 2 * CAMERA_RADIUS, safeOBB.Orientation);
                double?safeIntersection = safeObbWithCollisionExtents.Intersects(ref safeOBBLine);
                if (!safeIntersection.HasValue)
                {
                    safeIntersection = safeOBB.HalfExtent.Length();
                }
                double safeDistance = safeIntersection.Value;
                castStartSafe = line.From + line.Direction * safeDistance;
            }

            {
                double?unsafeIntersection = safeOBB.Intersects(ref safeOBBLine);
                if (!requireRaycast && unsafeIntersection.HasValue)
                {
                    var castStartUnsafe = line.From + line.Direction * unsafeIntersection.Value;
                    var castEndUnsafe   = castStartSafe + line.Direction;
                    // short raycast, not causing problems with asteroids generating geometry
                    Physics.MyPhysics.CastRay(castStartUnsafe, castEndUnsafe, m_raycastList, MyPhysics.DefaultCollisionLayer);
                    if (!IsRaycastOK(m_raycastList))
                    {
                        return(false);
                    }
                }
            }

            if (requireRaycast)
            {
                // short raycast, not causing problems with asteroids generating geometry
                Physics.MyPhysics.CastRay(line.From, castStartSafe + line.Direction, m_raycastList, MyPhysics.DefaultCollisionLayer);
                if (!IsRaycastOK(m_raycastList))
                {
                    return(false);
                }
            }

            HkShape shape = new HkSphereShape(CAMERA_RADIUS);

            try
            {
                // small shape, not causing problems with asteroids generating geometry
                Physics.MyPhysics.GetPenetrationsShape(shape, ref castStartSafe, ref Quaternion.Identity, m_rigidList, 15);
                if (m_rigidList.Count > 0)
                {
                    bool sameGrid = false;
                    if (MySession.ControlledEntity != null && m_rigidList[0].Body != null)
                    {
                        sameGrid = m_rigidList[0].GetCollisionEntity() == MySession.ControlledEntity;
                    }

                    if (sameGrid)
                    {
                        castStartSafe += line.Direction;
                    }
                }

                var  shapeCastLine = new LineD(castStartSafe, m_position);
                uint steps         = 1;
                uint stepIdx       = 0;
                if (shapeCastLine.Length > SHAPE_CAST_STEP)
                {
                    steps = (uint)Math.Ceiling(shapeCastLine.Length / SHAPE_CAST_STEP);
                    if (steps >= SHAPE_CAST_MAX_STEP_COUNT)
                    {
                        steps = SHAPE_CAST_MAX_STEP_COUNT - 1;
                    }
                    stepIdx = m_updateCount % steps;
                    m_lastShapeCastDistance[stepIdx] = float.PositiveInfinity;

                    Vector3D step = shapeCastLine.Direction * (shapeCastLine.Length / steps);
                    shapeCastLine = new LineD(castStartSafe + stepIdx * step, castStartSafe + (stepIdx + 1) * step);
                }

                if (false)
                {
                    BoundingBoxD bbox = BoundingBoxD.CreateInvalid();
                    bbox.Include(new BoundingSphereD(shapeCastLine.From, CAMERA_RADIUS));
                    bbox.Include(new BoundingSphereD(shapeCastLine.To, CAMERA_RADIUS));
                    VRageRender.MyRenderProxy.DebugDrawAABB(bbox, Color.Crimson, 1f, 1f, true);
                }

                var matrix = MatrixD.CreateTranslation(shapeCastLine.From);
                HkContactPointData?cpd;
                if (controlledEntity.Physics != null && controlledEntity.Physics.CharacterProxy != null)
                {
                    cpd = MyPhysics.CastShapeReturnContactData(shapeCastLine.To, shape, ref matrix, controlledEntity.Physics.CharacterCollisionFilter, 0.0f);
                }
                else
                {
                    cpd = MyPhysics.CastShapeReturnContactData(shapeCastLine.To, shape, ref matrix, HkGroupFilter.CalcFilterInfo(MyPhysics.DefaultCollisionLayer, 0), 0.0f);
                }
                if (cpd.HasValue)
                {
                    var point = shapeCastLine.From + shapeCastLine.Direction * shapeCastLine.Length * cpd.Value.DistanceFraction;
                    m_lastShapeCastDistance[stepIdx] = (float)(castStartSafe - point).Length();
                }
                else
                {
                    m_lastShapeCastDistance[stepIdx] = float.PositiveInfinity;
                }


                float?dist = null;
                for (int i = 0; i < steps; ++i)
                {
                    if (m_lastShapeCastDistance[i] != float.PositiveInfinity)
                    {
                        dist = Math.Min(m_lastShapeCastDistance[i], dist ?? float.PositiveInfinity);
                    }
                }

                if (dist.HasValue)
                {
                    if (dist == 0.0f)
                    {
                        return(false);
                    }
                    else
                    {
                        m_positionSafe = castStartSafe + shapeCastLine.Direction * dist.Value;
                    }
                }
                else
                {
                    m_positionSafe = m_position;
                }
                return(true);
            }
            finally
            {
                shape.RemoveReference();
            }
        }
Exemple #13
0
        public void CalculateRotationHints(MatrixD drawMatrix, BoundingBoxD worldBox, bool draw, bool fixedAxes = false, bool hideForwardAndUpArrows = false)
        {
            Matrix  cameraView = MySector.MainCamera.ViewMatrix;
            MatrixD camWorld   = MatrixD.Invert(cameraView);

            camWorld.Translation = drawMatrix.Translation - 6 * camWorld.Forward;
            cameraView           = MatrixD.Invert(camWorld);

            m_viewProjection.View = cameraView;


            drawMatrix.Translation         -= camWorld.Translation;
            m_viewProjection.CameraPosition = camWorld.Translation;
            camWorld.Translation            = Vector3D.Zero;
            Matrix cameraViewAtZero = MatrixD.Transpose(camWorld);


            m_viewProjection.ViewAtZero = cameraViewAtZero;



            Vector2 screenSize = MyGuiManager.GetScreenSizeFromNormalizedSize(Vector2.One);
            float   previewRatio = 2.75f;
            int     hintsWidth = (int)(screenSize.X / previewRatio), hintsHeight = (int)(screenSize.Y / previewRatio), hintsXOffset = 0, hintsYOffset = 0;

            m_viewProjection.Viewport = new MyViewport(
                (int)MySector.MainCamera.Viewport.Width - hintsWidth - hintsXOffset,
                hintsYOffset,
                hintsWidth,
                hintsHeight);

            m_viewProjection.DepthRead  = false;
            m_viewProjection.Projection = Matrix.CreatePerspectiveFieldOfView(MathHelper.PiOver4, (float)hintsWidth / hintsHeight, 0.1f, 10);



            worldBox = new BoundingBoxD(-new Vector3(MyDefinitionManager.Static.GetCubeSize(MyCubeSize.Large) * 0.5f), new Vector3(MyDefinitionManager.Static.GetCubeSize(MyCubeSize.Large)) * 0.5f);


            //m_rotationHintsViewProjection.Projection = MySector.MainCamera.ProjectionMatrix;



            int projectionId = 0;

            VRageRender.MyRenderProxy.AddBillboardViewProjection(projectionId, m_viewProjection);

            //MySimpleObjectDraw.DrawTransparentBox(ref drawMatrix,
            //                ref worldBox, ref Vector4.One, MySimpleObjectRasterizer.Wireframe, 1, 0.04f, null, null, false, 0);
            if (draw)
            {
                var white = Color.White;
                var red   = Color.Red;
                MySimpleObjectDraw.DrawTransparentBox(ref drawMatrix,
                                                      ref worldBox, ref white, ref red, MySimpleObjectRasterizer.Solid, 1, 0.04f, "SquareFullColor", null, false, projectionId, 100);

                Vector2 hintText = new Vector2((int)(MySector.MainCamera.Viewport.Width - hintsWidth - hintsXOffset + hintsWidth / 2), hintsYOffset + 0.9f * hintsHeight);
                m_mountpointNotification.SetTextFormatArguments(MyInput.Static.GetGameControl(MyControlsSpace.CUBE_DEFAULT_MOUNTPOINT).GetControlButtonName(MyGuiInputDeviceEnum.Keyboard));
                VRageRender.MyRenderProxy.DebugDrawText2D(hintText, m_mountpointNotification.GetText(), Color.White, 1, MyGuiDrawAlignEnum.HORISONTAL_CENTER_AND_VERTICAL_TOP);
            }

            MyOrientedBoundingBoxD rotateHintsBox = new MyOrientedBoundingBoxD(Vector3D.Transform(worldBox.Center, drawMatrix), worldBox.HalfExtents, Quaternion.CreateFromRotationMatrix(drawMatrix));

            //VRageRender.MyRenderProxy.DebugDrawOBB(rotateHintsBox, Vector3.One, 1, false, false);


            rotateHintsBox.GetCorners(m_cubeVertices, 0);

            //for (int vi = 0; vi < 8; vi++)
            //{
            //    VRageRender.MyRenderProxy.DebugDrawText3D(m_cubeVertices[vi], vi.ToString(), Color.White, 0.7f, false);
            //}

            //for (int vi = 0; vi < 4; vi++)
            //{
            //    VRageRender.MyRenderProxy.DebugDrawText3D((m_cubeVertices[MyOrientedBoundingBox.StartXVertices[vi]] + m_cubeVertices[MyOrientedBoundingBox.EndXVertices[vi]]) * 0.5f, vi.ToString(), Color.Red, 0.7f, false);
            //    VRageRender.MyRenderProxy.DebugDrawText3D((m_cubeVertices[MyOrientedBoundingBox.StartYVertices[vi]] + m_cubeVertices[MyOrientedBoundingBox.EndYVertices[vi]]) * 0.5f, vi.ToString(), Color.Green, 0.7f, false);
            //    VRageRender.MyRenderProxy.DebugDrawText3D((m_cubeVertices[MyOrientedBoundingBox.StartZVertices[vi]] + m_cubeVertices[MyOrientedBoundingBox.EndZVertices[vi]]) * 0.5f, vi.ToString(), Color.Blue, 0.7f, false);
            //}

            int closestXAxis, closestXAxis2;

            GetClosestCubeEdge(m_cubeVertices, Vector3D.Zero, MyOrientedBoundingBox.StartXVertices, MyOrientedBoundingBox.EndXVertices, out closestXAxis, out closestXAxis2);
            Vector3D startXVertex  = m_cubeVertices[MyOrientedBoundingBox.StartXVertices[closestXAxis]];
            Vector3D endXVertex    = m_cubeVertices[MyOrientedBoundingBox.EndXVertices[closestXAxis]];
            Vector3D startXVertex2 = m_cubeVertices[MyOrientedBoundingBox.StartXVertices[closestXAxis2]];
            Vector3D endXVertex2   = m_cubeVertices[MyOrientedBoundingBox.EndXVertices[closestXAxis2]];

            int closestYAxis, closestYAxis2;

            GetClosestCubeEdge(m_cubeVertices, Vector3D.Zero, MyOrientedBoundingBox.StartYVertices, MyOrientedBoundingBox.EndYVertices, out closestYAxis, out closestYAxis2);
            Vector3D startYVertex  = m_cubeVertices[MyOrientedBoundingBox.StartYVertices[closestYAxis]];
            Vector3D endYVertex    = m_cubeVertices[MyOrientedBoundingBox.EndYVertices[closestYAxis]];
            Vector3D startYVertex2 = m_cubeVertices[MyOrientedBoundingBox.StartYVertices[closestYAxis2]];
            Vector3D endYVertex2   = m_cubeVertices[MyOrientedBoundingBox.EndYVertices[closestYAxis2]];

            int closestZAxis, closestZAxis2;

            GetClosestCubeEdge(m_cubeVertices, Vector3D.Zero, MyOrientedBoundingBox.StartZVertices, MyOrientedBoundingBox.EndZVertices, out closestZAxis, out closestZAxis2);
            Vector3D startZVertex  = m_cubeVertices[MyOrientedBoundingBox.StartZVertices[closestZAxis]];
            Vector3D endZVertex    = m_cubeVertices[MyOrientedBoundingBox.EndZVertices[closestZAxis]];
            Vector3D startZVertex2 = m_cubeVertices[MyOrientedBoundingBox.StartZVertices[closestZAxis2]];
            Vector3D endZVertex2   = m_cubeVertices[MyOrientedBoundingBox.EndZVertices[closestZAxis2]];

            m_cubeEdges.Clear();
            m_cubeEdges.Add(new BoxEdge()
            {
                Axis = 0, Edge = new LineD(startXVertex, endXVertex)
            });
            m_cubeEdges.Add(new BoxEdge()
            {
                Axis = 1, Edge = new LineD(startYVertex, endYVertex)
            });
            m_cubeEdges.Add(new BoxEdge()
            {
                Axis = 2, Edge = new LineD(startZVertex, endZVertex)
            });

            if (!fixedAxes)
            {
                int rotDirection;

                RotationRightAxis      = GetBestAxis(m_cubeEdges, MySector.MainCamera.WorldMatrix.Right, out rotDirection);
                RotationRightDirection = rotDirection;

                RotationUpAxis      = GetBestAxis(m_cubeEdges, MySector.MainCamera.WorldMatrix.Up, out rotDirection);
                RotationUpDirection = rotDirection;

                RotationForwardAxis      = GetBestAxis(m_cubeEdges, MySector.MainCamera.WorldMatrix.Forward, out rotDirection);
                RotationForwardDirection = rotDirection;
            }

            string rightControlName1 = MyInput.Static.GetGameControl(MyControlsSpace.CUBE_ROTATE_HORISONTAL_POSITIVE).GetControlButtonName(MyGuiInputDeviceEnum.Keyboard).ToString();
            string rightControlName2 = MyInput.Static.GetGameControl(MyControlsSpace.CUBE_ROTATE_HORISONTAL_NEGATIVE).GetControlButtonName(MyGuiInputDeviceEnum.Keyboard).ToString();
            string upControlName1    = MyInput.Static.GetGameControl(MyControlsSpace.CUBE_ROTATE_VERTICAL_POSITIVE).GetControlButtonName(MyGuiInputDeviceEnum.Keyboard).ToString();
            string upControlName2    = MyInput.Static.GetGameControl(MyControlsSpace.CUBE_ROTATE_VERTICAL_NEGATIVE).GetControlButtonName(MyGuiInputDeviceEnum.Keyboard).ToString();
            string forwControlName1  = MyInput.Static.GetGameControl(MyControlsSpace.CUBE_ROTATE_ROLL_POSITIVE).GetControlButtonName(MyGuiInputDeviceEnum.Keyboard).ToString();
            string forwControlName2  = MyInput.Static.GetGameControl(MyControlsSpace.CUBE_ROTATE_ROLL_NEGATIVE).GetControlButtonName(MyGuiInputDeviceEnum.Keyboard).ToString();

            if (MyInput.Static.IsJoystickConnected())
            {
                rightControlName1 = MyControllerHelper.GetCodeForControl(MySpaceBindingCreator.CX_BUILD_MODE, MyControlsSpace.CUBE_ROTATE_HORISONTAL_POSITIVE).ToString();
                rightControlName2 = MyControllerHelper.GetCodeForControl(MySpaceBindingCreator.CX_BUILD_MODE, MyControlsSpace.CUBE_ROTATE_HORISONTAL_NEGATIVE).ToString();
                upControlName1    = MyControllerHelper.GetCodeForControl(MySpaceBindingCreator.CX_BUILD_MODE, MyControlsSpace.CUBE_ROTATE_VERTICAL_POSITIVE).ToString();
                upControlName2    = MyControllerHelper.GetCodeForControl(MySpaceBindingCreator.CX_BUILD_MODE, MyControlsSpace.CUBE_ROTATE_VERTICAL_NEGATIVE).ToString();
                forwControlName1  = MyControllerHelper.GetCodeForControl(MySpaceBindingCreator.CX_BUILD_MODE, MyControlsSpace.CUBE_ROTATE_ROLL_POSITIVE).ToString();
                forwControlName2  = MyControllerHelper.GetCodeForControl(MySpaceBindingCreator.CX_BUILD_MODE, MyControlsSpace.CUBE_ROTATE_ROLL_NEGATIVE).ToString();
            }

            Vector3D rightStart = Vector3D.Zero;
            Vector3D rightEnd = Vector3D.Zero;
            Vector3D upStart = Vector3D.Zero;
            Vector3D upEnd = Vector3D.Zero;
            Vector3D forwStart = Vector3D.Zero;
            Vector3D forwEnd = Vector3D.Zero;
            Vector3D rightStart2 = Vector3D.Zero;
            Vector3D rightEnd2 = Vector3D.Zero;
            Vector3D upStart2 = Vector3D.Zero;
            Vector3D upEnd2 = Vector3D.Zero;
            Vector3D forwStart2 = Vector3D.Zero;
            Vector3D forwEnd2 = Vector3D.Zero;
            int      rightAxis = -1, upAxis = -1, forwAxis = -1;
            int      closestRightEdge = -1, closestUpEdge = -1, closestForwEdge = -1;
            int      closestRightEdge2 = -1, closestUpEdge2 = -1, closestForwEdge2 = -1;

            if (RotationRightAxis == 0)
            {
                rightStart        = startXVertex;
                rightEnd          = endXVertex;
                rightStart2       = startXVertex2;
                rightEnd2         = endXVertex2;
                rightAxis         = 0;
                closestRightEdge  = closestXAxis;
                closestRightEdge2 = closestXAxis2;
            }
            else
            if (RotationRightAxis == 1)
            {
                rightStart        = startYVertex;
                rightEnd          = endYVertex;
                rightStart2       = startYVertex2;
                rightEnd2         = endYVertex2;
                rightAxis         = 1;
                closestRightEdge  = closestYAxis;
                closestRightEdge2 = closestYAxis2;
            }
            else
            if (RotationRightAxis == 2)
            {
                rightStart        = startZVertex;
                rightEnd          = endZVertex;
                rightStart2       = startZVertex2;
                rightEnd2         = endZVertex2;
                rightAxis         = 2;
                closestRightEdge  = closestZAxis;
                closestRightEdge2 = closestZAxis2;
            }
            else
            {
                System.Diagnostics.Debug.Assert(false, "Not defined axis");
            }

            if (RotationUpAxis == 0)
            {
                upStart        = startXVertex;
                upEnd          = endXVertex;
                upStart2       = startXVertex2;
                upEnd2         = endXVertex2;
                upAxis         = 0;
                closestUpEdge  = closestXAxis;
                closestUpEdge2 = closestXAxis2;
            }
            else
            if (RotationUpAxis == 1)
            {
                upStart        = startYVertex;
                upEnd          = endYVertex;
                upStart2       = startYVertex2;
                upEnd2         = endYVertex2;
                upAxis         = 1;
                closestUpEdge  = closestYAxis;
                closestUpEdge2 = closestYAxis2;
            }
            else
            if (RotationUpAxis == 2)
            {
                upStart        = startZVertex;
                upEnd          = endZVertex;
                upStart2       = startZVertex2;
                upEnd2         = endZVertex2;
                upAxis         = 2;
                closestUpEdge  = closestZAxis;
                closestUpEdge2 = closestZAxis2;
            }

            if (RotationForwardAxis == 0)
            {
                forwStart        = startXVertex;
                forwEnd          = endXVertex;
                forwStart2       = startXVertex2;
                forwEnd2         = endXVertex2;
                forwAxis         = 0;
                closestForwEdge  = closestXAxis;
                closestForwEdge2 = closestXAxis2;
            }
            else
            if (RotationForwardAxis == 1)
            {
                forwStart        = startYVertex;
                forwEnd          = endYVertex;
                forwStart2       = startYVertex2;
                forwEnd2         = endYVertex2;
                forwAxis         = 1;
                closestForwEdge  = closestYAxis;
                closestForwEdge2 = closestYAxis2;
            }
            else
            if (RotationForwardAxis == 2)
            {
                forwStart        = startZVertex;
                forwEnd          = endZVertex;
                forwStart2       = startZVertex2;
                forwEnd2         = endZVertex2;
                forwAxis         = 2;
                closestForwEdge  = closestZAxis;
                closestForwEdge2 = closestZAxis2;
            }

            float textScale = 0.7f;

            //Closest axis
            //VRageRender.MyRenderProxy.DebugDrawLine3D(rightStart, rightEnd, Color.Red, Color.Red, false);
            //VRageRender.MyRenderProxy.DebugDrawLine3D(upStart, upEnd, Color.Green, Color.Green, false);
            //VRageRender.MyRenderProxy.DebugDrawLine3D(forwStart, forwEnd, Color.Blue, Color.Blue, false);


            if (draw)
            {
                //if all axis are visible, all are shown on edges
                //if 1 axis is not visible, other 2 must be shown on faces
                //if 2 are not visible, they are shown on faces and the one is shown on face center
                //Vector3 camVector = Vector3.Normalize(rotateHintsBox.Center - MySector.MainCamera.Position);
                Vector3D camVector      = MySector.MainCamera.ForwardVector;
                Vector3D rightDirection = Vector3.Normalize(rightEnd - rightStart);
                Vector3D upDirection    = Vector3.Normalize(upEnd - upStart);
                Vector3D forwDirection  = Vector3.Normalize(forwEnd - forwStart);
                float    dotRight       = Math.Abs(Vector3.Dot(camVector, rightDirection));
                float    dotUp          = Math.Abs(Vector3.Dot(camVector, upDirection));
                float    dotForw        = Math.Abs(Vector3.Dot(camVector, forwDirection));

                bool drawRightOnFace = false, drawUpOnFace = false, drawForwOnFace = false;
                bool drawRightOnFaceCenter = false, drawUpOnFaceCenter = false, drawForwOnFaceCenter = false;

                float dotAngle = 0.4f;

                if (dotRight < dotAngle)
                {
                    if (dotUp < dotAngle)
                    {
                        drawForwOnFaceCenter = true;
                        drawRightOnFace      = true;
                        drawUpOnFace         = true;

                        System.Diagnostics.Debug.Assert(dotForw >= dotAngle);
                    }
                    else if (dotForw < dotAngle)
                    {
                        drawUpOnFaceCenter = true;
                        drawRightOnFace    = true;
                        drawForwOnFace     = true;

                        System.Diagnostics.Debug.Assert(dotUp >= dotAngle);
                    }
                    else
                    {
                        drawUpOnFace   = true;
                        drawForwOnFace = true;
                    }
                }
                else
                if (dotUp < dotAngle)
                {
                    if (dotRight < dotAngle)
                    {
                        drawForwOnFaceCenter = true;
                        drawRightOnFace      = true;
                        drawUpOnFace         = true;

                        System.Diagnostics.Debug.Assert(dotForw >= dotAngle);
                    }
                    else if (dotForw < dotAngle)
                    {
                        drawRightOnFaceCenter = true;
                        drawUpOnFace          = true;
                        drawForwOnFace        = true;

                        System.Diagnostics.Debug.Assert(dotRight >= dotAngle);
                    }
                    else
                    {
                        drawRightOnFace = true;
                        drawForwOnFace  = true;
                    }
                }
                else
                if (dotForw < dotAngle)
                {
                    if (dotRight < dotAngle)
                    {
                        drawUpOnFaceCenter = true;
                        drawRightOnFace    = true;
                        drawForwOnFace     = true;

                        System.Diagnostics.Debug.Assert(dotUp >= dotAngle);
                    }
                    else if (dotUp < dotAngle)
                    {
                        drawUpOnFaceCenter = true;
                        drawRightOnFace    = true;
                        drawForwOnFace     = true;

                        System.Diagnostics.Debug.Assert(dotRight >= dotAngle);
                    }
                    else
                    {
                        drawUpOnFace    = true;
                        drawRightOnFace = true;
                    }
                }

                //Draw according to cube visual appearance

                if (!(hideForwardAndUpArrows && RotationRightAxis != 1))
                {
                    if (drawRightOnFaceCenter)
                    {
                        //                VRageRender.MyRenderProxy.DebugDrawSphere((forwStart + forwEnd + forwStart2 + forwEnd2) * 0.25f, 0.2f, Vector3.Right, 1.0f, false, false);
                        Vector3D faceCenter = (forwStart + forwEnd + forwStart2 + forwEnd2) * 0.25f;

                        MyTransparentGeometry.AddBillboardOriented(
                            "ArrowLeftGreen",
                            Vector4.One,
                            faceCenter - RotationForwardDirection * forwDirection * 0.2f - RotationRightDirection * rightDirection * 0.01f,
                            -RotationForwardDirection * forwDirection,
                            -RotationUpDirection * upDirection,
                            0.2f,
                            110, false, projectionId);

                        MyTransparentGeometry.AddBillboardOriented(
                            "ArrowRightGreen",
                            Vector4.One,
                            faceCenter + RotationForwardDirection * forwDirection * 0.2f - RotationRightDirection * rightDirection * 0.01f,
                            RotationForwardDirection * forwDirection,
                            RotationUpDirection * upDirection,
                            0.2f,
                            110, false, projectionId);

                        VRageRender.MyRenderProxy.DebugDrawText3D(faceCenter - RotationForwardDirection * forwDirection * 0.2f - RotationRightDirection * rightDirection * 0.01f, rightControlName2, Color.White, textScale, false, MyGuiDrawAlignEnum.HORISONTAL_CENTER_AND_VERTICAL_CENTER, projectionId);
                        VRageRender.MyRenderProxy.DebugDrawText3D(faceCenter + RotationForwardDirection * forwDirection * 0.2f - RotationRightDirection * rightDirection * 0.01f, rightControlName1, Color.White, textScale, false, MyGuiDrawAlignEnum.HORISONTAL_CENTER_AND_VERTICAL_CENTER, projectionId);
                    }
                    else
                    if (drawRightOnFace)
                    {
                        //VRageRender.MyRenderProxy.DebugDrawLine3D(rightStart2, rightEnd2, Color.Red, Color.Red, false);

                        Vector3 normalRightBack, normalRightForw;
                        MyOrientedBoundingBox.GetNormalBetweenEdges(rightAxis, closestRightEdge, closestRightEdge2, out normalRightForw);
                        Vector3D rightCenter          = (rightStart + rightEnd) * 0.5f;
                        Vector3D rightNormalForwWorld = Vector3D.TransformNormal(normalRightForw, drawMatrix);

                        MyOrientedBoundingBox.GetNormalBetweenEdges(rightAxis, closestRightEdge2, closestRightEdge, out normalRightBack);
                        Vector3D rightCenter2         = (rightStart2 + rightEnd2) * 0.5f;
                        Vector3D rightNormalBackWorld = Vector3D.TransformNormal(normalRightBack, drawMatrix);

                        //VRageRender.MyRenderProxy.DebugDrawLine3D(rightCenter, rightCenter + rightNormalForwWorld, Color.Red, Color.Red, false);
                        //VRageRender.MyRenderProxy.DebugDrawLine3D(rightCenter2, rightCenter2 + rightNormalBackWorld, Color.Red, Color.Red, false);

                        int  normalEdge = -1;
                        bool opposite   = false;
                        if (closestRightEdge == 0 && closestRightEdge2 == 3)
                        {
                            normalEdge = closestRightEdge + 1;
                        }
                        else
                        if ((closestRightEdge < closestRightEdge2) || (closestRightEdge == 3 && closestRightEdge2 == 0))
                        {
                            normalEdge = closestRightEdge - 1;
                            opposite   = true;
                        }
                        else
                        {
                            normalEdge = closestRightEdge + 1;
                        }

                        if (RotationRightDirection < 0)
                        {
                            opposite = !opposite;
                        }

                        Vector3 rightOffset;
                        MyOrientedBoundingBox.GetNormalBetweenEdges(rightAxis, closestRightEdge, normalEdge, out rightOffset);
                        Vector3D rightOffsetWorld = Vector3D.TransformNormal(rightOffset, drawMatrix);

                        //VRageRender.MyRenderProxy.DebugDrawText3D(rightCenter + rightNormalForwWorld * 0.6f - rightOffsetWorld * 0.01f, opposite ? rightControlName2 : rightControlName1, Color.White, textScale, false);
                        //VRageRender.MyRenderProxy.DebugDrawText3D(rightCenter2 + rightNormalBackWorld * 0.6f - rightOffsetWorld * 0.01f, opposite ? rightControlName1 : rightControlName2, Color.White, textScale, false);

                        MyTransparentGeometry.AddBillboardOriented(
                            "ArrowGreen",
                            Vector4.One,
                            rightCenter + rightNormalForwWorld * 0.4f - rightOffsetWorld * 0.01f,
                            rightNormalBackWorld,
                            rightDirection,
                            0.5f,
                            110, false, projectionId);

                        MyTransparentGeometry.AddBillboardOriented(
                            "ArrowGreen",
                            Vector4.One,
                            rightCenter2 + rightNormalBackWorld * 0.4f - rightOffsetWorld * 0.01f,
                            rightNormalForwWorld,
                            rightDirection,
                            0.5f,
                            110, false, projectionId);

                        VRageRender.MyRenderProxy.DebugDrawText3D(rightCenter + rightNormalForwWorld * 0.3f - rightOffsetWorld * 0.01f, opposite ? rightControlName1 : rightControlName2, Color.White, textScale, false, MyGuiDrawAlignEnum.HORISONTAL_CENTER_AND_VERTICAL_CENTER, projectionId);
                        VRageRender.MyRenderProxy.DebugDrawText3D(rightCenter2 + rightNormalBackWorld * 0.3f - rightOffsetWorld * 0.01f, opposite ? rightControlName2 : rightControlName1, Color.White, textScale, false, MyGuiDrawAlignEnum.HORISONTAL_CENTER_AND_VERTICAL_CENTER, projectionId);
                    }
                    else     //draw on edge
                    {
                        Vector3 normalRightBack, normalRightForw;
                        MyOrientedBoundingBox.GetNormalBetweenEdges(rightAxis, closestRightEdge, closestRightEdge + 1, out normalRightForw);
                        MyOrientedBoundingBox.GetNormalBetweenEdges(rightAxis, closestRightEdge, closestRightEdge - 1, out normalRightBack);
                        Vector3D rightCenter          = (rightStart + rightEnd) * 0.5f;
                        Vector3D rightNormalForwWorld = Vector3D.TransformNormal(normalRightForw, drawMatrix);
                        Vector3D rightNormalBackWorld = Vector3D.TransformNormal(normalRightBack, drawMatrix);
                        //VRageRender.MyRenderProxy.DebugDrawLine3D(rightCenter, rightCenter + rightNormalForwWorld, Color.Red, Color.Red, false);
                        //VRageRender.MyRenderProxy.DebugDrawLine3D(rightCenter, rightCenter + rightNormalBackWorld, Color.Red, Color.Red, false);

                        MyTransparentGeometry.AddBillboardOriented(
                            "ArrowGreen",
                            Vector4.One,
                            rightCenter + rightNormalForwWorld * 0.3f - rightNormalBackWorld * 0.01f,
                            rightNormalForwWorld,
                            rightDirection,
                            0.5f,
                            110, false, projectionId);

                        MyTransparentGeometry.AddBillboardOriented(
                            "ArrowGreen",
                            Vector4.One,
                            rightCenter + rightNormalBackWorld * 0.3f - rightNormalForwWorld * 0.01f,
                            rightNormalBackWorld,
                            rightDirection,
                            0.5f,
                            110, false, projectionId);

                        VRageRender.MyRenderProxy.DebugDrawText3D(rightCenter + rightNormalForwWorld * 0.3f - rightNormalBackWorld * 0.01f, RotationRightDirection < 0 ? rightControlName1 : rightControlName2, Color.White, textScale, false, MyGuiDrawAlignEnum.HORISONTAL_CENTER_AND_VERTICAL_CENTER, projectionId);
                        VRageRender.MyRenderProxy.DebugDrawText3D(rightCenter + rightNormalBackWorld * 0.3f - rightNormalForwWorld * 0.01f, RotationRightDirection < 0 ? rightControlName2 : rightControlName1, Color.White, textScale, false, MyGuiDrawAlignEnum.HORISONTAL_CENTER_AND_VERTICAL_CENTER, projectionId);
                    }
                }

                if (!(hideForwardAndUpArrows && RotationUpAxis != 1))
                {
                    if (drawUpOnFaceCenter)
                    {
                        //VRageRender.MyRenderProxy.DebugDrawSphere((forwStart + forwEnd + forwStart2 + forwEnd2) * 0.25f, 0.2f, Vector3.Up, 1.0f, false, false);

                        Vector3D faceCenter = (forwStart + forwEnd + forwStart2 + forwEnd2) * 0.25f;

                        MyTransparentGeometry.AddBillboardOriented(
                            "ArrowLeftRed",
                            Vector4.One,
                            faceCenter - RotationRightDirection * rightDirection * 0.2f - RotationUpDirection * upDirection * 0.01f,
                            -RotationRightDirection * rightDirection,
                            -RotationForwardDirection * forwDirection,
                            0.2f,
                            110, false, projectionId);

                        MyTransparentGeometry.AddBillboardOriented(
                            "ArrowRightRed",
                            Vector4.One,
                            faceCenter + RotationRightDirection * rightDirection * 0.2f - RotationUpDirection * upDirection * 0.01f,
                            RotationRightDirection * rightDirection,
                            RotationForwardDirection * forwDirection,
                            0.2f,
                            110, false, projectionId);

                        VRageRender.MyRenderProxy.DebugDrawText3D(faceCenter - RotationRightDirection * rightDirection * 0.2f - RotationUpDirection * upDirection * 0.01f, upControlName1, Color.White, textScale, false, MyGuiDrawAlignEnum.HORISONTAL_CENTER_AND_VERTICAL_CENTER, projectionId);
                        VRageRender.MyRenderProxy.DebugDrawText3D(faceCenter + RotationRightDirection * rightDirection * 0.2f - RotationUpDirection * upDirection * 0.01f, upControlName2, Color.White, textScale, false, MyGuiDrawAlignEnum.HORISONTAL_CENTER_AND_VERTICAL_CENTER, projectionId);
                    }
                    else
                    if (drawUpOnFace)
                    {
                        //VRageRender.MyRenderProxy.DebugDrawLine3D(upStart2, upEnd2, Color.Green, Color.Green, false);

                        Vector3 normalUpBack, normalUpForw;
                        MyOrientedBoundingBox.GetNormalBetweenEdges(upAxis, closestUpEdge, closestUpEdge2, out normalUpForw);
                        Vector3D upCenter          = (upStart + upEnd) * 0.5f;
                        Vector3  upNormalForwWorld = Vector3.TransformNormal(normalUpForw, drawMatrix);

                        MyOrientedBoundingBox.GetNormalBetweenEdges(upAxis, closestUpEdge2, closestUpEdge, out normalUpBack);
                        Vector3D upCenter2         = (upStart2 + upEnd2) * 0.5f;
                        Vector3  upNormalBackWorld = Vector3.TransformNormal(normalUpBack, drawMatrix);

                        //VRageRender.MyRenderProxy.DebugDrawLine3D(upCenter, upCenter + upNormalForwWorld, Color.Green, Color.Green, false);
                        //VRageRender.MyRenderProxy.DebugDrawLine3D(upCenter2, upCenter2 + upNormalBackWorld, Color.Green, Color.Green, false);

                        int  normalEdge = -1;
                        bool opposite   = false;
                        if (closestUpEdge == 0 && closestUpEdge2 == 3)
                        {
                            normalEdge = closestUpEdge + 1;
                        }
                        else
                        if ((closestUpEdge < closestUpEdge2) || (closestUpEdge == 3 && closestUpEdge2 == 0))
                        {
                            normalEdge = closestUpEdge - 1;
                            opposite   = true;
                        }
                        else
                        {
                            normalEdge = closestUpEdge + 1;
                        }

                        if (RotationUpDirection < 0)
                        {
                            opposite = !opposite;
                        }

                        Vector3 upOffset;
                        MyOrientedBoundingBox.GetNormalBetweenEdges(upAxis, closestUpEdge, normalEdge, out upOffset);
                        Vector3 upOffsetWorld = Vector3.TransformNormal(upOffset, drawMatrix);

                        //VRageRender.MyRenderProxy.DebugDrawText3D(upCenter + upNormalForwWorld * 0.6f - upOffsetWorld * 0.01f, opposite ? upControlName1 : upControlName2, Color.White, textScale, false);
                        //VRageRender.MyRenderProxy.DebugDrawText3D(upCenter2 + upNormalBackWorld * 0.6f - upOffsetWorld * 0.01f, opposite ? upControlName2 : upControlName1, Color.White, textScale, false);

                        MyTransparentGeometry.AddBillboardOriented(
                            "ArrowRed",
                            Vector4.One,
                            upCenter + upNormalForwWorld * 0.4f - upOffsetWorld * 0.01f,
                            upNormalBackWorld,
                            upDirection,
                            0.5f,
                            110, false, projectionId);

                        MyTransparentGeometry.AddBillboardOriented(
                            "ArrowRed",
                            Vector4.One,
                            upCenter2 + upNormalBackWorld * 0.4f - upOffsetWorld * 0.01f,
                            upNormalForwWorld,
                            upDirection,
                            0.5f,
                            110, false, projectionId);

                        VRageRender.MyRenderProxy.DebugDrawText3D(upCenter + upNormalForwWorld * 0.3f - upOffsetWorld * 0.01f, opposite ? upControlName2 : upControlName1, Color.White, textScale, false, MyGuiDrawAlignEnum.HORISONTAL_CENTER_AND_VERTICAL_CENTER, projectionId);
                        VRageRender.MyRenderProxy.DebugDrawText3D(upCenter2 + upNormalBackWorld * 0.3f - upOffsetWorld * 0.01f, opposite ? upControlName1 : upControlName2, Color.White, textScale, false, MyGuiDrawAlignEnum.HORISONTAL_CENTER_AND_VERTICAL_CENTER, projectionId);
                    }
                    else     //draw on edge
                    {
                        Vector3 normalUpBack, normalUpForw;
                        MyOrientedBoundingBox.GetNormalBetweenEdges(upAxis, closestUpEdge, closestUpEdge + 1, out normalUpForw);
                        MyOrientedBoundingBox.GetNormalBetweenEdges(upAxis, closestUpEdge, closestUpEdge - 1, out normalUpBack);
                        Vector3D upCenter          = (upStart + upEnd) * 0.5f;
                        Vector3  upNormalForwWorld = Vector3.TransformNormal(normalUpForw, drawMatrix);
                        Vector3  upNormalBackWorld = Vector3.TransformNormal(normalUpBack, drawMatrix);
                        //VRageRender.MyRenderProxy.DebugDrawLine3D(upCenter, upCenter + upNormalForwWorld, Color.Green, Color.Green, false);
                        //VRageRender.MyRenderProxy.DebugDrawLine3D(upCenter, upCenter + upNormalBackWorld, Color.Green, Color.Green, false);

                        MyTransparentGeometry.AddBillboardOriented(
                            "ArrowRed",
                            Vector4.One,
                            upCenter + upNormalForwWorld * 0.3f - upNormalBackWorld * 0.01f,
                            upNormalForwWorld,
                            upDirection,
                            0.5f,
                            110, false, projectionId);

                        MyTransparentGeometry.AddBillboardOriented(
                            "ArrowRed",
                            Vector4.One,
                            upCenter + upNormalBackWorld * 0.3f - upNormalForwWorld * 0.01f,
                            upNormalBackWorld,
                            upDirection,
                            0.5f,
                            110, false, projectionId);

                        VRageRender.MyRenderProxy.DebugDrawText3D(upCenter + upNormalForwWorld * 0.6f - upNormalBackWorld * 0.01f, RotationUpDirection > 0 ? upControlName1 : upControlName2, Color.White, textScale, false, MyGuiDrawAlignEnum.HORISONTAL_CENTER_AND_VERTICAL_CENTER, projectionId);
                        VRageRender.MyRenderProxy.DebugDrawText3D(upCenter + upNormalBackWorld * 0.6f - upNormalForwWorld * 0.01f, RotationUpDirection > 0 ? upControlName2 : upControlName1, Color.White, textScale, false, MyGuiDrawAlignEnum.HORISONTAL_CENTER_AND_VERTICAL_CENTER, projectionId);
                    }
                }

                if (!(hideForwardAndUpArrows && RotationForwardAxis != 1))
                {
                    if (drawForwOnFaceCenter)
                    {
                        //VRageRender.MyRenderProxy.DebugDrawSphere((rightStart + rightEnd + rightStart2 + rightEnd2) * 0.25f, 0.2f, Vector3.Backward, 1.0f, false, false);

                        Vector3D faceCenter = (rightStart + rightEnd + rightStart2 + rightEnd2) * 0.25f;

                        MyTransparentGeometry.AddBillboardOriented(
                            "ArrowLeftBlue",
                            Vector4.One,
                            faceCenter + RotationUpDirection * upDirection * 0.2f - RotationForwardDirection * forwDirection * 0.01f,
                            RotationUpDirection * upDirection,
                            -RotationRightDirection * rightDirection,
                            0.2f,
                            110, false, projectionId);

                        MyTransparentGeometry.AddBillboardOriented(
                            "ArrowRightBlue",
                            Vector4.One,
                            faceCenter - RotationUpDirection * upDirection * 0.2f - RotationForwardDirection * forwDirection * 0.01f,
                            -RotationUpDirection * upDirection,
                            RotationRightDirection * rightDirection,
                            0.2f,
                            110, false, projectionId);

                        VRageRender.MyRenderProxy.DebugDrawText3D(faceCenter + RotationUpDirection * upDirection * 0.2f - RotationForwardDirection * forwDirection * 0.01f, forwControlName1, Color.White, textScale, false, MyGuiDrawAlignEnum.HORISONTAL_LEFT_AND_VERTICAL_CENTER, projectionId);
                        VRageRender.MyRenderProxy.DebugDrawText3D(faceCenter - RotationUpDirection * upDirection * 0.2f - RotationForwardDirection * forwDirection * 0.01f, forwControlName2, Color.White, textScale, false, MyGuiDrawAlignEnum.HORISONTAL_LEFT_AND_VERTICAL_CENTER, projectionId);
                    }
                    else
                    if (drawForwOnFace)
                    {
                        //VRageRender.MyRenderProxy.DebugDrawLine3D(forwStart2, forwEnd2, Color.Blue, Color.Blue, false);

                        Vector3 normalForwBack, normalForwForw;
                        MyOrientedBoundingBox.GetNormalBetweenEdges(forwAxis, closestForwEdge, closestForwEdge2, out normalForwForw);
                        Vector3D forwCenter          = (forwStart + forwEnd) * 0.5f;
                        Vector3  forwNormalForwWorld = Vector3.TransformNormal(normalForwForw, drawMatrix);

                        MyOrientedBoundingBox.GetNormalBetweenEdges(forwAxis, closestForwEdge2, closestForwEdge, out normalForwBack);
                        Vector3D forwCenter2         = (forwStart2 + forwEnd2) * 0.5f;
                        Vector3  forwNormalBackWorld = Vector3.TransformNormal(normalForwBack, drawMatrix);

                        //VRageRender.MyRenderProxy.DebugDrawLine3D(forwCenter, forwCenter + forwNormalForwWorld, Color.Blue, Color.Blue, false);
                        //VRageRender.MyRenderProxy.DebugDrawLine3D(forwCenter2, forwCenter2 + forwNormalBackWorld, Color.Blue, Color.Blue, false);

                        int  normalEdge = -1;
                        bool opposite   = false;
                        if (closestForwEdge == 0 && closestForwEdge2 == 3)
                        {
                            normalEdge = closestForwEdge + 1;
                        }
                        else
                        if ((closestForwEdge < closestForwEdge2) || (closestForwEdge == 3 && closestForwEdge2 == 0))
                        {
                            normalEdge = closestForwEdge - 1;
                            opposite   = true;
                        }
                        else
                        {
                            normalEdge = closestForwEdge + 1;
                        }

                        if (RotationForwardDirection < 0)
                        {
                            opposite = !opposite;
                        }

                        Vector3 forwOffset;
                        MyOrientedBoundingBox.GetNormalBetweenEdges(forwAxis, closestForwEdge, normalEdge, out forwOffset);
                        Vector3 forwOffsetWorld = Vector3.TransformNormal(forwOffset, drawMatrix);

                        //VRageRender.MyRenderProxy.DebugDrawText3D(forwCenter + forwNormalForwWorld * 0.6f - forwOffsetWorld * 0.01f, opposite ? forwControlName2 : forwControlName1, Color.White, textScale, false);
                        //VRageRender.MyRenderProxy.DebugDrawText3D(forwCenter2 + forwNormalBackWorld * 0.6f - forwOffsetWorld * 0.01f, opposite ? forwControlName1 : forwControlName2, Color.White, textScale, false);

                        MyTransparentGeometry.AddBillboardOriented(
                            "ArrowBlue",
                            Vector4.One,
                            forwCenter + forwNormalForwWorld * 0.4f - forwOffsetWorld * 0.01f,
                            forwNormalBackWorld,
                            forwDirection,
                            0.5f,
                            110, false, projectionId);

                        MyTransparentGeometry.AddBillboardOriented(
                            "ArrowBlue",
                            Vector4.One,
                            forwCenter2 + forwNormalBackWorld * 0.4f - forwOffsetWorld * 0.01f,
                            forwNormalForwWorld,
                            forwDirection,
                            0.5f,
                            110, false, projectionId);

                        VRageRender.MyRenderProxy.DebugDrawText3D(forwCenter + forwNormalForwWorld * 0.3f - forwOffsetWorld * 0.01f, opposite ? forwControlName1 : forwControlName2, Color.White, textScale, false, MyGuiDrawAlignEnum.HORISONTAL_CENTER_AND_VERTICAL_CENTER, projectionId);
                        VRageRender.MyRenderProxy.DebugDrawText3D(forwCenter2 + forwNormalBackWorld * 0.3f - forwOffsetWorld * 0.01f, opposite ? forwControlName2 : forwControlName1, Color.White, textScale, false, MyGuiDrawAlignEnum.HORISONTAL_CENTER_AND_VERTICAL_CENTER, projectionId);
                    }
                    else     //draw on edge
                    {
                        Vector3 normalForwBack, normalForwForw;
                        MyOrientedBoundingBox.GetNormalBetweenEdges(forwAxis, closestForwEdge, closestForwEdge + 1, out normalForwForw);
                        MyOrientedBoundingBox.GetNormalBetweenEdges(forwAxis, closestForwEdge, closestForwEdge - 1, out normalForwBack);
                        Vector3D forwCenter          = (forwStart + forwEnd) * 0.5f;
                        Vector3  forwNormalForwWorld = Vector3.TransformNormal(normalForwForw, drawMatrix);
                        Vector3  forwNormalBackWorld = Vector3.TransformNormal(normalForwBack, drawMatrix);
                        //VRageRender.MyRenderProxy.DebugDrawLine3D(forwCenter, forwCenter + forwNormalForwWorld, Color.Blue, Color.Blue, false);
                        //VRageRender.MyRenderProxy.DebugDrawLine3D(forwCenter, forwCenter + forwNormalBackWorld, Color.Blue, Color.Blue, false);

                        MyTransparentGeometry.AddBillboardOriented(
                            "ArrowBlue",
                            Vector4.One,
                            forwCenter + forwNormalForwWorld * 0.3f - forwNormalBackWorld * 0.01f,
                            forwNormalForwWorld,
                            forwDirection,
                            0.5f,
                            110, false, projectionId);

                        MyTransparentGeometry.AddBillboardOriented(
                            "ArrowBlue",
                            Vector4.One,
                            forwCenter + forwNormalBackWorld * 0.3f - forwNormalForwWorld * 0.01f,
                            forwNormalBackWorld,
                            forwDirection,
                            0.5f,
                            110, false, projectionId);

                        VRageRender.MyRenderProxy.DebugDrawText3D(forwCenter + forwNormalForwWorld * 0.3f - forwNormalBackWorld * 0.01f, RotationForwardDirection < 0 ? forwControlName1 : forwControlName2, Color.White, textScale, false, MyGuiDrawAlignEnum.HORISONTAL_CENTER_AND_VERTICAL_CENTER, projectionId);
                        VRageRender.MyRenderProxy.DebugDrawText3D(forwCenter + forwNormalBackWorld * 0.3f - forwNormalForwWorld * 0.01f, RotationForwardDirection < 0 ? forwControlName2 : forwControlName1, Color.White, textScale, false, MyGuiDrawAlignEnum.HORISONTAL_CENTER_AND_VERTICAL_CENTER, projectionId);
                    }
                }
            }
        }
        public bool IsCameraPositionOk(Matrix worldMatrix)
        {
            IMyCameraController cameraController = MySession.Static.CameraController;
            if (cameraController == null)
                return true;

            MyEntity topControlledEntity = ((MyEntity)cameraController).GetTopMostParent();
            if (topControlledEntity.Closed) return false;

            var localAABBHr = topControlledEntity.PositionComp.LocalAABBHr;
            Vector3D center = Vector3D.Transform((Vector3D)localAABBHr.Center, worldMatrix);

            var safeOBB = new MyOrientedBoundingBoxD(center, localAABBHr.HalfExtents, Quaternion.CreateFromRotationMatrix(worldMatrix.GetOrientation()));
            //VRageRender.MyRenderProxy.DebugDrawOBB(safeOBB, Vector3.One, 1, false, false);
            //VRageRender.MyRenderProxy.DebugDrawAxis(topControlledEntity.WorldMatrix, 2, false);

            bool camPosIsOk = HandleIntersection(topControlledEntity, safeOBB, topControlledEntity is Sandbox.Game.Entities.Character.MyCharacter, true, m_target, m_targetOrientation.Forward);

            return camPosIsOk;
        }
            public override void Draw()
            {
                base.Draw();

                if (m_showVoxelProbe)
                {
                    float halfSize = m_probeSize * .5f;
                    float lodSize  = 1 << m_probeLod;

                    if (m_moveProbe)
                    {
                        m_probePosition = MySector.MainCamera.Position + MySector.MainCamera.ForwardVector * m_probeSize * 3;
                    }

                    BoundingBox  bb;
                    BoundingBoxD bbp; // Box used for drawing and finding the probe and drawing

                    bb  = new BoundingBox(m_probePosition - halfSize, m_probePosition + halfSize);
                    bbp = (BoundingBoxD)bb;

                    m_voxels.Clear();
                    MyGamePruningStructure.GetAllVoxelMapsInBox(ref bbp, m_voxels);

                    MyVoxelBase map      = null;
                    double      distance = double.PositiveInfinity;

                    foreach (var vox in m_voxels)
                    {
                        var d = Vector3D.Distance(vox.WorldMatrix.Translation, m_probePosition);
                        if (d < distance)
                        {
                            distance = d;
                            map      = vox;
                        }
                    }

                    ContainmentType cont = ContainmentType.Disjoint;

                    if (map != null)
                    {
                        if (map is MyVoxelPhysics)
                        {
                            map = ((MyVoxelPhysics)map).Parent;
                        }

                        Vector3 localPos = Vector3.Transform(m_probePosition, map.PositionComp.WorldMatrixInvScaled);
                        localPos += map.SizeInMetresHalf;

                        // Create similar bounding box in storage space
                        bb = new BoundingBox(localPos - halfSize, localPos + halfSize);

                        m_probedVoxel = map;

                        Section("Probing {1}: {0}", map.StorageName, map.GetType().Name);
                        Text("Probe mode: {0}", m_mode);

                        if (m_mode == ProbeMode.Intersect)
                        {
                            Text("Local Pos: {0}", localPos);
                            Text("Probe Size: {0}", m_probeSize);
                            cont = map.Storage.Intersect(ref bb, false);
                            Text("Result: {0}", cont.ToString());
                            bbp = (BoundingBoxD)bb;
                        }
                        else
                        {
                            Vector3I min = Vector3I.Floor(bb.Min / lodSize + .5f);
                            Vector3I max = min + ((int)m_probeSize >> m_probeLod) - 1;

                            bbp = new BoundingBoxD(min << m_probeLod, (max + 1) << m_probeLod);

                            Text("Probe Size: {0}({1})", (max - min).X + 1, m_probeSize);
                            Text("Probe LOD: {0}", m_probeLod);

                            var requestData           = (MyStorageDataTypeEnum)(int)m_mode;
                            MyVoxelRequestFlags flags = MyVoxelRequestFlags.ContentChecked;

                            m_target.Resize(max - min + 1);
                            m_target.Clear(MyStorageDataTypeEnum.Content, 0);
                            m_target.Clear(MyStorageDataTypeEnum.Material, 0);
                            map.Storage.ReadRange(m_target, (MyStorageDataTypeFlags)(1 << (int)requestData), m_probeLod, ref min, ref max, ref flags);

                            if (requestData == MyStorageDataTypeEnum.Content)
                            {
                                if (flags.HasFlag(MyVoxelRequestFlags.EmptyContent))
                                {
                                    cont = ContainmentType.Disjoint;
                                }
                                else if (flags.HasFlag(MyVoxelRequestFlags.FullContent))
                                {
                                    cont = ContainmentType.Contains;
                                }
                                else
                                {
                                    int val = m_target.ValueWhenAllEqual(requestData);
                                    if (val == -1)
                                    {
                                        cont = ContainmentType.Intersects;
                                    }
                                    else if (val >= MyVoxelConstants.VOXEL_ISO_LEVEL)
                                    {
                                        cont = ContainmentType.Contains;
                                    }
                                    else
                                    {
                                        cont = ContainmentType.Disjoint;
                                    }
                                }

                                DrawContentsInfo(m_target);
                            }
                            else
                            {
                                cont = ContainmentType.Disjoint;
                                DrawMaterialsInfo(m_target);
                            }

                            Text(Color.Yellow, 1.5f, "Voxel Editing:");
                            Text("Value to set (Ctrl+Mousewheel): {0}", m_valueToSet);
                            if (m_probeLod != 0)
                            {
                                Text(Color.Red, "Writing to storage is only possible when probe is set to LOD 0");
                            }
                            else
                            {
                                Text("Use primary mouse button to set.");
                                Text("Position/Extents: {0}/{1}", bbp.Min, bbp.Extents);

                                if (MyInput.Static.IsLeftMousePressed())
                                {
                                    if (requestData == MyStorageDataTypeEnum.Content)
                                    {
                                        m_target.BlockFillContent(Vector3I.Zero, m_target.Size3D - Vector3I.One, m_valueToSet);
                                    }
                                    else
                                    {
                                        m_target.BlockFillMaterial(Vector3I.Zero, m_target.Size3D - Vector3I.One, m_valueToSet);
                                    }

                                    map.Storage.WriteRange(m_target, (MyStorageDataTypeFlags)(1 << (int)requestData), ref min, ref max);
                                }
                            }
                        }
                    }
                    else
                    {
                        Section("No Voxel Found");
                        Text("Probe mode: {0}", m_mode);
                        Text("Probe Size: {0}", m_probeSize);
                    }

                    Color c = ColorForContainment(cont);
                    if (map != null)
                    {
                        bbp = bbp.Translate(-map.SizeInMetresHalf);
                        MyOrientedBoundingBoxD oobb = new MyOrientedBoundingBoxD(bbp, map.WorldMatrix);
                        MyRenderProxy.DebugDrawOBB(oobb, c, 0.5f, true, false);
                    }
                    else
                    {
                        MyRenderProxy.DebugDrawAABB(bbp, c, 0.5f, 1.0f, true);
                    }
                }
            }
        public override void DebugDraw()
        {
            if (MyDebugDrawSettings.DEBUG_DRAW_FIXED_BLOCK_QUERIES)
            {
                foreach (var b in m_cubeGrid.GetBlocks())
                {
                    var geometryBox = b.FatBlock.GetGeometryLocalBox();                    
                    //geometryBox.Inflate(0.5f);
                    Vector3 halfExtents = geometryBox.Size / 2;

                    Vector3D pos;                    
                    b.ComputeScaledCenter(out pos);
                    pos += geometryBox.Center;                    
                    pos = Vector3D.Transform(pos, m_cubeGrid.WorldMatrix);

                    Matrix blockMatrix;
                    b.Orientation.GetMatrix(out blockMatrix);
                    var q = Quaternion.CreateFromRotationMatrix(blockMatrix * m_cubeGrid.WorldMatrix.GetOrientation());

                    Sandbox.Engine.Physics.MyPhysics.GetPenetrationsBox(ref halfExtents, ref pos, ref q, m_penetrations, Sandbox.Engine.Physics.MyPhysics.CollisionLayers.CollideWithStaticLayer);
                    bool isStatic = false;
                    foreach (var p in m_penetrations)
                    {
                        var e = p.GetCollisionEntity();
                        if (e != null && e is MyVoxelMap)
                        {
                            isStatic = true;
                            break;
                        }
                    }

                    m_penetrations.Clear();



                    MyOrientedBoundingBoxD obb = new MyOrientedBoundingBoxD(pos, halfExtents, q);
                    MyRenderProxy.DebugDrawOBB(obb, isStatic ? Color.Green : Color.Red, 0.1f, false, false);
                }
            }

            if (MyDebugDrawSettings.DEBUG_DRAW_GRID_NAMES || MyDebugDrawSettings.DEBUG_DRAW_GRID_CONTROL)
            {
                string text = "";
                var color = Color.White;

                if (MyDebugDrawSettings.DEBUG_DRAW_GRID_NAMES) text += m_cubeGrid.ToString() + " ";
                if (MyDebugDrawSettings.DEBUG_DRAW_GRID_CONTROL)
                {
                    var controllingPlayer = Sync.Players.GetControllingPlayer(m_cubeGrid);
                    if (controllingPlayer != null)
                    {
                        text += "Controlled by: " + controllingPlayer.DisplayName;
                        color = Color.LightGreen;
                    }
                }

                MyRenderProxy.DebugDrawText3D(m_cubeGrid.PositionComp.WorldAABB.Center, text, color, 0.7f, false, MyGuiDrawAlignEnum.HORISONTAL_CENTER_AND_VERTICAL_CENTER);
            }

            MyRenderComponentCubeGrid gridRender = m_cubeGrid.Render;
            if (MyDebugDrawSettings.DEBUG_DRAW_BLOCK_GROUPS)
            {
                var tpos = m_cubeGrid.PositionComp.WorldMatrix.Translation;
                foreach (var group in m_cubeGrid.BlockGroups)
                {
                    MyRenderProxy.DebugDrawText3D(tpos, group.Name.ToString(), Color.Red, 1, false);
                    tpos += m_cubeGrid.PositionComp.WorldMatrix.Right * group.Name.Length * 0.1f;
                }
            }

            if (MyDebugDrawSettings.DEBUG_DRAW_GRID_DIRTY_BLOCKS)
            {
                foreach (var b in m_dirtyBlocks)
                {
                    var color = m_cubeGrid.GetCubeBlock(b.Key) != null ? Color.Red.ToVector3() : Color.Yellow.ToVector3();

                    var m = Matrix.CreateScale(m_cubeGrid.GridSize) * Matrix.CreateTranslation(b.Key * m_cubeGrid.GridSize) * m_cubeGrid.WorldMatrix;
                    MyRenderProxy.DebugDrawOBB(m, color, 0.15f, false, true);
                }
            }

            // Bone debug draw
            if (MyDebugDrawSettings.DEBUG_DRAW_DISPLACED_BONES)
            {
                Vector3 cameraPos = (Vector3)MySector.MainCamera.Position;

                foreach (var bone in m_cubeGrid.Skeleton.Bones)
                {
                    var bonePos = (bone.Key / (float)m_cubeGrid.Skeleton.BoneDensity) * gridRender.GridSize + bone.Value;
                    bonePos -= new Vector3(gridRender.GridSize / m_cubeGrid.Skeleton.BoneDensity);
                    Vector3 pos = Vector3.Transform(bonePos, (Matrix)m_cubeGrid.PositionComp.WorldMatrix);
                    MyRenderProxy.DebugDrawSphere(pos, 0.05f, Color.Red.ToVector3(), 0.5f, false, true);
                    if ((cameraPos - pos).LengthSquared() < 200.0f)
                        MyRenderProxy.DebugDrawText3D(pos, bone.Key.ToString(), Color.Red, 0.4f, false);
                }
            }

            if (MyDebugDrawSettings.DEBUG_DRAW_STRUCTURAL_INTEGRITY &&
                m_cubeGrid.StructuralIntegrity != null)
            {
                m_cubeGrid.StructuralIntegrity.DebugDraw();
            }

            if (MyDebugDrawSettings.DEBUG_DRAW_CUBES)
            {
                foreach (var cubeBlock in m_cubeGrid.CubeBlocks)
                {
                    var cb = cubeBlock.FatBlock;
                    if (cb == null) continue;

                    cb.DebugDraw();
                }
            }

            m_cubeGrid.GridSystems.DebugDraw();

            if (MyDebugDrawSettings.DEBUG_DRAW_GRID_TERMINAL_SYSTEMS)
            {
                /* if (grid.OnBlockAdded != null)
                 {
                     MyRenderProxy.DebugDrawText3D(Entity.PositionComp.WorldMatrix.Translation + new Vector3(0.0f, 0.0f, 0.5f), grid.OnBlockAdded.GetInvocationList().Count().ToString(), Color.NavajoWhite, 1.0f, false);
                 }*/
            }

            if (MyFakes.ENABLE_TRASH_REMOVAL && MyDebugDrawSettings.DEBUG_DRAW_TRASH_REMOVAL)
            {
                bool isTrash = m_cubeGrid.IsTrash();
                Color color = isTrash ? Color.Red : Color.Green;
                float sphereRadius = m_cubeGrid.PositionComp.LocalAABB.HalfExtents.AbsMax();
                Vector3D com = m_cubeGrid.Physics != null ? m_cubeGrid.Physics.CenterOfMassWorld : m_cubeGrid.PositionComp.WorldMatrix.Translation;
                MyRenderProxy.DebugDrawSphere(com, sphereRadius, color, 1.0f, false);
            }

            if (MyDebugDrawSettings.DEBUG_DRAW_GRID_ORIGINS)
            {
                MyRenderProxy.DebugDrawAxis(m_cubeGrid.PositionComp.WorldMatrix, 1.0f, false);
            }

            if (MyDebugDrawSettings.ENABLE_DEBUG_DRAW && MyDebugDrawSettings.DEBUG_DRAW_MOUNT_POINTS_ALL)
            {
                foreach (MySlimBlock block in m_cubeGrid.GetBlocks())
                {
                    if((m_cubeGrid.GridIntegerToWorld(block.Position) - MySector.MainCamera.Position).LengthSquared() < 200)
                        DebugDrawMountPoints(block);
                }
            }

            if(MyDebugDrawSettings.DEBUG_DRAW_BLOCK_INTEGRITY)
            {
                if (MySector.MainCamera != null && (MySector.MainCamera.Position - m_cubeGrid.PositionComp.WorldVolume.Center).Length() < 16 +m_cubeGrid.PositionComp.WorldVolume.Radius)
                    foreach (var cubeBlock in m_cubeGrid.CubeBlocks)
                    {
                        var pos = m_cubeGrid.GridIntegerToWorld(cubeBlock.Position);
                        if (m_cubeGrid.GridSizeEnum == MyCubeSize.Large || (MySector.MainCamera != null && (MySector.MainCamera.Position - pos).LengthSquared() < 9))
                        {
                            float integrity = 0;
                            if (cubeBlock.FatBlock is MyCompoundCubeBlock)
                            {
                                foreach (var b in (cubeBlock.FatBlock as MyCompoundCubeBlock).GetBlocks())
                                    integrity += b.Integrity * b.BlockDefinition.MaxIntegrityRatio;
                            }
                            else
                                integrity = cubeBlock.Integrity * cubeBlock.BlockDefinition.MaxIntegrityRatio;
                            MyRenderProxy.DebugDrawText3D(m_cubeGrid.GridIntegerToWorld(cubeBlock.Position), ((int)integrity).ToString(), Color.White, m_cubeGrid.GridSizeEnum == MyCubeSize.Large ? 0.65f : 0.5f, false);
                        }
                    }
            }

            base.DebugDraw();
        }
Exemple #17
0
        public override void DebugDraw()
        {
            if (MyDebugDrawSettings.DEBUG_DRAW_FIXED_BLOCK_QUERIES)
            {
                foreach (var b in m_cubeGrid.GetBlocks())
                {
                    var geometryBox = b.FatBlock.GetGeometryLocalBox();
                    //geometryBox.Inflate(0.5f);
                    Vector3 halfExtents = geometryBox.Size / 2;

                    Vector3D pos;
                    b.ComputeScaledCenter(out pos);
                    pos += geometryBox.Center;
                    pos  = Vector3D.Transform(pos, m_cubeGrid.WorldMatrix);

                    Matrix blockMatrix;
                    b.Orientation.GetMatrix(out blockMatrix);
                    var q = Quaternion.CreateFromRotationMatrix(blockMatrix * m_cubeGrid.WorldMatrix.GetOrientation());

                    Sandbox.Engine.Physics.MyPhysics.GetPenetrationsBox(ref halfExtents, ref pos, ref q, m_penetrations, Sandbox.Engine.Physics.MyPhysics.CollisionLayers.CollideWithStaticLayer);
                    bool isStatic = false;
                    foreach (var p in m_penetrations)
                    {
                        var e = p.GetCollisionEntity();
                        if (e != null && e is MyVoxelMap)
                        {
                            isStatic = true;
                            break;
                        }
                    }

                    m_penetrations.Clear();



                    MyOrientedBoundingBoxD obb = new MyOrientedBoundingBoxD(pos, halfExtents, q);
                    MyRenderProxy.DebugDrawOBB(obb, isStatic ? Color.Green : Color.Red, 0.1f, false, false);
                }
            }

            if (MyDebugDrawSettings.DEBUG_DRAW_GRID_NAMES || MyDebugDrawSettings.DEBUG_DRAW_GRID_CONTROL)
            {
                string text  = "";
                var    color = Color.White;

                if (MyDebugDrawSettings.DEBUG_DRAW_GRID_NAMES)
                {
                    text += m_cubeGrid.ToString() + " ";
                }
                if (MyDebugDrawSettings.DEBUG_DRAW_GRID_CONTROL)
                {
                    var controllingPlayer = Sync.Players.GetControllingPlayer(m_cubeGrid);
                    if (controllingPlayer != null)
                    {
                        text += "Controlled by: " + controllingPlayer.DisplayName;
                        color = Color.LightGreen;
                    }
                }

                MyRenderProxy.DebugDrawText3D(m_cubeGrid.PositionComp.WorldAABB.Center, text, color, 0.7f, false, MyGuiDrawAlignEnum.HORISONTAL_CENTER_AND_VERTICAL_CENTER);
            }

            MyRenderComponentCubeGrid gridRender = m_cubeGrid.Render;

            if (MyDebugDrawSettings.DEBUG_DRAW_BLOCK_GROUPS)
            {
                var tpos = m_cubeGrid.PositionComp.WorldMatrix.Translation;
                foreach (var group in m_cubeGrid.BlockGroups)
                {
                    MyRenderProxy.DebugDrawText3D(tpos, group.Name.ToString(), Color.Red, 1, false);
                    tpos += m_cubeGrid.PositionComp.WorldMatrix.Right * group.Name.Length * 0.1f;
                }
            }

            if (MyDebugDrawSettings.DEBUG_DRAW_GRID_DIRTY_BLOCKS)
            {
                foreach (var b in m_dirtyBlocks)
                {
                    var color = m_cubeGrid.GetCubeBlock(b.Key) != null?Color.Red.ToVector3() : Color.Yellow.ToVector3();

                    var m = Matrix.CreateScale(m_cubeGrid.GridSize) * Matrix.CreateTranslation(b.Key * m_cubeGrid.GridSize) * m_cubeGrid.WorldMatrix;
                    MyRenderProxy.DebugDrawOBB(m, color, 0.15f, false, true);
                }
            }

            // Bone debug draw
            if (MyDebugDrawSettings.DEBUG_DRAW_DISPLACED_BONES)
            {
                Vector3 cameraPos = (Vector3)MySector.MainCamera.Position;

                foreach (var bone in m_cubeGrid.Skeleton.Bones)
                {
                    var bonePos = (bone.Key / (float)m_cubeGrid.Skeleton.BoneDensity) * gridRender.GridSize + bone.Value;
                    bonePos -= new Vector3(gridRender.GridSize / m_cubeGrid.Skeleton.BoneDensity);
                    Vector3 pos = Vector3.Transform(bonePos, (Matrix)m_cubeGrid.PositionComp.WorldMatrix);
                    MyRenderProxy.DebugDrawSphere(pos, 0.05f, Color.Red.ToVector3(), 0.5f, false, true);
                    if ((cameraPos - pos).LengthSquared() < 200.0f)
                    {
                        MyRenderProxy.DebugDrawText3D(pos, bone.Key.ToString(), Color.Red, 0.4f, false);
                    }
                }
            }

            if (MyDebugDrawSettings.DEBUG_DRAW_STRUCTURAL_INTEGRITY &&
                m_cubeGrid.StructuralIntegrity != null)
            {
                m_cubeGrid.StructuralIntegrity.DebugDraw();
            }

            if (MyDebugDrawSettings.DEBUG_DRAW_CUBES)
            {
                foreach (var cubeBlock in m_cubeGrid.CubeBlocks)
                {
                    var cb = cubeBlock.FatBlock;
                    if (cb == null)
                    {
                        continue;
                    }

                    cb.DebugDraw();
                }
            }

            m_cubeGrid.GridSystems.DebugDraw();

            if (MyDebugDrawSettings.DEBUG_DRAW_GRID_TERMINAL_SYSTEMS)
            {
                /* if (grid.OnBlockAdded != null)
                 * {
                 *   MyRenderProxy.DebugDrawText3D(Entity.PositionComp.WorldMatrix.Translation + new Vector3(0.0f, 0.0f, 0.5f), grid.OnBlockAdded.GetInvocationList().Count().ToString(), Color.NavajoWhite, 1.0f, false);
                 * }*/
            }

            if (MyFakes.ENABLE_TRASH_REMOVAL && MyDebugDrawSettings.DEBUG_DRAW_TRASH_REMOVAL)
            {
                bool     isTrash      = m_cubeGrid.IsTrash();
                Color    color        = isTrash ? Color.Red : Color.Green;
                float    sphereRadius = m_cubeGrid.PositionComp.LocalAABB.HalfExtents.AbsMax();
                Vector3D com          = m_cubeGrid.Physics != null ? m_cubeGrid.Physics.CenterOfMassWorld : m_cubeGrid.PositionComp.WorldMatrix.Translation;
                MyRenderProxy.DebugDrawSphere(com, sphereRadius, color, 1.0f, false);
            }

            if (MyDebugDrawSettings.DEBUG_DRAW_GRID_ORIGINS)
            {
                MyRenderProxy.DebugDrawAxis(m_cubeGrid.PositionComp.WorldMatrix, 1.0f, false);
            }

            if (MyDebugDrawSettings.ENABLE_DEBUG_DRAW && MyDebugDrawSettings.DEBUG_DRAW_MOUNT_POINTS_ALL)
            {
                foreach (MySlimBlock block in m_cubeGrid.GetBlocks())
                {
                    if ((m_cubeGrid.GridIntegerToWorld(block.Position) - MySector.MainCamera.Position).LengthSquared() < 200)
                    {
                        DebugDrawMountPoints(block);
                    }
                }
            }

            if (MyDebugDrawSettings.DEBUG_DRAW_BLOCK_INTEGRITY)
            {
                if (MySector.MainCamera != null && (MySector.MainCamera.Position - m_cubeGrid.PositionComp.WorldVolume.Center).Length() < 16 + m_cubeGrid.PositionComp.WorldVolume.Radius)
                {
                    foreach (var cubeBlock in m_cubeGrid.CubeBlocks)
                    {
                        var pos = m_cubeGrid.GridIntegerToWorld(cubeBlock.Position);
                        if (m_cubeGrid.GridSizeEnum == MyCubeSize.Large || (MySector.MainCamera != null && (MySector.MainCamera.Position - pos).LengthSquared() < 9))
                        {
                            float integrity = 0;
                            if (cubeBlock.FatBlock is MyCompoundCubeBlock)
                            {
                                foreach (var b in (cubeBlock.FatBlock as MyCompoundCubeBlock).GetBlocks())
                                {
                                    integrity += b.Integrity * b.BlockDefinition.MaxIntegrityRatio;
                                }
                            }
                            else
                            {
                                integrity = cubeBlock.Integrity * cubeBlock.BlockDefinition.MaxIntegrityRatio;
                            }
                            MyRenderProxy.DebugDrawText3D(m_cubeGrid.GridIntegerToWorld(cubeBlock.Position), ((int)integrity).ToString(), Color.White, m_cubeGrid.GridSizeEnum == MyCubeSize.Large ? 0.65f : 0.5f, false);
                        }
                    }
                }
            }

            base.DebugDraw();
        }
 /// <summary>
 /// Adds the vertices from the physical body (rock) that is inside the given OBB
 /// </summary>
 /// <param name="voxelMap"></param>
 /// <param name="border"></param>
 /// <param name="originPosition"></param>
 /// <param name="obb"></param>
 /// <param name="bbList"></param>
 private void AddVoxelVertices(MyVoxelMap voxelMap, float border, Vector3D originPosition, MyOrientedBoundingBoxD obb, List<BoundingBoxD> bbList)
 {
     AddVoxelMesh(voxelMap, voxelMap.Storage, null, border, originPosition, obb, bbList);
 }
Exemple #19
0
        private static int RemoveStations(MySessionComponentEconomy meh, List <MyFaction> factionList, bool deleteFaction = false)
        {
            var removedStations         = 0;
            var removeStationList       = new List <MyFaction>();
            var deletedStationPositions = new List <MyOrientedBoundingBoxD>();

            foreach (var faction in factionList)
            {
                foreach (var station in faction.Stations)
                {
                    MyEntities.TryGetEntityById(station.StationEntityId, out var entity);
                    if (entity != null)
                    {
                        deletedStationPositions.Add(new MyOrientedBoundingBoxD(entity.PositionComp.LocalAABB, entity.PositionComp.WorldMatrixRef));
                        entity.Close();
                    }

                    meh.RemoveStationGrid(station.Id);
                    meh.RemoveStationGrid(station.StationEntityId);
                    removeStationList.Add(faction);
                    removedStations++;
                }
            }

            RemoveStation(removeStationList);

            //Cleanup safezones of deleted stations using position.
            var safeZones    = new HashSet <MySafeZone>(MySessionComponentSafeZones.SafeZones);
            var delSafeZones = new List <MySafeZone>();

            foreach (var zone in safeZones)
            {
                var zonePosition =
                    new MyOrientedBoundingBoxD(zone.PositionComp.LocalAABB, zone.PositionComp.WorldMatrixRef);

                foreach (var position in deletedStationPositions)
                {
                    if (!position.Intersects(ref zonePosition))
                    {
                        continue;
                    }
                    delSafeZones.Add(zone);
                    break;
                }
            }

            foreach (var zone in delSafeZones)
            {
                zone.Close();
            }

            if (!deleteFaction)
            {
                CleanupReputations();
                return(removedStations);
            }

            foreach (var faction in factionList)
            {
                RemoveFaction(faction);
            }

            CleanupReputations();
            return(removedStations);
        }
        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();
        }
Exemple #21
0
        protected override void DoDetection(bool useHead)
        {
            ProfilerShort.Begin("DoDetection");
            if (Character == MySession.Static.ControlledEntity)
            {
                MyHud.SelectedObjectHighlight.RemoveHighlight();
            }

            var head    = Character.GetHeadMatrix(false);
            var headPos = head.Translation - (Vector3D)head.Forward * 0.3; // Move to center of head, we don't want eyes (in front of head)

            Vector3D from;
            Vector3D dir;

            if (!useHead)
            {
                //Ondrej version
                var cameraMatrix = MySector.MainCamera.WorldMatrix;
                dir  = cameraMatrix.Forward;
                from = MyUtils.LinePlaneIntersection(headPos, (Vector3)dir, cameraMatrix.Translation, (Vector3)dir);
            }
            else
            {
                //Petr version
                dir  = head.Forward;
                from = headPos;
            }

            Vector3D to = from + dir * MyConstants.DEFAULT_INTERACTIVE_DISTANCE;

            //EnableDetectorsInArea(from);
            GatherDetectorsInArea(from);
            float        closestDetector    = float.MaxValue;
            IMyEntity    closestEntity      = null;
            IMyUseObject closestInteractive = null;

            foreach (var entity in m_detectableEntities)
            {
                if (entity == Character)
                {
                    continue;
                }
                var use = entity.Components.Get <MyUseObjectsComponentBase>() as MyUseObjectsComponent;
                if (use != null)
                {
                    float detectorDistance;
                    var   interactive = use.RaycastDetectors(from, to, out detectorDistance);
                    if (Math.Abs(detectorDistance) < Math.Abs(closestDetector))
                    {
                        closestDetector    = detectorDistance;
                        closestEntity      = entity;
                        closestInteractive = interactive;
                    }
                }

                //Floating object handling - give FO useobject component!
                var use2 = entity as IMyUseObject;
                if (use2 != null)
                {
                    var m    = use2.ActivationMatrix;
                    var ray  = new RayD(from, to - from);
                    var obb  = new MyOrientedBoundingBoxD(m);
                    var dist = obb.Intersects(ref ray);
                    if (dist.HasValue && Math.Abs(dist.Value) < Math.Abs(closestDetector))
                    {
                        closestDetector    = (float)dist.Value;
                        closestEntity      = entity;
                        closestInteractive = use2;
                    }
                }
            }
            m_detectableEntities.Clear();
            //VRageRender.MyRenderProxy.DebugDrawLine3D(from, to, Color.Red, Color.Green, true);
            //VRageRender.MyRenderProxy.DebugDrawSphere(headPos, 0.05f, Color.Red.ToVector3(), 1.0f, false);

            StartPosition = from;

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

            bool hasInteractive = false;

            int index = 0;

            while (index < m_hits.Count && (m_hits[index].HkHitInfo.Body == null || m_hits[index].HkHitInfo.GetHitEntity() == Character ||
                                            m_hits[index].HkHitInfo.GetHitEntity() == null ||
                                            m_hits[index].HkHitInfo.Body.HasProperty(HkCharacterRigidBody.MANIPULATED_OBJECT) ||
                                            m_hits[index].HkHitInfo.Body.Layer == MyPhysics.CollisionLayers.VoxelLod1CollisionLayer)) // Skip invalid hits and self character
            {
                index++;
            }

            if (index < m_hits.Count && m_hits[index].HkHitInfo.HitFraction > closestDetector - 0.05f)//compensation
            {
                // TODO: Uncomment to enforce that character must face object by front to activate it
                //if (TestInteractionDirection(head.Forward, h.Position - GetPosition()))
                //return;
                HitPosition = from + dir * closestDetector;
                MyUseObjectsComponentBase useObject;
                if (closestEntity.Components.TryGet <MyUseObjectsComponentBase>(out useObject))
                {
                    var detectorPhysics = useObject.DetectorPhysics;
                    HitMaterial = detectorPhysics.GetMaterialAt(HitPosition);
                    HitBody     = ((MyPhysicsBody)detectorPhysics).RigidBody;
                }
                else
                {
                    HitMaterial = closestEntity.Physics.GetMaterialAt(HitPosition);
                    HitBody     = ((MyPhysicsBody)closestEntity.Physics).RigidBody;
                }

                DetectedEntity = closestEntity;
                var interactive = closestInteractive;

                if (UseObject != null && interactive != null && UseObject != interactive)
                {
                    UseObject.OnSelectionLost();
                }

                //if (interactive != null && interactive.SupportedActions != UseActionEnum.None && (Vector3D.Distance(from, (Vector3D)h.Position)) < interactive.InteractiveDistance && Character == MySession.Static.ControlledEntity)
                if (interactive != null && interactive.SupportedActions != UseActionEnum.None && closestDetector * MyConstants.DEFAULT_INTERACTIVE_DISTANCE < interactive.InteractiveDistance && Character == MySession.Static.ControlledEntity)
                {
                    HandleInteractiveObject(interactive);

                    UseObject      = interactive;
                    hasInteractive = true;
                }
            }

            if (!hasInteractive)
            {
                if (UseObject != null)
                {
                    UseObject.OnSelectionLost();
                }

                UseObject = null;
            }

            ProfilerShort.End();
        }
 /// <summary>
 /// Returns the specified corner from the OBB.
 /// </summary>
 /// <param name="obb"></param>
 /// <param name="corner"></param>
 /// <returns>Returns the </returns>
 public static Vector3D GetOBBCorner(MyOrientedBoundingBoxD obb, OBBCorner corner)
 {
     Vector3D[] corners = new Vector3D[8];
     obb.GetCorners(corners, 0);
     return corners[(int)corner];
 }
Exemple #23
0
        public static void DebugDrawClusters()
        {
            if (Clusters == null)
            {
                return;
            }

            double  previewScale  = 2000;
            MatrixD previewMatrix = MatrixD.CreateWorld(DebugDrawClustersMatrix.Translation + previewScale * DebugDrawClustersMatrix.Forward, Vector3D.Forward, Vector3D.Up);

            m_resultWorlds.Clear();

            Clusters.GetAll(m_resultWorlds);

            BoundingBoxD totalBox = BoundingBoxD.CreateInvalid();

            foreach (var res in m_resultWorlds)
            {
                totalBox = totalBox.Include(res.AABB);
            }

            double maxAxis = totalBox.Size.AbsMax();
            //double scaleAxis = 0.057142857142857141;
            double scaleAxis = previewScale / maxAxis;

            //Vector3D scale = new Vector3D(totalBox.Size.X * scaleAxis, totalBox.Size.Y * scaleAxis, totalBox.Size.Z * scaleAxis);

            Vector3D center = totalBox.Center;

            totalBox.Min -= center;
            totalBox.Max -= center;

            {
                BoundingBoxD           scaledBox = new BoundingBoxD(totalBox.Min * scaleAxis * 1.02f, totalBox.Max * scaleAxis * 1.02f);
                MyOrientedBoundingBoxD oriented  = new MyOrientedBoundingBoxD(scaledBox, previewMatrix);
                MyRenderProxy.DebugDrawOBB(oriented, Vector3.Up, 1, false, false);

                MyRenderProxy.DebugDrawAxis(previewMatrix, 50, false);

                if (MySession.Static != null)
                {
                    foreach (var player in Sandbox.Game.Multiplayer.Sync.Players.GetOnlinePlayers())
                    {
                        if (player.Character != null)
                        {
                            var playerPos = Vector3D.Transform((player.Character.PositionComp.GetPosition() - center) * scaleAxis, previewMatrix);
                            MyRenderProxy.DebugDrawSphere(playerPos, 10, Vector3.One, 1, false);
                        }
                    }
                }
            }

            Clusters.GetAllStaticObjects(m_clusterStaticObjects);
            foreach (var staticBB in m_clusterStaticObjects)
            {
                BoundingBoxD scaledBox = new BoundingBoxD((staticBB.Min - center) * scaleAxis, (staticBB.Max - center) * scaleAxis);

                MyOrientedBoundingBoxD oriented = new MyOrientedBoundingBoxD(scaledBox, previewMatrix);

                MyRenderProxy.DebugDrawOBB(oriented, Color.Blue, 1, false, false);
            }

            foreach (var res in m_resultWorlds)
            {
                BoundingBoxD scaledBox = new BoundingBoxD((res.AABB.Min - center) * scaleAxis, (res.AABB.Max - center) * scaleAxis);

                MyOrientedBoundingBoxD oriented = new MyOrientedBoundingBoxD(scaledBox, previewMatrix);

                MyRenderProxy.DebugDrawOBB(oriented, Vector3.One, 1, false, false);

                foreach (var rb in ((HkWorld)res.UserData).CharacterRigidBodies)
                {
                    Vector3D rbCenter = res.AABB.Center + rb.Position;
                    rbCenter = (rbCenter - center) * scaleAxis;
                    rbCenter = Vector3D.Transform(rbCenter, previewMatrix);

                    Vector3D velocity = rb.LinearVelocity;
                    velocity = Vector3D.TransformNormal(velocity, previewMatrix) * 10;
                    MyRenderProxy.DebugDrawLine3D(rbCenter, rbCenter + velocity, Color.Blue, Color.White, false);
                }

                foreach (var rb in ((HkWorld)res.UserData).RigidBodies)
                {
                    MyOrientedBoundingBoxD rbbb = new MyOrientedBoundingBoxD((BoundingBoxD)rb.GetEntity().LocalAABB, rb.GetEntity().WorldMatrix);
                    rbbb.Center      = (rbbb.Center - center) * scaleAxis;
                    rbbb.HalfExtent *= scaleAxis;
                    rbbb.Transform(previewMatrix);
                    MyRenderProxy.DebugDrawOBB(rbbb, Color.Yellow, 1, false, false);

                    //BoundingBoxD rbaa = rb.GetEntity().WorldAABB;
                    //rbaa.Min = (rbaa.Min - center) * scaleAxis;
                    //rbaa.Max = (rbaa.Max - center) * scaleAxis;
                    //MyRenderProxy.DebugDrawAABB(rbaa, new Vector3(0.8f, 0.8f, 0.8f), 1, 1, false);

                    Vector3D velocity = rb.LinearVelocity;
                    velocity = Vector3D.TransformNormal(velocity, previewMatrix) * 10;
                    MyRenderProxy.DebugDrawLine3D(rbbb.Center, rbbb.Center + velocity, Color.Red, Color.White, false);

                    if (velocity.Length() > 1)
                    {
                        BoundingBoxD           ideal    = new BoundingBoxD(rb.GetEntity().WorldAABB.Center - MyHavokCluster.IdealClusterSize / 2, rb.GetEntity().WorldAABB.Center + MyHavokCluster.IdealClusterSize / 2);
                        MyOrientedBoundingBoxD idealObb = new MyOrientedBoundingBoxD(ideal, MatrixD.Identity);
                        idealObb.Center      = (ideal.Center - center) * scaleAxis;
                        idealObb.HalfExtent *= scaleAxis;
                        idealObb.Transform(previewMatrix);
                        MyRenderProxy.DebugDrawOBB(idealObb, new Vector3(0, 0, 1), 1, false, false);
                    }
                }
            }
        }
        public override void DebugDraw()
        {

            if (MyDebugDrawSettings.DEBUG_DRAW_CONSTRAINTS)
            {
                int i = 0;
                foreach (var c in Constraints)
                {
                    if (c.IsDisposed)
                        continue;

                    Color col = Color.Green;

                    if (!IsConstraintValid(c))
                        col = Color.Red;

                    Vector3 pivotA, pivotB;
                    c.GetPivotsInWorld(out pivotA, out pivotB);
                    var pos = ClusterToWorld(pivotA);
                    MyRenderProxy.DebugDrawSphere(pos, 0.2f, col, 1, false);
                    MyRenderProxy.DebugDrawText3D(pos, i.ToString(), Color.White, 0.7f, true);
                    i++;
                    pos = ClusterToWorld(pivotB);
                    MyRenderProxy.DebugDrawSphere(pos, 0.2f, col, 1, false);
                }
            }

            if (MyDebugDrawSettings.DEBUG_DRAW_INERTIA_TENSORS && RigidBody != null)
            {
                var com = ClusterToWorld(RigidBody.CenterOfMassWorld);
                VRageRender.MyRenderProxy.DebugDrawLine3D(com, com + RigidBody.AngularVelocity, Color.Blue, Color.Red, false);
                var invMass = 1/RigidBody.Mass;
                var diag = RigidBody.InertiaTensor.Scale;
                var betSq = (diag.X - diag.Y + diag.Z) * invMass * 6;
                var gamaSq = diag.X * invMass * 12 - betSq;
                var alpSq = diag.Z * invMass * 12 - betSq;

                var scale = 1.01f * 0.5f;
                var he = new Vector3(Math.Sqrt(alpSq), Math.Sqrt(betSq), Math.Sqrt(gamaSq)) * scale;

                MyOrientedBoundingBoxD obb = new MyOrientedBoundingBoxD(new BoundingBoxD(-he, he), MatrixD.Identity);
                obb.Transform(RigidBody.GetRigidBodyMatrix());
                obb.Center = CenterOfMassWorld;// RigidBody.GetBody().ClusterToWorld(RigidBody.CenterOfMassWorld);
                VRageRender.MyRenderProxy.DebugDrawOBB(obb, Color.Purple, 0.05f, false, false);
                //VRageRender.MyRenderProxy.DebugDrawText3D(obb.Center, Entity.ToString(), Color.Purple, 0.5f, false);
            }

            if (MyDebugDrawSettings.DEBUG_DRAW_PHYSICS_SHAPES && !IsWelded)
            {
                const float alpha = 0.3f;

                //if (!Enabled)
                //    return;

                var offset = MyPhysics.Clusters.GetObjectOffset(ClusterObjectID);

                if (RigidBody != null && BreakableBody != null)
                {
                    Vector3D com = Vector3D.Transform((Vector3D)BreakableBody.BreakableShape.CoM, RigidBody.GetRigidBodyMatrix()) + offset;
                    Color color = RigidBody.GetMotionType() != Havok.HkMotionType.Box_Inertia ? Color.Gray : RigidBody.IsActive ? Color.Red : Color.Blue;
                    VRageRender.MyRenderProxy.DebugDrawSphere(RigidBody.CenterOfMassWorld + offset, 0.2f, color, 1, false);

                    VRageRender.MyRenderProxy.DebugDrawAxis(Entity.PositionComp.WorldMatrix, 0.2f, false);
                }

                int index;
                if (RigidBody != null)
                {
                    index = 0;
                    Matrix rbMatrix = RigidBody.GetRigidBodyMatrix();
                    MatrixD worldMatrix = MatrixD.CreateWorld(rbMatrix.Translation + offset, rbMatrix.Forward, rbMatrix.Up);

                    MyPhysicsDebugDraw.DrawCollisionShape(RigidBody.GetShape(), worldMatrix, alpha, ref index);
                }

                if (RigidBody2 != null)
                {
                    index = 0;
                    Matrix rbMatrix = RigidBody2.GetRigidBodyMatrix();
                    MatrixD worldMatrix = MatrixD.CreateWorld(rbMatrix.Translation + offset, rbMatrix.Forward, rbMatrix.Up);

                    MyPhysicsDebugDraw.DrawCollisionShape(RigidBody2.GetShape(), worldMatrix, alpha, ref index);
                }

                if (CharacterProxy != null)
                {
                    index = 0;
                    //MatrixD characterTransform = MatrixD.CreateWorld(CharacterProxy.Position + offset, CharacterProxy.Forward, CharacterProxy.Up);
                    Matrix rbMatrix = CharacterProxy.GetRigidBodyTransform();
                    MatrixD worldMatrix = MatrixD.CreateWorld(rbMatrix.Translation + offset, rbMatrix.Forward, rbMatrix.Up);

                    MyPhysicsDebugDraw.DrawCollisionShape(CharacterProxy.GetShape(), worldMatrix, alpha, ref index);
                }
            }
        }
        public void DebugDraw()
        {
            MatrixD mat = MatrixD.Invert(m_worldInv);
            Quaternion orientation = Quaternion.CreateFromRotationMatrix(mat.GetOrientation());
            foreach (var segment in m_segments)
            {
                Vector3D halfExtents = new Vector3D(segment.Size) * 0.51;
                Vector3D center = new Vector3D(segment.Min + segment.Max) * 0.5;
                center = Vector3D.Transform(center, mat);

                var obb = new MyOrientedBoundingBoxD(center, halfExtents, orientation);
                MyRenderProxy.DebugDrawOBB(obb, Color.Red, 0.5f, false, false);
            }
        }
        public static void DrawMountPoints(float cubeSize, MyCubeBlockDefinition def, MatrixD drawMatrix, MyCubeBlockDefinition.MountPoint[] mountPoints)
        {
            Color color = Color.Yellow;
            Vector3I centerGrid = def.Center;
            Vector3 centerOffset = def.Size * 0.5f;
            Matrix drawTransf = MatrixD.CreateTranslation((centerGrid - centerOffset) * cubeSize) * drawMatrix;

            // Visualize existing mount points as yellow cuboids
            for (int i = 0; i < mountPoints.Length; ++i)
            {
                if (mountPoints[i].Normal == Base6Directions.IntDirections[0] && !MyDebugDrawSettings.DEBUG_DRAW_MOUNT_POINTS_AXIS0)
                    continue;
                if (mountPoints[i].Normal == Base6Directions.IntDirections[1] && !MyDebugDrawSettings.DEBUG_DRAW_MOUNT_POINTS_AXIS1)
                    continue;
                if (mountPoints[i].Normal == Base6Directions.IntDirections[2] && !MyDebugDrawSettings.DEBUG_DRAW_MOUNT_POINTS_AXIS2)
                    continue;
                if (mountPoints[i].Normal == Base6Directions.IntDirections[3] && !MyDebugDrawSettings.DEBUG_DRAW_MOUNT_POINTS_AXIS3)
                    continue;
                if (mountPoints[i].Normal == Base6Directions.IntDirections[4] && !MyDebugDrawSettings.DEBUG_DRAW_MOUNT_POINTS_AXIS4)
                    continue;
                if (mountPoints[i].Normal == Base6Directions.IntDirections[5] && !MyDebugDrawSettings.DEBUG_DRAW_MOUNT_POINTS_AXIS5)
                    continue;

                var start = mountPoints[i].Start - centerGrid;
                var end = mountPoints[i].End - centerGrid;
                var box = new BoundingBoxD(Vector3.Min(start, end) * cubeSize, Vector3.Max(start, end) * cubeSize);
                //MySimpleObjectDraw.DrawTransparentBox(ref drawTransf, ref box, ref color, MySimpleObjectRasterizer.SolidAndWireframe, 1, 0.1f);

                MyOrientedBoundingBoxD boxD = new MyOrientedBoundingBoxD(box, drawTransf);

                VRageRender.MyRenderProxy.DebugDrawOBB(boxD, color, 0.2f, true, false);
            }
        }
 public void DebugDraw()
 {
     var mat = MatrixD.Invert(m_worldInv);
     MyOrientedBoundingBoxD obb = new MyOrientedBoundingBoxD(MatrixD.CreateScale(m_halfExtents) * mat);
     MyRenderProxy.DebugDrawOBB(obb, Color.Red, 0.3f, false, false);
 }
        public void CalculateRotationHints(MatrixD drawMatrix, BoundingBoxD worldBox, bool draw, bool fixedAxes = false, bool hideForwardAndUpArrows = false)
        {
			drawMatrix.Translation = Vector3D.Zero;
			MatrixD drawInverse = MatrixD.Invert(drawMatrix);
			drawInverse *= drawMatrix.GetOrientation();
			drawInverse *= MySector.MainCamera.ViewMatrixAtZero;

			MatrixD camWorld = MatrixD.Invert(drawInverse); //MatrixD.Invert(MySector.MainCamera.ViewMatrixAtZero)*MatrixD.Invert(drawMatrix.GetOrientation())*drawMatrix;

			m_viewProjection.ViewAtZero = MatrixD.CreateLookAt(Vector3D.Zero, camWorld.Forward, camWorld.Up);
			m_viewProjection.ViewAtZero.Translation = new Vector3D(0,0,-6);
			m_viewProjection.View = drawInverse;
            m_viewProjection.View.Translation += new Vector3D(0, 0, -6);
            m_viewProjection.CameraPosition = camWorld.Translation;

            Vector2 screenSize = MyGuiManager.GetScreenSizeFromNormalizedSize(Vector2.One);
            float previewRatio = 2.5f;
            int hintsWidth = (int)(screenSize.X / previewRatio), hintsHeight = (int)(screenSize.Y / previewRatio), hintsXOffset = 0, hintsYOffset = 0;

            m_viewProjection.Viewport = new MyViewport(
                (int)MySector.MainCamera.Viewport.Width - hintsWidth - hintsXOffset,
                hintsYOffset,
                hintsWidth,
                hintsHeight);

            m_viewProjection.DepthRead = false;
            m_viewProjection.Projection = Matrix.CreatePerspectiveFieldOfView(MathHelper.PiOver4, (float)hintsWidth / hintsHeight, 0.1f, 10);


            

            worldBox = new BoundingBoxD(-new Vector3(MyDefinitionManager.Static.GetCubeSize(MyCubeSize.Large) * 0.5f), new Vector3(MyDefinitionManager.Static.GetCubeSize(MyCubeSize.Large)) * 0.5f);

            
            //m_rotationHintsViewProjection.Projection = MySector.MainCamera.ProjectionMatrix;


            

            int projectionId = 0;
            VRageRender.MyRenderProxy.AddBillboardViewProjection(projectionId, m_viewProjection);

            //MySimpleObjectDraw.DrawTransparentBox(ref drawMatrix,
            //                ref worldBox, ref Vector4.One, MySimpleObjectRasterizer.Wireframe, 1, 0.04f, null, null, false, 0);
            if (draw)
            {
                var white = Color.White;
                MySimpleObjectDraw.DrawTransparentBox(ref drawMatrix,
                              ref worldBox, ref white, MySimpleObjectRasterizer.Solid, 1, 0.04f, "SquareFullColor", null, false, projectionId, 100);
            }

            MyOrientedBoundingBoxD rotateHintsBox = new MyOrientedBoundingBoxD(Vector3D.Transform(worldBox.Center, drawMatrix), worldBox.HalfExtents, Quaternion.CreateFromRotationMatrix(drawMatrix));
            //VRageRender.MyRenderProxy.DebugDrawOBB(rotateHintsBox, Vector3.One, 1, false, false);


            rotateHintsBox.GetCorners(m_cubeVertices, 0);

            //for (int vi = 0; vi < 8; vi++)
            //{
            //    VRageRender.MyRenderProxy.DebugDrawText3D(m_cubeVertices[vi], vi.ToString(), Color.White, 0.7f, false);
            //}

            //for (int vi = 0; vi < 4; vi++)
            //{
            //    VRageRender.MyRenderProxy.DebugDrawText3D((m_cubeVertices[MyOrientedBoundingBox.StartXVertices[vi]] + m_cubeVertices[MyOrientedBoundingBox.EndXVertices[vi]]) * 0.5f, vi.ToString(), Color.Red, 0.7f, false);
            //    VRageRender.MyRenderProxy.DebugDrawText3D((m_cubeVertices[MyOrientedBoundingBox.StartYVertices[vi]] + m_cubeVertices[MyOrientedBoundingBox.EndYVertices[vi]]) * 0.5f, vi.ToString(), Color.Green, 0.7f, false);
            //    VRageRender.MyRenderProxy.DebugDrawText3D((m_cubeVertices[MyOrientedBoundingBox.StartZVertices[vi]] + m_cubeVertices[MyOrientedBoundingBox.EndZVertices[vi]]) * 0.5f, vi.ToString(), Color.Blue, 0.7f, false);
            //}

            int closestXAxis, closestXAxis2;
            GetClosestCubeEdge(m_cubeVertices, MyOrientedBoundingBox.StartXVertices, MyOrientedBoundingBox.EndXVertices, out closestXAxis, out closestXAxis2);
            Vector3D startXVertex = m_cubeVertices[MyOrientedBoundingBox.StartXVertices[closestXAxis]];
            Vector3D endXVertex = m_cubeVertices[MyOrientedBoundingBox.EndXVertices[closestXAxis]];
            Vector3D startXVertex2 = m_cubeVertices[MyOrientedBoundingBox.StartXVertices[closestXAxis2]];
            Vector3D endXVertex2 = m_cubeVertices[MyOrientedBoundingBox.EndXVertices[closestXAxis2]];

            int closestYAxis, closestYAxis2;
            GetClosestCubeEdge(m_cubeVertices, MyOrientedBoundingBox.StartYVertices, MyOrientedBoundingBox.EndYVertices, out closestYAxis, out closestYAxis2);
            Vector3D startYVertex = m_cubeVertices[MyOrientedBoundingBox.StartYVertices[closestYAxis]];
            Vector3D endYVertex = m_cubeVertices[MyOrientedBoundingBox.EndYVertices[closestYAxis]];
            Vector3D startYVertex2 = m_cubeVertices[MyOrientedBoundingBox.StartYVertices[closestYAxis2]];
            Vector3D endYVertex2 = m_cubeVertices[MyOrientedBoundingBox.EndYVertices[closestYAxis2]];

            int closestZAxis, closestZAxis2;
            GetClosestCubeEdge(m_cubeVertices, MyOrientedBoundingBox.StartZVertices, MyOrientedBoundingBox.EndZVertices, out closestZAxis, out closestZAxis2);
            Vector3D startZVertex = m_cubeVertices[MyOrientedBoundingBox.StartZVertices[closestZAxis]];
            Vector3D endZVertex = m_cubeVertices[MyOrientedBoundingBox.EndZVertices[closestZAxis]];
            Vector3D startZVertex2 = m_cubeVertices[MyOrientedBoundingBox.StartZVertices[closestZAxis2]];
            Vector3D endZVertex2 = m_cubeVertices[MyOrientedBoundingBox.EndZVertices[closestZAxis2]];

            m_cubeEdges.Clear();
            m_cubeEdges.Add(new BoxEdge() { Axis = 0, Edge = new LineD(startXVertex, endXVertex) });
            m_cubeEdges.Add(new BoxEdge() { Axis = 1, Edge = new LineD(startYVertex, endYVertex) });
            m_cubeEdges.Add(new BoxEdge() { Axis = 2, Edge = new LineD(startZVertex, endZVertex) });

            if (!fixedAxes)
            {
                int rotDirection;

                RotationRightAxis = GetBestAxis(m_cubeEdges, MySector.MainCamera.WorldMatrix.Right, out rotDirection);
                RotationRightDirection = rotDirection;

                RotationUpAxis = GetBestAxis(m_cubeEdges, MySector.MainCamera.WorldMatrix.Up, out rotDirection);
                RotationUpDirection = rotDirection;

                RotationForwardAxis = GetBestAxis(m_cubeEdges, MySector.MainCamera.WorldMatrix.Forward, out rotDirection);
                RotationForwardDirection = rotDirection;
            }

            string rightControlName1 = MyInput.Static.GetGameControl(MyControlsSpace.CUBE_ROTATE_HORISONTAL_POSITIVE).GetControlButtonName(MyGuiInputDeviceEnum.Keyboard).ToString();
            string rightControlName2 = MyInput.Static.GetGameControl(MyControlsSpace.CUBE_ROTATE_HORISONTAL_NEGATIVE).GetControlButtonName(MyGuiInputDeviceEnum.Keyboard).ToString();
            string upControlName1 = MyInput.Static.GetGameControl(MyControlsSpace.CUBE_ROTATE_VERTICAL_POSITIVE).GetControlButtonName(MyGuiInputDeviceEnum.Keyboard).ToString();
            string upControlName2 = MyInput.Static.GetGameControl(MyControlsSpace.CUBE_ROTATE_VERTICAL_NEGATIVE).GetControlButtonName(MyGuiInputDeviceEnum.Keyboard).ToString();
            string forwControlName1 = MyInput.Static.GetGameControl(MyControlsSpace.CUBE_ROTATE_ROLL_POSITIVE).GetControlButtonName(MyGuiInputDeviceEnum.Keyboard).ToString();
            string forwControlName2 = MyInput.Static.GetGameControl(MyControlsSpace.CUBE_ROTATE_ROLL_NEGATIVE).GetControlButtonName(MyGuiInputDeviceEnum.Keyboard).ToString();

            if (MyInput.Static.IsJoystickConnected())
            {
                rightControlName1 = MyControllerHelper.GetCodeForControl(MySpaceBindingCreator.CX_BUILD_MODE, MyControlsSpace.CUBE_ROTATE_HORISONTAL_POSITIVE).ToString();
                rightControlName2 = MyControllerHelper.GetCodeForControl(MySpaceBindingCreator.CX_BUILD_MODE, MyControlsSpace.CUBE_ROTATE_HORISONTAL_NEGATIVE).ToString();
                upControlName1 = MyControllerHelper.GetCodeForControl(MySpaceBindingCreator.CX_BUILD_MODE, MyControlsSpace.CUBE_ROTATE_VERTICAL_POSITIVE).ToString();
                upControlName2 = MyControllerHelper.GetCodeForControl(MySpaceBindingCreator.CX_BUILD_MODE, MyControlsSpace.CUBE_ROTATE_VERTICAL_NEGATIVE).ToString();
                forwControlName1 = MyControllerHelper.GetCodeForControl(MySpaceBindingCreator.CX_BUILD_MODE, MyControlsSpace.CUBE_ROTATE_ROLL_POSITIVE).ToString();
                forwControlName2 = MyControllerHelper.GetCodeForControl(MySpaceBindingCreator.CX_BUILD_MODE, MyControlsSpace.CUBE_ROTATE_ROLL_NEGATIVE).ToString();
            }

            Vector3D rightStart = Vector3D.Zero;
            Vector3D rightEnd = Vector3D.Zero;
            Vector3D upStart = Vector3D.Zero;
            Vector3D upEnd = Vector3D.Zero;
            Vector3D forwStart = Vector3D.Zero;
            Vector3D forwEnd = Vector3D.Zero;
            Vector3D rightStart2 = Vector3D.Zero;
            Vector3D rightEnd2 = Vector3D.Zero;
            Vector3D upStart2 = Vector3D.Zero;
            Vector3D upEnd2 = Vector3D.Zero;
            Vector3D forwStart2 = Vector3D.Zero;
            Vector3D forwEnd2 = Vector3D.Zero;
            int rightAxis = -1, upAxis = -1, forwAxis = -1;
            int closestRightEdge = -1, closestUpEdge = -1, closestForwEdge = -1;
            int closestRightEdge2 = -1, closestUpEdge2 = -1, closestForwEdge2 = -1;

            if (RotationRightAxis == 0)
            {
                rightStart = startXVertex;
                rightEnd = endXVertex;
                rightStart2 = startXVertex2;
                rightEnd2 = endXVertex2;
                rightAxis = 0;
                closestRightEdge = closestXAxis;
                closestRightEdge2 = closestXAxis2;
            }
            else
                if (RotationRightAxis == 1)
                {
                    rightStart = startYVertex;
                    rightEnd = endYVertex;
                    rightStart2 = startYVertex2;
                    rightEnd2 = endYVertex2;
                    rightAxis = 1;
                    closestRightEdge = closestYAxis;
                    closestRightEdge2 = closestYAxis2;
                }
                else
                    if (RotationRightAxis == 2)
                    {
                        rightStart = startZVertex;
                        rightEnd = endZVertex;
                        rightStart2 = startZVertex2;
                        rightEnd2 = endZVertex2;
                        rightAxis = 2;
                        closestRightEdge = closestZAxis;
                        closestRightEdge2 = closestZAxis2;
                    }
                    else
                    {
                        System.Diagnostics.Debug.Assert(false, "Not defined axis");
                    }

            if (RotationUpAxis == 0)
            {
                upStart = startXVertex;
                upEnd = endXVertex;
                upStart2 = startXVertex2;
                upEnd2 = endXVertex2;
                upAxis = 0;
                closestUpEdge = closestXAxis;
                closestUpEdge2 = closestXAxis2;
            }
            else
                if (RotationUpAxis == 1)
                {
                    upStart = startYVertex;
                    upEnd = endYVertex;
                    upStart2 = startYVertex2;
                    upEnd2 = endYVertex2;
                    upAxis = 1;
                    closestUpEdge = closestYAxis;
                    closestUpEdge2 = closestYAxis2;
                }
                else
                    if (RotationUpAxis == 2)
                    {
                        upStart = startZVertex;
                        upEnd = endZVertex;
                        upStart2 = startZVertex2;
                        upEnd2 = endZVertex2;
                        upAxis = 2;
                        closestUpEdge = closestZAxis;
                        closestUpEdge2 = closestZAxis2;
                    }

            if (RotationForwardAxis == 0)
            {
                forwStart = startXVertex;
                forwEnd = endXVertex;
                forwStart2 = startXVertex2;
                forwEnd2 = endXVertex2;
                forwAxis = 0;
                closestForwEdge = closestXAxis;
                closestForwEdge2 = closestXAxis2;
            }
            else
                if (RotationForwardAxis == 1)
                {
                    forwStart = startYVertex;
                    forwEnd = endYVertex;
                    forwStart2 = startYVertex2;
                    forwEnd2 = endYVertex2;
                    forwAxis = 1;
                    closestForwEdge = closestYAxis;
                    closestForwEdge2 = closestYAxis2;
                }
                else
                    if (RotationForwardAxis == 2)
                    {
                        forwStart = startZVertex;
                        forwEnd = endZVertex;
                        forwStart2 = startZVertex2;
                        forwEnd2 = endZVertex2;
                        forwAxis = 2;
                        closestForwEdge = closestZAxis;
                        closestForwEdge2 = closestZAxis2;
                    }

            float textScale = 0.7f;

            //Closest axis
            //VRageRender.MyRenderProxy.DebugDrawLine3D(rightStart, rightEnd, Color.Red, Color.Red, false);
            //VRageRender.MyRenderProxy.DebugDrawLine3D(upStart, upEnd, Color.Green, Color.Green, false);
            //VRageRender.MyRenderProxy.DebugDrawLine3D(forwStart, forwEnd, Color.Blue, Color.Blue, false);


            if (draw)
            {
                //if all axis are visible, all are shown on edges
                //if 1 axis is not visible, other 2 must be shown on faces
                //if 2 are not visible, they are shown on faces and the one is shown on face center
                //Vector3 camVector = Vector3.Normalize(rotateHintsBox.Center - MySector.MainCamera.Position);
                Vector3D camVector = MySector.MainCamera.ForwardVector;
                Vector3D rightDirection = Vector3.Normalize(rightEnd - rightStart);
                Vector3D upDirection = Vector3.Normalize(upEnd - upStart);
                Vector3D forwDirection = Vector3.Normalize(forwEnd - forwStart);
                float dotRight = Math.Abs(Vector3.Dot(camVector, rightDirection));
                float dotUp = Math.Abs(Vector3.Dot(camVector, upDirection));
                float dotForw = Math.Abs(Vector3.Dot(camVector, forwDirection));

                bool drawRightOnFace = false, drawUpOnFace = false, drawForwOnFace = false;
                bool drawRightOnFaceCenter = false, drawUpOnFaceCenter = false, drawForwOnFaceCenter = false;

                float dotAngle = 0.4f;

                if (dotRight < dotAngle)
                {
                    if (dotUp < dotAngle)
                    {
                        drawForwOnFaceCenter = true;
                        drawRightOnFace = true;
                        drawUpOnFace = true;

                        System.Diagnostics.Debug.Assert(dotForw >= dotAngle);
                    }
                    else if (dotForw < dotAngle)
                    {
                        drawUpOnFaceCenter = true;
                        drawRightOnFace = true;
                        drawForwOnFace = true;

                        System.Diagnostics.Debug.Assert(dotUp >= dotAngle);
                    }
                    else
                    {
                        drawUpOnFace = true;
                        drawForwOnFace = true;
                    }
                }
                else
                    if (dotUp < dotAngle)
                    {
                        if (dotRight < dotAngle)
                        {
                            drawForwOnFaceCenter = true;
                            drawRightOnFace = true;
                            drawUpOnFace = true;

                            System.Diagnostics.Debug.Assert(dotForw >= dotAngle);
                        }
                        else if (dotForw < dotAngle)
                        {
                            drawRightOnFaceCenter = true;
                            drawUpOnFace = true;
                            drawForwOnFace = true;

                            System.Diagnostics.Debug.Assert(dotRight >= dotAngle);
                        }
                        else
                        {
                            drawRightOnFace = true;
                            drawForwOnFace = true;
                        }
                    }
                    else
                        if (dotForw < dotAngle)
                        {
                            if (dotRight < dotAngle)
                            {
                                drawUpOnFaceCenter = true;
                                drawRightOnFace = true;
                                drawForwOnFace = true;

                                System.Diagnostics.Debug.Assert(dotUp >= dotAngle);
                            }
                            else if (dotUp < dotAngle)
                            {
                                drawUpOnFaceCenter = true;
                                drawRightOnFace = true;
                                drawForwOnFace = true;

                                System.Diagnostics.Debug.Assert(dotRight >= dotAngle);
                            }
                            else
                            {
                                drawUpOnFace = true;
                                drawRightOnFace = true;
                            }
                        }

                //Draw according to cube visual appearance

                if (!(hideForwardAndUpArrows && RotationRightAxis != 1))
                {
                    if (drawRightOnFaceCenter)
                    {
                        //                VRageRender.MyRenderProxy.DebugDrawSphere((forwStart + forwEnd + forwStart2 + forwEnd2) * 0.25f, 0.2f, Vector3.Right, 1.0f, false, false);
                        Vector3D faceCenter = (forwStart + forwEnd + forwStart2 + forwEnd2) * 0.25f;

                        MyTransparentGeometry.AddBillboardOriented(
                               "ArrowLeftGreen",
                               Vector4.One,
                               faceCenter - RotationForwardDirection * forwDirection * 0.2f - RotationRightDirection * rightDirection * 0.01f,
                               -RotationForwardDirection * forwDirection,
                               -RotationUpDirection * upDirection,
                               0.2f,
                               110, false, projectionId);

                        MyTransparentGeometry.AddBillboardOriented(
                               "ArrowRightGreen",
                               Vector4.One,
                               faceCenter + RotationForwardDirection * forwDirection * 0.2f - RotationRightDirection * rightDirection * 0.01f,
                               RotationForwardDirection * forwDirection,
                               RotationUpDirection * upDirection,
                               0.2f,
                               110, false, projectionId);

                        VRageRender.MyRenderProxy.DebugDrawText3D(faceCenter - RotationForwardDirection * forwDirection * 0.2f - RotationRightDirection * rightDirection * 0.01f, rightControlName2, Color.White, textScale, false, MyGuiDrawAlignEnum.HORISONTAL_CENTER_AND_VERTICAL_CENTER, projectionId);
                        VRageRender.MyRenderProxy.DebugDrawText3D(faceCenter + RotationForwardDirection * forwDirection * 0.2f - RotationRightDirection * rightDirection * 0.01f, rightControlName1, Color.White, textScale, false, MyGuiDrawAlignEnum.HORISONTAL_CENTER_AND_VERTICAL_CENTER, projectionId);
                    }
                    else
                        if (drawRightOnFace)
                        {
                            //VRageRender.MyRenderProxy.DebugDrawLine3D(rightStart2, rightEnd2, Color.Red, Color.Red, false);

                            Vector3 normalRightBack, normalRightForw;
                            MyOrientedBoundingBox.GetNormalBetweenEdges(rightAxis, closestRightEdge, closestRightEdge2, out normalRightForw);
                            Vector3D rightCenter = (rightStart + rightEnd) * 0.5f;
                            Vector3D rightNormalForwWorld = Vector3D.TransformNormal(normalRightForw, drawMatrix);

                            MyOrientedBoundingBox.GetNormalBetweenEdges(rightAxis, closestRightEdge2, closestRightEdge, out normalRightBack);
                            Vector3D rightCenter2 = (rightStart2 + rightEnd2) * 0.5f;
                            Vector3D rightNormalBackWorld = Vector3D.TransformNormal(normalRightBack, drawMatrix);

                            //VRageRender.MyRenderProxy.DebugDrawLine3D(rightCenter, rightCenter + rightNormalForwWorld, Color.Red, Color.Red, false);
                            //VRageRender.MyRenderProxy.DebugDrawLine3D(rightCenter2, rightCenter2 + rightNormalBackWorld, Color.Red, Color.Red, false);

                            int normalEdge = -1;
                            bool opposite = false;
                            if (closestRightEdge == 0 && closestRightEdge2 == 3)
                                normalEdge = closestRightEdge + 1;
                            else
                                if ((closestRightEdge < closestRightEdge2) || (closestRightEdge == 3 && closestRightEdge2 == 0))
                                {
                                    normalEdge = closestRightEdge - 1;
                                    opposite = true;
                                }
                                else
                                    normalEdge = closestRightEdge + 1;

                            if (RotationRightDirection < 0) opposite = !opposite;

                            Vector3 rightOffset;
                            MyOrientedBoundingBox.GetNormalBetweenEdges(rightAxis, closestRightEdge, normalEdge, out rightOffset);
                            Vector3D rightOffsetWorld = Vector3D.TransformNormal(rightOffset, drawMatrix);

                            //VRageRender.MyRenderProxy.DebugDrawText3D(rightCenter + rightNormalForwWorld * 0.6f - rightOffsetWorld * 0.01f, opposite ? rightControlName2 : rightControlName1, Color.White, textScale, false);
                            //VRageRender.MyRenderProxy.DebugDrawText3D(rightCenter2 + rightNormalBackWorld * 0.6f - rightOffsetWorld * 0.01f, opposite ? rightControlName1 : rightControlName2, Color.White, textScale, false);

                            MyTransparentGeometry.AddBillboardOriented(
                               "ArrowGreen",
                               Vector4.One,
                               rightCenter + rightNormalForwWorld * 0.4f - rightOffsetWorld * 0.01f,
                               rightNormalBackWorld,
                               rightDirection,
                               0.5f,
                               110, false, projectionId);

                            MyTransparentGeometry.AddBillboardOriented(
                               "ArrowGreen",
                               Vector4.One,
                               rightCenter2 + rightNormalBackWorld * 0.4f - rightOffsetWorld * 0.01f,
                               rightNormalForwWorld,
                               rightDirection,
                               0.5f,
                               110, false, projectionId);

                            VRageRender.MyRenderProxy.DebugDrawText3D(rightCenter + rightNormalForwWorld * 0.3f - rightOffsetWorld * 0.01f, opposite ? rightControlName1 : rightControlName2, Color.White, textScale, false, MyGuiDrawAlignEnum.HORISONTAL_CENTER_AND_VERTICAL_CENTER, projectionId);
                            VRageRender.MyRenderProxy.DebugDrawText3D(rightCenter2 + rightNormalBackWorld * 0.3f - rightOffsetWorld * 0.01f, opposite ? rightControlName2 : rightControlName1, Color.White, textScale, false, MyGuiDrawAlignEnum.HORISONTAL_CENTER_AND_VERTICAL_CENTER, projectionId);

                        }
                        else //draw on edge
                        {
                            Vector3 normalRightBack, normalRightForw;
                            MyOrientedBoundingBox.GetNormalBetweenEdges(rightAxis, closestRightEdge, closestRightEdge + 1, out normalRightForw);
                            MyOrientedBoundingBox.GetNormalBetweenEdges(rightAxis, closestRightEdge, closestRightEdge - 1, out normalRightBack);
                            Vector3D rightCenter = (rightStart + rightEnd) * 0.5f;
                            Vector3D rightNormalForwWorld = Vector3D.TransformNormal(normalRightForw, drawMatrix);
                            Vector3D rightNormalBackWorld = Vector3D.TransformNormal(normalRightBack, drawMatrix);
                            //VRageRender.MyRenderProxy.DebugDrawLine3D(rightCenter, rightCenter + rightNormalForwWorld, Color.Red, Color.Red, false);
                            //VRageRender.MyRenderProxy.DebugDrawLine3D(rightCenter, rightCenter + rightNormalBackWorld, Color.Red, Color.Red, false);

                            MyTransparentGeometry.AddBillboardOriented(
                                "ArrowGreen",
                                Vector4.One,
                                rightCenter + rightNormalForwWorld * 0.3f - rightNormalBackWorld * 0.01f,
                                rightNormalForwWorld,
                                rightDirection,
                                0.5f,
                                110, false, projectionId);

                            MyTransparentGeometry.AddBillboardOriented(
                               "ArrowGreen",
                               Vector4.One,
                               rightCenter + rightNormalBackWorld * 0.3f - rightNormalForwWorld * 0.01f,
                               rightNormalBackWorld,
                               rightDirection,
                               0.5f,
                               110, false, projectionId);

                            VRageRender.MyRenderProxy.DebugDrawText3D(rightCenter + rightNormalForwWorld * 0.3f - rightNormalBackWorld * 0.01f, RotationRightDirection < 0 ? rightControlName1 : rightControlName2, Color.White, textScale, false, MyGuiDrawAlignEnum.HORISONTAL_CENTER_AND_VERTICAL_CENTER, projectionId);
                            VRageRender.MyRenderProxy.DebugDrawText3D(rightCenter + rightNormalBackWorld * 0.3f - rightNormalForwWorld * 0.01f, RotationRightDirection < 0 ? rightControlName2 : rightControlName1, Color.White, textScale, false, MyGuiDrawAlignEnum.HORISONTAL_CENTER_AND_VERTICAL_CENTER, projectionId);

                        }
                }

                if (!(hideForwardAndUpArrows && RotationUpAxis != 1))
                {
                    if (drawUpOnFaceCenter)
                    {
                        //VRageRender.MyRenderProxy.DebugDrawSphere((forwStart + forwEnd + forwStart2 + forwEnd2) * 0.25f, 0.2f, Vector3.Up, 1.0f, false, false);

                        Vector3D faceCenter = (forwStart + forwEnd + forwStart2 + forwEnd2) * 0.25f;

                        MyTransparentGeometry.AddBillboardOriented(
                               "ArrowLeftRed",
                               Vector4.One,
                               faceCenter - RotationRightDirection * rightDirection * 0.2f - RotationUpDirection * upDirection * 0.01f,
                               -RotationRightDirection * rightDirection,
                               -RotationForwardDirection * forwDirection,
                               0.2f,
                               110, false, projectionId);

                        MyTransparentGeometry.AddBillboardOriented(
                               "ArrowRightRed",
                               Vector4.One,
                               faceCenter + RotationRightDirection * rightDirection * 0.2f - RotationUpDirection * upDirection * 0.01f,
                               RotationRightDirection * rightDirection,
                               RotationForwardDirection * forwDirection,
                               0.2f,
                               110, false, projectionId);

                        VRageRender.MyRenderProxy.DebugDrawText3D(faceCenter - RotationRightDirection * rightDirection * 0.2f - RotationUpDirection * upDirection * 0.01f, upControlName1, Color.White, textScale, false, MyGuiDrawAlignEnum.HORISONTAL_CENTER_AND_VERTICAL_CENTER, projectionId);
                        VRageRender.MyRenderProxy.DebugDrawText3D(faceCenter + RotationRightDirection * rightDirection * 0.2f - RotationUpDirection * upDirection * 0.01f, upControlName2, Color.White, textScale, false, MyGuiDrawAlignEnum.HORISONTAL_CENTER_AND_VERTICAL_CENTER, projectionId);
                    }
                    else
                        if (drawUpOnFace)
                        {
                            //VRageRender.MyRenderProxy.DebugDrawLine3D(upStart2, upEnd2, Color.Green, Color.Green, false);

                            Vector3 normalUpBack, normalUpForw;
                            MyOrientedBoundingBox.GetNormalBetweenEdges(upAxis, closestUpEdge, closestUpEdge2, out normalUpForw);
                            Vector3D upCenter = (upStart + upEnd) * 0.5f;
                            Vector3 upNormalForwWorld = Vector3.TransformNormal(normalUpForw, drawMatrix);

                            MyOrientedBoundingBox.GetNormalBetweenEdges(upAxis, closestUpEdge2, closestUpEdge, out normalUpBack);
                            Vector3D upCenter2 = (upStart2 + upEnd2) * 0.5f;
                            Vector3 upNormalBackWorld = Vector3.TransformNormal(normalUpBack, drawMatrix);

                            //VRageRender.MyRenderProxy.DebugDrawLine3D(upCenter, upCenter + upNormalForwWorld, Color.Green, Color.Green, false);
                            //VRageRender.MyRenderProxy.DebugDrawLine3D(upCenter2, upCenter2 + upNormalBackWorld, Color.Green, Color.Green, false);

                            int normalEdge = -1;
                            bool opposite = false;
                            if (closestUpEdge == 0 && closestUpEdge2 == 3)
                                normalEdge = closestUpEdge + 1;
                            else
                                if ((closestUpEdge < closestUpEdge2) || (closestUpEdge == 3 && closestUpEdge2 == 0))
                                {
                                    normalEdge = closestUpEdge - 1;
                                    opposite = true;
                                }
                                else
                                    normalEdge = closestUpEdge + 1;

                            if (RotationUpDirection < 0) opposite = !opposite;

                            Vector3 upOffset;
                            MyOrientedBoundingBox.GetNormalBetweenEdges(upAxis, closestUpEdge, normalEdge, out upOffset);
                            Vector3 upOffsetWorld = Vector3.TransformNormal(upOffset, drawMatrix);

                            //VRageRender.MyRenderProxy.DebugDrawText3D(upCenter + upNormalForwWorld * 0.6f - upOffsetWorld * 0.01f, opposite ? upControlName1 : upControlName2, Color.White, textScale, false);
                            //VRageRender.MyRenderProxy.DebugDrawText3D(upCenter2 + upNormalBackWorld * 0.6f - upOffsetWorld * 0.01f, opposite ? upControlName2 : upControlName1, Color.White, textScale, false);

                            MyTransparentGeometry.AddBillboardOriented(
                              "ArrowRed",
                              Vector4.One,
                              upCenter + upNormalForwWorld * 0.4f - upOffsetWorld * 0.01f,
                              upNormalBackWorld,
                              upDirection,
                              0.5f,
                              110, false, projectionId);

                            MyTransparentGeometry.AddBillboardOriented(
                               "ArrowRed",
                               Vector4.One,
                               upCenter2 + upNormalBackWorld * 0.4f - upOffsetWorld * 0.01f,
                               upNormalForwWorld,
                               upDirection,
                               0.5f,
                               110, false, projectionId);

                            VRageRender.MyRenderProxy.DebugDrawText3D(upCenter + upNormalForwWorld * 0.3f - upOffsetWorld * 0.01f, opposite ? upControlName2 : upControlName1, Color.White, textScale, false, MyGuiDrawAlignEnum.HORISONTAL_CENTER_AND_VERTICAL_CENTER, projectionId);
                            VRageRender.MyRenderProxy.DebugDrawText3D(upCenter2 + upNormalBackWorld * 0.3f - upOffsetWorld * 0.01f, opposite ? upControlName1 : upControlName2, Color.White, textScale, false, MyGuiDrawAlignEnum.HORISONTAL_CENTER_AND_VERTICAL_CENTER, projectionId);

                        }
                        else //draw on edge
                        {
                            Vector3 normalUpBack, normalUpForw;
                            MyOrientedBoundingBox.GetNormalBetweenEdges(upAxis, closestUpEdge, closestUpEdge + 1, out normalUpForw);
                            MyOrientedBoundingBox.GetNormalBetweenEdges(upAxis, closestUpEdge, closestUpEdge - 1, out normalUpBack);
                            Vector3D upCenter = (upStart + upEnd) * 0.5f;
                            Vector3 upNormalForwWorld = Vector3.TransformNormal(normalUpForw, drawMatrix);
                            Vector3 upNormalBackWorld = Vector3.TransformNormal(normalUpBack, drawMatrix);
                            //VRageRender.MyRenderProxy.DebugDrawLine3D(upCenter, upCenter + upNormalForwWorld, Color.Green, Color.Green, false);
                            //VRageRender.MyRenderProxy.DebugDrawLine3D(upCenter, upCenter + upNormalBackWorld, Color.Green, Color.Green, false);

                            MyTransparentGeometry.AddBillboardOriented(
                                "ArrowRed",
                                Vector4.One,
                                upCenter + upNormalForwWorld * 0.3f - upNormalBackWorld * 0.01f,
                                upNormalForwWorld,
                                upDirection,
                                0.5f,
                                110, false, projectionId);

                            MyTransparentGeometry.AddBillboardOriented(
                               "ArrowRed",
                               Vector4.One,
                               upCenter + upNormalBackWorld * 0.3f - upNormalForwWorld * 0.01f,
                               upNormalBackWorld,
                               upDirection,
                               0.5f,
                               110, false, projectionId);

                            VRageRender.MyRenderProxy.DebugDrawText3D(upCenter + upNormalForwWorld * 0.6f - upNormalBackWorld * 0.01f, RotationUpDirection > 0 ? upControlName1 : upControlName2, Color.White, textScale, false, MyGuiDrawAlignEnum.HORISONTAL_CENTER_AND_VERTICAL_CENTER, projectionId);
                            VRageRender.MyRenderProxy.DebugDrawText3D(upCenter + upNormalBackWorld * 0.6f - upNormalForwWorld * 0.01f, RotationUpDirection > 0 ? upControlName2 : upControlName1, Color.White, textScale, false, MyGuiDrawAlignEnum.HORISONTAL_CENTER_AND_VERTICAL_CENTER, projectionId);
                        }
                }

                if (!(hideForwardAndUpArrows && RotationForwardAxis != 1))
                {
                    if (drawForwOnFaceCenter)
                    {
                        //VRageRender.MyRenderProxy.DebugDrawSphere((rightStart + rightEnd + rightStart2 + rightEnd2) * 0.25f, 0.2f, Vector3.Backward, 1.0f, false, false);

                        Vector3D faceCenter = (rightStart + rightEnd + rightStart2 + rightEnd2) * 0.25f;

                        MyTransparentGeometry.AddBillboardOriented(
                               "ArrowLeftBlue",
                               Vector4.One,
                               faceCenter + RotationUpDirection * upDirection * 0.2f - RotationForwardDirection * forwDirection * 0.01f,
                               RotationUpDirection * upDirection,
                               -RotationRightDirection * rightDirection,
                               0.2f,
                               110, false, projectionId);

                        MyTransparentGeometry.AddBillboardOriented(
                               "ArrowRightBlue",
                               Vector4.One,
                               faceCenter - RotationUpDirection * upDirection * 0.2f - RotationForwardDirection * forwDirection * 0.01f,
                               -RotationUpDirection * upDirection,
                               RotationRightDirection * rightDirection,
                               0.2f,
                               110, false, projectionId);

                        VRageRender.MyRenderProxy.DebugDrawText3D(faceCenter + RotationUpDirection * upDirection * 0.2f - RotationForwardDirection * forwDirection * 0.01f, forwControlName1, Color.White, textScale, false, MyGuiDrawAlignEnum.HORISONTAL_LEFT_AND_VERTICAL_CENTER, projectionId);
                        VRageRender.MyRenderProxy.DebugDrawText3D(faceCenter - RotationUpDirection * upDirection * 0.2f - RotationForwardDirection * forwDirection * 0.01f, forwControlName2, Color.White, textScale, false, MyGuiDrawAlignEnum.HORISONTAL_LEFT_AND_VERTICAL_CENTER, projectionId);
                    }
                    else
                        if (drawForwOnFace)
                        {
                            //VRageRender.MyRenderProxy.DebugDrawLine3D(forwStart2, forwEnd2, Color.Blue, Color.Blue, false);

                            Vector3 normalForwBack, normalForwForw;
                            MyOrientedBoundingBox.GetNormalBetweenEdges(forwAxis, closestForwEdge, closestForwEdge2, out normalForwForw);
                            Vector3D forwCenter = (forwStart + forwEnd) * 0.5f;
                            Vector3 forwNormalForwWorld = Vector3.TransformNormal(normalForwForw, drawMatrix);

                            MyOrientedBoundingBox.GetNormalBetweenEdges(forwAxis, closestForwEdge2, closestForwEdge, out normalForwBack);
                            Vector3D forwCenter2 = (forwStart2 + forwEnd2) * 0.5f;
                            Vector3 forwNormalBackWorld = Vector3.TransformNormal(normalForwBack, drawMatrix);

                            //VRageRender.MyRenderProxy.DebugDrawLine3D(forwCenter, forwCenter + forwNormalForwWorld, Color.Blue, Color.Blue, false);
                            //VRageRender.MyRenderProxy.DebugDrawLine3D(forwCenter2, forwCenter2 + forwNormalBackWorld, Color.Blue, Color.Blue, false);

                            int normalEdge = -1;
                            bool opposite = false;
                            if (closestForwEdge == 0 && closestForwEdge2 == 3)
                                normalEdge = closestForwEdge + 1;
                            else
                                if ((closestForwEdge < closestForwEdge2) || (closestForwEdge == 3 && closestForwEdge2 == 0))
                                {
                                    normalEdge = closestForwEdge - 1;
                                    opposite = true;
                                }
                                else
                                    normalEdge = closestForwEdge + 1;

                            if (RotationForwardDirection < 0) opposite = !opposite;

                            Vector3 forwOffset;
                            MyOrientedBoundingBox.GetNormalBetweenEdges(forwAxis, closestForwEdge, normalEdge, out forwOffset);
                            Vector3 forwOffsetWorld = Vector3.TransformNormal(forwOffset, drawMatrix);

                            //VRageRender.MyRenderProxy.DebugDrawText3D(forwCenter + forwNormalForwWorld * 0.6f - forwOffsetWorld * 0.01f, opposite ? forwControlName2 : forwControlName1, Color.White, textScale, false);
                            //VRageRender.MyRenderProxy.DebugDrawText3D(forwCenter2 + forwNormalBackWorld * 0.6f - forwOffsetWorld * 0.01f, opposite ? forwControlName1 : forwControlName2, Color.White, textScale, false);

                            MyTransparentGeometry.AddBillboardOriented(
                               "ArrowBlue",
                               Vector4.One,
                               forwCenter + forwNormalForwWorld * 0.4f - forwOffsetWorld * 0.01f,
                               forwNormalBackWorld,
                               forwDirection,
                               0.5f,
                               110, false, projectionId);

                            MyTransparentGeometry.AddBillboardOriented(
                               "ArrowBlue",
                               Vector4.One,
                               forwCenter2 + forwNormalBackWorld * 0.4f - forwOffsetWorld * 0.01f,
                               forwNormalForwWorld,
                               forwDirection,
                               0.5f,
                               110, false, projectionId);

                            VRageRender.MyRenderProxy.DebugDrawText3D(forwCenter + forwNormalForwWorld * 0.3f - forwOffsetWorld * 0.01f, opposite ? forwControlName1 : forwControlName2, Color.White, textScale, false, MyGuiDrawAlignEnum.HORISONTAL_CENTER_AND_VERTICAL_CENTER, projectionId);
                            VRageRender.MyRenderProxy.DebugDrawText3D(forwCenter2 + forwNormalBackWorld * 0.3f - forwOffsetWorld * 0.01f, opposite ? forwControlName2 : forwControlName1, Color.White, textScale, false, MyGuiDrawAlignEnum.HORISONTAL_CENTER_AND_VERTICAL_CENTER, projectionId);
                        }
                        else //draw on edge
                        {
                            Vector3 normalForwBack, normalForwForw;
                            MyOrientedBoundingBox.GetNormalBetweenEdges(forwAxis, closestForwEdge, closestForwEdge + 1, out normalForwForw);
                            MyOrientedBoundingBox.GetNormalBetweenEdges(forwAxis, closestForwEdge, closestForwEdge - 1, out normalForwBack);
                            Vector3D forwCenter = (forwStart + forwEnd) * 0.5f;
                            Vector3 forwNormalForwWorld = Vector3.TransformNormal(normalForwForw, drawMatrix);
                            Vector3 forwNormalBackWorld = Vector3.TransformNormal(normalForwBack, drawMatrix);
                            //VRageRender.MyRenderProxy.DebugDrawLine3D(forwCenter, forwCenter + forwNormalForwWorld, Color.Blue, Color.Blue, false);
                            //VRageRender.MyRenderProxy.DebugDrawLine3D(forwCenter, forwCenter + forwNormalBackWorld, Color.Blue, Color.Blue, false);

                            MyTransparentGeometry.AddBillboardOriented(
                                "ArrowBlue",
                                Vector4.One,
                                forwCenter + forwNormalForwWorld * 0.3f - forwNormalBackWorld * 0.01f,
                                forwNormalForwWorld,
                                forwDirection,
                                0.5f,
                                110, false, projectionId);

                            MyTransparentGeometry.AddBillboardOriented(
                               "ArrowBlue",
                               Vector4.One,
                               forwCenter + forwNormalBackWorld * 0.3f - forwNormalForwWorld * 0.01f,
                               forwNormalBackWorld,
                               forwDirection,
                               0.5f,
                               110, false, projectionId);

                            VRageRender.MyRenderProxy.DebugDrawText3D(forwCenter + forwNormalForwWorld * 0.3f - forwNormalBackWorld * 0.01f, RotationForwardDirection < 0 ? forwControlName1 : forwControlName2, Color.White, textScale, false, MyGuiDrawAlignEnum.HORISONTAL_CENTER_AND_VERTICAL_CENTER, projectionId);
                            VRageRender.MyRenderProxy.DebugDrawText3D(forwCenter + forwNormalBackWorld * 0.3f - forwNormalForwWorld * 0.01f, RotationForwardDirection < 0 ? forwControlName2 : forwControlName1, Color.White, textScale, false, MyGuiDrawAlignEnum.HORISONTAL_CENTER_AND_VERTICAL_CENTER, projectionId);
                        }
                }
            }
        }
 // Draw OBB and highlight it white if selected
 private void DrawOBB(MyOrientedBoundingBoxD obb, Color color, float alpha, int identificationIndex)
 {
     if (identificationIndex == m_selected)
     {
         MyRenderProxy.DebugDrawOBB(obb, Color.White, 0.2f, false, false);
     }
     else
     {
         MyRenderProxy.DebugDrawOBB(obb, color, alpha, false, false);
     }
 }
        /// <summary>
        /// Handles camera collisions with environment
        /// </summary>
        /// <param name="controlledEntity"></param>
        /// <param name="shakeActive"></param>
        /// <param name="headPosition"></param>
        /// <param name="headDirection"></param>
        /// <returns>False if no correct position was found</returns>
        private bool HandleIntersection(MyEntity controlledEntity, MyOrientedBoundingBoxD safeOBB, bool requireRaycast, bool shakeActive, Vector3D headPosition, Vector3 headDirection)
        {
            var line = new LineD(m_target, m_position);

            var safeOBBLine = new LineD(line.From, line.From + line.Direction * 2 * safeOBB.HalfExtent.Length());
            Vector3D castStartSafe;
            {
                MyOrientedBoundingBoxD safeObbWithCollisionExtents = new MyOrientedBoundingBoxD(safeOBB.Center, safeOBB.HalfExtent + 2 * CAMERA_RADIUS, safeOBB.Orientation);
                double? safeIntersection = safeObbWithCollisionExtents.Intersects(ref safeOBBLine);
                if (!safeIntersection.HasValue)
                    safeIntersection = safeOBB.HalfExtent.Length();
                double safeDistance = safeIntersection.Value;
                castStartSafe = line.From + line.Direction * safeDistance;
            }

            {
                double? unsafeIntersection = safeOBB.Intersects(ref safeOBBLine);
                if (!requireRaycast && unsafeIntersection.HasValue)
                {
                    var castStartUnsafe = line.From + line.Direction * unsafeIntersection.Value;
                    var castEndUnsafe = castStartSafe + line.Direction;
                    // short raycast, not causing problems with asteroids generating geometry
                    Physics.MyPhysics.CastRay(castStartUnsafe, castEndUnsafe, m_raycastList, MyPhysics.DefaultCollisionLayer);
                    if (!IsRaycastOK(m_raycastList))
                    {
                        return false;
                    }
                }
            }

            if (requireRaycast)
            {
                // short raycast, not causing problems with asteroids generating geometry
                Physics.MyPhysics.CastRay(line.From, castStartSafe + line.Direction, m_raycastList, MyPhysics.DefaultCollisionLayer);
                if (!IsRaycastOK(m_raycastList))
                {
                    return false;
                }
            }

            HkShape shape = new HkSphereShape(CAMERA_RADIUS);
            try
            {
                // small shape, not causing problems with asteroids generating geometry
                Physics.MyPhysics.GetPenetrationsShape(shape, ref castStartSafe, ref Quaternion.Identity, m_rigidList, 15);
                if (m_rigidList.Count > 0)
                {
                    bool sameGrid = false;
                    if (MySession.ControlledEntity != null && m_rigidList[0].Body != null)
                    {
                        sameGrid = m_rigidList[0].GetCollisionEntity() == MySession.ControlledEntity;
                    }

                    if (sameGrid)
                        castStartSafe += line.Direction;
                }

                var shapeCastLine = new LineD(castStartSafe, m_position);
                uint steps = 1;
                uint stepIdx = 0;
                if (shapeCastLine.Length > SHAPE_CAST_STEP)
                {
                    steps = (uint)Math.Ceiling(shapeCastLine.Length / SHAPE_CAST_STEP);
                    if (steps >= SHAPE_CAST_MAX_STEP_COUNT)
                        steps = SHAPE_CAST_MAX_STEP_COUNT - 1;
                    stepIdx = m_updateCount % steps;
                    m_lastShapeCastDistance[stepIdx] = float.PositiveInfinity;

                    Vector3D step = shapeCastLine.Direction * (shapeCastLine.Length / steps);
                    shapeCastLine = new LineD(castStartSafe + stepIdx * step, castStartSafe + (stepIdx + 1) * step);
                }

                if (false)
                {
                    BoundingBoxD bbox = BoundingBoxD.CreateInvalid();
                    bbox.Include(new BoundingSphereD(shapeCastLine.From, CAMERA_RADIUS));
                    bbox.Include(new BoundingSphereD(shapeCastLine.To, CAMERA_RADIUS));
                    VRageRender.MyRenderProxy.DebugDrawAABB(bbox, Color.Crimson, 1f, 1f, true);
                }

                var matrix = MatrixD.CreateTranslation(shapeCastLine.From);
                HkContactPointData? cpd;
                if (controlledEntity.Physics != null && controlledEntity.Physics.CharacterProxy != null)
                    cpd = MyPhysics.CastShapeReturnContactData(shapeCastLine.To, shape, ref matrix, controlledEntity.Physics.CharacterCollisionFilter, 0.0f); 
                else
                    cpd = MyPhysics.CastShapeReturnContactData(shapeCastLine.To, shape, ref matrix, HkGroupFilter.CalcFilterInfo(MyPhysics.DefaultCollisionLayer,0), 0.0f);
                if (cpd.HasValue)
                {
                    var point = shapeCastLine.From + shapeCastLine.Direction * shapeCastLine.Length * cpd.Value.DistanceFraction;
                    m_lastShapeCastDistance[stepIdx] = (float)(castStartSafe - point).Length();
                }
                else
                {
                    m_lastShapeCastDistance[stepIdx] = float.PositiveInfinity;
                }


                float? dist = null;
                for (int i = 0; i < steps; ++i)
                {
                    if (m_lastShapeCastDistance[i] != float.PositiveInfinity)
                        dist = Math.Min(m_lastShapeCastDistance[i], dist ?? float.PositiveInfinity);
                }

                if (dist.HasValue)
                {
                    if (dist == 0.0f)
                    {
                        return false;
                    }
                    else
                    {
                        m_positionSafe = castStartSafe + shapeCastLine.Direction * dist.Value;
                    }
                }
                else
                {
                    m_positionSafe = m_position;
                }
                return true;
            }
            finally
            {
                shape.RemoveReference();
            }
        }
Exemple #31
0
        public static unsafe void DisableItemsInObb(this MyEnvironmentSector sector, ref MyOrientedBoundingBoxD obb)
        {
            if (sector.DataView == null)
                return;

            obb.Center -= sector.SectorCenter;

            for (int sectorInd = 0; sectorInd < sector.DataView.LogicalSectors.Count; sectorInd++)
            {
                var logicalSector = sector.DataView.LogicalSectors[sectorInd];
                var logicalItems = logicalSector.Items;
                var cnt = logicalItems.Count;

                fixed (ItemInfo* items = logicalItems.GetInternalArray())
                    for (int i = 0; i < cnt; ++i)
                    {
                        if (items[i].DefinitionIndex >= 0 && obb.Contains(ref items[i].Position))
                            logicalSector.EnableItem(i, false);
                    }
            }
        }
        protected override void DoDetection(bool useHead)
        {
            ProfilerShort.Begin("DoDetection");
            if (Character == MySession.Static.ControlledEntity)
                MyHud.SelectedObjectHighlight.RemoveHighlight();

            var head = Character.GetHeadMatrix(false);
            var headPos = head.Translation - (Vector3D)head.Forward * 0.3; // Move to center of head, we don't want eyes (in front of head)

            Vector3D from;
            Vector3D dir;

            if (!useHead)
            {
                //Ondrej version
                var cameraMatrix = MySector.MainCamera.WorldMatrix;
                dir = cameraMatrix.Forward;
                from = MyUtils.LinePlaneIntersection(headPos, (Vector3)dir, cameraMatrix.Translation, (Vector3)dir);
            }
            else
            {
                //Petr version
                dir = head.Forward;
                from = headPos;
            }

            Vector3D to = from + dir * MyConstants.DEFAULT_INTERACTIVE_DISTANCE;

            //EnableDetectorsInArea(from);
            GatherDetectorsInArea(from);
            float closestDetector = float.MaxValue;
            IMyEntity closestEntity = null;
            IMyUseObject closestInteractive = null;
            foreach(var entity in m_detectableEntities)
            {
                if (entity == Character)
                    continue;
                var use = entity.Components.Get<MyUseObjectsComponentBase>() as MyUseObjectsComponent;
                if(use != null)
                {
                    float detectorDistance;
                    var interactive = use.RaycastDetectors(from, to, out detectorDistance);
                    if(Math.Abs(detectorDistance) < Math.Abs(closestDetector))
                    {
                        closestDetector = detectorDistance;
                        closestEntity = entity;
                        closestInteractive = interactive;
                    }
                }

                //Floating object handling - give FO useobject component!
                var use2 = entity as IMyUseObject;
                if (use2 != null)
                {
                    var m = use2.ActivationMatrix;
                    var ray = new RayD(from, to - from);
                    var obb = new MyOrientedBoundingBoxD(m);
                    var dist = obb.Intersects(ref ray);
                    if(dist.HasValue && Math.Abs(dist.Value) < Math.Abs(closestDetector))
                    {
                        closestDetector = (float)dist.Value;
                        closestEntity = entity;
                        closestInteractive = use2;
                    }
                }
            }
            m_detectableEntities.Clear();
            //VRageRender.MyRenderProxy.DebugDrawLine3D(from, to, Color.Red, Color.Green, true);
            //VRageRender.MyRenderProxy.DebugDrawSphere(headPos, 0.05f, Color.Red.ToVector3(), 1.0f, false);

            StartPosition = from;

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

            bool hasInteractive = false;

            int index = 0;
            while (index < m_hits.Count && (m_hits[index].HkHitInfo.Body == null || m_hits[index].HkHitInfo.GetHitEntity() == Character
                || m_hits[index].HkHitInfo.GetHitEntity() == null
                || m_hits[index].HkHitInfo.Body.HasProperty(HkCharacterRigidBody.MANIPULATED_OBJECT)
                || m_hits[index].HkHitInfo.Body.Layer == MyPhysics.CollisionLayers.VoxelLod1CollisionLayer)) // Skip invalid hits and self character
            {
                index++;
            }

            if (index < m_hits.Count && m_hits[index].HkHitInfo.HitFraction > closestDetector - 0.05f)//compensation
            {
                // TODO: Uncomment to enforce that character must face object by front to activate it
                //if (TestInteractionDirection(head.Forward, h.Position - GetPosition()))
                //return;
                HitPosition = from + dir * closestDetector;
                MyUseObjectsComponentBase useObject;
                if(closestEntity.Components.TryGet<MyUseObjectsComponentBase>(out useObject))
                {
                    var detectorPhysics = useObject.DetectorPhysics;
                    HitMaterial = detectorPhysics.GetMaterialAt(HitPosition);
                    HitBody = ((MyPhysicsBody)detectorPhysics).RigidBody;
                }
                else
                {
                    HitMaterial = closestEntity.Physics.GetMaterialAt(HitPosition);
                    HitBody = ((MyPhysicsBody)closestEntity.Physics).RigidBody;
                }

                DetectedEntity = closestEntity;
                var interactive = closestInteractive;

                if (UseObject != null && interactive != null && UseObject != interactive)
                {
                    UseObject.OnSelectionLost();
                }

                //if (interactive != null && interactive.SupportedActions != UseActionEnum.None && (Vector3D.Distance(from, (Vector3D)h.Position)) < interactive.InteractiveDistance && Character == MySession.Static.ControlledEntity)
                if (interactive != null && interactive.SupportedActions != UseActionEnum.None && closestDetector * MyConstants.DEFAULT_INTERACTIVE_DISTANCE < interactive.InteractiveDistance && Character == MySession.Static.ControlledEntity)
                {
                    HandleInteractiveObject(interactive);

                    UseObject = interactive;
                    hasInteractive = true;
                }
            }

            if (!hasInteractive)
            {
                if (UseObject != null)
                {
                    UseObject.OnSelectionLost();
                }

                UseObject = null;         
            }

            ProfilerShort.End();
        }
Exemple #33
0
        public static void DebugDrawOBB(MyOrientedBoundingBoxD obb, Color color, float alpha, bool depthRead, bool smooth, bool persistent = false)
        {
            MatrixD obbMatrix = MatrixD.CreateFromQuaternion(obb.Orientation);
            obbMatrix.Right *= obb.HalfExtent.X*2;
            obbMatrix.Up *= obb.HalfExtent.Y*2;
            obbMatrix.Forward *= obb.HalfExtent.Z*2;
            obbMatrix.Translation = obb.Center;

            DebugDrawOBB(obbMatrix, color, alpha, depthRead, smooth, persistent: persistent);
        }
        /// <summary>
        /// Gets the ground vertices and the target grid vertices
        /// </summary>
        public WorldVerticesInfo GetWorldVertices(float border, Vector3D originPosition, MyOrientedBoundingBoxD obb, List<BoundingBoxD> boundingBoxes, List<MyVoxelMap> trackedEntities)
        {
            ClearWorldVertices();

            AddEntities(border, originPosition, obb, boundingBoxes, trackedEntities);
            AddGround(border, originPosition, obb, boundingBoxes);

            return m_worldVertices;
        }
            public override void Draw()
            {
                base.Draw();


                var pos = new Vector2(600, 100);
                foreach (var t in m_dbgComponents)
                {
                    var has = SelectedEntity != null && SelectedEntity.Components.Contains(t);
                    VRageRender.MyRenderProxy.DebugDrawText2D(pos, t.Name, has ? Color.Green : Color.White, 0.5f);
                    pos.Y += 10;
                }

                pos = new Vector2(580, 100 + 10 * m_memoryA);
                VRageRender.MyRenderProxy.DebugDrawText2D(pos, ">>", Color.White, 0.5f);
                if (SelectedEntity != null)
                {
                    var bbd = new BoundingBoxD(SelectedEntity.PositionComp.LocalAABB.Min, SelectedEntity.PositionComp.LocalAABB.Max);
                    MyOrientedBoundingBoxD obb = new MyOrientedBoundingBoxD(bbd, SelectedEntity.WorldMatrix);
                    //VRageRender.MyRenderProxy.DebugDrawOBB(obb, Color.White, 1, false, false);
                    VRageRender.MyRenderProxy.DebugDrawAABB(SelectedEntity.PositionComp.WorldAABB, Color.White, 1, 1, false);
                }

                DrawBodyInfo();
                //if (!MySandboxGame.Static.IsRunning)
                //    return;
                //VRageRender.MyRenderProxy.DebugDrawText2D(new Vector2(0.1f, 0.1f), "Destruction: " + (MyPerGameSettings.Destruction ? "ON" : "OFF"), Color.Red, 1);
                //VRageRender.MyRenderProxy.DebugDrawText2D(new Vector2(200f, 5f), "(Ctrl+Shift+D)", Color.Red, 0.65f);
                //VRageRender.MyRenderProxy.DebugDrawText2D(new Vector2(0.3f, 20f), "Strenght: " + STRENGHT, Color.Red, 1);
                //VRageRender.MyRenderProxy.DebugDrawText2D(new Vector2(0.1f, 40f), "Fracture: " + (FRACTURE ? "ON" : "OFF"), Color.Red, 1);
                //VRageRender.MyRenderProxy.DebugDrawText2D(new Vector2(160f, 45f), "(Ctrl+Shift+F)", Color.Red, 0.65f);
                //VRageRender.MyRenderProxy.DebugDrawText2D(new Vector2(0.1f, 60f), "Integrity: " + (MyFakes.DESTRUCTION_STRUCTURAL_INTEGRITY ? "ON" : "OFF"), Color.Red, 1);
                //VRageRender.MyRenderProxy.DebugDrawText2D(new Vector2(160f, 65f), "(Ctrl+I)", Color.Red, 0.65f);
                //VRageRender.MyRenderProxy.DebugDrawText2D(new Vector2(0.1f, 80f), "Position: " + POSITION, Color.Red, 1);
                //VRageRender.MyRenderProxy.DebugDrawText2D(new Vector2(0.1f, 100f), "Split: " + (GRID_SPLIT ? "ON" : "OFF"), Color.Red, 1);
                //VRageRender.MyRenderProxy.DebugDrawText2D(new Vector2(0.1f, 120f), "AConn: " + (!ManualConnect ? "ON" : "OFF"), Color.Red, 1);
                //VRageRender.MyRenderProxy.DebugDrawText2D(new Vector2(0.1f, 140f), "Hammer: " + (DestructionTool ? "ON" : "OFF"), Color.Red, 1);


                //VRageRender.MyRenderProxy.DebugDrawText2D(new Vector2(0.1f, 0.1f), "MassMultiplier " + MassMultiplier, Color.Red, 1);
                //VRageRender.MyRenderProxy.DebugDrawText2D(new Vector2(0.3f, 20f), ApplyMassMultiplier ? "ON" : "OFF", Color.Red, 1);
                //VRageRender.MyRenderProxy.DebugDrawText2D(new Vector2(0.3f, 40f), "Num1, N, B, ;, '", Color.Red, 1);
            }
        /// <summary>
        /// Adds the vertices from the grid blocks that are inside the given OBB
        /// </summary>
        /// <param name="grid"></param>
        /// <param name="obb"></param>
        /// <param name="vertices"></param>
        private void AddGridVerticesInsideOBB(MyCubeGrid grid, MyOrientedBoundingBoxD obb)
        {
            var aabb = obb.GetAABB();

            var gridGroup = MyCubeGridGroups.Static.Logical.GetGroup(grid);
            foreach (var node in gridGroup.Nodes)
            {
                var cubeGrid = (MyCubeGrid)node.NodeData;
                m_rdPathfinding.AddToTrackedGrids(cubeGrid);

                var worldMatrix = cubeGrid.WorldMatrix;
                worldMatrix.Translation -= m_center;
                var toRDWorld = MatrixD.Transform(worldMatrix, rdWorldQuaternion);

                if (MyPerGameSettings.Game == GameEnum.SE_GAME)
                {
                    var box = aabb.TransformFast(cubeGrid.PositionComp.WorldMatrixNormalizedInv);
                    Vector3I start = new Vector3I((int)Math.Round(box.Min.X), (int)Math.Round(box.Min.Y), (int)Math.Round(box.Min.Z));
                    Vector3I end = new Vector3I((int)Math.Round(box.Max.X), (int)Math.Round(box.Max.Y), (int)Math.Round(box.Max.Z));
                    start = Vector3I.Min(start, end);
                    end = Vector3I.Max(start, end);

                    ProfilerShort.Begin("GetShapesInInterval");
                    if (cubeGrid.Physics != null)
                        cubeGrid.Physics.Shape.GetShapesInInterval(start, end, m_tmpShapes);
                    ProfilerShort.End();

                    ProfilerShort.Begin("AddVertices");
                    foreach (var shape in m_tmpShapes)
                        AddPhysicalShape(shape, toRDWorld);

                    m_tmpShapes.Clear();
                    ProfilerShort.End();
                }
            }
        }
        /// <summary>
        /// Handles camera collisions with environment
        /// </summary>
        /// <returns>False if no correct position was found</returns>
        private void HandleIntersection(MyEntity controlledEntity)
        {
            Debug.Assert(controlledEntity != null);
            MyEntity parentEntity = controlledEntity.GetTopMostParent() ?? controlledEntity;
            var parentEntityAsCubeGrid = parentEntity as MyCubeGrid;
            if (parentEntityAsCubeGrid != null && parentEntityAsCubeGrid.IsStatic)
                parentEntity = controlledEntity;  // cancel previous assignment, topmost parent is a station, we need smaller bounding box

            // line from target to eye
            LineD line = new LineD(m_target, m_position);
            // oriented bb of the entity
            MyOrientedBoundingBoxD safeObb = GetEntitySafeOBB(parentEntity);
            // oriented bb of the entity + camera radius
            MyOrientedBoundingBoxD safeObbWithCollisionExtents = 
                new MyOrientedBoundingBoxD(safeObb.Center, safeObb.HalfExtent + (controlledEntity.Parent == null ? 0.5 : 2.0) * CAMERA_RADIUS, safeObb.Orientation);

            // start = target, end = eye
            // find safe start...
            LineD safeOBBLine = new LineD(line.From + line.Direction * 2 * safeObb.HalfExtent.Length(), line.From);
            double? safeIntersection = safeObbWithCollisionExtents.Intersects(ref safeOBBLine);
            Vector3D castStartSafe = safeIntersection != null ? (safeOBBLine.From + safeOBBLine.Direction * safeIntersection.Value) : m_target;

            if (controlledEntity.Parent != null && safeIntersection != null)
            {
                MatrixD shapeCastStart = MatrixD.CreateTranslation(castStartSafe);
                HkShape hkSphere = new HkSphereShape(CAMERA_RADIUS * 2);
                var hitInfo = MyPhysics.CastShapeReturnContactBodyData(m_target, hkSphere, ref shapeCastStart, 0, 0);

                //VRageRender.MyRenderProxy.DebugDrawCapsule(castStartSafe, m_target, CAMERA_RADIUS * 2, Color.Orange, false);
                
                MyEntity hitEntity = hitInfo.HasValue ? hitInfo.Value.HkHitInfo.GetHitEntity() as MyEntity : null;
                MyEntity entity = controlledEntity;

                var hitEntityWeldingGroup = hitEntity != null ? MyWeldingGroups.Static.GetGroup(hitEntity) : null;
                bool weldingGroupEquals = false;

                while (entity != null && !weldingGroupEquals)
                {
                    if (hitEntityWeldingGroup == MyWeldingGroups.Static.GetGroup(entity))
                        weldingGroupEquals = true;

                    entity = entity.Parent;
                }

                if (hitInfo.HasValue && hitEntityWeldingGroup != null && weldingGroupEquals)
                {
                    castStartSafe = castStartSafe + hitInfo.Value.HkHitInfo.HitFraction * (m_target - castStartSafe);
                }
                else
                {
                    safeObb = GetEntitySafeOBB(controlledEntity);
                    safeObbWithCollisionExtents = new MyOrientedBoundingBoxD(safeObb.Center, safeObb.HalfExtent + 0.5f * CAMERA_RADIUS, safeObb.Orientation);
                    safeIntersection = safeObbWithCollisionExtents.Intersects(ref safeOBBLine);
                    castStartSafe = safeIntersection != null ? (safeOBBLine.From + safeOBBLine.Direction * safeIntersection.Value) : m_target;
                }
                hkSphere.RemoveReference();
            }

            // raycast against occluders
            Vector3D safePositionCandidate;
            //double lastSafeMinimumDistance = m_safeMinimumDistance;
            m_safeMinimumDistance = controlledEntity is MyCharacter ? 0 : (castStartSafe - m_target).Length(); // store current safe minimum dist
            m_safeMinimumDistance = Math.Max(m_safeMinimumDistance, MIN_VIEWER_DISTANCE);
            //if (lastSafeMinimumDistance + 30.0f < m_safeMinimumDistance)
            //{
            //    castStartSafe = m_target + (castStartSafe - m_target) / m_safeMinimumDistance * lastSafeMinimumDistance;
            //    m_safeMinimumDistance = lastSafeMinimumDistance;
            //}
            Vector3D raycastOrigin = (controlledEntity is MyCharacter) ? m_target : castStartSafe;
            MyCameraRaycastResult raycastResult = RaycastOccludingObjects(controlledEntity, ref raycastOrigin, ref m_position,
                ref castStartSafe, out safePositionCandidate);

            // visual debugging :)
            if (m_debugDraw)
            {
                VRageRender.MyRenderProxy.DebugDrawOBB(safeObb, Color.Red, 0.1f, false, true);
                VRageRender.MyRenderProxy.DebugDrawOBB(safeObbWithCollisionExtents, Color.Yellow, 0.0f, false, true);
                VRageRender.MyRenderProxy.DebugDrawArrow3D(safeOBBLine.From, safeOBBLine.To, Color.White, Color.Purple,
                    false);
                VRageRender.MyRenderProxy.DebugDrawArrow3D(safeOBBLine.From, castStartSafe, Color.White, Color.Red,
                    false);
                VRageRender.MyRenderProxy.DebugDrawArrow3D(castStartSafe, m_position, Color.White, Color.Orange, false);

                VRageRender.MyRenderProxy.DebugDrawSphere(castStartSafe, 0.2f, Color.Green, 1.0f, false, true);
                VRageRender.MyRenderProxy.DebugDrawSphere(safePositionCandidate, 1.0f, Color.LightPink, 1, false);
            }

            switch (raycastResult)
            {
                case MyCameraRaycastResult.Ok:
                case MyCameraRaycastResult.FoundOccluder:
                    m_positionCurrentIsSafe = true;
                    {
                        double distFromCandidateToTarget = (safePositionCandidate - m_target).Length();
                        if (m_disableSpringThisFrame)
                        {
                            m_lastRaycastDist = (float) distFromCandidateToTarget;
                        }

                        if (!m_disableSpringThisFrame && 
                            ((distFromCandidateToTarget > m_lastRaycastDist + CAMERA_RADIUS && distFromCandidateToTarget > m_safeMinimumDistance)
                            || raycastResult == MyCameraRaycastResult.Ok))
                        {
                            // now we need it from the other side
                            double newDist = (safePositionCandidate - m_position).Length();
                            // new safe position is further from target => change over time (zoom out)
                            if (m_positionSafeZoomingOutTimeout <= 0)
                            {
                                float distDiffZoomSpeed = 1 -
                                                          MathHelper.Clamp((float) Math.Abs(m_lastRaycastDist - newDist), 0.0f,
                                                              1.0f - MyEngineConstants.UPDATE_STEP_SIZE_IN_SECONDS);
                                m_positionSafeZoomingOutSpeed += distDiffZoomSpeed;
                                m_positionSafeZoomingOutSpeed = MathHelper.Clamp(m_positionSafeZoomingOutSpeed, 0.0f,
                                    1.0f);

                                Vector3D targetToPosSafe = m_positionSafe - m_target;
                                double lenTargetToPosSafe = targetToPosSafe.Length();
                                Vector3D rotatedPositionSafe = m_target +
                                                               Vector3D.Normalize(safePositionCandidate - m_target) *
                                                               lenTargetToPosSafe;
                                m_positionSafe = Vector3D.Lerp(rotatedPositionSafe, safePositionCandidate,
                                    m_positionSafeZoomingOutSpeed);
                            }
                            else
                            {
                                m_positionSafeZoomingOutTimeout -= MyEngineConstants.UPDATE_STEP_SIZE_IN_MILLISECONDS;

                                Vector3D targetToPosSafe = m_positionSafe - m_target;
                                double lenTargetToPosSafe = targetToPosSafe.Length();
                                m_positionSafe = m_target + Vector3D.Normalize(safePositionCandidate - m_target) * lenTargetToPosSafe;
                            }
                        }
                        else
                        {
                            // new safe position is closer or closer than safe distance => instant change
                            m_positionSafeZoomingOutSpeed = 0.0f;    // set zooming out speed to zero for next time
                            m_positionSafeZoomingOutTimeout = 0;// controlledEntity.Parent != null ? m_positionSafeZoomingOutDefaultTimeoutMs : 0;
                            m_positionSafe = safePositionCandidate;
                            m_disableSpringThisFrame = true;
                            m_positionCurrentIsSafe = distFromCandidateToTarget >= m_safeMinimumDistance;
                        }
                    }
                    break;
                //case MyCameraRaycastResult.FoundOccluderNoSpace:
                default:
                    m_positionSafeZoomingOutSpeed = 1.0f; // we're in first person, change instantly to third if possible
                    m_positionCurrentIsSafe = false;
                    break;    
            }

            m_lastRaycastDist = (float)(m_positionSafe - m_position).Length();

            if (m_debugDraw)
            {
                VRageRender.MyRenderProxy.DebugDrawSphere(m_positionSafe, 0.225f, Color.Purple, 1, false);
                VRageRender.MyRenderProxy.DebugDrawSphere(safePositionCandidate, 0.2f, Color.Azure, 1, false);
            }
        }
        private unsafe Vector3* GetMiddleOBBLocalPoints(MyOrientedBoundingBoxD obb, ref Vector3* points)
        {
            Vector3 xDiff = obb.Orientation.Right * (float)obb.HalfExtent.X;
            Vector3 zDiff = obb.Orientation.Forward * (float)obb.HalfExtent.Z;

            Vector3 localPosition = obb.Center - m_planet.PositionComp.GetPosition();

            points[0] = localPosition - xDiff - zDiff;
            points[1] = localPosition + xDiff - zDiff;
            points[2] = localPosition + xDiff + zDiff;
            points[3] = localPosition - xDiff + zDiff;

            return points;
        }
 private static MyOrientedBoundingBoxD GetEntitySafeOBB(MyEntity controlledEntity)
 {
     var localAABB = controlledEntity.PositionComp.LocalAABB;
     Vector3D center = Vector3D.Transform((Vector3D) localAABB.Center, controlledEntity.WorldMatrix);
     var safeOBB = new MyOrientedBoundingBoxD(center, localAABB.HalfExtents, Quaternion.CreateFromRotationMatrix(controlledEntity.WorldMatrix.GetOrientation()));
     return safeOBB;
 }
        private void AddGround(float border, Vector3D originPosition, MyOrientedBoundingBoxD obb, List<BoundingBoxD> bbList)
        {
            ProfilerShort.Begin("Predict terrain - SetTerrainLimits()");
            bool hasTerrain = SetTerrainLimits(ref obb);
            ProfilerShort.End();

            if (!hasTerrain)
                return;

            AddVoxelMesh(m_planet, m_planet.Storage, m_meshCache, border, originPosition, obb, bbList);
        }
        /// <summary>
        /// Fills a "horizontal" line of OBBs
        /// </summary>
        private void FillOBBHorizontalLine(MyOrientedBoundingBoxD lineCenterOBB, Vector2I currentIndex, double angle)
        {
            m_obbs[currentIndex.Y][currentIndex.X] = lineCenterOBB;

            for (int i = 0; i < OBBsPerLine; i++)
                if (i != currentIndex.X)
                {
                    var ob = CreateOBB(NewTransformedPoint(lineCenterOBB.Center,
                                                           lineCenterOBB.Orientation.Right,
                                                           (float)(angle * (i - m_middleCoord))),
                                       lineCenterOBB.Orientation.Right);
                    m_obbs[currentIndex.Y][i] = ob;
                }
        }
        private bool QueryEmptyOrFull(int minX, int minY, int minZ, int maxX, int maxY, int maxZ)
        {
            ////return false;
            var bb = new BoundingBox(new Vector3(minX, minY, minZ), new Vector3(maxX, maxY, maxZ));
            if (bb.Volume() < 100)
                return false;

            //bb.Translate(m_voxelMap.StorageMin);
            var result = m_voxelMap.Storage.Intersect(ref bb, false) != ContainmentType.Intersects;
            {
                var bbd = new BoundingBoxD(new Vector3(minX, minY, minZ) * 8, new Vector3(maxX, maxY, maxZ) * 8);
                bbd.Transform(Entity.WorldMatrix);
                var obb = new MyOrientedBoundingBoxD(bbd, Entity.WorldMatrix);
                MyRenderProxy.DebugDrawAABB(bbd, result ? Color.Green : Color.Red, 1, 1, false);
            }
            return result;
        }
Exemple #43
0
        public override void Handle()
        {
            var tmpEntities = new HashSet <IMyEntity>();

            MyAPIGateway.Entities.GetEntities(tmpEntities);
            if (tmpEntities.Count == 0)
            {
                Logging.Instance.WriteLine("Failed to get list of entities in ShipyardDetection.");
                return;
            }

            //copy the list of entities because concurrency
            IMyEntity[] entities = tmpEntities.ToArray();

            //run through our current list of shipyards and make sure they're still valid
            var itemsToRemove   = new HashSet <ShipyardItem>();
            var firstCheckBlock = Profiler.Start(FullName, nameof(Handle), "First Check");

            foreach (ShipyardItem item in ShipyardsList)
            {
                if (!AreToolsConnected(item.Tools))
                {
                    Logging.Instance.WriteLine("remove item tools " + item.Tools.Length);
                    item.Disable();
                    itemsToRemove.Add(item);
                    foreach (var tool in item.Tools)
                    {
                        Communication.SendCustomInfo(tool.EntityId, "Invalid Shipyard: All tools must be on the same conveyor network!");
                    }
                    continue;
                }

                if (item.Tools.Any(x => x.Closed || x.MarkedForClose))
                {
                    Logging.Instance.WriteLine("remove item closed tools " + item.Tools.Length);
                    item.Disable();
                    itemsToRemove.Add(item);
                    continue;
                }

                if (!entities.Contains(item.YardEntity) || item.YardEntity.Closed || item.YardEntity.MarkedForClose)
                {
                    Logging.Instance.WriteLine("remove item entity");
                    item.Disable();
                    itemsToRemove.Add(item);
                    continue;
                }

                using (Profiler.Start(FullName, nameof(Handle), "Physics Check"))
                {
                    if (item.YardEntity.Physics == null ||
                        item.StaticYard && (!item.YardEntity.Physics.IsStatic || !((IMyCubeGrid)item.YardEntity).IsInVoxels()))
                    {
                        Logging.Instance.WriteLine("remove item physics");
                        itemsToRemove.Add(item);
                        item.Disable();
                        foreach (var tool in item.Tools)
                        {
                            Communication.SendCustomInfo(tool.EntityId, "Invalid Shipyard: Shipyard must be anchored to voxels!");
                        }
                        continue;
                    }
                }

                if (item.Tools.Any(t => ((IMyTerminalBlock)t).CustomInfo.Contains("Invalid Shipyard")))
                {
                    foreach (var tool in item.Tools)
                    {
                        Communication.SendCustomInfo(tool.EntityId, string.Empty);
                    }
                }
            }
            firstCheckBlock.End();

            foreach (ShipyardItem item in itemsToRemove)
            {
                item.YardType = ShipyardType.Invalid;
                Communication.SendYardState(item);
                ShipyardsList.Remove(item);
            }

            foreach (IMyEntity entity in entities)
            {
                _corners.Clear();
                var grid = entity as IMyCubeGrid;

                if (grid?.Physics == null || grid.Closed || grid.MarkedForClose)
                {
                    continue;
                }

                if (ShipyardsList.Any(x => x.EntityId == entity.EntityId))
                {
                    continue;
                }

                var gridBlocks = new List <IMySlimBlock>();
                grid.GetBlocks(gridBlocks);

                foreach (IMySlimBlock slimBlock in gridBlocks.ToArray())
                {
                    var collector = slimBlock.FatBlock as IMyCollector;
                    if (collector == null)
                    {
                        continue;
                    }

                    if (collector.BlockDefinition.SubtypeId.StartsWith("ShipyardCorner"))
                    {
                        _corners.Add(slimBlock.FatBlock);
                    }
                }

                if (_corners.Count != 8)
                {
                    foreach (var tool in _corners)
                    {
                        Communication.SendCustomInfo(tool.EntityId, $"Invalid Shipyard: Must be 8 corner blocks, there are {_corners.Count} on this grid!");
                    }
                    continue;
                }

                if (_corners.Any(c => c.BlockDefinition.SubtypeId != _corners[0].BlockDefinition.SubtypeId))
                {
                    foreach (var tool in _corners)
                    {
                        Communication.SendCustomInfo(tool.EntityId, $"Invalid Shipyard: All 8 corner blocks must be the same type!");
                    }
                    continue;
                }

                using (Profiler.Start(FullName, nameof(Handle), "Static Check"))
                {
                    if (_corners[0].BlockDefinition.SubtypeId == "ShipyardCorner_Large" && !ShipyardCore.Debug)
                    {
                        if (!grid.IsStatic || !grid.IsInVoxels())
                        {
                            Logging.Instance.WriteDebug($"Yard {grid.EntityId} failed: Static check");
                            foreach (var tool in _corners)
                            {
                                Communication.SendCustomInfo(tool.EntityId, "Invalid Shipyard: Shipyard must be anchored to voxels!");
                            }
                            continue;
                        }
                    }
                }

                if (!IsYardValid(entity, _corners))
                {
                    continue;
                }

                //add an offset of 2.5m because the corner points are at the center of a 3^3 block, and the yard will be 2.5m short in all dimensions
                MyOrientedBoundingBoxD testBox = MathUtility.CreateOrientedBoundingBox((IMyCubeGrid)entity, _corners.Select(x => x.GetPosition()).ToList(), 2.5);

                Logging.Instance.WriteLine("Found yard");
                var item = new ShipyardItem(
                    testBox,
                    _corners.ToArray(),
                    ShipyardType.Disabled,
                    entity);
                item.Settings = ShipyardSettings.Instance.GetYardSettings(item.EntityId);
                foreach (IMyCubeBlock tool in _corners)
                {
                    item.BlocksToProcess.Add(tool.EntityId, new BlockTarget[3]);
                }

                ShipyardsList.Add(item);
                Communication.SendNewYard(item);
                foreach (var tool in item.Tools)
                {
                    Communication.SendCustomInfo(tool.EntityId, "");
                }
            }

            Communication.SendYardCount();
        }