如何将多个 3D 对象合并为一个网格以消除视觉故障?

How to merge multiple 3D objects as a single Mesh in order to remove a visual glitch?

我一直在使用 JavaFX 3D 生成大量体素地形。出于某种原因,每当我生成景观时,景观的右侧总会有这些奇怪的黑线。我试过更改 PerspectiveCamera 的 near 和 far 剪辑值,但它们似乎没有效果。如果你需要它,我的近剪辑值设置为0.1,我的远剪辑值设置为100000.0

这是我的程序的图片,如您所见,主要在风景的右侧存在明显的视觉故障。

我很确定视觉故障是由于每个立方体都是它自己的对象这一事实造成的。所以在上图中,我创建了 22500 个立方体对象,并用调整后的颜色放置它们以形成景观。

有没有办法创建一个巨大的网格来替换我的大量立方体对象,同时仍然保留颜色?

感谢您的帮助!

合并立方体

通过使用 ScatterMesh from the FXyz library,您可以将立方体对象(我认为每个立方体都是一个 Box)中的所有单独网格合并到一个大三角形网格中,同时保持它们的独特性颜色.

假设您有一组 3D 坐标,每个坐标都定义一个立方体,并且每个坐标(立方体)有一个给定的颜色,这个小代码片段演示了如何做到这一点。它基于 CUBE 标记的使用,这些标记将为散点图中的每个点创建一个 CuboidMesh

List<Double> coordinates = Arrays.asList(x0,y0,z0,...); // n points
List<Color> colors = Arrays.asList(new Color(),...); // n colors

// create org.fxyz3d.geometry.Point3D for each cube with x,y,z,f (index of color)
List<Point3D> cubes = new ArrayList<>();

AtomicInteger i = new AtomicInteger();
colors.stream()
      .forEach(c -> cubes.add(new Point3D(coordinates.get(i.getAndIncrement()), 
                coordinates.get(i.getAndIncrement()), 
                coordinates.get(i.getAndIncrement()),
                colors.indexOf(c))));

// create scatterMesh from cubes, each cube with a size of 20 pixels
ScatterMesh scatterMesh = new ScatterMesh(cubes, 20);

// apply `CUBE` marker
scatterMesh.setMarker(MarkerFactory.Marker.CUBE);

// apply same `f` value to all 8 vertices of each cube
scatterMesh.setFunctionData(cubes.stream()
            .flatMap(p -> Collections.nCopies(8, p.f).stream()).collect(Collectors.toList()));

// Apply texture based on the list of colors 
scatter.setTextureModeVertices3D(new Palette.ListColorPalette(colors), p -> p.f);

通过这种方法,您将得到一个单一的网格。可以使用 PickResult 和一些从给定坐标找到立方体的逻辑来访问立方体。

另一个可以简化识别给定地形高度立方体的选项是使用每个给定高度的 ScatterMesh(将具有相同的颜色):

List<ScatterMesh> scatterMeshList = new ArrayList<>();

// Collect different heights
List<Float> heights = cubes.stream()
            .map(b -> b.z)
            .distinct()
            .collect(Collectors.toList());


scatterMeshList = heights.stream()
        .map(h -> {
            List<Point3D> cubesPerH = cubes.stream()
                    .filter(p -> p.z == h)
                    .collect(Collectors.toList());
            int colorIndex = (int)cubesPerH.get(0).f;

            ScatterMesh scatterMesh = new ScatterMesh(cubesPerH, 20);
            scatterMesh.setMarker(MarkerFactory.Marker.CUBE);
            scatterMesh.setTextureModeNone(colors.get(colorIndex));
            return scatterMesh;
        })
    .collect(Collectors.toList());

工件

具有单个或少量散点网格而不是数百或数千个立方体网格在性能方面显然更好。

但是,这可能无法解决在渲染具有给定纹理的 JavaFX 3D 形状时出现的伪影问题。这是一个已知问题,但我没有找到它,所以它肯定是 reported.