private void GetCellLineIntersectionOctree(ref VRage.Game.Models.MyIntersectionResultLineTriangle?result, ref Line modelSpaceLine, ref float?minDistanceUntilNow, CellData cachedDataCell, IntersectionFlags flags)
        {
            m_overlapElementCache.Clear();
            if (cachedDataCell.Octree != null)
            {
                Vector3 packedStart, packedEnd;
                cachedDataCell.GetPackedPosition(ref modelSpaceLine.From, out packedStart);
                cachedDataCell.GetPackedPosition(ref modelSpaceLine.To, out packedEnd);
                var ray = new Ray(packedStart, packedEnd - packedStart);
                cachedDataCell.Octree.GetIntersectionWithLine(ref ray, m_overlapElementCache);
            }

            for (int j = 0; j < m_overlapElementCache.Count; j++)
            {
                var i = m_overlapElementCache[j];

                if (cachedDataCell.VoxelTriangles == null) //probably not calculated yet
                {
                    continue;
                }

                // this should never happen
                if (i >= cachedDataCell.VoxelTriangles.Length)
                {
                    Debug.Assert(i < cachedDataCell.VoxelTriangles.Length);
                    continue;
                }

                MyVoxelTriangle voxelTriangle = cachedDataCell.VoxelTriangles[i];

                MyTriangle_Vertexes triangleVertices;
                cachedDataCell.GetUnpackedPosition(voxelTriangle.VertexIndex0, out triangleVertices.Vertex0);
                cachedDataCell.GetUnpackedPosition(voxelTriangle.VertexIndex1, out triangleVertices.Vertex1);
                cachedDataCell.GetUnpackedPosition(voxelTriangle.VertexIndex2, out triangleVertices.Vertex2);

                Vector3 calculatedTriangleNormal = MyUtils.GetNormalVectorFromTriangle(ref triangleVertices);
                if (!calculatedTriangleNormal.IsValid())
                {
                    continue;
                }
                //We dont want backside intersections
                if (((int)(flags & IntersectionFlags.FLIPPED_TRIANGLES) == 0) &&
                    Vector3.Dot(modelSpaceLine.Direction, calculatedTriangleNormal) > 0)
                {
                    continue;
                }

                // AABB intersection test removed, AABB is tested inside BVH
                float?distance = MyUtils.GetLineTriangleIntersection(ref modelSpaceLine, ref triangleVertices);

                //  If intersection occured and if distance to intersection is closer to origin than any previous intersection
                if ((distance != null) && ((result == null) || (distance.Value < result.Value.Distance)))
                {
                    minDistanceUntilNow = distance.Value;
                    result = new VRage.Game.Models.MyIntersectionResultLineTriangle(ref triangleVertices, ref calculatedTriangleNormal, distance.Value);
                }
            }
        }
        public bool Intersect(ref Line localLine, out VRage.Game.Models.MyIntersectionResultLineTriangle result, IntersectionFlags flags)
        {
            MyPrecalcComponent.AssertUpdateThread();

            ProfilerShort.Begin("VoxelMap.LineIntersection AABB sweep");
            m_sweepResultCache.Clear();
            MyGridIntersection.Calculate(
                m_sweepResultCache,
                (int)MyVoxelConstants.GEOMETRY_CELL_SIZE_IN_METRES,
                localLine.From,
                localLine.To,
                new Vector3I(0, 0, 0),
                m_cellsCount - 1
                );
            ProfilerShort.End();

            ProfilerShort.Begin("VoxelMap.LineIntersection test AABBs");
            float?      minDistanceUntilNow = null;
            BoundingBox cellBoundingBox;
            MyCellCoord cell = new MyCellCoord();

            VRage.Game.Models.MyIntersectionResultLineTriangle?tmpResult = null;
            for (int index = 0; index < m_sweepResultCache.Count; index++)
            {
                cell.CoordInLod = m_sweepResultCache[index];

                MyVoxelCoordSystems.GeometryCellCoordToLocalAABB(ref cell.CoordInLod, out cellBoundingBox);

                float?distanceToBoundingBox = MyUtils.GetLineBoundingBoxIntersection(ref localLine, ref cellBoundingBox);

                // Sweep results are sorted; when we get far enough, make an early exit
                const float earlyOutDistance = 1.948557f * MyVoxelConstants.GEOMETRY_CELL_SIZE_IN_METRES;  // = sqrt(3) * 9/8 * cell_side
                if (minDistanceUntilNow != null && distanceToBoundingBox != null && minDistanceUntilNow + earlyOutDistance < distanceToBoundingBox.Value)
                {
                    break;
                }

                //  Get cell from cache. If not there, precalc it and store in the cache.
                //  If null is returned, we know that cell doesn't contain any triangleVertexes so we don't need to do intersections.
                CellData cachedDataCell = GetCell(ref cell);

                if (cachedDataCell == null || cachedDataCell.VoxelTrianglesCount == 0)
                {
                    continue;
                }

                GetCellLineIntersectionOctree(ref tmpResult, ref localLine, ref minDistanceUntilNow, cachedDataCell, flags);
            }

            ProfilerShort.End();

            result = tmpResult ?? default(VRage.Game.Models.MyIntersectionResultLineTriangle);
            return(tmpResult.HasValue);
        }
        private void GetCellLineIntersectionOctree(ref VRage.Game.Models.MyIntersectionResultLineTriangle? result, ref Line modelSpaceLine, ref float? minDistanceUntilNow, CellData cachedDataCell, IntersectionFlags flags)
        {
            m_overlapElementCache.Clear();
            if (cachedDataCell.Octree != null)
            {
                Vector3 packedStart, packedEnd;
                cachedDataCell.GetPackedPosition(ref modelSpaceLine.From, out packedStart);
                cachedDataCell.GetPackedPosition(ref modelSpaceLine.To, out packedEnd);
                var ray = new Ray(packedStart, packedEnd - packedStart);
                cachedDataCell.Octree.GetIntersectionWithLine(ref ray, m_overlapElementCache);
            }

            for (int j = 0; j < m_overlapElementCache.Count; j++)
            {
                var i = m_overlapElementCache[j];

                if (cachedDataCell.VoxelTriangles == null) //probably not calculated yet
                    continue;

                // this should never happen
                if (i >= cachedDataCell.VoxelTriangles.Length)
                {
                    Debug.Assert(i < cachedDataCell.VoxelTriangles.Length);
                    continue;
                }

                MyVoxelTriangle voxelTriangle = cachedDataCell.VoxelTriangles[i];

                MyTriangle_Vertexes triangleVertices;
                cachedDataCell.GetUnpackedPosition(voxelTriangle.VertexIndex0, out triangleVertices.Vertex0);
                cachedDataCell.GetUnpackedPosition(voxelTriangle.VertexIndex1, out triangleVertices.Vertex1);
                cachedDataCell.GetUnpackedPosition(voxelTriangle.VertexIndex2, out triangleVertices.Vertex2);

                Vector3 calculatedTriangleNormal = MyUtils.GetNormalVectorFromTriangle(ref triangleVertices);
                if (!calculatedTriangleNormal.IsValid())
                    continue;
                //We dont want backside intersections
                if (((int)(flags & IntersectionFlags.FLIPPED_TRIANGLES) == 0) &&
                    Vector3.Dot(modelSpaceLine.Direction, calculatedTriangleNormal) > 0)
                    continue;

                // AABB intersection test removed, AABB is tested inside BVH
                float? distance = MyUtils.GetLineTriangleIntersection(ref modelSpaceLine, ref triangleVertices);

                //  If intersection occured and if distance to intersection is closer to origin than any previous intersection
                if ((distance != null) && ((result == null) || (distance.Value < result.Value.Distance)))
                {
                    minDistanceUntilNow = distance.Value;
                    result = new VRage.Game.Models.MyIntersectionResultLineTriangle(ref triangleVertices, ref calculatedTriangleNormal, distance.Value);
                }
            }
        }