2014-05-20 5 views
0

Я делаю приложение визуализации javafx для трехмерных точек. Так как я новичок в JavaFX, я начал из учебника, представленный на сайте оракула:Как улучшить производительность Javafx 3d?

http://docs.oracle.com/javase/8/javafx/graphics-tutorial/javafx-3d-graphics.htm#JFXGR256

В приведенном выше примере работает отлично на моем Mac, но после добавления больше очков, двигайте мышь, которая вызывает камеру чтобы вращать и, следовательно, люди могли просматривать объекты с разных сторон, стали очень медленными и просто неприменимыми.

Я в настоящее время есть данные для кролика с около 40000 точек: visualisation of a rabbit with about 40000 points

код, я использовал, чтобы вращать камеру:

cameraXform.ry.setAngle(cameraXform.ry.getAngle() - mouseDeltaX * MOUSE_SPEED * modifier * ROTATION_SPEED);    
cameraXform.rx.setAngle(cameraXform.rx.getAngle() + mouseDeltaY * MOUSE_SPEED * modifier * ROTATION_SPEED); 

который является таким же, как и в примере оракула.

То, что я пробовал:

  1. набор JVM флаг -Djavafx.animation.fullspeed = правда, это немного помогло, но не имеет существенного значения.
  2. установить флаг JVM -Djavafx.autoproxy.disable = true, это не помогло.
  3. установить кэш в true и CacheHint в Cache.SPEED, это не имело большого значения.
  4. Создайте еще один поток, чтобы сделать поворот и синхронизируйте его после вычисления, это не помогло ни одному.

Любая помощь приветствуется. Спасибо заранее!

+0

Вы не указали столько информации о своем фактическом приложении. Я чувствую, что любое замедление не связано с преобразованием камеры, а в структуру оставшегося графика сцены. Или сказать так: ** Если ** вы отдаете эти 40000 очков как 40000 сфер, то неудивительно, что он становится слишком медленным ... – Marco13

+0

@ Marco13 Спасибо за ваш ответ. Да, я делаю точки в виде сфер, потому что мне нужно установить перемещение мыши для каждой точки, чтобы я мог показать ее координаты, если вы наложите на нее мышь.Можете ли вы дать мне какой-либо совет, чтобы я мог поместить эти трехмерные точки в один узел (если это возможно), и я могу отобразить его координаты (x, y, z), как только я наведу на него мышь? Благодаря! –

+0

Для трехмерной части JavaFX они, очевидно, заимствовали некоторые концепции из Java3D, и там у нас была та же проблема. Я не знаю «хорошего» решения для этого. Можно управлять всей геометрией вручную (в «TriangleMesh») и делать сбор вручную, но это будет означать * значительное * усилие, и это вряд ли возможно здесь. Первая, более простая попытка может заключаться в замене 'Sphere' на 'Box'es: они * намного меньше геометрии, поэтому, вероятно, быстрее, вы вряд ли заметите визуальную разницу на уровне масштабирования, как на скриншоте, и они все еще позволяют мыши-зависанию - просто идея ... – Marco13

ответ

1

Вот как я создал облако точек, используя тетраэдры в треугольной сетке. кажется, работает быстрее, чем использование сфер или квадратов. этот код помог мне scalafx google code

import java.util.ArrayList; 
import javafx.scene.shape.TriangleMesh; 

public class TetrahedronMesh extends TriangleMesh { 
    private ArrayList<Point3i> vertices; 
    private int[] facesLink; 

    public TetrahedronMesh(double length, ArrayList<Point3i> v) { 
     this.vertices = v; 
     if (length > 0.0) { 
      float[] points = new float[vertices.size() * 12]; 
      int[] faces = new int[vertices.size() * 24]; 
      facesLink = new int[vertices.size() * 4]; 
      float[] texCoords = new float[vertices.size() * 12]; 
      int vertexCounter = 0; 
      int primitiveCounter = 0; 
      int pointCounter = 0; 
      int facesCounter = 0; 
      int texCounter = 0; 
      for (Point3i vertex : vertices) { 
       vertex.scale(100); 
       points[primitiveCounter] = vertex.x; 
       points[primitiveCounter + 1] = (float) (vertex.y - (length 
         * Math.sqrt(3.0)/3.0)); 
       points[primitiveCounter + 2] = -vertex.z; 
       points[primitiveCounter + 3] = (float) (vertex.x + (length/2.0)); 
       points[primitiveCounter + 4] = (float) (vertex.y + (length 
         * Math.sqrt(3.0)/6.0)); 
       points[primitiveCounter + 5] = -vertex.z; 
       points[primitiveCounter + 6] = (float) (vertex.x - (length/2.0)); 
       points[primitiveCounter + 7] = (float) (vertex.y + (length 
         * Math.sqrt(3.0)/6.0)); 
       points[primitiveCounter + 8] = -vertex.z; 
       points[primitiveCounter + 9] = vertex.x; 
       points[primitiveCounter + 10] = vertex.y; 
       points[primitiveCounter + 11] = (float) -(vertex.z - (length * Math 
         .sqrt(2.0/3.0))); 
       faces[facesCounter] = pointCounter + 0; 
       faces[facesCounter + 1] = pointCounter + 0; 
       faces[facesCounter + 2] = pointCounter + 1; 
       faces[facesCounter + 3] = pointCounter + 1; 
       faces[facesCounter + 4] = pointCounter + 2; 
       faces[facesCounter + 5] = pointCounter + 2; 
       faces[facesCounter + 6] = pointCounter + 1; 
       faces[facesCounter + 7] = pointCounter + 1; 
       faces[facesCounter + 8] = pointCounter + 0; 
       faces[facesCounter + 9] = pointCounter + 0; 
       faces[facesCounter + 10] = pointCounter + 3; 
       faces[facesCounter + 11] = pointCounter + 3; 
       faces[facesCounter + 12] = pointCounter + 2; 
       faces[facesCounter + 13] = pointCounter + 2; 
       faces[facesCounter + 14] = pointCounter + 1; 
       faces[facesCounter + 15] = pointCounter + 1; 
       faces[facesCounter + 16] = pointCounter + 3; 
       faces[facesCounter + 17] = pointCounter + 4; 
       faces[facesCounter + 18] = pointCounter + 0; 
       faces[facesCounter + 19] = pointCounter + 0; 
       faces[facesCounter + 20] = pointCounter + 2; 
       faces[facesCounter + 21] = pointCounter + 2; 
       faces[facesCounter + 22] = pointCounter + 3; 
       faces[facesCounter + 23] = pointCounter + 5; 
       facesLink[pointCounter] = vertexCounter; 
       facesLink[pointCounter + 1] = vertexCounter; 
       facesLink[pointCounter + 2] = vertexCounter; 
       facesLink[pointCounter + 3] = vertexCounter; 
       texCoords[texCounter] = 0.5f; 
       texCoords[texCounter + 1] = 1.0f; 
       texCoords[texCounter + 2] = 0.75f; 
       texCoords[texCounter + 3] = (float) (1.0 - Math.sqrt(3.0)/4.0); 
       texCoords[texCounter + 4] = 0.25f; 
       texCoords[texCounter + 5] = (float) (1.0 - Math.sqrt(3.0)/4.0); 
       texCoords[texCounter + 6] = 1.0f; 
       texCoords[texCounter + 7] = 1.0f; 
       texCoords[texCounter + 8] = 0.5f; 
       texCoords[texCounter + 9] = (float) (1.0 - Math.sqrt(3.0)/2.0); 
       texCoords[texCounter + 10] = 0.0f; 
       texCoords[texCounter + 11] = 1.0f; 
       vertexCounter++; 
       primitiveCounter += 12; 
       pointCounter += 4; 
       facesCounter += 24; 
       texCounter += 12; 
      } 
      getPoints().setAll(points); 
      getFaces().setAll(faces); 
      getTexCoords().setAll(texCoords); 
      // getFaceSmoothingGroups().setAll(0, 1, 2, 3); 
     } 
    } 

    public Point3i getPointFromFace(int faceId) { 
     return vertices.get(facesLink[faceId]); 
    } 
} 

Point3i код следующим

public class Point3i { 
    public int x; 
    public int y; 
    public int z; 

    public Point3i() { 
     x = 0; 
     y = 0; 
     z = 0; 
    } 
} 

Выбор точки, используя сцену

scene.setOnMousePressed(new EventHandler<MouseEvent>() { 
     @Override 
     public void handle(MouseEvent me) { 
      PickResult pr = me.getPickResult(); 
      int faceId = pr.getIntersectedFace(); 
      if (faceId != -1) { 
       Point3i p = tetrahedronMesh.getPointFromFace(faceId); 
      } 
     } 
    }); 
+0

Это похоже на то, что я предложил в комментарии. Трудность здесь, вероятно, будет заключаться в том, что ассер также нуждался в некоторой «мышиной»/сборке. Должно быть стоит +1, тем не менее ... – Marco13

+0

Функция getPointFromFace возвращает точку, основанную на выбранном треугольнике – MitchBroadhead

+0

О, я вижу, 'PickResult' предоставляет пересекаемую грань (я не так хорошо знаком с JavaFX (пока), извините ...) – Marco13

0

Я знаю, что это старый, но для других ..

Вместо создания новой формы все вместе, каждый из predef ined shape Sphere, Box, Cylinder, позволяет вам установить количество делений в конструкторе.

Сфера, например, по умолчанию равна 64 делениям, 32 по долготе, 32 для широты. вы можете легко сделать ... = новая Сфера (радиус, деления); (4 - это минимум, который я считаю для Сферы).

+0

Я пробовал это, но он по-прежнему вращается, как будто объект застрял в сиропе. – MitchBroadhead

Смежные вопросы