예제 #1
0
        public bool IntersectsMesh(TransformMatrix thisTransform, Octave3DMesh otherMesh, TransformMatrix otherTransform)
        {
            OrientedBox thisOOBB = new OrientedBox(ModelAABB);

            thisOOBB.Transform(thisTransform);
            OrientedBox otherOOBB = new OrientedBox(otherMesh.ModelAABB);

            otherOOBB.Transform(otherTransform);

            if (!thisOOBB.Intersects(otherOOBB))
            {
                return(false);
            }

            List <Triangle3D> thisTriangles = GetOverlappedTriangles(otherOOBB, thisTransform);

            for (int thisTriIndex = 0; thisTriIndex < thisTriangles.Count; ++thisTriIndex)
            {
                Triangle3D        thisTri        = thisTriangles[thisTriIndex];
                OrientedBox       thisTriOOBB    = new OrientedBox(thisTri.GetEncapsulatingBox());
                List <Triangle3D> otherTriangles = otherMesh.GetOverlappedTriangles(thisTriOOBB, otherTransform);
                for (int otherTriIndex = 0; otherTriIndex < otherTriangles.Count; ++otherTriIndex)
                {
                    Triangle3D otherTri = otherTriangles[otherTriIndex];
                    if (thisTri.IntersectsTriangle(otherTri))
                    {
                        return(true);
                    }
                }
            }

            return(false);
        }
예제 #2
0
 public Triangle3D(Triangle3D source)
 {
     _points    = new Vector3[3];
     _points[0] = source.Point0;
     _points[1] = source.Point1;
     _points[2] = source.Point2;
     _plane     = source._plane;
     _area      = source._area;
 }
        public Triangle3DIntersectInfo(Triangle3D firstTriangle, Triangle3D secondTriangle,
                                       List <Vector3> firstTraingleIntersectionPoints, List <Vector3> secondTraingleIntersectionPoints)
        {
            _firstTriangle  = firstTriangle;
            _secondTriangle = secondTriangle;

            _firstTriangleIntersectionPoints  = new List <Vector3>(firstTraingleIntersectionPoints);
            _secondTriangleIntersectionPoints = new List <Vector3>(secondTraingleIntersectionPoints);

            _allIntersectionPoints = new List <Vector3>(_firstTriangleIntersectionPoints);
            _allIntersectionPoints.AddRange(_secondTriangleIntersectionPoints);
        }
예제 #4
0
        /// <summary>
        /// Registers the mesh trianlge with the specified index with the tree.
        /// </summary>
        /// <returns>
        /// True if the trianlge was registered and false otherwise. The only
        /// scenario in which the method can return false is when the triangle
        /// is degenerate.
        /// </returns>
        private bool RegisterTriangle(int triangleIndex)
        {
            // Retrieve the triangle from the mesh. If it is degenerate, we return false.
            Triangle3D triangle = _octave3DMesh.GetTriangle(triangleIndex);

            if (triangle.IsDegenerate)
            {
                return(false);
            }

            // Create the triangle node data and instruct the tree to add this node
            var meshSphereTreeTriangle = new MeshSphereTreeTriangle(triangleIndex);

            _sphereTree.AddTerminalNode(triangle.GetEncapsulatingSphere(), meshSphereTreeTriangle);

            return(true);
        }
예제 #5
0
        public bool IntersectsTriangle(Triangle3D triangle, out Triangle3DIntersectInfo intersectInfo)
        {
            intersectInfo = new Triangle3DIntersectInfo();
            if (triangle.Normal.IsAlignedWith(Normal))
            {
                return(false);
            }

            float            t;
            List <Segment3D> otherTriSegments = triangle.GetSegments();
            var firstTriIntersectionPoints    = new List <Vector3>();

            foreach (var segment in otherTriSegments)
            {
                Ray3D ray = new Ray3D(segment.StartPoint, segment.EndPoint);
                if (Raycast(ray, out t))
                {
                    firstTriIntersectionPoints.Add(ray.GetPoint(t));
                }
            }

            List <Segment3D> thisTriSegments = GetSegments();
            var secondTriIntersectionPoints  = new List <Vector3>();

            foreach (var segment in thisTriSegments)
            {
                Ray3D ray = new Ray3D(segment.StartPoint, segment.EndPoint);
                if (triangle.Raycast(ray, out t))
                {
                    secondTriIntersectionPoints.Add(ray.GetPoint(t));
                }
            }

            if (firstTriIntersectionPoints.Count != 0 || secondTriIntersectionPoints.Count != 0)
            {
                intersectInfo = new Triangle3DIntersectInfo(this, triangle, firstTriIntersectionPoints, secondTriIntersectionPoints);
                return(true);
            }

            return(false);
        }
예제 #6
0
        public List <Triangle3DIntersectInfo> GetIntersectingTriangles(TransformMatrix thisTransform, Octave3DMesh otherMesh, TransformMatrix otherTransform)
        {
            OrientedBox thisOOBB = new OrientedBox(ModelAABB);

            thisOOBB.Transform(thisTransform);
            OrientedBox otherOOBB = new OrientedBox(otherMesh.ModelAABB);

            otherOOBB.Transform(otherTransform);

            if (thisOOBB.Intersects(otherOOBB))
            {
                List <Triangle3D> thisTriangles = GetOverlappedTriangles(otherOOBB, thisTransform);

                var output = new List <Triangle3DIntersectInfo>(50);
                Triangle3DIntersectInfo intersectInfo;
                for (int thisTriIndex = 0; thisTriIndex < thisTriangles.Count; ++thisTriIndex)
                {
                    Triangle3D thisTri = thisTriangles[thisTriIndex];

                    OrientedBox       thisTriOOBB    = new OrientedBox(thisTri.GetEncapsulatingBox());
                    List <Triangle3D> otherTriangles = otherMesh.GetOverlappedTriangles(thisTriOOBB, otherTransform);

                    for (int otherTriIndex = 0; otherTriIndex < otherTriangles.Count; ++otherTriIndex)
                    {
                        Triangle3D otherTri = otherTriangles[otherTriIndex];
                        if (thisTri.IntersectsTriangle(otherTri, out intersectInfo))
                        {
                            output.Add(intersectInfo);
                        }
                    }
                }

                return(output);
            }
            else
            {
                return(new List <Triangle3DIntersectInfo>());
            }
        }
예제 #7
0
        /// <summary>
        /// Performs a ray cast against the mesh tree and returns an instance of the 'MeshRayHit'
        /// class which holds information about the ray hit. The method returns the hit which is
        /// closest to the ray origin. If no triangle was hit, the method returns null.
        /// </summary>
        public MeshRayHit Raycast(Ray ray, TransformMatrix meshTransformMatrix)
        {
            // If the tree was not yet build, we need to build it because we need
            // the triangle information in order to perform the raycast.
            if (!_wasBuilt)
            {
                Build();
            }

            // When the sphere tree is constructed it is constructed in the mesh local space (i.e. it takes
            // no position/rotation/scale into account). This is required because a mesh can be shared by
            // lots of different objects each with its own transform data. This is why we need the mes matrix
            // parameter. It allows us to transform the ray in the mesh local space and perform our tests there.
            Ray meshLocalSpaceRay = ray.InverseTransform(meshTransformMatrix.ToMatrix4x4x);

            // First collect all terminal nodes which are intersected by this ray. If no nodes
            // are intersected, we will return null.
            List <SphereTreeNodeRayHit <MeshSphereTreeTriangle> > nodeRayHits = _sphereTree.RaycastAll(meshLocalSpaceRay);

            if (nodeRayHits.Count == 0)
            {
                return(null);
            }

            // We now have to loop thorugh all intersected nodes and find the triangle whose
            // intersection point is closest to the ray origin.
            float      minT                   = float.MaxValue;
            Triangle3D closestTriangle        = null;
            int        indexOfClosestTriangle = -1;
            Vector3    closestHitPoint        = Vector3.zero;

            foreach (var nodeRayHit in nodeRayHits)
            {
                // Retrieve the data associated with the node and construct the mesh triangle instance
                MeshSphereTreeTriangle sphereTreeTriangle = nodeRayHit.HitNode.Data;
                Triangle3D             meshTriangle       = _octave3DMesh.GetTriangle(sphereTreeTriangle.TriangleIndex);

                // Check if the ray intersects the trianlge which resides in the node
                float hitEnter;
                if (meshTriangle.Raycast(meshLocalSpaceRay, out hitEnter))
                {
                    // The trianlge is intersected by the ray, but we also have to ensure that the
                    // intersection point is closer than what we have found so far. If it is, we
                    // store all relevant information.
                    if (hitEnter < minT)
                    {
                        minT                   = hitEnter;
                        closestTriangle        = meshTriangle;
                        indexOfClosestTriangle = sphereTreeTriangle.TriangleIndex;
                        closestHitPoint        = meshLocalSpaceRay.GetPoint(hitEnter);
                    }
                }
            }

            // If we found the closest triangle, we can construct the ray hit instance and return it.
            // Otherwise we return null. This can happen when the ray intersects the triangle node
            // spheres, but the triangles themselves.
            if (closestTriangle != null)
            {
                // We have worked in mesh local space up until this point, but we want to return the
                // hit info in world space, so we have to transform the hit data accordingly.
                closestHitPoint = meshTransformMatrix.MultiplyPoint(closestHitPoint);
                minT            = (ray.origin - closestHitPoint).magnitude;
                Vector3 worldNormal = meshTransformMatrix.MultiplyVector(closestTriangle.Normal);

                return(new MeshRayHit(ray, minT, _octave3DMesh, indexOfClosestTriangle, closestHitPoint, worldNormal, meshTransformMatrix));
            }
            else
            {
                return(null);
            }
        }
예제 #8
0
        public void UpdateForMouseMovement()
        {
            if (!_isActive)
            {
                return;
            }

            if (MouseButtonStates.Instance.IsMouseButtonDown(MouseButton.Left))
            {
                _state = ObjectVertexSnapSessionState.SnapToDestination;
            }
            else
            {
                _state = ObjectVertexSnapSessionState.SelectSourceVertex;
            }

            if (_state == ObjectVertexSnapSessionState.SelectSourceVertex)
            {
                if (_sourceObjects == null || _sourceObjects.Count == 0)
                {
                    _objectMask.ObjectCollectionMask.UnmaskAll();
                    MouseCursorRayHit cursorRayHit = GetCursorRayHit();
                    if (cursorRayHit.WasAnObjectHit)
                    {
                        GameObjectRayHit objectRayHit = cursorRayHit.ClosestObjectRayHit;
                        MeshRayHit       meshRayHit   = objectRayHit.ObjectMeshHit;
                        if (meshRayHit != null)
                        {
                            Octave3DMesh octaveMesh = meshRayHit.HitMesh;

                            Triangle3D sourceTriangle = octaveMesh.GetTriangle(meshRayHit.HitTriangleIndex);
                            sourceTriangle.TransformPoints(objectRayHit.HitObject.transform.localToWorldMatrix);

                            _sourceVertex = sourceTriangle.GetPointClosestToPoint(meshRayHit.HitPoint);
                            _sourceObject = objectRayHit.HitObject;
                            _objectMask.ObjectCollectionMask.Mask(_sourceObject.transform.root.gameObject.GetAllChildrenIncludingSelf());
                        }
                        else
                        {
                            SpriteRenderer spriteRenderer = objectRayHit.HitObject.GetComponent <SpriteRenderer>();
                            if (spriteRenderer != null)
                            {
                                _sourceObject = objectRayHit.HitObject;
                                _sourceVertex = Vector3Extensions.GetClosestPointToPoint(objectRayHit.ObjectBoxHit.HitBox.GetCenterAndCornerPoints(), objectRayHit.HitPoint);
                                _objectMask.ObjectCollectionMask.Mask(_sourceObject.transform.root.gameObject.GetAllChildrenIncludingSelf());
                            }
                        }
                    }
                }
                else
                {
                    MouseCursorRayHit cursorRayHit = GetCursorRayHit();
                    if (cursorRayHit.WasAnObjectHit)
                    {
                        GameObjectRayHit objectRayHit = cursorRayHit.ClosestObjectRayHit;
                        MeshRayHit       meshRayHit   = objectRayHit.ObjectMeshHit;
                        if (meshRayHit != null)
                        {
                            Octave3DMesh octaveMesh = meshRayHit.HitMesh;

                            Triangle3D sourceTriangle = octaveMesh.GetTriangle(meshRayHit.HitTriangleIndex);
                            sourceTriangle.TransformPoints(objectRayHit.HitObject.transform.localToWorldMatrix);
                            _sourceVertex = sourceTriangle.GetPointClosestToPoint(meshRayHit.HitPoint);
                        }
                        else
                        {
                            SpriteRenderer spriteRenderer = objectRayHit.HitObject.GetComponent <SpriteRenderer>();
                            if (spriteRenderer != null)
                            {
                                _sourceVertex = Vector3Extensions.GetClosestPointToPoint(objectRayHit.ObjectBoxHit.HitBox.GetCenterAndCornerPoints(), objectRayHit.HitPoint);
                            }
                        }
                    }

                    foreach (var parent in _sourceParents)
                    {
                        _objectMask.ObjectCollectionMask.Mask(parent.GetAllChildrenIncludingSelf());
                    }
                }
            }
            else
            {
                MouseCursorRayHit cursorRayHit = GetCursorRayHit();
                if (cursorRayHit.WasAnythingHit)
                {
                    bool useGridCellHit = false;
                    if (!cursorRayHit.WasAnObjectHit)
                    {
                        useGridCellHit = true;
                    }
                    else
                    if (cursorRayHit.WasAnObjectHit && cursorRayHit.WasACellHit)
                    {
                        float gridCellHitEnter = cursorRayHit.GridCellRayHit.HitEnter;
                        float objectHitEnter   = cursorRayHit.ClosestObjectRayHit.HitEnter;
                        if (gridCellHitEnter < Mathf.Max(0.0f, (objectHitEnter - 1e-3f)))
                        {
                            useGridCellHit = true;
                        }
                    }

                    if (useGridCellHit)
                    {
                        XZGridCell       hitCell  = cursorRayHit.GridCellRayHit.HitCell;
                        XZOrientedQuad3D cellQuad = hitCell.Quad;

                        _destinationObject   = null;
                        _destinationGridCell = hitCell;

                        _snapPosition = cellQuad.GetPointClosestToPoint(cursorRayHit.GridCellRayHit.HitPoint, true);
                        SnapToDestination();
                    }
                    else
                    {
                        GameObjectRayHit objectRayHit = cursorRayHit.ClosestObjectRayHit;
                        MeshRayHit       meshRayHit   = objectRayHit.ObjectMeshHit;
                        if (meshRayHit != null)
                        {
                            _destinationObject = objectRayHit.HitObject;
                            Triangle3D destinationTriangle = meshRayHit.HitMesh.GetTriangle(meshRayHit.HitTriangleIndex);
                            destinationTriangle.TransformPoints(_destinationObject.transform.localToWorldMatrix);
                            _destinationGridCell = null;

                            _snapPosition = destinationTriangle.GetPointClosestToPoint(meshRayHit.HitPoint);
                            SnapToDestination();
                        }
                        else
                        {
                            SpriteRenderer spriteRenderer = objectRayHit.HitObject.GetComponent <SpriteRenderer>();
                            if (spriteRenderer != null)
                            {
                                _destinationGridCell = null;
                                _destinationObject   = objectRayHit.HitObject;

                                _snapPosition = Vector3Extensions.GetClosestPointToPoint(objectRayHit.ObjectBoxHit.HitBox.GetCenterAndCornerPoints(), objectRayHit.HitPoint);
                                SnapToDestination();
                            }
                        }
                    }
                }
            }
        }