0
\$\begingroup\$

Here is the function to draw a triangle that represents the camera field of view in a minimap. The problem with this code snippet is that when I rotate up and down (Change the pitch of camera) the viewport triangle also rotates up/down.

void makeViewPortCube()
{
    if (player.GetComponent<Camera>() == null)
    {
        // Debug.LogError("Please assing a Main Camera to Follow");
        return;
    }

    if (viewPortMesh == null)
    {
        viewPortGameobject = new GameObject();
        viewPortGameobject.AddComponent<MeshFilter>().mesh = makeStartingMeshForViewPort(2.0f, 2.0f);
        viewPortGameobject.AddComponent<MeshRenderer>().material = materiaForViewPortGameobject();
        viewPortGameobject.name = "View Port Object";
        viewPortMesh = viewPortGameobject.GetComponent<MeshFilter>().mesh;
        viewPortGameobject.layer = LayerMask.NameToLayer("MiniMap");
        viewPortGameobject.transform.position = new Vector3(viewPortGameobject.transform.position.x, /*transform.position.y-*/100, viewPortGameobject.transform.position.z);
    }

    // change vertices of the viewport
    Vector3[] aVertexList = viewPortMesh.vertices;

    if (stopRotation == false)
    {
        //Orignial
        aVertexList[1] = player.GetComponent<Camera>().ScreenToWorldPoint(new Vector3(Screen.width, 0, 10f));
        aVertexList[2] = player.GetComponent<Camera>().ScreenToWorldPoint(new Vector3(Screen.width, 0, player.GetComponent<Camera>().nearClipPlane));
        aVertexList[3] = player.GetComponent<Camera>().ScreenToWorldPoint(new Vector3(0, Screen.height / 4, player.GetComponent<Camera>().nearClipPlane));

        aVertexList[0] = player.GetComponent<Camera>().ScreenToWorldPoint(new Vector3(0, Screen.height / 4, 10f));

        for (int i = 0; i < 4; i++)
        {
            aVertexList[i].y = 3;
        }
    }

    viewPortMesh.vertices = aVertexList;
    viewPortMesh.RecalculateBounds();
}
\$\endgroup\$
2
  • 1
    \$\begingroup\$ Note that we refer to the axes of rotation by which axis we're rotating around. So ordinarily "y-axis rotation" means rotation around the y axis, meaning yaw left and right. The pitching up & down rotation you describe here would usually be termed an x-axis rotation — you'll notice when you do this rotation in Unity and look and the Euler angle fields in the inspector, it's the x component that's changing. \$\endgroup\$ Commented Mar 20, 2020 at 8:41
  • \$\begingroup\$ Thanks for reminding the terms. Yes, I want to to restrict the impact of camera pitch on on triangle. \$\endgroup\$ Commented Mar 20, 2020 at 11:01

1 Answer 1

1
\$\begingroup\$

Instead of using ScreenToWorldPoint, I would do something like the following:

// Get the camera once. GetComponent is an expensive call, so cache the result whenever
// you can instead of calling it repeatedly.
Camera theCamera = player.GetComponent<Camera>();

// The camera's far plane gives the view distance
float viewDistance = theCamera.farClipPlane;

// The camera's current orientation (defined by its "forward" direction) gives the view
// direction. Project onto the ground plane to ignore the up/down part.
Vector3 viewDirection = Vector3.ProjectOnPlane(theCamera.forward, Vector3.up).normalized;

// Get the view width from the camera's field of view
float verticalFoV = theCamera.fieldOfView;
float horizFoV = Camera.VerticalToHorizontalFieldOfView(verticalFoV, theCamera.aspect);

// Get the left and right sides of the view
Quaternion q = Quaternion.AngleAxis(horizFoV / 2f, Vector3.up);
Vector3 rightDir = q * viewDirection;
Vector3 leftDir = -q * viewDirection;

// And finally, to get all three vertices
// (Not sure why you have four in your question...)
Vector3 start = theCamera.transform.position;
Vector3 rightEnd = start + rightDir * viewDistance;
Vector3 leftEnd = start + leftDir * viewDistance;

If you are not comfortable with Quaternions, then you could replace that part with:

float rightAngle = (theCamera.transform.eulerAngles.y + horizFoV_rad/2f) * Mathf.Deg2Rad;
float leftAngle = (theCamera.transform.eulerAngles.y - horizFoV_rad/2f) * Mathf.Deg2Rad;

Vector3 rightDir = new Vector3(Mathf.Sin(rightAngle), 0, Mathf.Cos(rightAngle));
Vector3 leftDir = new Vector3(Mathf.Sin(leftAngle), 0, Mathf.Cos(leftAngle));
// Note that I might have the Sin & Cos backwards, none of this has been tested

By the way, Sebastian Lague made a great tutorial series on field of view visualization, available on Youtube. It's not quite what you are doing, but it should be similar enough to be helpful.

\$\endgroup\$

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.