我正在创建一个光线跟踪的我的世界风格的体素引擎。我将水平存储在单个3d阵列中,其中每个值代表体素的类型,例如, 0 =空气,1 =石头等。之后体素需要具有某些特性,例如,有些可能是纹理化的,并且在放置它们时可能必须执行某些操作。
我想到的第一个也是最明显的解决方案是使用OnPlace等方法创建基本体素类,这些方法将由其他类型派生。但我不确定如何将其链接回地图,我需要一种非常快的方式(光线跟踪速度很慢)且灵活,但我不知道。有什么建议吗?
答案 0 :(得分:3)
我认为您需要使用Dictionary。为每个班级提供一个ID是很好的,您可以轻松地将其放入公共的只读属性中。然后创建一个字典,其中键是ID,值是类类型。这样你就可以有效地存储关卡并使用字典(快速但内存有些昂贵)来查找每个块应该如何渲染。
当程序启动时,您需要使用反射并遍历体素基类的所有子类以创建字典。
如果您计划支持mods / plugins,那么您需要能够搜索超过自己的程序集(最难的部分是获取对程序集的引用,之后它只是回收代码)但是现在只需要开始你自己的。
答案 1 :(得分:3)
明显的方法是拥有3d对象数组(class Voxel
)并使用location = {int x, int y, int z};
进行反向引用。
请注意,将“voxel”中的引用完全退回到位置可能是个好主意,因此您不需要为每个单元格使用唯一对象。您可以考虑使用flyweight pattern分享类似“体素”对象的大部分日期,即使您仍然需要保留对地图的引用。
答案 2 :(得分:0)
我并不完全是你所要求的,因为当你说“枚举类”时,它会让我想到使用反射迭代对象属性;显然,这不是你想要做的。
对我而言,听起来更像是你的3D数组应该是持有对象而不是整数。如果你有一个所有体素继承的Voxel
基类,则不需要类型说明符。相反,您只需将抽象方法放在基类中,然后在派生类中重写它们。一旦完成所有设置,任何处理数组的代码都应该能够与它进行交互,而不需要知道派生类的类型。
应用程序代码应该只将其视为Voxel
类型的数组。在任何给定的Voxel
上调用方法应该执行特定于该类型的体素的行为。这是继承和多态的基本思想。
答案 3 :(得分:0)
好的,你的性能瓶颈不是“选择体素类型”。这是几百万条光线的交叉和碰撞检测(每个像素至少 1,但你不会得到每像素只有1条光线的良好渲染),你需要以60fps的速度进行跟踪。 / p>
这些天疯狂的唯一方法是使用GPU光线追踪
因此,您主要关心的不是“使用什么数据结构”来确定体素类型。它是GPU上高效的光线交叉代码。
NVIDIA目前有一个名为Optix的光线跟踪引擎。
答案 4 :(得分:0)
很大程度上取决于您遍历rendering the voxels数据的方式。对于渲染octree可能是一个很好的解决方案(或者可能是K-d tree)
我建议您首先关注需要哪种访问(可能通过测试),然后进行优化。