• Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
0
Question by 1337GameDev · Mar 17, 2014 at 03:58 AM · raycastrenderplaneminimapfrustrum

project view frustrum of camera onto plane as white rectangle

I am building a minimap with a rectangle indicating the camera's view, and I want to be able to generate a rectangle showing where the camera can view, as a rectangle (and not a trapezoid). The camera can rotate, and so will this rectangle.

How would I render this rectangle (assuming a plane is used to help) and make sure it is rendered on a certain layer (to show it on the minimap)?

I found new information, and determined I have to do something with eh view frustum planes. I know these planes are "infinite", so i have to raycast along the edges of the camera's frustum, and want to raycast until I hit a specific gameObject collider. Then I have to somehow generate a rectangle mesh from this, and then set it's color or material to white. How would I do this? I would essentially draw 4 rectangles, one for each "side" of the rectangle I want as my frustum visual.

I also acquired new information, I found a way to generate the camera frustum planes, as a mesh, using the near clip and far clip distance. I used the class form this post: Generate Frustum Mesh to generate the frustum mesh. I now need to get the 4 points of the far clip plane, the near clip plane, and do raycasts along the edges to my surface to generate what I want. Then want to use those points to generate a mesh dynamically to create my rectangle.

How would I get the right plane vertices I want?

I found how to get the vertices I want, I can use a method, and some trigonometry to get the clip plane points at a certain distance. I found this video that describes this function:

 public struct ClipPlanePoints{
         public Vector3 UpperLeft;
         public Vector3 UpperRight;
         public Vector3 LowerLeft;
         public Vector3 LowerRight;
     }
 
 
 public static ClipPlanePoints CameraClipPlanePoints(this Camera cam, float d)
     {
         ClipPlanePoints clipPlanePoints = ClipPlanePoints();
         Transform camTrans = cam.transform;
         Vector3 camPos = camTrans.position;
         float halfFOV = cam.fieldOfView*0.5 * Mathf.Deg2Rad;
         float aspect = cam.aspect;
 
         float height = Mathf.Tan(halfFOV) * d;
         float width = height*aspect;
 
         //lower right
         clipPlanePoints.LowerRight = (camPos + camTrans.forward * d);
         clipPlanePoints.LowerRight += (camTrans.right*width);
         clipPlanePoints.LowerRight -= (camTrans.up * height);
 
         //lower left
         clipPlanePoints.LowerLeft = (camPos + camTrans.forward * d);
         clipPlanePoints.LowerLeft -= (camTrans.right*width);
         clipPlanePoints.LowerLeft -= (camTrans.up * height);
 
         //upperRight
         clipPlanePoints.UpperRight = (camPos + camTrans.forward * d);
         clipPlanePoints.UpperRight += (camTrans.right*width);
         clipPlanePoints.UpperRight += (camTrans.up * height);
 
         //upperLeft
         clipPlanePoints.UpperLeft = (camPos + camTrans.forward * d);
         clipPlanePoints.UpperLeft -= (camTrans.right*width);
         clipPlanePoints.UpperLeft += (camTrans.up * height);
 
         
         return clipPlanePoints;
     }

This gets the points at a certain distance from the camera. Now, I just have to do raycasts from the near clip plane points, to the far clip plane points, and determine the colliding points (base don layer) and use those to build a mesh to render my rectangle.

I found out a decent way (but doesnt work if the camera frustum is out of bounds of the ground surface you're projecting onto):

 using UnityEngine;
 using System.Collections;
 
 public class RenderCameraFrustum:MonoBehaviour 
 {
     bool hasRendered = false;
     bool renderFullFrustum = false;
     bool projectMesh = false;
     bool projectRectangles = true;
     public Material material;
     public CameraExtension.ClipPlanePoints result;
     public float width = 0.5f;
     // Use this for initialization
     void Start() 
     {
         
     }
     
     // Update is called once per frame
     void Update() 
     {
         if(!hasRendered)
         {
             hasRendered=true;
             GameObject g = new GameObject("render");
             g.transform.position = transform.position;
             g.AddComponent<MeshFilter>();
             g.AddComponent<MeshRenderer>();
             MeshRenderer r = g.GetComponent<MeshRenderer>();
             r.material = material;
             MeshFilter m = g.GetComponent<MeshFilter>();
             if(renderFullFrustum)
             {
                 m.mesh = camera.GenerateFrustumMesh();
                 //m.RecalculateNormals();
             }
             else if(projectMesh)
             {
                 //do 4 raycasts, one for each corner vertex
                 //first get frustum points, 2 sets, near and far
                 CameraExtension.ClipPlanePoints nearPoints = camera.CameraClipPlanePoints(camera.nearClipPlane);
                 CameraExtension.ClipPlanePoints farPoints = camera.CameraClipPlanePoints(camera.farClipPlane);
 
                 result = new CameraExtension.ClipPlanePoints();
                 Vector3 rectangleDestination = new Vector3();
                 Vector3 dir = new Vector3();
                 LayerMask lm = LayerMask.NameToLayer("Ground");
                 int mask = 1 << lm.value;
                 //top left
                 dir = farPoints.UpperLeft-nearPoints.UpperLeft;
                 RaycastHit hit;
                 if (Physics.Raycast(nearPoints.UpperLeft, dir, out hit,camera.farClipPlane,mask ))
                 {
                     Debug.Log("raycast upperLeft hit");
                     result.UpperLeft = hit.point;
                 }
 
                 //top right
                 dir = farPoints.UpperRight-nearPoints.UpperRight;
                 if (Physics.Raycast(nearPoints.UpperRight, dir, out hit,camera.farClipPlane,mask ))
                 {
                     Debug.Log("raycast upperLeft hit");
                     result.UpperRight = hit.point;
                 }
 
                 //bottom left
                 dir = farPoints.LowerLeft-nearPoints.LowerLeft;
                 if (Physics.Raycast(nearPoints.LowerLeft, dir, out hit,camera.farClipPlane,mask ))
                 {
                     Debug.Log("raycast upperLeft hit");
                     result.LowerLeft = hit.point;
                 }
 
                 //bottom right
                 dir = farPoints.LowerRight-nearPoints.LowerRight;
                 if (Physics.Raycast(nearPoints.LowerRight, dir, out hit,camera.farClipPlane,mask ))
                 {
                     Debug.Log("raycast upperLeft hit");
                     result.LowerRight = hit.point;
                 }
 
                 //now use these points to create a mesh
                 //UL
                 //UR
                 //LL
                 //LR
                 Vector3[] vertices = new Vector3[]
                 {
                     result.UpperLeft,
                     result.UpperRight,
                     result.LowerLeft,
                     result.LowerRight
                 };
 
                 Vector3[] normals = 
                 {
                     -Vector3.forward,
                     -Vector3.forward,
                     -Vector3.forward,
                     -Vector3.forward
                 };
 
                 Vector2[] uv = new Vector2[]
                 {
                     new Vector2(1, 1),
                     new Vector2(1, 0),
                     new Vector2(0, 1),
                     new Vector2(0, 0),
                 };
                 
                 int[] triangles = new int[]
                 {
                     0, 1, 2,
                     2, 1, 3,
                 };
                 m.mesh.Clear();
                 m.mesh.vertices = vertices;
                 m.mesh.triangles = triangles;
                 m.mesh.normals = normals;
                 m.mesh.uv = uv;
                 //set object position at collided object, then move it with camera.
                 if (Physics.Raycast(camera.transform.position, camera.transform.forward, out hit,camera.farClipPlane,mask ))
                 {
                     //Debug.Log("raycast forward hit");
                     rectangleDestination = hit.point;
                 }
                 g.transform.position = rectangleDestination;
                 //debug output points
                 Debug.Log("near points: 1-["+nearPoints.UpperLeft+"] 2-["+nearPoints.UpperRight+"] 3-["+nearPoints.LowerRight+"] 4-["+nearPoints.LowerLeft+"]");
                 Debug.Log("far points: 1-["+farPoints.UpperLeft+"] 2-["+farPoints.UpperRight+"] 3-["+farPoints.LowerRight+"] 4-["+farPoints.LowerLeft+"]");
 
                 Debug.Log("result points: 1-["+result.UpperLeft+"] 2-["+result.UpperRight+"] 3-["+result.LowerRight+"] 4-["+result.LowerLeft+"]");
             }
             else if(projectRectangles)
             {
                 //do 4 raycasts, one for each corner vertex
                 //first get frustum points, 2 sets, near and far
                 CameraExtension.ClipPlanePoints nearPoints = camera.CameraClipPlanePoints(camera.nearClipPlane);
                 CameraExtension.ClipPlanePoints farPoints = camera.CameraClipPlanePoints(camera.farClipPlane);
 
                 CameraExtension.ClipPlanePoints innerResult = new CameraExtension.ClipPlanePoints();
 
                 result = new CameraExtension.ClipPlanePoints();
                 Vector3 rectangleDestination = new Vector3();
                 Vector3 dir = new Vector3();
                 LayerMask lm = LayerMask.NameToLayer("Ground");
                 int mask = 1 << lm.value;
                 //top left
                 dir = farPoints.UpperLeft-nearPoints.UpperLeft;
                 RaycastHit hit;
                 if (Physics.Raycast(nearPoints.UpperLeft, dir, out hit,camera.farClipPlane,mask ))
                 {
                     //Debug.Log("raycast upperLeft hit");
                     result.UpperLeft = hit.point;
                 }
                 
                 //top right
                 dir = farPoints.UpperRight-nearPoints.UpperRight;
                 if (Physics.Raycast(nearPoints.UpperRight, dir, out hit,camera.farClipPlane,mask ))
                 {
                     Debug.Log("raycast upperLeft hit");
                     result.UpperRight = hit.point;
                 }
                 
                 //bottom left
                 dir = farPoints.LowerLeft-nearPoints.LowerLeft;
                 if (Physics.Raycast(nearPoints.LowerLeft, dir, out hit,camera.farClipPlane,mask ))
                 {
                     //Debug.Log("raycast upperLeft hit");
                     result.LowerLeft = hit.point;
                 }
                 
                 //bottom right
                 dir = farPoints.LowerRight-nearPoints.LowerRight;
                 if (Physics.Raycast(nearPoints.LowerRight, dir, out hit,camera.farClipPlane,mask ))
                 {
                     //Debug.Log("raycast upperLeft hit");
                     result.LowerRight = hit.point;
                 }
 
                 //now get inner rectangle points
                 innerResult.UpperLeft = new Vector3(result.UpperLeft.x+width, result.UpperLeft.y-width, result.UpperLeft.z);
                 innerResult.UpperRight = new Vector3(result.UpperRight.x-width, result.UpperRight.y-width, result.UpperRight.z);
                 innerResult.LowerLeft = new Vector3(result.LowerLeft.x+width, result.LowerLeft.y+width, result.LowerLeft.z);
                 innerResult.LowerRight = new Vector3(result.LowerRight.x-width, result.LowerRight.y+width, result.LowerRight.z);
                 Debug.Log("result inner points: 1-["+innerResult.UpperLeft+"] 2-["+innerResult.UpperRight+"] 3-["+innerResult.LowerRight+"] 4-["+innerResult.LowerLeft+"]");
                 //now use these points to create a mesh
                 //UL
                 //UR
                 //LL
                 //LR
                 Vector3[] vertices = new Vector3[]
                 {
                     //left part
                     result.UpperLeft,
                     innerResult.UpperLeft,
                     result.LowerLeft,
                     innerResult.LowerLeft,
                     //top part
                     result.UpperLeft,
                     result.UpperRight,
                     innerResult.UpperLeft,
                     innerResult.UpperRight,
                     //right part
                     innerResult.UpperRight,
                     result.UpperRight,
                     innerResult.LowerRight,
                     result.LowerRight,
                     //bottom part
                     innerResult.LowerLeft,
                     innerResult.LowerRight,
                     result.LowerLeft,
                     result.LowerRight
                 };
                 
                 Vector3[] normals = 
                 {
                     -Vector3.forward,
                     -Vector3.forward,
                     -Vector3.forward,
                     -Vector3.forward,
 
                     -Vector3.forward,
                     -Vector3.forward,
                     -Vector3.forward,
                     -Vector3.forward,
 
                     -Vector3.forward,
                     -Vector3.forward,
                     -Vector3.forward,
                     -Vector3.forward,
 
                     -Vector3.forward,
                     -Vector3.forward,
                     -Vector3.forward,
                     -Vector3.forward
                 };
                 
                 Vector2[] uv = new Vector2[]
                 {
                     new Vector2(1, 1),
                     new Vector2(1, 0),
                     new Vector2(0, 1),
                     new Vector2(0, 0),
 
                     new Vector2(1, 1),
                     new Vector2(1, 0),
                     new Vector2(0, 1),
                     new Vector2(0, 0),
 
                     new Vector2(1, 1),
                     new Vector2(1, 0),
                     new Vector2(0, 1),
                     new Vector2(0, 0),
 
                     new Vector2(1, 1),
                     new Vector2(1, 0),
                     new Vector2(0, 1),
                     new Vector2(0, 0)
                 };
 
                 //UL 0
                 //UR 1
                 //LL 2
                 //LR 3
                 int[] triangles = new int[]
                 {
                     0, 1, 2,
                     2, 1, 3,
 
                     4, 5, 6,
                     6, 5, 7,
 
                     8, 9, 10,
                     10, 9, 11,
 
                     12, 13, 14,
                     14, 13, 15
                 };
                 m.mesh.Clear();
                 m.mesh.vertices = vertices;
                 m.mesh.triangles = triangles;
                 m.mesh.normals = normals;
                 m.mesh.uv = uv;
                 //set object position at collided object, then move it with camera.
                 if (Physics.Raycast(camera.transform.position, camera.transform.forward, out hit,camera.farClipPlane,mask ))
                 {
                     //Debug.Log("raycast forward hit");
                     rectangleDestination = hit.point;
                 }
                 g.transform.position = rectangleDestination;
                 //debug output points
                 //Debug.Log("near points: 1-["+nearPoints.UpperLeft+"] 2-["+nearPoints.UpperRight+"] 3-["+nearPoints.LowerRight+"] 4-["+nearPoints.LowerLeft+"]");
                 //Debug.Log("far points: 1-["+farPoints.UpperLeft+"] 2-["+farPoints.UpperRight+"] 3-["+farPoints.LowerRight+"] 4-["+farPoints.LowerLeft+"]");
                 
                 //Debug.Log("result points: 1-["+result.UpperLeft+"] 2-["+result.UpperRight+"] 3-["+result.LowerRight+"] 4-["+result.LowerLeft+"]");
             }
 
         }
     }
 }
 

This script does do more than necessary, and switches on booleans to render other frustum pars.

Comment
Add comment
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

0 Replies

· Add your reply
  • Sort: 

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Welcome to Unity Answers

If you’re new to Unity Answers, please check our User Guide to help you navigate through our website and refer to our FAQ for more information.

Before posting, make sure to check out our Knowledge Base for commonly asked Unity questions.

Check our Moderator Guidelines if you’re a new moderator and want to work together in an effort to improve Unity Answers and support our users.

Follow this Question

Answers Answers and Comments

20 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Top down look rotation snaps when looking left, right, and back 1 Answer

rotate towards a raycast hit point 2 Answers

Find TextureCoordinates from plane with out raycast only using mouse position on plan 0 Answers

Screen point to point on Plane WITHOUT Raycast? 1 Answer

Help with some C# 1 Answer


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges