PositionAndRotation TargetPositionAndRotation(GameObject[] targets)
    {
        float halfVerticalFovRad   = (_camera.fieldOfView * Mathf.Deg2Rad) / 2f;
        float halfHorizontalFovRad = Mathf.Atan(Mathf.Tan(halfVerticalFovRad) * _camera.aspect);

        var rotation        = Quaternion.Euler(Pitch, Yaw, Roll);
        var inverseRotation = Quaternion.Inverse(rotation);

        var targetsRotatedToCameraIdentity = targets.Select(target => inverseRotation * target.transform.position).ToArray();

        float furthestPointDistanceFromCamera = targetsRotatedToCameraIdentity.Max(target => target.z);
        float projectionPlaneZ = furthestPointDistanceFromCamera + 3f;

        ProjectionHits viewProjectionLeftAndRightEdgeHits =
            ViewProjectionEdgeHits(targetsRotatedToCameraIdentity, ProjectionEdgeHits.LEFT_RIGHT, projectionPlaneZ, halfHorizontalFovRad).AddPadding(PaddingRight, PaddingLeft);
        ProjectionHits viewProjectionTopAndBottomEdgeHits =
            ViewProjectionEdgeHits(targetsRotatedToCameraIdentity, ProjectionEdgeHits.TOP_BOTTOM, projectionPlaneZ, halfVerticalFovRad).AddPadding(PaddingUp, PaddingDown);

        var requiredCameraPerpedicularDistanceFromProjectionPlane =
            Mathf.Max(
                RequiredCameraPerpedicularDistanceFromProjectionPlane(viewProjectionTopAndBottomEdgeHits, halfVerticalFovRad),
                RequiredCameraPerpedicularDistanceFromProjectionPlane(viewProjectionLeftAndRightEdgeHits, halfHorizontalFovRad)
                );

        Vector3 cameraPositionIdentity = new Vector3(
            (viewProjectionLeftAndRightEdgeHits.Max + viewProjectionLeftAndRightEdgeHits.Min) / 2f,
            (viewProjectionTopAndBottomEdgeHits.Max + viewProjectionTopAndBottomEdgeHits.Min) / 2f,
            projectionPlaneZ - requiredCameraPerpedicularDistanceFromProjectionPlane);


        return(new PositionAndRotation(rotation * cameraPositionIdentity, rotation));
    }
Exemplo n.º 2
0
    private void DebugDrawProjectionRays(Vector3 cameraPositionIdentity, ProjectionHits viewProjectionLeftAndRightEdgeHits,
                                         ProjectionHits viewProjectionTopAndBottomEdgeHits, float requiredCameraPerpedicularDistanceFromProjectionPlane,
                                         IEnumerable <Vector3> targetsRotatedToCameraIdentity, float projectionPlaneZ, float halfHorizontalFovRad,
                                         float halfVerticalFovRad)
    {
        if (_debugProjection == DebugProjection.DISABLE)
        {
            return;
        }

        DebugDrawProjectionRay(
            cameraPositionIdentity,
            new Vector3((viewProjectionLeftAndRightEdgeHits.Max - viewProjectionLeftAndRightEdgeHits.Min) / 2f,
                        (viewProjectionTopAndBottomEdgeHits.Max - viewProjectionTopAndBottomEdgeHits.Min) / 2f,
                        requiredCameraPerpedicularDistanceFromProjectionPlane), new Color32(31, 119, 180, 255));
        DebugDrawProjectionRay(
            cameraPositionIdentity,
            new Vector3((viewProjectionLeftAndRightEdgeHits.Max - viewProjectionLeftAndRightEdgeHits.Min) / 2f,
                        -(viewProjectionTopAndBottomEdgeHits.Max - viewProjectionTopAndBottomEdgeHits.Min) / 2f,
                        requiredCameraPerpedicularDistanceFromProjectionPlane), new Color32(31, 119, 180, 255));
        DebugDrawProjectionRay(
            cameraPositionIdentity,
            new Vector3(-(viewProjectionLeftAndRightEdgeHits.Max - viewProjectionLeftAndRightEdgeHits.Min) / 2f,
                        (viewProjectionTopAndBottomEdgeHits.Max - viewProjectionTopAndBottomEdgeHits.Min) / 2f,
                        requiredCameraPerpedicularDistanceFromProjectionPlane), new Color32(31, 119, 180, 255));
        DebugDrawProjectionRay(
            cameraPositionIdentity,
            new Vector3(-(viewProjectionLeftAndRightEdgeHits.Max - viewProjectionLeftAndRightEdgeHits.Min) / 2f,
                        -(viewProjectionTopAndBottomEdgeHits.Max - viewProjectionTopAndBottomEdgeHits.Min) / 2f,
                        requiredCameraPerpedicularDistanceFromProjectionPlane), new Color32(31, 119, 180, 255));

        foreach (var target in targetsRotatedToCameraIdentity)
        {
            float distanceFromProjectionPlane = projectionPlaneZ - target.z;
            float halfHorizontalProjectionVolumeCircumcircleDiameter = Mathf.Sin(Mathf.PI - ((Mathf.PI / 2f) + halfHorizontalFovRad)) / (distanceFromProjectionPlane);
            float projectionHalfHorizontalSpan = Mathf.Sin(halfHorizontalFovRad) / halfHorizontalProjectionVolumeCircumcircleDiameter;
            float halfVerticalProjectionVolumeCircumcircleDiameter = Mathf.Sin(Mathf.PI - ((Mathf.PI / 2f) + halfVerticalFovRad)) / (distanceFromProjectionPlane);
            float projectionHalfVerticalSpan = Mathf.Sin(halfVerticalFovRad) / halfVerticalProjectionVolumeCircumcircleDiameter;

            DebugDrawProjectionRay(target,
                                   new Vector3(projectionHalfHorizontalSpan, 0f, distanceFromProjectionPlane),
                                   new Color32(214, 39, 40, 255));
            DebugDrawProjectionRay(target,
                                   new Vector3(-projectionHalfHorizontalSpan, 0f, distanceFromProjectionPlane),
                                   new Color32(214, 39, 40, 255));
            DebugDrawProjectionRay(target,
                                   new Vector3(0f, projectionHalfVerticalSpan, distanceFromProjectionPlane),
                                   new Color32(214, 39, 40, 255));
            DebugDrawProjectionRay(target,
                                   new Vector3(0f, -projectionHalfVerticalSpan, distanceFromProjectionPlane),
                                   new Color32(214, 39, 40, 255));
        }
    }
Exemplo n.º 3
0
    private static float RequiredCameraPerpedicularDistanceFromProjectionPlane(ProjectionHits viewProjectionEdgeHits, float halfFovRad)
    {
        float distanceBetweenEdgeProjectionHits = viewProjectionEdgeHits.Max - viewProjectionEdgeHits.Min;

        return((distanceBetweenEdgeProjectionHits / 2f) / Mathf.Tan(halfFovRad));
    }