在由大 Point3f 数组组成的 shape3D 中移动单个 Point3f

move individual Point3f in shape3D consisting of big Point3f array

我有以下代码在 canvas3D 中绘制 4 个点 window

public final class energon extends JPanel {    

    int s = 0, count = 0;

    public energon() {
        setLayout(new BorderLayout());
        GraphicsConfiguration gc=SimpleUniverse.getPreferredConfiguration();
        Canvas3D canvas3D = new Canvas3D(gc);//See the added gc? this is a preferred config
        add("Center", canvas3D);

        BranchGroup scene = createSceneGraph();
        scene.compile();

        // SimpleUniverse is a Convenience Utility class
        SimpleUniverse simpleU = new SimpleUniverse(canvas3D);


        // This moves the ViewPlatform back a bit so the
        // objects in the scene can be viewed.
        simpleU.getViewingPlatform().setNominalViewingTransform();

        simpleU.addBranchGraph(scene);
    }
    public BranchGroup createSceneGraph() {
        BranchGroup lineGroup = new BranchGroup();
        Appearance app = new Appearance();
        ColoringAttributes ca = new ColoringAttributes(new Color3f(204.0f, 204.0f,          204.0f), ColoringAttributes.SHADE_FLAT);
        app.setColoringAttributes(ca);

        Point3f[] plaPts = new Point3f[4];

        for (int i = 0; i < 2; i++) {
            for (int j = 0; j <2; j++) {
                plaPts[count] = new Point3f(i/10.0f,j/10.0f,0);
                //Look up line, i and j are divided by 10.0f to be able to
                //see the points inside the view screen
                count++;
            }
        }
        PointArray pla = new PointArray(4, GeometryArray.COORDINATES);
        pla.setCoordinates(0, plaPts);
        Shape3D plShape = new Shape3D(pla, app);
        TransformGroup objRotate = new TransformGroup();
        objRotate.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
        objRotate.addChild(plShape);
        lineGroup.addChild(objRotate);
        return lineGroup;
    }

    public static void main(String[] args) {
        JFrame frame = new JFrame();
        frame.add(new JScrollPane(new energon()));
        frame.setSize(300, 300);
        frame.setVisible(true);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }
}

现在我想添加一个定时任务,定期更新 plaPts Point3f 数组中的一个点的位置。然而,当我调用 plaPts[1].setX(2) 时,屏幕上没有任何反应,它们保持在相同的位置。

是否必须将每个点都放在单独的 TransformGroup 中(由 shape3D 和大小为 1 的 Point3f 数组组成)才能实现?我稍后要使用 100000 个点,如果它们都在单独的 TransformGroups 中,对性能是否不利?有更简单的方法吗?像 shape3D.repaint() 这样的东西,它会根据 plaPTS 中的新值自动更新点的位置。

不要不要使用10000个TransformGroup实例,这将导致可怕的性能(与单个PointArray相比)。

你应该看看GeometryArray JavaDocs,特别是关于通过复制使用数据和通过引用使用数据之间的区别.

较新版本的Java3D只支持复制方法。 (您的方法可以使用 by reference 方法,但您仍然需要触发更新)。

通过复制使用数据的事实意味着当您创建Point3f数组的复制将它传递给 PointArray 方法的构造函数。所以修改这些点不会影响PointArray.

相反,您可以使用setCoordinate方法修改点数。这是一个示例,您可以简单地添加此方法并将 PointArray 传递给它:

private static void moveOnePointOf(final PointArray pa)
{
    pa.setCapability(PointArray.ALLOW_COORDINATE_WRITE);
    Thread t = new Thread(new Runnable()
    {
        Point3f p = new Point3f();
        @Override
        public void run()
        {
            while (true)
            {
                pa.getCoordinate(0, p);
                p.x = (float)Math.sin(System.currentTimeMillis()/1000.0);;
                pa.setCoordinate(0, p);

                try
                {
                    Thread.sleep(100);
                }
                catch (InterruptedException e)
                {
                    Thread.currentThread().interrupt();
                }
            }
        }
    });
    t.setDaemon(true);
    t.start();
}

进一步的说明和提示:

  • 不要对每个点使用一个线程。这只是一个例子 ;-)
  • 别忘了设置写入坐标的能力:

    pointArray.setCapability(PointArray.ALLOW_COORDINATE_WRITE);
    
  • 您甚至可以考虑完全不使用 Point3f 数组,而是直接在 PointArray 中设置坐标

  • 在某些系统上,本机渲染组件有些奇怪。对于 Java3D 或其他基于 OpenGL 的 windows,这意味着 window 最初是灰色的,除非您调整它的大小或重新绘制它。您可以通过添加

    来避免这种情况
    System.setProperty("sun.awt.noerasebackground", "true");
    

    作为您的 main 方法的第一行。