예제 #1
0
 public void TransformPoints(TransformMatrix transformMatrix)
 {
     _points[0] = transformMatrix.MultiplyPoint(_points[0]);
     _points[1] = transformMatrix.MultiplyPoint(_points[1]);
     _points[2] = transformMatrix.MultiplyPoint(_points[2]);
     CalculateAreaAndPlane();
 }
예제 #2
0
        private void CalculateInitialMinMaxPoints(out Vector3 minPoint, out Vector3 maxPoint)
        {
            // We will sort the points along the X axis, but we have to take the polygon's coordinate
            // system into account because if we use the global X axis, we will run into trouble when
            // all points of the polygon reside on the YZ plane (i.e. same X coordinate).
            Vector3 polyLocalRight, polyLocalLook;

            if (_polygonNormal.IsAlignedWith(Vector3.up))
            {
                polyLocalRight = Vector3.right;
                polyLocalLook  = Vector3.Cross(polyLocalRight, Vector3.up);
                polyLocalLook.Normalize();
            }
            else
            {
                polyLocalRight = Vector3.Cross(_polygonNormal, Vector3.up);
                polyLocalRight.Normalize();
                polyLocalLook = Vector3.Cross(polyLocalRight, _polygonNormal);
                polyLocalLook.Normalize();
            }

            Quaternion      polyRotation    = Quaternion.LookRotation(polyLocalLook, _polygonNormal);
            TransformMatrix transformMatrix = new TransformMatrix(Vector3.zero, polyRotation, Vector3.one);

            // Note: We will work in polygon local space and transform the points to world space after we are done.
            minPoint = transformMatrix.MultiplyPointInverse(_polygonPointsOnSamePlane[0]);
            maxPoint = transformMatrix.MultiplyPointInverse(_polygonPointsOnSamePlane[0]);
            for (int ptIndex = 0; ptIndex < _polygonPointsOnSamePlane.Count; ++ptIndex)
            {
                Vector3 point = transformMatrix.MultiplyPointInverse(_polygonPointsOnSamePlane[ptIndex]);
                if (point.x < minPoint.x)
                {
                    minPoint = point;
                }
                if (point.x > maxPoint.x)
                {
                    maxPoint = point;
                }
            }

            minPoint = transformMatrix.MultiplyPoint(minPoint);
            maxPoint = transformMatrix.MultiplyPoint(maxPoint);
        }
예제 #3
0
        public Box Transform(TransformMatrix transformMatrix)
        {
            Vector3 rightAxis = transformMatrix.GetNormalizedRightAxisNoScaleSign();
            Vector3 upAxis    = transformMatrix.GetNormalizedUpAxisNoScaleSign();
            Vector3 lookAxis  = transformMatrix.GetNormalizedLookAxisNoScaleSign();
            Vector3 scale     = transformMatrix.Scale;

            Vector3 newCenter = transformMatrix.MultiplyPoint(Center);

            Vector3 boxExtents      = Extents;
            Vector3 newExtentsRight = rightAxis * boxExtents.x * scale.x;
            Vector3 newExtentsUp    = upAxis * boxExtents.y * scale.y;
            Vector3 newExtentsLook  = lookAxis * boxExtents.z * scale.z;

            float newExtentsX = Mathf.Abs(newExtentsRight.x) + Mathf.Abs(newExtentsUp.x) + Mathf.Abs(newExtentsLook.x);
            float newExtentsY = Mathf.Abs(newExtentsRight.y) + Mathf.Abs(newExtentsUp.y) + Mathf.Abs(newExtentsLook.y);
            float newExtentsZ = Mathf.Abs(newExtentsRight.z) + Mathf.Abs(newExtentsUp.z) + Mathf.Abs(newExtentsLook.z);

            Vector3 newSize = new Vector3(newExtentsX, newExtentsY, newExtentsZ) * 2.0f;

            return(new Box(newCenter, newSize));
        }
예제 #4
0
        public bool Raycast(Ray ray, out float t)
        {
            TransformMatrix transformMatrix = TransformMatrix;
            Ray             modelSpaceRay   = ray.InverseTransform(transformMatrix.ToMatrix4x4x);

            float modelSpaceT;

            if (_modelSpaceBox.Raycast(modelSpaceRay, out modelSpaceT))
            {
                // Note: The intersection offset (i.e. T value) we have calculated so far is expressed in the box model space.
                //       We have to calculate the intersection point in world space and use that to calculate the world space
                //       T value which we will store in the output parameter.
                Vector3 modelSpaceIntersectionPoint = modelSpaceRay.GetPoint(modelSpaceT);
                Vector3 worldIntersectionPoint      = transformMatrix.MultiplyPoint(modelSpaceIntersectionPoint);

                t = (ray.origin - worldIntersectionPoint).magnitude;
                return(true);
            }
            else
            {
                t = 0.0f;
                return(false);
            }
        }
예제 #5
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);
            }
        }
예제 #6
0
        /// <summary>
        /// Returns the world space vertices overlapped by the specified box.
        /// </summary>
        public List <Vector3> GetOverlappedWorldVerts(OrientedBox box, 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();
            }

            // Work in mesh model space because the tree data exists in model space
            OrientedBox meshSpaceOOBB    = new OrientedBox(box);
            Matrix4x4   inverseTransform = meshTransformMatrix.ToMatrix4x4x.inverse;

            meshSpaceOOBB.Transform(inverseTransform);

            // Used to avoid duplicate indices since there can be triangles which share the same vertices
            // and we don't want to return the same vertex multiple times.
            HashSet <int> usedIndices = new HashSet <int>();

            // Retrieve the nodes overlapped by the specified box
            List <SphereTreeNode <MeshSphereTreeTriangle> > overlappedNodes = _sphereTree.OverlapBox(meshSpaceOOBB);

            if (overlappedNodes.Count == 0)
            {
                return(new List <Vector3>());
            }

            // Loop through all nodes
            var overlappedWorldVerts = new List <Vector3>(50);

            foreach (var node in overlappedNodes)
            {
                // Get the triangle associated with the node
                int triangleIndex = node.Data.TriangleIndex;

                MeshTriangleInfo triangleInfo   = _octave3DMesh.GetMeshTriangleInfo(triangleIndex);
                List <Vector3>   trianglePoints = triangleInfo.ModelSpaceTriangle.GetPoints();

                for (int ptIndex = 0; ptIndex < trianglePoints.Count; ++ptIndex)
                {
                    if (usedIndices.Contains(triangleInfo.VertIndices[ptIndex]))
                    {
                        continue;
                    }

                    Vector3 point = trianglePoints[ptIndex];
                    if (meshSpaceOOBB.ContainsPoint(point))
                    {
                        overlappedWorldVerts.Add(meshTransformMatrix.MultiplyPoint(point));
                        usedIndices.Add(triangleInfo.VertIndices[ptIndex]);
                    }
                }

                /*Triangle3D modelSpaceTriangle = _octave3DMesh.GetTriangle(triangleIndex);
                 *
                 * // Now check which of the triangle points resides inside the box
                 * List<Vector3> trianglePoints = modelSpaceTriangle.GetPoints();
                 * foreach(var pt in trianglePoints)
                 * {
                 *  // When a point resides inside the box, we will transform it in world space and add it to the final point list
                 *  if (box.ContainsPoint(pt)) overlappedWorldVerts.Add(meshTransformMatrix.MultiplyPoint(pt));
                 * }*/
            }

            return(overlappedWorldVerts);
        }
예제 #7
0
        public Vector3 GetBoxFaceCenter(BoxFace boxFace)
        {
            Vector3 modelSpaceCenter = _modelSpaceBox.GetBoxFaceCenter(boxFace);

            return(TransformMatrix.MultiplyPoint(modelSpaceCenter));
        }
예제 #8
0
 public void SetTransformMatrix(TransformMatrix transformMatrix)
 {
     Rotation = transformMatrix.Rotation;
     _scale   = transformMatrix.Scale;
     Center   = transformMatrix.MultiplyPoint(_modelSpaceBox.Center);
 }
예제 #9
0
 public void Transform(TransformMatrix transformMatrix)
 {
     Rotation = transformMatrix.Rotation * Rotation;
     _scale   = Vector3.Scale(transformMatrix.Scale, _scale);
     Center   = transformMatrix.MultiplyPoint(Center);
 }