Stop Mesh rendering if it intersect - c#

I am generating a camera frustum mesh through code and it is working fine.
Now I am searching for a solution (shader based or else) to restrict
the camera frustum mesh if it intersects with any object. As you can see in the image, my frustum is passing through the plane which is not correct.
How can I control it? I searched and tried to apply different kinds of shaders but nothing seems to work.

Get the frustum planes of the camera.
Plane[] frustumPlanes = GeometryUtility.CalculateFrustumPlanes(Camera.main); //Or whatever camera you are using
For each GameObject in the scene, get its Renderer component's bounds if any.
Renderer renderer = GetComponent<Renderer>();
if (renderer != null)
{
//get renderer.bounds
}
Test if the renderers bounds intersect with any of the frustum planes.
bool canSee = GeometryUtility.TestPlanesAABB(frustumPlanes, renderer.bounds);
if (canSee)
{
//do something
}
This should be a pretty good approximation of whether your camera can "see" the mesh (i.e if the frustum intersects with any object)

Related

Clamp the canvas to sphere

I have got a sphere that moves in the world space with respect to the camera. I'm clamping an image to the sphere so that it moves together with the sphere. I'm using the following code to do so. This is attached to the sphere gameobject.
public class ClampImage : MonoBehaviour
{
public Camera FirstpersonCamera;
public GameObject image;
void Update()
{
//get the position of the sphere in the worldspace
Vector3 spherePosition = FirstpersonCamera.WorldToScreenPoint(this.transform.position);
//assign the world position of the sphere to the image
image.transform.position = spherePosition;
}
}
I tried to use the same code to clamp the Canvas itself to the sphere but it is not being clamped to the sphere. How do I clamp the entire canvas to the sphere?
Update:
entire canvas refers to the canvas together with its child Gameobjects like texts and images.
The canvas is within the PlayerGameobject. The following are the settings for the canvas and the player Gameobject.
Canvas setting:
Player Gameobject setting:
I have registered the player in place of the image. It just vanishes completely when I ran the code.
If you group the UI items you want in a panel, you can move the panel by placing it in your "image" variable as thats a GameObject, and then you can move the panel as required and all objects will move with it

Translate position from 3D camera to 2D camera

Currently I have 2 cameras, one for viewing the 3D objects (Perspective), and the other camera to view 2D objects (Orthographic).
(Also, the view of the camera never intercepts each other.)
I am trying to display a 2D object based on the position of a 3D object, like so:
What I have is the respective 2D and 3D Camera, as well as the Vector3 position of the 3D GameObject.
What I currently have:
public Vector2 Convert3DPositionTo2DPosition(Camera camera3D, Vector3 position3D, Camera camera2D) {
var tempPos = camera3D.WorldToViewportPoint(position3D);
return camera2D.ViewportToWorldPoint(tempPos);
}
The only problem is that the returned position is not completely aligned with the 3D position.
Which results in this kind of results:
Also, I have made sure that both the 3D and 2D object have their pivot point are set correctly in the center, but it still does not work as intended.
(I am currently using Unity 2019.1.14f1)
Edit
TLDR of what I want:
I want a world position that is based on an object in view of the 3D camera which is now in view of the 2D camera and have them look like they are in the same position in the player's point of view (display screen).
What I am going to instantiate in afterwards (using that position) is a non-UI GameObject.
More specifically a particle system.
Check the Viewport Rect settings for both of your Cameras!
if there is any difference between the two cameras you will always get an offset in the positions.
I tested your solution using
public Camera camera3d;
public Camera camera2d;
public Transform obj3d;
public Transform obj2d;
void Update()
{
obj2d.position = camera2d.ViewportToWorldPoint(camera3d.WorldToViewportPoint(obj3d.position));
}
and it just works fine - as long as the Viewport Rect settings match - as you can see here and here.

Camera.main.ScreenToWorldPoint(Input.mousePosition) always returns camera position, doesnt matter where i click

I am trying to create a script that converts mouseclick position into position in GridLayout. I trying to use Camera.main.ScreenToWorldPoint(), but its returning coordinates of camera, not of the point clicked, doesnt metter if i use static camera or camera fixed on player. I attached this script to CharacterRobotBoy prefab from standard unity assets.
using UnityEngine;
public class Position : MonoBehaviour
{
void Update()
{
if (Input.GetMouseButtonUp(0))
{
Vector3 pz = Camera.main.ScreenToWorldPoint(Input.mousePosition);
Debug.Log("camera:"+pz);
pz.z = 0;
GridLayout gridLayout = transform.parent.GetComponentInParent<GridLayout>();
Vector3Int cellPosition = gridLayout.WorldToCell(pz);
Debug.Log("cell position:"+cellPosition);
}
}
}
Can my code be fixed for the task, or is there a different solution for the problem. Thanks for your help.
PS: I am new to unity.
Suppose you have a flat plane and a camera looking at it from above.
Think of the screen as the lens of the camera, and the cursor as a small ant walking over it. If I remember correctly, ScreenToWorldPoint returns the location of the ant in world-space, which is somewhere in the sky. By setting z := 0, you get a point directly below the camera, regardless of where the cursor is.
What you should do instead is cast a ray from the center of the camera-view through the ant, and collide it with the plane. The collision point is what you are looking for.
It can be done via the ScreenPointToRay method.
You should check out Brackeys RPG tutorial, he's done something similar.
Hope it helps :)

How to use Graphic Raycaster with WorldSpace UI?

I'm trying to figure out how Graphic.Raycaster works, but documentation doesn't help. I want to use it to cast raycast from some position at a certain angle and hit the UI. The other thing is that I don't know how to make it interact with the UI(drag, click etc.). I know that's broad subject, but I just can't find any good explanation of how to use it, so I would be grateful for any explanation.
From Unity docs:
The Graphic Raycaster is used to raycast against a Canvas. The
Raycaster looks at all Graphics on the canvas and determines if any of
them have been hit.
You can use EventSystem.RaycastAll to raycast against graphics(UI) elements.
Here is a short example for your case:
void Update() {
// Example: get controller's current orientation:
Quaternion ori = GvrController.Orientation;
// If you want a vector that points in the direction of the controller
// you can just multiply this quat by Vector3.forward:
Vector3 vector = ori * Vector3.forward;
// ...or you can just change the rotation of some entity on your scene
// (e.g. the player's arm) to match the controller's orientation
playerArmObject.transform.localRotation = ori;
// Example: check if touchpad was just touched
if (GvrController.TouchDown) {
// Do something.
// TouchDown is true for 1 frame after touchpad is touched.
PointerEventData pointerData = new PointerEventData(EventSystem.current);
pointerData.position = Input.mousePosition; // use the position from controller as start of raycast instead of mousePosition.
List<RaycastResult> results = new List<RaycastResult>();
EventSystem.current.RaycastAll(pointerData, results);
if (results.Count > 0) {
//WorldUI is my layer name
if (results[0].gameObject.layer == LayerMask.NameToLayer("WorldUI")){
string dbg = "Root Element: {0} \n GrandChild Element: {1}";
Debug.Log(string.Format(dbg, results[results.Count-1].gameObject.name,results[0].gameObject.name));
//Debug.Log("Root Element: "+results[results.Count-1].gameObject.name);
//Debug.Log("GrandChild Element: "+results[0].gameObject.name);
results.Clear();
}
}
}
The above script is not tested by myself. So there might be some errors.
Here are some other references to help you understand more:
Graphics Raycaster of Unity; How does it work?
Raycast against UI in world space
How to raycast against uGUI objects from an arbitrary screen/canvas position
How do you perform a Graphic Raycast?
GraphicRaycaster
Hope it helps.
Umair M's current suggestion doesn't handle the fact that the ray is originating in world space and traveling at an angle.
It doesn't look to me like you can do a GUI raycast in world space at an angle even if your canvas is in world space. This page suggests a technique of creating a non-rendering camera, moving it around in 3D space with the ray you want to cast, and then doing the GUI raycast relative to that camera. I haven't tried it yet, but it sounds promising.

Translate coordinates to another plane

My main plane is Rectangle(0,0,10000,10000) for example.
My screen plane (ie virtual position) is Rectangle(1000,1000,1920,1080).
My Texture2D is Rectangle(1500,1200,200,100) in main plane.
I need to translate my Texture2D coordinates to my screen plane. I tried with Matrix.Translate without success.
I must get Texture2D = Rectangle(500,200,200,100) in screen plane.
In order to get the Texture2D from (1500, 1200) to (500, 200) you have to use a translation of (-1000, -1000) which are the inverse numbers from your screen plane's coordinates. In code your translation would be something like this
Matrix transform = Matrix.CreateTranslation(-screenPlane.x, -screenPlane.y, 0);
The theory is that you want to move the texture like if your camera was on (0, 0) instead of (1000, 1000). You have to move the texture by (-1000, -1000) in order to do so.
Check the web for 2D camera classes, always usefull to know how cameras work :)
This one for example: http://www.david-amador.com/2009/10/xna-camera-2d-with-zoom-and-rotation/

Categories

Resources