代码之家  ›  专栏  ›  技术社区  ›  Fattie

Unity函数可以从3D管道立即访问2D框?

  •  5
  • Fattie  · 技术社区  · 7 年前

    enter image description here

    当然,得到AABB很简单,Unity有直接的功能,

    enter image description here

    (您可能必须以通常的方式“添加渲染器的所有边界框”,没有问题。)

    因此,Unity确实有一个直接的功能,即在每一帧的内部网格/渲染管道之外,立即为您提供3D AABB框。

    现在,对于所讨论的相机,按位置,AABB确实覆盖了某个2D边界框。。。

    enter image description here

    事实上。。。有没有某种内置的直接方法来找到统一的橙色2D盒子??

    问题-Unity是否有一个功能,可以立即从管道中生成二维frustrum框?

    我不需要一个手动解决方案,我问的是引擎是否在每一帧的管道中都提供了这个方案?

    有电话吗?

    (事实上,最好有这个……)

    enter image description here

    我的感觉是

    • 尤其是闭塞系统
    • 阴影

    肯定会知道橙色的盒子,甚至可能是管道内的蓝色盒子,就在图形卡旁边,就像它知道给定网格的AABB一样。

    我们知道,Unity允许您在给定网格的每一帧立即点击AABB 3D框:事实上Unity是否提供了此处所示的“2D frustrum bound”?

    2 回复  |  直到 7 年前
        1
  •  2
  •   Draco18s no longer trusts SE    7 年前

    据我所知,没有 内置

    然而,你自己发现这些极端是非常容易的。获取网格的边界框(屏幕截图中显示的长方体)就是这样做的,您只是在一个变换的空间中进行。

    1. 循环浏览网格的所有垂直方向,执行以下操作:
    2. Transform
    3. Transform 从世界空间到屏幕空间
    4. 在所有顶点上循环之后,将有4个值:min-X、min-Y、max-X和max-Y

    你也可以先表演 Gift Wrapping 首先,只处理得到的凸包(因为不属于凸包的点永远不会超出凸包的边界)。如果要在模型在屏幕上移动、缩放或旋转时绘制此屏幕空间矩形,并且必须重新计算边界框,则需要执行此操作并缓存结果。

    请注意,这是 如果模型有效 (例如,如果你的人形机器人站起来做跳跃动作)。为动画情况求解要困难得多,因为为了求解凸壳,必须将每个动画的每一帧都视为原始网格的一部分(以确保任何动画都不会将网格的一部分移动到凸壳之外),这会大大增加复杂性。

        2
  •  0
  •   Eric    6 年前

    三维边界框

    1. 获取给定的游戏对象三维边界框的中心和大小
    2. 将位置转换为GUI空间(屏幕空间)

    功能 GUI3dRectWithObject 将返回屏幕上给定游戏对象的三维边界框。

    1. 遍历给定游戏对象中的每个顶点
    2. 将每个顶点的位置转换为世界空间,并转换为GUI空间(屏幕空间)
    3. 查找4角值:x1、x2、y1、y2

    功能 GUI2dRectWithObject

    public static Rect GUI3dRectWithObject(GameObject go)
    {
    
        Vector3 cen = go.GetComponent<Renderer>().bounds.center;
        Vector3 ext = go.GetComponent<Renderer>().bounds.extents;
        Vector2[] extentPoints = new Vector2[8]
        {
                WorldToGUIPoint(new Vector3(cen.x-ext.x, cen.y-ext.y, cen.z-ext.z)),
                WorldToGUIPoint(new Vector3(cen.x+ext.x, cen.y-ext.y, cen.z-ext.z)),
                WorldToGUIPoint(new Vector3(cen.x-ext.x, cen.y-ext.y, cen.z+ext.z)),
                WorldToGUIPoint(new Vector3(cen.x+ext.x, cen.y-ext.y, cen.z+ext.z)),
                WorldToGUIPoint(new Vector3(cen.x-ext.x, cen.y+ext.y, cen.z-ext.z)),
                WorldToGUIPoint(new Vector3(cen.x+ext.x, cen.y+ext.y, cen.z-ext.z)),
                WorldToGUIPoint(new Vector3(cen.x-ext.x, cen.y+ext.y, cen.z+ext.z)),
                WorldToGUIPoint(new Vector3(cen.x+ext.x, cen.y+ext.y, cen.z+ext.z))
        };
        Vector2 min = extentPoints[0];
        Vector2 max = extentPoints[0];
        foreach (Vector2 v in extentPoints)
        {
            min = Vector2.Min(min, v);
            max = Vector2.Max(max, v);
        }
        return new Rect(min.x, min.y, max.x - min.x, max.y - min.y);
    }
    
    public static Rect GUI2dRectWithObject(GameObject go)
    {
        Vector3[] vertices = go.GetComponent<MeshFilter>().mesh.vertices;
    
        float x1 = float.MaxValue, y1 = float.MaxValue, x2 = 0.0f, y2 = 0.0f;
    
        foreach (Vector3 vert in vertices)
        {
            Vector2 tmp = WorldToGUIPoint(go.transform.TransformPoint(vert));
    
            if (tmp.x < x1) x1 = tmp.x;
            if (tmp.x > x2) x2 = tmp.x;
            if (tmp.y < y1) y1 = tmp.y;
            if (tmp.y > y2) y2 = tmp.y;
        }
    
        Rect bbox = new Rect(x1, y1, x2 - x1, y2 - y1);
        Debug.Log(bbox);
        return bbox;
    }
    
    public static Vector2 WorldToGUIPoint(Vector3 world)
    {
        Vector2 screenPoint = Camera.main.WorldToScreenPoint(world);
        screenPoint.y = (float)Screen.height - screenPoint.y;
        return screenPoint;
    }
    

    Example

    参考: Is there an easy way to get on-screen render size (bounds)?

    推荐文章