예제 #1
0
 private void GetCellLineIntersectionOctree(ref MyIntersectionResultLineTriangle?result, ref Line modelSpaceLine, ref float?minDistanceUntilNow, CellData cachedDataCell, IntersectionFlags flags)
 {
     m_overlapElementCache.Clear();
     if (cachedDataCell.Octree != null)
     {
         Vector3 vector;
         Vector3 vector2;
         cachedDataCell.GetPackedPosition(ref modelSpaceLine.From, out vector);
         cachedDataCell.GetPackedPosition(ref modelSpaceLine.To, out vector2);
         Ray ray = new Ray(vector, vector2 - vector);
         cachedDataCell.Octree.GetIntersectionWithLine(ref ray, m_overlapElementCache);
     }
     for (int i = 0; i < m_overlapElementCache.Count; i++)
     {
         int index = m_overlapElementCache[i];
         if ((cachedDataCell.VoxelTriangles != null) && (index < cachedDataCell.VoxelTriangles.Length))
         {
             MyTriangle_Vertices vertices;
             MyVoxelTriangle     triangle = cachedDataCell.VoxelTriangles[index];
             cachedDataCell.GetUnpackedPosition(triangle.V0, out vertices.Vertex0);
             cachedDataCell.GetUnpackedPosition(triangle.V1, out vertices.Vertex1);
             cachedDataCell.GetUnpackedPosition(triangle.V2, out vertices.Vertex2);
             Vector3 normalVectorFromTriangle = MyUtils.GetNormalVectorFromTriangle(ref vertices);
             if (normalVectorFromTriangle.IsValid() && (((flags & IntersectionFlags.FLIPPED_TRIANGLES) != ((IntersectionFlags)0)) || (Vector3.Dot(modelSpaceLine.Direction, normalVectorFromTriangle) <= 0f)))
             {
                 float?lineTriangleIntersection = MyUtils.GetLineTriangleIntersection(ref modelSpaceLine, ref vertices);
                 if ((lineTriangleIntersection != null) && ((result == 0) || (lineTriangleIntersection.Value < result.Value.Distance)))
                 {
                     minDistanceUntilNow = new float?(lineTriangleIntersection.Value);
                     result = new MyIntersectionResultLineTriangle(0, ref vertices, ref normalVectorFromTriangle, lineTriangleIntersection.Value);
                 }
             }
         }
     }
 }
예제 #2
0
        private void GetCellLineIntersectionOctree(ref 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 MyIntersectionResultLineTriangle(ref triangleVertices, ref calculatedTriangleNormal, distance.Value);
                }
            }
        }
예제 #3
0
        public bool Intersect(ref Line localLine, out MyIntersectionResultLineTriangle result, IntersectionFlags flags)
        {
            MyIntersectionResultLineTriangle valueOrDefault;

            m_sweepResultCache.Clear();
            MyGridIntersection.Calculate(m_sweepResultCache, 8f, localLine.From, localLine.To, new Vector3I(0, 0, 0), this.m_cellsCount - 1);
            float?      minDistanceUntilNow = null;
            MyCellCoord cell = new MyCellCoord();
            MyIntersectionResultLineTriangle?nullable2 = null;

            for (int i = 0; i < m_sweepResultCache.Count; i++)
            {
                BoundingBox box;
                cell.CoordInLod = m_sweepResultCache[i];
                MyVoxelCoordSystems.GeometryCellCoordToLocalAABB(ref cell.CoordInLod, out box);
                float?lineBoundingBoxIntersection = MyUtils.GetLineBoundingBoxIntersection(ref localLine, ref box);
                if ((minDistanceUntilNow != null) && (lineBoundingBoxIntersection != null))
                {
                    float?nullable1;
                    float?nullable5 = minDistanceUntilNow;
                    float num3      = 15.58846f;
                    if (nullable5 != null)
                    {
                        nullable1 = new float?(nullable5.GetValueOrDefault() + num3);
                    }
                    else
                    {
                        nullable1 = null;
                    }
                    float?nullable4 = nullable1;
                    float num2      = lineBoundingBoxIntersection.Value;
                    if ((nullable4.GetValueOrDefault() < num2) & (nullable4 != null))
                    {
                        break;
                    }
                }
                CellData cachedDataCell = this.GetCell(ref cell);
                if ((cachedDataCell != null) && (cachedDataCell.VoxelTrianglesCount != 0))
                {
                    this.GetCellLineIntersectionOctree(ref nullable2, ref localLine, ref minDistanceUntilNow, cachedDataCell, flags);
                }
            }
            MyIntersectionResultLineTriangle?nullable7 = nullable2;

            if (nullable7 != null)
            {
                valueOrDefault = nullable7.GetValueOrDefault();
            }
            else
            {
                valueOrDefault = new MyIntersectionResultLineTriangle();
            }
            result = valueOrDefault;
            return(nullable2 != null);
        }
예제 #4
0
        public bool Intersect(ref Line localLine, out 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();
            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(MyIntersectionResultLineTriangle);
            return(tmpResult.HasValue);
        }
        /// <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;
        }
예제 #6
0
        //  Finds intersection between line and model, using octree for speedup the lookup.
        //  Another speedup is, that first we check triangles that are directly in the node and then start
        //  checking node's childs. But only if child node instersection is less than last know min distance.
        MyIntersectionResultLineTriangle?GetIntersectionWithLineRecursive(MyModel model, ref MyLine line, float?minDistanceUntilNow)
        {
            //  Check if line intersects bounding box of this node and if distance to bounding box is less then last know min distance
            float?distanceToBoundingBox = MyUtils.GetLineBoundingBoxIntersection(ref line, ref m_boundingBox);

            if ((distanceToBoundingBox.HasValue == false) || ((minDistanceUntilNow != null) && (minDistanceUntilNow < distanceToBoundingBox.Value)))
            {
                return(null);
            }

            //  Triangles that are directly in this node
            MyIntersectionResultLineTriangle?foundIntersection = null;

            // temporary variable for storing tirngle boundingbox info
            BoundingBox triangleBoundingBox = new BoundingBox();

            MinerWars.AppCode.Game.Managers.MyPerformanceCounter.PerCameraDraw.RayCastTrianglesProcessed += m_triangleIndices.Count;

            for (int i = 0; i < m_triangleIndices.Count; i++)
            {
                int triangleIndex = m_triangleIndices[i];

                model.GetTriangleBoundingBox(triangleIndex, ref triangleBoundingBox);

                //  First test intersection of triangleVertexes's bounding box with line's bounding box. And only if they overlap or intersect, do further intersection tests.
                if (MyUtils.IsBoxIntersectingBox(triangleBoundingBox, ref line.BoundingBox) == true)
                {
                    //  See that we swaped vertex indices!!
                    MyTriangle_Vertexes     triangle;
                    MyTriangleVertexIndices triangleIndices = model.Triangles[triangleIndex];
                    triangle.Vertex0 = model.GetVertex(triangleIndices.I0);
                    triangle.Vertex1 = model.GetVertex(triangleIndices.I2);
                    triangle.Vertex2 = model.GetVertex(triangleIndices.I1);

                    float?distance = MyUtils.GetLineTriangleIntersection(ref line, ref triangle);

                    //  If intersection occured and if distance to intersection is closer to origin than any previous intersection
                    if ((distance != null) && ((foundIntersection == null) || (distance.Value < foundIntersection.Value.Distance)))
                    {
                        Vector3 calculatedTriangleNormal = MyUtils.GetNormalVectorFromTriangle(ref triangle);

                        //  We need to remember original triangleVertexes coordinates (not transformed by world matrix)
                        foundIntersection = new MyIntersectionResultLineTriangle(ref triangle, ref calculatedTriangleNormal, distance.Value);
                    }
                }
            }

            //  Get intersection with childs of this node
            if (m_childs != null)
            {
                for (int i = 0; i < m_childs.Count; i++)
                {
                    MyIntersectionResultLineTriangle?childIntersection = m_childs[i].GetIntersectionWithLineRecursive(model, ref line,
                                                                                                                      (foundIntersection == null) ? (float?)null : foundIntersection.Value.Distance);

                    //  If intersection occured and if distance to intersection is closer to origin than any previous intersection
                    foundIntersection = MyIntersectionResultLineTriangle.GetCloserIntersection(ref foundIntersection, ref childIntersection);
                }
            }

            return(foundIntersection);
        }
예제 #7
0
        private void GetCellLineIntersectionOctree(ref MyIntersectionResultLineTriangle? result, ref MyLine modelSpaceLine, ref float? minDistanceUntilNow, MyVoxelCacheCellData cachedDataCell, IntersectionFlags flags)
        {
            //MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().StartProfilingBlock("VoxelMap.ClearList Octree");
            OctreeOverlapElementList.Clear();
            //MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().EndProfilingBlock();
            if (cachedDataCell.Octree != null)
            {
                //MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().StartProfilingBlock("VoxelMap.LineIntersection Octree prun");
                var ray = new Ray(modelSpaceLine.From, modelSpaceLine.Direction);
                cachedDataCell.Octree.GetIntersectionWithLine(ref ray, OctreeOverlapElementList);
                //cachedDataCell.Octree.GetAllTriangles(OctreeOverlapElementList);
                //MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().EndProfilingBlock();
            }

            //MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().StartProfilingBlock("VoxelMap.LineIntersection test tris Octree");

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

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

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

                MyVoxelTriangle voxelTriangle = cachedDataCell.VoxelTriangles[i];

                MyVoxelVertex voxelVertex0 = cachedDataCell.VoxelVertices[voxelTriangle.VertexIndex0];
                MyVoxelVertex voxelVertex1 = cachedDataCell.VoxelVertices[voxelTriangle.VertexIndex1];
                MyVoxelVertex voxelVertex2 = cachedDataCell.VoxelVertices[voxelTriangle.VertexIndex2];

                MyTriangle_Vertexes triangleVertices;
                triangleVertices.Vertex0 = voxelVertex0.Position;
                triangleVertices.Vertex1 = voxelVertex1.Position;
                triangleVertices.Vertex2 = voxelVertex2.Position;


                Vector3 calculatedTriangleNormal = MyUtils.GetNormalVectorFromTriangle(ref triangleVertices);

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

                // draw triangles that were tested
                if (MyFakes.DRAW_TESTED_TRIANGLES_IN_VOXEL_LINE_INTERSECTION)
                {
                    Vector3 avg02 = (voxelVertex0.Position + voxelVertex1.Position + voxelVertex2.Position) * 0.33333333333f * 0.2f;
                    MyDebugDrawCachedLines.AddLine(PositionLeftBottomCorner + voxelVertex0.Position * 0.8f + avg02, PositionLeftBottomCorner + voxelVertex1.Position * 0.8f + avg02, Color.White, Color.White);
                    MyDebugDrawCachedLines.AddLine(PositionLeftBottomCorner + voxelVertex1.Position * 0.8f + avg02, PositionLeftBottomCorner + voxelVertex2.Position * 0.8f + avg02, Color.White, Color.White);
                    MyDebugDrawCachedLines.AddLine(PositionLeftBottomCorner + voxelVertex2.Position * 0.8f + avg02, PositionLeftBottomCorner + voxelVertex0.Position * 0.8f + avg02, Color.White, Color.White);
                }

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

                //if (distance != null) allIntersections.Add(distance.Value);

                //  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 MyIntersectionResultLineTriangle(ref triangleVertices, ref calculatedTriangleNormal, distance.Value);
                }
            }

            //MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().EndProfilingBlock();
        }
예제 #8
0
        private MyIntersectionResultLineTriangle?GetIntersectionWithLineRecursive(MyModel model, ref Line line, double?minDistanceUntilNow)
        {
            double?nullable4;
            double?nullable1;
            float? lineBoundingBoxIntersection = MyUtils.GetLineBoundingBoxIntersection(ref line, ref this.m_boundingBox);

            if (lineBoundingBoxIntersection != null)
            {
                nullable1 = new double?((double)lineBoundingBoxIntersection.GetValueOrDefault());
            }
            else
            {
                nullable4 = null;
                nullable1 = nullable4;
            }
            double?nullable = nullable1;

            if (nullable != null)
            {
                if (minDistanceUntilNow != null)
                {
                    nullable4 = minDistanceUntilNow;
                    double num = nullable.Value;
                    if ((nullable4.GetValueOrDefault() < num) & (nullable4 != null))
                    {
                        goto TR_0000;
                    }
                }
                MyIntersectionResultLineTriangle?a = null;
                BoundingBox boundingBox            = new BoundingBox();
                BoundingBox box = BoundingBox.CreateInvalid().Include(line.From).Include(line.To);
                for (int i = 0; i < this.m_triangleIndices.Count; i++)
                {
                    int triangleIndex = this.m_triangleIndices[i];
                    model.GetTriangleBoundingBox(triangleIndex, ref boundingBox);
                    if (boundingBox.Intersects(ref box))
                    {
                        MyTriangle_Vertices     vertices;
                        MyTriangleVertexIndices indices = model.Triangles[triangleIndex];
                        vertices.Vertex0 = model.GetVertex(indices.I0);
                        vertices.Vertex1 = model.GetVertex(indices.I2);
                        vertices.Vertex2 = model.GetVertex(indices.I1);
                        float?lineTriangleIntersection = MyUtils.GetLineTriangleIntersection(ref line, ref vertices);
                        if ((lineTriangleIntersection != null) && ((a == null) || (lineTriangleIntersection.Value < a.Value.Distance)))
                        {
                            Vector3 normalVectorFromTriangle = MyUtils.GetNormalVectorFromTriangle(ref vertices);
                            a = new MyIntersectionResultLineTriangle(triangleIndex, ref vertices, ref normalVectorFromTriangle, lineTriangleIntersection.Value);
                        }
                    }
                }
                if (this.m_childs != null)
                {
                    for (int j = 0; j < this.m_childs.Count; j++)
                    {
                        double?nullable8;
                        if (a != null)
                        {
                            nullable8 = new double?((double)a.Value.Distance);
                        }
                        else
                        {
                            nullable4 = null;
                            nullable8 = nullable4;
                        }
                        MyIntersectionResultLineTriangle?b = this.m_childs[j].GetIntersectionWithLineRecursive(model, ref line, nullable8);
                        a = MyIntersectionResultLineTriangle.GetCloserIntersection(ref a, ref b);
                    }
                }
                return(a);
            }
TR_0000:
            return(null);
        }