Answer the question
In order to leave comments, you need to log in
World Space Curved UI?
Tell me how to correct it so that buttons and stuff can be pressed normally in worldspace mode?
Initially, everything works in screen space-camera, if you switch to worldspace and see, for example, only half of the canvas with buttons, then you can no longer click on them. Mapping needs to be fixed somehow.
public class CylinderMapping : CanvasMapping
{
protected override void Awake()
{
base.Awake();
if (m_canvas.renderMode != RenderMode.ScreenSpaceCamera)
{
Debug.LogWarning("Cylinder mapping works best in ScreenSpaceCamera mode", this);
}
}
#region CanvasMapping
public override bool MapScreenToCanvas(Vector2 screenCoord, out Vector2 o_canvasCoord)
{
Camera worldCamera = m_canvas.worldCamera;
if (worldCamera != null)
{
// Get the camera transform
Transform worldCameraTransform = worldCamera.transform;
// Get a ray from the camera through the point on the screen
Ray ray3D = worldCamera.ScreenPointToRay(screenCoord);
// Transform the ray direction into view space
Vector3 localRayDirection = worldCameraTransform.InverseTransformDirection(ray3D.direction);
// Calculate the view space size of the canvas
float thetaFOVH = worldCamera.fieldOfView * 0.5f * Mathf.Deg2Rad;
float tanFOVH = Mathf.Tan(thetaFOVH);
float tanFOVW = tanFOVH * worldCamera.aspect;
// Flatten cylinder and ray to 2D so this becomes a ray circle intersection
Vector2 rayDirection2D = new Vector2(localRayDirection.x, localRayDirection.z);
Vector2 circlePosition = new Vector2(0.0f, 1.0f + (tanFOVW * m_depth));
float circleRadius = tanFOVW * m_radius;
// Determine the far intersection, if there is one
float farIntersection;
if (RayCircle2D(Vector2.zero, rayDirection2D, circlePosition, circleRadius, out farIntersection))
{
// Intersection point on the XZ plane
Vector2 cylinderXZ = (rayDirection2D * farIntersection) - circlePosition;
// XZ -> angle around cylinder
float cylinderTheta = Mathf.Atan2(cylinderXZ.x, cylinderXZ.y);
// Y intersection
float cylinderY = localRayDirection.y * farIntersection;
// To viewport [-1, 1]
float viewportX = cylinderTheta / (m_angle * 0.5f * Mathf.Deg2Rad);
float viewportY = cylinderY / tanFOVH;
// To canvas
Vector2 canvasSize = m_canvas.pixelRect.size;
o_canvasCoord.x = ((viewportX * 0.5f) + 0.5f) * canvasSize.x;
o_canvasCoord.y = ((viewportY * 0.5f) + 0.5f) * canvasSize.y;
#if DEBUG_VISUALISE
{
Vector3 intersection3D = worldCameraTransform.TransformPoint(localRayDirection * (farIntersection * m_canvas.planeDistance));
Debug.DrawLine(worldCameraTransform.position, intersection3D);
}
#endif
return true;
}
}
o_canvasCoord = Vector2.zero;
return false;
}
public override void SetCanvasToScreenParameters(Material material)
{
material.SetFloat("Cylinder_Depth", m_depth * 0.5f);
material.SetFloat("Cylinder_Angle", m_angle * Mathf.Deg2Rad);
material.SetFloat("Cylinder_Radius", m_radius * 0.5f);
}
#endregion
bool RayCircle2D(Vector2 rayStart, Vector2 rayDirection, Vector2 circlePosition, float circleRadius, out float o_farIntersection)
{
Vector2 f = rayStart - circlePosition;
float a = Vector2.Dot(rayDirection, rayDirection);
float b = 2.0f * Vector2.Dot(f, rayDirection);
float c = Vector2.Dot(f, f) - (circleRadius * circleRadius);
float discriminantSq = (b * b) - (4.0f * a * c);
if (discriminantSq < 0.0f)
{
// No intersection
o_farIntersection = 0.0f;
return false;
}
else
{
float discriminant = Mathf.Sqrt(discriminantSq);
o_farIntersection = (-b + discriminant) / (2.0f * a);
return true;
}
}
[SerializeField]
[Range(-10.0f, 10.0f)]
float m_depth = -1.0f;
[SerializeField]
[Range(0.0f, 360.0f)]
float m_angle = 180.0f;
[SerializeField]
[Range(0.0f, 10.0f)]
float m_radius = 1.0f;
}
Answer the question
In order to leave comments, you need to log in
Didn't find what you were looking for?
Ask your questionAsk a Question
731 491 924 answers to any question