Ejemplo n.º 1
0
        private void GetHitEntityAndPosition(LineD line, out IMyEntity entity, out MyHitInfo hitInfoRet, out object customdata)
        {
            entity     = null;
            hitInfoRet = new MyHitInfo();
            customdata = 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;
                        hitInfoRet.Position = hitInfo.Position;
                        hitInfoRet.Normal   = hitInfo.HkHitInfo.Normal;
                        hitInfoRet.ShapeKey = hitInfo.HkHitInfo.GetShapeKey(0);
                    }
                }

                // 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 : hitInfoRet.Position);
                    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;
                                    hitInfoRet.Position = m_charHitInfo.Triangle.IntersectionPointInWorldSpace;
                                    hitInfoRet.Normal   = m_charHitInfo.Triangle.NormalInWorldSpace;
                                    customdata          = 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)
                    {
                        hitInfoRet.Position = m_charHitInfo.Triangle.IntersectionPointInWorldSpace;
                        hitInfoRet.Normal   = m_charHitInfo.Triangle.NormalInWorldSpace;
                        customdata          = m_charHitInfo;
                    }
                    else
                    {
                        entity = null; // no hit.
                    }
                }
                else
                {
                    MyCubeGrid grid = entity as MyCubeGrid;
                    if (grid != null)
                    {
                        bool success = grid.GetIntersectionWithLine(ref line, ref m_cubeGridHitInfo);
                        if (success)
                        {
                            hitInfoRet.Position = m_cubeGridHitInfo.Triangle.IntersectionPointInWorldSpace;
                            hitInfoRet.Normal   = m_cubeGridHitInfo.Triangle.NormalInWorldSpace;
                            if (Vector3.Dot(hitInfoRet.Normal, line.Direction) > 0)
                            {
                                hitInfoRet.Normal = -hitInfoRet.Normal;
                            }

                            customdata = m_cubeGridHitInfo;
                        }

                        MyHitInfo info = new MyHitInfo();
                        info.Position = hitInfoRet.Position;
                        info.Normal   = hitInfoRet.Normal;
                    }

                    MyVoxelBase voxel = entity as MyVoxelBase;
                    if (voxel != null)
                    { //get accurate hit because of particles and decals
                        MyIntersectionResultLineTriangleEx?res;
                        if (voxel.GetIntersectionWithLine(ref line, out res, IntersectionFlags.DIRECT_TRIANGLES))
                        {
                            hitInfoRet.Position = res.Value.IntersectionPointInWorldSpace;
                            hitInfoRet.Normal   = res.Value.NormalInWorldSpace;
                            hitInfoRet.ShapeKey = 0;
                        }
                    }
                }
            } while (entity == null && ++raycastListIndex < m_entityRaycastResult.Count);
        }
Ejemplo n.º 2
0
        public override bool DebugDraw()
        {
            var minCorner = m_voxelMap.PositionLeftBottomCorner;

            if (MyDebugDrawSettings.DEBUG_DRAW_VOXEL_MAP_AABB)
            {
                VRageRender.MyRenderProxy.DebugDrawAABB(m_voxelMap.PositionComp.WorldAABB, Color.White, 1f, 1f, true);
                VRageRender.MyRenderProxy.DebugDrawLine3D(minCorner, minCorner + new Vector3(1f, 0f, 0f), Color.Red, Color.Red, true);
                VRageRender.MyRenderProxy.DebugDrawLine3D(minCorner, minCorner + new Vector3(0f, 1f, 0f), Color.Green, Color.Green, true);
                VRageRender.MyRenderProxy.DebugDrawLine3D(minCorner, minCorner + new Vector3(0f, 0f, 1f), Color.Blue, Color.Blue, true);

                VRageRender.MyRenderProxy.DebugDrawAxis(Matrix.Identity, 2f, true);
                VRageRender.MyRenderProxy.DebugDrawAxis(m_voxelMap.PositionComp.WorldMatrix, 1f, true);
            }

            m_voxelMap.Storage.DebugDraw(m_voxelMap, MyDebugDrawSettings.DEBUG_DRAW_VOXELS_MODE);
            if (m_voxelMap.Physics != null)
            {
                m_voxelMap.Physics.DebugDraw();
            }
            if (MyDebugDrawSettings.DEBUG_DRAW_VOXEL_GEOMETRY_CELL)
            {
                LineD worldLine;
                if (false)
                {
                    var entityMatrix = MySession.ControlledEntity.Entity.WorldMatrix;
                    worldLine = new LineD(entityMatrix.Translation, entityMatrix.Translation + 25f * entityMatrix.Forward);
                }
                else
                {
                    var camera = MySector.MainCamera;
                    worldLine = new LineD(camera.Position, camera.Position + 25f * camera.ForwardVector);
                }
                MyIntersectionResultLineTriangleEx?result;
                bool depthRead = true;
                if (m_voxelMap.GetIntersectionWithLine(ref worldLine, out result))
                {
                    var t = result.Value.Triangle.InputTriangle;
                    MyRenderProxy.DebugDrawTriangle(
                        t.Vertex0 + minCorner,
                        t.Vertex1 + minCorner,
                        t.Vertex2 + minCorner,
                        Color.Red, true, false);
                    Vector3I     cellCoord, voxelCoord;
                    var          worldPosition = result.Value.IntersectionPointInWorldSpace;
                    BoundingBoxD voxelAabb;
                    MyVoxelCoordSystems.WorldPositionToVoxelCoord(minCorner, ref worldPosition, out voxelCoord);
                    MyVoxelCoordSystems.VoxelCoordToWorldAABB(minCorner, ref voxelCoord, out voxelAabb);
                    MyRenderProxy.DebugDrawAABB(voxelAabb, Vector3.UnitY, 1f, 1f, true);
                    MyVoxelCoordSystems.WorldPositionToGeometryCellCoord(minCorner, ref worldPosition, out cellCoord);
                    MyVoxelCoordSystems.GeometryCellCoordToWorldAABB(minCorner, ref cellCoord, out voxelAabb);
                    MyRenderProxy.DebugDrawAABB(voxelAabb, Vector3.UnitZ, 1f, 1f, true);

                    bool      isEmpty;
                    MyIsoMesh cell;
                    if (m_voxelMap.Storage.Geometry.TryGetMesh(new MyCellCoord(0, cellCoord), out isEmpty, out cell) && !isEmpty)
                    {
                        MyVoxelVertex tmp;
                        var           triangleBatch = MyRenderProxy.PrepareDebugDrawTriangles();
                        for (int i = 0; i < cell.VerticesCount; ++i)
                        {
                            cell.GetUnpackedVertex(i, out tmp);
                            triangleBatch.AddVertex(tmp.Position);
                            tmp.Position += minCorner;
                            MyRenderProxy.DebugDrawLine3D(tmp.Position, tmp.Position + tmp.Normal * MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF, Color.Gray, Color.White, depthRead);
                        }
                        for (int i = 0; i < cell.TrianglesCount; ++i)
                        {
                            triangleBatch.AddIndex(cell.Triangles[i].VertexIndex2);
                            triangleBatch.AddIndex(cell.Triangles[i].VertexIndex1);
                            triangleBatch.AddIndex(cell.Triangles[i].VertexIndex0);
                        }
                        MyRenderProxy.DebugDrawTriangles(triangleBatch, Matrix.CreateTranslation(minCorner), Color.CornflowerBlue, depthRead, false);
                    }
                }
            }
            return(true);
        }