我正在使用 Java 和 Java3D 构建一个可以“飞行”通过的相对简单的银河系模型。
到目前为止,我有一个简单的版本,可以读取 40,000 个已知恒星并将它们(通过键盘+鼠标导航)显示为 Sphere 对象。然而,有几个问题阻碍了进一步的进展。
我正在努力解决的一个问题是我需要根据它们的视星等来渲染恒星,这是恒星绝对亮度(对数标度)和它与观察者的当前距离的函数。视星等非常低的恒星(例如从地球轨道上看到的比邻星)应该是不可见的,而极亮的恒星(例如天津四)即使在距地球相对较大的距离处也应该是可见的。
所以我不能仅仅根据它们固定的“实际”大小和它们与当前观测位置的距离来显示星星。这会导致即使是非常暗淡的近距离恒星也会出现巨大的斑点,而像天津四这样异常明亮的恒星由于距离太远而根本不会显示。
问题是,如何在不动态分配和删除 Java3d 对象的情况下根据其视星等表示恒星的图像,视星等根据其与当前视点位置的距离而变化?或者,如果我必须在渲染开始后更改 Java3D 中的对象,我怎样才能在不降低帧速率的情况下做到这一点?
我试过使用透明度;这只会让巨大的圆圈更难看到。我试过使用雾,但它完全模糊了遥远的星星(和星座线)。我尝试将 Spheres 转换为 Shape3D 对象,但这会占用两倍的堆空间。
一个快乐的特例是我不需要显示任何视星等大于 7.00 的恒星,因为人眼看不到它们。理论上,我应该只需要根据我在空间中的当前位置为我能看到的任何东西生成一个 3D 对象。与为数据库中的每个星形创建一个 Sphere 对象相比,这不仅可以提高性能,还可以帮助我避免用完 Java 堆空间。(我有超过 100,000 颗真正的星星想要包括在内,但是在 40,000 颗之后我的堆空间已经用完了,而且我尝试过的任何 Java 设置都没有给我更多的堆空间。)
我知道这种星光亮度的动态显示是可能的。卓越的 Space Engine 模拟程序的创建者做到了(并且设法获得每秒 60 帧)。我一辈子都想不通他是怎么做到的。
我完全希望我已经达到了我幼稚实现的极限,并且获得可接受的性能和功能的唯一方法是重新设计整个显示概念。我很想看到一些关于如何使用 Java3D 进行动态对象可见性的具体答案,但在这一点上,我将满足于专家的推测。(我不想放弃 Java3D,但我也愿意接受那里的具体建议。)