2015-09-11 2 views
0

У меня есть следующий код, который рисует 4 точки в окне canvas3Dперемещать отдельные Point3f в shape3D, состоящие из большого массива Point3f

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); 
    } 
} 

Теперь я хочу добавить TimerTask, который регулярно обновляет положение одной из точек в массиве plaPts Point3f. Однако, когда я вызываю plaPts [1] .setX (2), на экране ничего не происходит, они остаются в том же положении.

Вам нужно иметь каждую точку в отдельной TransformGroup (состоящей из shape3D с массивом Point3f размера 1), чтобы это было возможно? Я позже буду использовать 100000 очков, это плохо для производительности, если все они находятся в отдельных TransformGroups? Есть ли более простой способ сделать это? Что-то вроде shape3D.repaint(), который автоматически обновляет положение точек на основе новых значений в plaPTS.

ответ

0

Do не использовать 10000 TransformGroup экземпляров, это приведет к ужасным производительности (по сравнению с одной PointArray).

Вы должны взглянуть на GeometryArray JavaDocs, в частности, о distiction между использованием данных путем копирования и по ссылке.

Новые версии Java3D поддерживают только путем копирования метода. (Ваш подход работал бы с методом по ссылке, но вам все равно придется запускать обновление).

Тот факт, что данные используются копированием означает, что копия вашего 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, это означает, что изначально окно является серым, если вы не измените его размер или не перерисуете. Вы можете избежать этого, добавив

    System.setProperty("sun.awt.noerasebackground", "true"); 
    

    в первой строке вашего метода main.