在 Unity 中查找一组 3D 点的定向边界框

2023-12-21

我有一组 3D 点,或者实际上是小球体,我需要使用 Unity 3D 将它们包围在尽可能小的 3D 框内。

在封闭框只能移动和缩放的情况下,解决方案非常简单,您只需迭代所有点并封装每个点即可。但我还需要找到盒子的最佳方向。

因此,为了用 ASCII 来说明问题,给出一个只有两点的基本 2D 场景:

Y
| * (0,1)
|
|
|
|               * (1,0)
-------------------- X

使用规则增长的边界框,您最终会得到一个非常大的封闭框,其中大部分为空白,而在这种情况下,我需要一个非常薄且绕 Z 轴旋转约 45 度的框。基本上只是一条连接两点的线。

但我永远不知道需要将多少点组合在一起。正如前面提到的,它必须以 3D 模式运行。

到目前为止,我只尝试了基本方法,即不旋转封装盒以获得最佳配合。结果确实离我需要的还很远。

我正在考虑一种基于遗传算法的强力方法,我生成大量随机框,然后简单地选择面积最小的框,同时仍包含所有点。然而,这太慢了。

GameObject go = points[0];
Bounds b = new Bounds(go.transform.position,go.transform.localScale);

for (int i=1;i<points.Count;i++)
{
    go = points[i];
    b.Encapsulate(new Bounds(go.transform.position, go.transform.localScale));
}

GameObject containingBox = Instantiate(boxPrefab);
containingBox.transform.position = b.center;
containingBox.transform.localScale = b.size;
containingBox.transform.rotation= Quaternion.Identity; //How to calculate?

嘿,我搜索了一下,发现了一个非常强大的库,它或多或少直接提供了您正在寻找的内容,甚至积极支持 Unity 类型:

几何3锐利 https://github.com/gradientspace/geometry3Sharp

Unity 项目的实现非常简单

  • 将项目下载为.zip
  • 解压文件夹geometry3Sharp-master进入你的Assets folder
  • 在Unity下ProjectSettings&右箭头;Player&右箭头;Other Settings&右箭头;Configuration&右箭头;Scripting Define Symbols insert

    G3_USING_UNITY;
    

    正如自述文件中所解释的那样:

    geometry3Sharp支持与Unity类型的透明转换。要启用此功能,请定义G3_USING_UNITY在您的 Unity 项目中,通过将此字符串添加到播放器设置中的脚本定义符号框中。

然后您可以简单地计算给定数组的定向边界框的边缘Vector3像这样的点:

using UnityEngine;
using g3;

public class Example : MonoBehaviour
{
    // Just for the demo I used Transforms so I can simply move them around in the scene
    public Transform[] transforms;

    private void OnDrawGizmos()
    {
        // First wehave to convert the Unity Vector3 array
        // into the g3 type g3.Vector3d
        var points3d = new Vector3d[transforms.Length];
        for (var i = 0; i < transforms.Length; i++)
        {
            // Thanks to the g3 library implictely casted from UnityEngine.Vector3 to g3.Vector3d
            points3d[i] = transforms[i].position;
        }

        // BOOM MAGIC!!!
        var orientedBoundingBox = new ContOrientedBox3(points3d);

        // Now just convert the information back to Unity Vector3 positions and axis
        // Since g3.Vector3d uses doubles but Unity Vector3 uses floats
        // we have to explicitly cast to Vector3
        var center = (Vector3)orientedBoundingBox.Box.Center;

        var axisX = (Vector3)orientedBoundingBox.Box.AxisX;
        var axisY = (Vector3)orientedBoundingBox.Box.AxisY;
        var axisZ = (Vector3)orientedBoundingBox.Box.AxisZ;
        var extends = (Vector3)orientedBoundingBox.Box.Extent;

        // Now we can simply calculate our 8 vertices of the bounding box
        var A = center - extends.z * axisZ - extends.x * axisX - axisY * extends.y;
        var B = center - extends.z * axisZ + extends.x * axisX - axisY * extends.y;
        var C = center - extends.z * axisZ + extends.x * axisX + axisY * extends.y;
        var D = center - extends.z * axisZ - extends.x * axisX + axisY * extends.y;

        var E = center + extends.z * axisZ - extends.x * axisX - axisY * extends.y;
        var F = center + extends.z * axisZ + extends.x * axisX - axisY * extends.y;
        var G = center + extends.z * axisZ + extends.x * axisX + axisY * extends.y;
        var H = center + extends.z * axisZ - extends.x * axisX + axisY * extends.y;

        // And finally visualize it
        Gizmos.DrawLine(A, B);
        Gizmos.DrawLine(B, C);
        Gizmos.DrawLine(C, D);
        Gizmos.DrawLine(D, A);

        Gizmos.DrawLine(E, F);
        Gizmos.DrawLine(F, G);
        Gizmos.DrawLine(G, H);
        Gizmos.DrawLine(H, E);

        Gizmos.DrawLine(A, E);
        Gizmos.DrawLine(B, F);
        Gizmos.DrawLine(D, H);
        Gizmos.DrawLine(C, G);

        // And Here we ca just be amazed ;)
    }
}

当然还有类似的东西

orientedBoundingBox.Box.Contains(Vector3d)

用于确定给定点是否位于该框中。


只因为鲁兹姆问:

当然,您可以稍微更改上面的脚本以仅使用实际的网格顶点:

public MeshFilter[] meshFilters;

private void OnDrawGizmos()
{
    var vertices = new List<Vector3>();
    foreach (var meshFilter in meshFilters)
    {
        // have to multiply the vertices' positions
        // with the lossyScale and add it to the transform.position 
        vertices.AddRange(meshFilter.sharedMesh.vertices.Select(vertex => meshFilter.transform.position + Vector3.Scale(vertex, meshFilter.transform.lossyScale)));
    }

    var points3d = new Vector3d[vertices.Count];

    for (var i = 0; i < vertices.Count; i++)
    {
        points3d[i] = vertices[i];
    }

    // ...
    // From here the code is the same as above

看起来基本一样

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在 Unity 中查找一组 3D 点的定向边界框 的相关文章

随机推荐

  • 从https页面转到http页面时是否发送HTTP标头Referer?

    经过几次测试后 我开始得出这样的结论 当用户从 https 页面单击到 http 页面时 浏览器不会发送 Referer HTTP 标头 这是出于什么安全原因 是在标准中的某个地方定义的吗 The HTTP RFC http www w3
  • 大数字的 NumberFormatter 问题

    我尝试使用此代码将字符串转换为数字 反之亦然 此代码必须打印相同的输出 但其输出不正确 谁能帮我 let formatter NumberFormatter NumberFormatter formatter locale Locale i
  • 如何在十亿像素位图上实现平移/缩放?

    在我的项目中 我使用来自高分辨率扫描仪的 未压缩的 16 位灰度 十亿像素图像来进行测量 由于这些位图无法加载到内存中 主要是由于内存碎片 我正在使用图块 以及光盘上的图块 TIFF 看StackOverflow 主题 https stac
  • ASP.NET MVC 2 并列为隐藏值?

    Hi 我有一个包含列表的 View 类 该列表解释了用户已上传的可用文件 使用 html 助手呈现 为了在提交时维护此数据 我在视图中添加了以下内容 我希望 mode ModelView Files 列表将返回到提交操作 但事实并非如此 是
  • 在浏览器中模拟linux终端

    我读过 Fabrice Bellard 在浏览器中模拟 Linux 的内容 Fabrice Bellard 的 Javascript Linux 模拟器如何工作 https stackoverflow com questions 60304
  • 如何编写Python表达式来过滤掉某些字符串

    有一个由多个数字组成的字符串 例如 12 03 5 897 7 10 74 0 103 12 05 6 4 1 8 98 我想用Python正则表达式仅输出那些带有 ONLY 的数字single dot 例如 12 03 and 5 897
  • 三字母组在 C++ 中仍然有效吗?

    我们都知道历史好奇心 https stackoverflow com a 1234618 560648那是二合字母和三合字母 http en wikipedia org wiki Digraphs and trigraphs 但随着近年来
  • 通过C#检索CRM中所有帐户的列表?

    我正在尝试从 CRM 2011 检索所有帐户记录 以便我可以使用 ForEach 循环循环浏览它们并填充下拉列表 我正在读这篇文章 检索实体列表 https stackoverflow com questions 7409091 retri
  • ARM TrustZone 的安全/正常世界与操作系统的内核/用户模式或 x86 的 Ring0/1/2/3?

    我读了这样的文档TrustZone 安全白皮书 http infocenter arm com help topic com arm doc prd29 genc 009492c PRD29 GENC 009492C trustzone s
  • 加密数据作为字符串

    我对加密和 C 语言很陌生 所以这可能是一个明显的问题 但我找不到解决问题的方法 我正在 C 上制作一个应用程序 并在 Linux 中使用 openssl 进行加密 我从这个 url 获得了一个 C 代码示例 该代码允许使用 SHA 加密和
  • 如何使用 dockerfile 在 aws sagemaker 中运行 python 文件

    我有一个 python 代码和一个经过预先训练的模型 并且有一个 model pkl 文件与我在代码所在的同一目录中 现在我必须运行它或将其部署到 aws sagemaker 但没有得到任何解决方案由于aws sagemaker仅支持两个命
  • Html5 拖放到 svg 元素上

    我正在尝试遵循 html5 拖放教程here http www html5rocks com tutorials dnd basics 我无法得到dragstart要注册的事件rect元素 如果我将事件从draggable to mouse
  • Java进程内存使用量不断增加

    前提条件 具有 16 GB RAM 的电脑 Ubuntu 16 10 x64 上安装了 JDK 1 8 x 一个基于 Spring 的标准 Web 应用程序 部署在 Tomcat 8 5 x 上 Tomcat 配置了以下参数 CATALIN
  • Python/Django 时间戳,包括毫秒

    我需要按以下格式打印 并传递给外部 API 当前日期时间 DD MM YYYY HH MM SS SSS 最后 3 个SSS表示毫秒 我知道如何使用 Python 打印当前的日期时间 最多微秒 strftime http docs pyth
  • 检查 CalledProcessError 的输出

    我正在使用 python 子进程模块中的 subprocess check output 来执行 ping 命令 我是这样做的 output subprocess check output ping c 2 W 2 1 1 1 1 它引发
  • 如何正确配置 NSFetchedResultsController

    我将 NSFetchedResultsController 放入我的代码中 这样我就可以对表视图数据进行很好的自动分段 所以我正在运行测试以确保一切正常 我的持久存储中有一个 Book 实体 我将首先以旧方式执行获取 然后尝试使用 NSFe
  • Django Admin:根据先前的字段值填充字段

    我在 django admin 中有一个模型如下 ChoiceA on false on false on true on true ChoiceB always always never never id models CharField
  • SAFESEH:NO 选项的实际作用

    我正在尝试使用boost asio spawn功能就像在example http www boost org doc libs 1 55 0 doc html boost asio example cpp03 spawn echo serv
  • 使用 Javascript 向用户发送 HTTP 附件(打开浏览器的“另存为...”对话框)

    我是网络开发的新手 所以如果这个问题很菜鸟 我深表歉意 我想在 Javascript 中请求时向用户提供服务器硬盘上的文件 即发送 HTTP 附件以触发浏览器的 另存为 对话框 用户单击页面上的按钮 服务器根据他 她的一些帐户设置 和其他参
  • 在 Unity 中查找一组 3D 点的定向边界框

    我有一组 3D 点 或者实际上是小球体 我需要使用 Unity 3D 将它们包围在尽可能小的 3D 框内 在封闭框只能移动和缩放的情况下 解决方案非常简单 您只需迭代所有点并封装每个点即可 但我还需要找到盒子的最佳方向 因此 为了用 ASC