Exemple #1
0
        Ray ScreenPointToRay(Vector2 viewPortPos)
        {
            Rect      viewport = new Rect(0, 0, Application.width, Application.height);
            Ray       ray      = new Ray();
            Vector3   o;
            Matrix4x4 clipToWorld;

            GetClipToWorldMatrix(out clipToWorld);

            Matrix4x4 camToWorld = GetCameraToWorldMatrix();

            if (!CameraUnProject(new Vector3(viewPortPos.x, viewPortPos.y, m_NearClip), camToWorld, clipToWorld, viewport, out o))
            {
                return(new Ray(transform.position, new Vector3(0, 0, 1)));
            }
            ray.origin = o;

            if (m_Orthographic)
            {
                // In orthographic projection we get better precision by circumventing the whole projection and subtraction.
                ray.direction = Vector3.Normalize(-camToWorld.GetAxisZ());
            }
            else
            {
                // We need to sample a point much further out than the near clip plane to ensure decimals in the ray direction
                // don't get lost when subtracting the ray origin position.
                if (!CameraUnProject(new Vector3(viewPortPos.x, viewPortPos.y, m_NearClip + 1000), camToWorld, clipToWorld, viewport, out o))
                {
                    return(new Ray(transform.position, new Vector3(0, 0, 1)));
                }
                Vector3 dir = o - ray.origin;
                ray.direction = (Vector3.Normalize(dir));
            }
            return(ray);
        }
Exemple #2
0
        bool CameraUnProject(Vector3 p, Matrix4x4 cameraToWorld, Matrix4x4 clipToWorld, Rect viewport, out Vector3 outP)
        {
            // pixels to -1..1
            Vector3 in_v;

            in_v.x = (p.x - viewport.x) * 2.0f / viewport.width - 1.0f;
            in_v.y = (p.y - viewport.y) * 2.0f / viewport.height - 1.0f;
            // It does not matter where the point we unproject lies in depth; so we choose 0.95, which
            // is further than near plane and closer than far plane, for precision reasons.
            // In a perspective camera setup (near=0.1, far=1000), a point at 0.95 projected depth is about
            // 5 units from the camera.
            in_v.z = 0.95f;

            Vector3 pointOnPlane;

            if (clipToWorld.PerspectiveMultiplyPoint3(in_v, out pointOnPlane))
            {
                // Now we have a point on the plane perpendicular to the viewing direction. We need to return the one that is on the line
                // towards this point, and at p.z distance along camera's viewing axis.
                Vector3 cameraPos = cameraToWorld.GetPosition();
                Vector3 dir       = pointOnPlane - cameraPos;

                // The camera/projection matrices follow OpenGL convention: positive Z is towards the viewer.
                // So negate it to get into Unity convention.
                Vector3 forward     = -cameraToWorld.GetAxisZ();
                float   distToPlane = Vector3.Dot(dir, forward);
                if (Mathf.Abs(distToPlane) >= 1.0e-6f)
                {
                    bool isPerspective = clipToWorld.IsPerspective();
                    if (isPerspective)
                    {
                        dir *= p.z / distToPlane;
                        outP = cameraPos + dir;
                    }
                    else
                    {
                        outP = pointOnPlane - forward * (distToPlane - p.z);
                    }
                    return(true);
                }
            }
            outP = new Vector3(0.0f, 0.0f, 0.0f);
            return(false);
        }
Exemple #3
0
        bool CameraProject(Vector3 p, Matrix4x4 cameraToWorld, Matrix4x4 worldToClip, Rect viewport, out Vector3 outP)
        {
            Vector3 clipPoint;

            outP = new Vector3(0, 0, 0);
            if (worldToClip.PerspectiveMultiplyPoint3(p, out clipPoint))
            {
                Vector3 cameraPos = cameraToWorld.GetPosition();
                Vector3 dir       = p - cameraPos;
                // The camera/projection matrices follow OpenGL convention: positive Z is towards the viewer.
                // So negate it to get into Unity convention.
                Vector3 forward = -cameraToWorld.GetAxisZ();
                float   dist    = Vector3.Dot(dir, forward);

                outP.x = viewport.x + (1.0f + clipPoint.x) * viewport.width * 0.5f;
                outP.y = viewport.y + (1.0f + clipPoint.y) * viewport.height * 0.5f;
                //outP.z = (1.0f + clipPoint.z) * 0.5f;
                outP.z = dist;

                return(true);
            }
            outP.Set(0.0f, 0.0f, 0.0f);
            return(false);
        }