/// <summary>
        /// Returns closest hit from line start position.
        /// </summary>
        public bool GetIntersectionWithLine(ref LineD line, ref MyCharacterHitInfo info, IntersectionFlags flags = IntersectionFlags.ALL_TRIANGLES)
        {
            // TODO: This now uses caspule of physics rigid body on the character, it needs to be changed to ragdoll
            //       Currently this approach will be used to support Characters with different skeleton than humanoid
            if (info == null)
                info = new MyCharacterHitInfo();

            info.Reset();

            bool capsulesReady = UpdateCapsuleBones();
            if (!capsulesReady)
                return false;

            double closestDistanceToHit = double.MaxValue;

            Vector3D hitPosition = Vector3D.Zero;
            Vector3D hitPosition2 = Vector3D.Zero;
            Vector3 hitNormal = Vector3.Zero;
            Vector3 hitNormal2 = Vector3.Zero;

            int capsuleIndex = -1;
            for (int i = 0; i < m_bodyCapsules.Length; i++)
            {
                CapsuleD capsule = m_bodyCapsules[i];
                if (capsule.Intersect(line, ref hitPosition, ref hitPosition2, ref hitNormal, ref hitNormal2))
                {
                    double distanceToHit = Vector3.Distance(hitPosition, line.From);
                    if (distanceToHit >= closestDistanceToHit)
                        continue;

                    closestDistanceToHit = distanceToHit;
                    capsuleIndex = i;
                }
            }

            if (capsuleIndex != -1)
            {
                Matrix worldMatrix = PositionComp.WorldMatrix;
                int boneIndex = FindBestBone(capsuleIndex, ref hitPosition, ref worldMatrix);

                // Transform line to model static position and compute accurate collision there
                // 1. Transform line in local coordinates (used later)
                Matrix worldMatrixInv = PositionComp.WorldMatrixNormalizedInv;
                Vector3 fromTrans = Vector3.Transform(line.From, ref worldMatrixInv);
                Vector3 toTrans = Vector3.Transform(line.To, ref worldMatrixInv);
                LineD lineLocal = new LineD(fromTrans, toTrans);

                // 2. Transform line to to bone pose in binding position
                var bone = AnimationController.CharacterBones[boneIndex];
                bone.ComputeAbsoluteTransform();
                Matrix boneAbsTrans = bone.AbsoluteTransform;
                Matrix skinTransform = bone.SkinTransform;
                Matrix boneTrans = skinTransform * boneAbsTrans;
                Matrix invBoneTrans = Matrix.Invert(boneTrans);
                fromTrans = Vector3.Transform(fromTrans, ref invBoneTrans);
                toTrans = Vector3.Transform(toTrans, ref invBoneTrans);

                // 3. Move back line to world coordinates
                LineD lineTransWorld = new LineD(Vector3.Transform(fromTrans, ref worldMatrix), Vector3.Transform(toTrans, ref worldMatrix));
                MyIntersectionResultLineTriangleEx? triangle_;
                bool success = base.GetIntersectionWithLine(ref lineTransWorld, out triangle_, flags);
                if (success)
                {
                    MyIntersectionResultLineTriangleEx triangle = triangle_.Value;

                    info.CapsuleIndex = capsuleIndex;
                    info.BoneIndex = boneIndex;
                    info.Capsule = m_bodyCapsules[info.CapsuleIndex];
                    info.HitHead = info.CapsuleIndex == 0 && m_bodyCapsules.Length > 1;
                    info.HitPositionBindingPose = triangle.IntersectionPointInObjectSpace;
                    info.HitNormalBindingPose = triangle.NormalInObjectSpace;

                    // 4. Move intersection from binding to dynamic pose
                    MyTriangle_Vertexes vertices = new MyTriangle_Vertexes();
                    vertices.Vertex0 = Vector3.Transform(triangle.Triangle.InputTriangle.Vertex0, ref boneTrans);
                    vertices.Vertex1 = Vector3.Transform(triangle.Triangle.InputTriangle.Vertex1, ref boneTrans);
                    vertices.Vertex2 = Vector3.Transform(triangle.Triangle.InputTriangle.Vertex2, ref boneTrans);
                    Vector3 triangleNormal = Vector3.TransformNormal(triangle.Triangle.InputTriangleNormal, boneTrans);
                    MyIntersectionResultLineTriangle triraw = new MyIntersectionResultLineTriangle(ref vertices, ref triangleNormal, triangle.Triangle.Distance);

                    Vector3 intersectionLocal = Vector3.Transform(triangle.IntersectionPointInObjectSpace, ref boneTrans);
                    Vector3 normalLocal = Vector3.TransformNormal(triangle.NormalInObjectSpace, boneTrans);

                    // 5. Store results
                    triangle = new MyIntersectionResultLineTriangleEx();
                    triangle.Triangle = triraw;
                    triangle.IntersectionPointInObjectSpace = intersectionLocal;
                    triangle.NormalInObjectSpace = normalLocal;
                    triangle.IntersectionPointInWorldSpace = Vector3.Transform(intersectionLocal, ref worldMatrix);
                    triangle.NormalInWorldSpace = Vector3.TransformNormal(normalLocal, worldMatrix);
                    triangle.InputLineInObjectSpace = lineLocal;

                    info.Triangle = triangle;

                    if (MyDebugDrawSettings.ENABLE_DEBUG_DRAW)
                    {
                        MyRenderProxy.DebugClearPersistentMessages();
                        MyRenderProxy.DebugDrawCapsule(info.Capsule.P0, info.Capsule.P1, info.Capsule.Radius, Color.Aqua, false, persistent: true);

                        Vector3 p0Local = Vector3.Transform(info.Capsule.P0, ref worldMatrixInv);
                        Vector3 p1Local = Vector3.Transform(info.Capsule.P1, ref worldMatrixInv);
                        Vector3 p0LocalTrans = Vector3.Transform(p0Local, ref invBoneTrans);
                        Vector3 p1LocalTrans = Vector3.Transform(p1Local, ref invBoneTrans);
                        MyRenderProxy.DebugDrawCapsule(Vector3.Transform(p0LocalTrans, ref worldMatrix), Vector3.Transform(p1LocalTrans, ref worldMatrix), info.Capsule.Radius, Color.Brown, false, persistent: true);

                        MyRenderProxy.DebugDrawLine3D(line.From, line.To, Color.Blue, Color.Red, false, true);
                        MyRenderProxy.DebugDrawLine3D(lineTransWorld.From, lineTransWorld.To, Color.Green, Color.Yellow, false, true);
                        MyRenderProxy.DebugDrawSphere(triangle.IntersectionPointInWorldSpace, 0.02f, Color.Red, 1, false, persistent: true);
                        MyRenderProxy.DebugDrawAxis((MatrixD)boneTrans * WorldMatrix, 0.1f, false, true, true);
                    }

                    return true;
                }
            }

            return false;
        }
        private void GetHitEntityAndPosition(LineD line, out IMyEntity entity, out Vector3D hitPosition, out Vector3 hitNormal, out MyCharacterHitInfo charHitInfo)
        {
            entity = null;
            hitPosition = hitNormal = Vector3.Zero;
            charHitInfo = null;

            // 1. rough raycast
            int raycastListIndex = 0;

            do
            {

                if (entity == null)
                {
                    if (raycastListIndex == 0) // cast only the first iteration
                    {
                        ProfilerShort.Begin("MyGamePruningStructure::CastProjectileRay");
                        MyPhysics.CastRay(line.From, line.To, m_raycastResult,
                            MyPhysics.CollisionLayers.DefaultCollisionLayer);
                        ProfilerShort.End();
                    }

                    if (raycastListIndex < m_raycastResult.Count)
                    {
                        MyPhysics.HitInfo hitInfo = m_raycastResult[raycastListIndex];

                        entity = hitInfo.HkHitInfo.GetHitEntity() as MyEntity;
                    	hitPosition = hitInfo.Position;
                    	hitNormal = hitInfo.HkHitInfo.Normal;
                    }
                }

                // 2. prevent shooting through characters, retest trajectory between entity and player
                if (!(entity is MyCharacter) || entity == null)
                {
                    // first: raycast, get all entities in line, limit distance if possible
                    LineD lineLimited = new LineD(line.From, entity == null ? line.To : hitPosition);
                    if (m_entityRaycastResult == null)
                    {
                        m_entityRaycastResult = new List<MyLineSegmentOverlapResult<MyEntity>>(16);
                    }
                    else
                    {
                        m_entityRaycastResult.Clear();
                    }
                    MyGamePruningStructure.GetAllEntitiesInRay(ref lineLimited, m_entityRaycastResult);
                    // second: precise tests, find best result
                    double bestDistanceSq = double.MaxValue;
                    IMyEntity entityBest = null;
                    for (int i = 0; i < m_entityRaycastResult.Count; i++)
                    {
                        if (m_entityRaycastResult[i].Element is MyCharacter)
                        {
                            MyCharacter hitCharacter = m_entityRaycastResult[i].Element as MyCharacter;
                            bool intersection = hitCharacter.GetIntersectionWithLine(ref line, ref m_charHitInfo);
                            if (intersection)
                            {
                                double distanceSq =
                                    Vector3D.DistanceSquared(m_charHitInfo.Triangle.IntersectionPointInWorldSpace,
                                        line.From);
                                if (distanceSq < bestDistanceSq && !IsIgnoredEntity(hitCharacter))
                                {
                                    bestDistanceSq = distanceSq;
                                    entityBest = hitCharacter;
                                    hitPosition = m_charHitInfo.Triangle.IntersectionPointInWorldSpace;
                                    hitNormal = m_charHitInfo.Triangle.NormalInWorldSpace;
                                    charHitInfo = m_charHitInfo;
                                }
                            }
                        }
                    }
                    // finally: do we have best result? then return it
                    if (entityBest != null)
                    {
                        entity = entityBest;
                        return; // this was precise result, so return
                    }
                }

                // 3. nothing found in the precise test? then fallback to already found results
                if (entity == null)
                    return; // no fallback results

                if (entity is MyCharacter) // retest character found in fallback
                {
                    MyCharacter hitCharacter = entity as MyCharacter;
                    bool intersection = hitCharacter.GetIntersectionWithLine(ref line, ref m_charHitInfo);
                    if (intersection)
                    {
                        hitPosition = m_charHitInfo.Triangle.IntersectionPointInWorldSpace;
                        hitNormal = m_charHitInfo.Triangle.NormalInWorldSpace;
                        charHitInfo = m_charHitInfo;
                    }
                    else
                    {
                        entity = null; // no hit.
                    }
                }
                else if (entity is MyGhostCharacter)
                {
                    MyHitInfo info = new MyHitInfo();
                    info.Position = hitPosition;
                    info.Normal = hitNormal;
                }
                else
                {
                    MyCubeGrid grid = entity as MyCubeGrid;
                    if (grid != null)
                    {
                        MyIntersectionResultLineTriangleEx? result;
                        bool success = grid.GetIntersectionWithLine(ref line, out result);
                        if (success && result.HasValue)
                        {
                            hitPosition = result.Value.IntersectionPointInWorldSpace;
                            hitNormal = result.Value.NormalInWorldSpace;
                            if (Vector3.Dot(hitNormal, line.Direction) > 0)
                                hitNormal = -hitNormal;
                        }

                        MyHitInfo info = new MyHitInfo();
                        info.Position = hitPosition;
                        info.Normal = hitNormal;
                    }
                }

            } while (entity == null && ++raycastListIndex < m_entityRaycastResult.Count);
        }