【问题标题】:Data Structure and Algorithm for a 3D Volume?3D 体积的数据结构和算法?
【发布时间】:2014-06-18 19:42:54
【问题描述】:

我一直在修补一些 Minecraft Bukkit 插件的开发,目前正在做一些事情,我需要能够定义空间的“体积”并确定实体(玩家)何时从该体积外部移动到内部(反之亦然)。

如果我将“音量”限制为盒子,它应该很简单。数据结构可以只维护 X/Y/Z 边界整数(因此总共 6 个整数),并且计算给定两个点(从和移动到)的进入/退出应该只是确定 A)是否所有三个 To 值都是在所有三个范围内,并且 B) 至少一个 From 值在其对应范围之外。

(虽然如果有更好、更高效的存储和计算方式,我会全力以赴。)

但是,如果“体积”不是一个简单的盒子怎么办?假设我有一个形状奇特的房间,并且想要封闭那个房间的体积。我可以单独安排多个“卷”来填充整个空间,但是当一个实体从一个移动到另一个时会导致误报。

之前没有在游戏或 3D 引擎方面工作过,我对如何构建这样的东西一无所知。但在我看来,这很可能是一个已经解决并且已知模式的问题。本质上,我正在尝试:

  1. 定义一个可以表示形状奇特的空间体积的数据结构(尽管至少基于块坐标)。
  2. 定义一种算法,在给定移动源和目标的情况下,该算法可以确定移动是否跨越了定义空间的边界。

是否有这方面的既定模式和实践?

【问题讨论】:

    标签: java algorithm data-structures 3d minecraft


    【解决方案1】:

    我不知道这之前是否在任何类型的视频游戏中使用过,但首先想到的是经典的Sieve of Eratosthenes implementation,唯一的变化是使boolean 数组3D,并使用键作为坐标。显然,尽管 xy 在 Minecraft 中的值可能很大,但您可能希望通过保存世界 0,0 位置和您的选择之间的偏移来节省空间,如下所示:

    class OddArea
    {
        static final int MAX_SELECTION_SIZE = 64; //Or whatever
    
        public final int xOffset, yOffset;
    
        // 256 = Chunk height
        public final boolean[][][] squares = new boolean[MAX_SELECTION_SIZE][MAX_SELECTION_SIZE][256];
    
        OddArea()
        {
            this(0, 0);
        }
    
        OddArea(final int xOffset, final int yOffset)
        {
            this.xOffset = xOffset;
            this.yOffset = yOffset;
        }
    
        void addBlock(final int x, final int y, final int z)
        {
            this.squares[x - this.xOffset][y - this.yOffset][z] = true;
        }
    
        boolean isInsideArea(final int x, final int y, final int z)
        {
            return this.squares[x - this.xOffset][y - this.yOffset][z];
        }
    }
    

    z 不需要偏移,因为 Minecraft 世界只有 256 个方块高。

    我能想到的唯一问题是,在开始填充对象之前,您必须知道最低 x,y 坐标

    【讨论】:

    • 求素数的算法(埃拉托色尼筛法)如何应用于边界交叉问题?
    • @JimGarrison 我指的是用你关心的实际值作为键存储布尔数组的风格。
    • 我真的很喜欢这种存储所有包含块的方法,而不是计算碰撞。根据我存储它们的方式,编辑存储的块可能是一项繁重的操作。但是编辑这些卷很少见,可能需要一两分钟,没问题。这会将处理移至该步骤,从而使“碰撞检测”部分可能更快。我什至可以以二进制搜索的方式存储坐标,以使计算变得非常快。
    • @MrLore 简单地使用一个布尔数组不会产生与筛子相关的东西。
    【解决方案2】:

    一般来说,您应该使用类似于kd trees 的数据结构。您可以将您的体积表示为立方体或球体的联合体,并且应该很容易评估对象是否进入体积。

    顺便说一句,要计算两个球体是否相交,请检查中心之间的距离是否小于半径之和。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-20
      • 1970-01-01
      • 1970-01-01
      • 2012-09-07
      • 2013-06-12
      • 2022-06-20
      相关资源
      最近更新 更多