예제 #1
0
        private float?ProcessTriangle(int triangleIndex)
        {
            System.Diagnostics.Debug.Assert((int)m_flags != 0);

            MyTriangle_Vertexes     triangle;
            MyTriangleVertexIndices triangleIndices = m_model.Triangles[triangleIndex];

            m_model.GetVertex(triangleIndices.I0, triangleIndices.I2, triangleIndices.I1, out triangle.Vertex0, out triangle.Vertex1, out triangle.Vertex2);

            Vector3 calculatedTriangleNormal = MyUtils.GetNormalVectorFromTriangle(ref triangle);

            //We dont want backside intersections
            if (((int)(m_flags & IntersectionFlags.FLIPPED_TRIANGLES) == 0) &&
                Vector3.Dot(m_line.Direction, calculatedTriangleNormal) > 0)
            {
                return(null);
            }

            Line  lineF    = (Line)m_line;
            float?distance = MyUtils.GetLineTriangleIntersection(ref lineF, ref triangle);

            if (distance.HasValue)
            {
                var result = new MyIntersectionResultLineTriangle(ref triangle, ref calculatedTriangleNormal, distance.Value);
                m_result.Add(result);
            }

            return(distance);
        }
예제 #2
0
        public MyIntersectionResultLineTriangleEx(MyIntersectionResultLineTriangle triangle, IMyEntity entity, ref LineD line, Vector3D intersectionPointInWorldSpace, Vector3 normalInWorldSpace)
        {
            Triangle = triangle;
            Entity   = entity;
            InputLineInObjectSpace = line;

            NormalInObjectSpace            = NormalInWorldSpace = normalInWorldSpace;
            IntersectionPointInWorldSpace  = intersectionPointInWorldSpace;
            IntersectionPointInObjectSpace = (Vector3)IntersectionPointInWorldSpace;
        }
 //  Find and return closer intersection of these two. If intersection is null then it's not really an intersection.
 public static MyIntersectionResultLineTriangle? GetCloserIntersection(ref MyIntersectionResultLineTriangle? a, ref MyIntersectionResultLineTriangle? b)
 {
     if (((a == null) && (b != null)) ||
         ((a != null) && (b != null) && (b.Value.Distance < a.Value.Distance)))
     {
         //  If only "b" contains valid intersection, or when it's closer than "a"
         return b;
     }
     else
     {
         //  This will be returned also when ((a == null) && (b == null))
         return a;
     }
 }
예제 #4
0
        public MyIntersectionResultLineTriangleEx(MyIntersectionResultLineTriangle triangle, IMyEntity entity, ref LineD line)
        {
            Triangle = triangle;
            Entity   = entity;
            InputLineInObjectSpace = line;

            NormalInObjectSpace            = MyUtils.GetNormalVectorFromTriangle(ref Triangle.InputTriangle);
            IntersectionPointInObjectSpace = line.From + line.Direction * Triangle.Distance;

            if (Entity is IMyVoxelBase)
            {
                IntersectionPointInWorldSpace = (Vector3D)IntersectionPointInObjectSpace;
                NormalInWorldSpace            = NormalInObjectSpace;

                //  This will move intersection point from world space into voxel map's object space
                IntersectionPointInObjectSpace = IntersectionPointInObjectSpace - ((IMyVoxelBase)Entity).PositionLeftBottomCorner;
            }
            else
            {
                var worldMatrix = Entity.WorldMatrix;
                NormalInWorldSpace            = (Vector3)MyUtils.GetTransformNormalNormalized((Vector3D)NormalInObjectSpace, ref worldMatrix);
                IntersectionPointInWorldSpace = Vector3D.Transform((Vector3D)IntersectionPointInObjectSpace, ref worldMatrix);
            }
        }
        public MyIntersectionResultLineTriangleEx(MyIntersectionResultLineTriangle triangle, IMyEntity entity, ref LineD line)
        {
            Triangle = triangle;
            Entity = entity;
            InputLineInObjectSpace = line;

            NormalInObjectSpace = MyUtils.GetNormalVectorFromTriangle(ref Triangle.InputTriangle);
            IntersectionPointInObjectSpace = line.From + line.Direction * Triangle.Distance;

            if (Entity is IMyVoxelBase)
            {
                IntersectionPointInWorldSpace = (Vector3D)IntersectionPointInObjectSpace;
                NormalInWorldSpace = NormalInObjectSpace;

                //  This will move intersection point from world space into voxel map's object space
                IntersectionPointInObjectSpace = IntersectionPointInObjectSpace - ((IMyVoxelBase)Entity).PositionLeftBottomCorner;
            }
            else
            {
                var worldMatrix = Entity.WorldMatrix;
                NormalInWorldSpace = (Vector3)MyUtils.GetTransformNormalNormalized((Vector3D)NormalInObjectSpace, ref worldMatrix);
                IntersectionPointInWorldSpace = Vector3D.Transform((Vector3D)IntersectionPointInObjectSpace, ref worldMatrix);
            }
        }
        //  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 LineD line, double? minDistanceUntilNow)
        {
            //  Check if line intersects bounding box of this node and if distance to bounding box is less then last know min distance
            Line lineF = (Line)line;
            double? distanceToBoundingBox = MyUtils.GetLineBoundingBoxIntersection(ref lineF, 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();
            BoundingBox lineBB = BoundingBox.CreateInvalid();
            lineBB = lineBB.Include(line.From);
            lineBB = lineBB.Include(line.To);

            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 (triangleBoundingBox.Intersects(ref lineBB))
                {
                    //  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);

                    double? distance = MyUtils.GetLineTriangleIntersection(ref lineF, 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) ? (double?)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;
        }
        public MyIntersectionResultLineTriangleEx(MyIntersectionResultLineTriangle triangle, IMyEntity entity, ref LineD line, Vector3D intersectionPointInWorldSpace, Vector3 normalInWorldSpace)
        {
            Triangle = triangle;
            Entity = entity;
            InputLineInObjectSpace = line;

            NormalInObjectSpace = NormalInWorldSpace = normalInWorldSpace;
            IntersectionPointInWorldSpace = intersectionPointInWorldSpace;
            IntersectionPointInObjectSpace = (Vector3)IntersectionPointInWorldSpace;
        }
예제 #8
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;
                cachedDataCell.GetPackedPosition(ref modelSpaceLine.From, out packedStart);
                var ray = new Ray(packedStart, modelSpaceLine.Direction);
                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);

                //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);
                }
            }
        }
예제 #9
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;
        }