Уже есть несколько решений.
Библиотека FXyz3D имеет CubeWorld
class, который дает вам точную сетку ссылок.
Его очень легко использовать. Просто импортируйте зависимость 'org.fxyz3d:fxyz3d:0.3.0'
из JCenter и используйте ее:
CubeWorld cubeWorld = new CubeWorld(5000, 500, true);
Sphere sphere = new Sphere(100);
sphere.setMaterial(new PhongMaterial(Color.FIREBRICK));
sphere.getTransforms().add(new Translate(100, 200, 300));
Scene scene = new Scene(new Group(cubeWorld, sphere), 800, 800, true, SceneAntialiasing.BALANCED);
Как видите, решение основано на использовании 2D-прямоугольников для каждой грани, а линии сетки создаются с помощью 3D-цилиндров. Он имеет очень хорошие функции (например, самозасветку или фронтальные лица в соответствии с камерой, не показывает сетку), но он довольно интенсивен в узлах (пример выше имеет 168 узлов).
Существуют и другие решения, в которых используется меньшее количество узлов. Например, для этого образца, который также связан с Leap Motion, я использовал TriangleMesh
.
Это простое решение, всего с двумя сетками. Однако вместо квадратов вы видите треугольники.
Итак, давайте попробуем избавиться от треугольников. Для этого я буду использовать PolygonMesh
, как и в этом другом вопросе, основанном на проекте 3DViewer, который доступен в репозитории OpenJFX, уже содержит PolygonalMesh, которая допускает любое количество точек на грани, поэтому любой полигон может быть гранью.
Это даст вам плоскую сетку, основанную на квадратных гранях:
private PolygonMesh createQuadrilateralMesh(float width, float height, int subDivX, int subDivY) {
final float minX = - width / 2f;
final float minY = - height / 2f;
final float maxX = width / 2f;
final float maxY = height / 2f;
final int pointSize = 3;
final int texCoordSize = 2;
// 4 point indices and 4 texCoord indices per face
final int faceSize = 8;
int numDivX = subDivX + 1;
int numVerts = (subDivY + 1) * numDivX;
float points[] = new float[numVerts * pointSize];
float texCoords[] = new float[numVerts * texCoordSize];
int faceCount = subDivX * subDivY;
int faces[][] = new int[faceCount][faceSize];
// Create points and texCoords
for (int y = 0; y <= subDivY; y++) {
float dy = (float) y / subDivY;
double fy = (1 - dy) * minY + dy * maxY;
for (int x = 0; x <= subDivX; x++) {
float dx = (float) x / subDivX;
double fx = (1 - dx) * minX + dx * maxX;
int index = y * numDivX * pointSize + (x * pointSize);
points[index] = (float) fx;
points[index + 1] = (float) fy;
points[index + 2] = 0.0f;
index = y * numDivX * texCoordSize + (x * texCoordSize);
texCoords[index] = dx;
texCoords[index + 1] = dy;
}
}
// Create faces
int index = 0;
for (int y = 0; y < subDivY; y++) {
for (int x = 0; x < subDivX; x++) {
int p00 = y * numDivX + x;
int p01 = p00 + 1;
int p10 = p00 + numDivX;
int p11 = p10 + 1;
int tc00 = y * numDivX + x;
int tc01 = tc00 + 1;
int tc10 = tc00 + numDivX;
int tc11 = tc10 + 1;
faces[index][0] = p00;
faces[index][1] = tc00;
faces[index][2] = p10;
faces[index][3] = tc10;
faces[index][4] = p11;
faces[index][5] = tc11;
faces[index][6] = p01;
faces[index++][7] = tc01;
}
}
int[] smooth = new int[faceCount];
PolygonMesh mesh = new PolygonMesh(points, texCoords, faces);
mesh.getFaceSmoothingGroups().addAll(smooth);
return mesh;
}
Таким образом, вы можете использовать 2 или 3 из них для создания такой системы координат:
public Group createGrid(float size, float delta) {
if (delta < 1) {
delta = 1;
}
final PolygonMesh plane = createQuadrilateralMesh(size, size, (int) (size / delta), (int) (size / delta));
final PolygonMesh plane2 = createQuadrilateralMesh(size, size, (int) (size / delta / 5), (int) (size / delta / 5));
PolygonMeshView meshViewXY = new PolygonMeshView(plane);
meshViewXY.setDrawMode(DrawMode.LINE);
meshViewXY.setCullFace(CullFace.NONE);
PolygonMeshView meshViewXZ = new PolygonMeshView(plane);
meshViewXZ.setDrawMode(DrawMode.LINE);
meshViewXZ.setCullFace(CullFace.NONE);
meshViewXZ.getTransforms().add(new Rotate(90, Rotate.X_AXIS));
PolygonMeshView meshViewYZ = new PolygonMeshView(plane);
meshViewYZ.setDrawMode(DrawMode.LINE);
meshViewYZ.setCullFace(CullFace.NONE);
meshViewYZ.getTransforms().add(new Rotate(90, Rotate.Y_AXIS));
PolygonMeshView meshViewXY2 = new PolygonMeshView(plane2);
meshViewXY2.setDrawMode(DrawMode.LINE);
meshViewXY2.setCullFace(CullFace.NONE);
meshViewXY2.getTransforms().add(new Translate(size / 1000f, size / 1000f, 0));
PolygonMeshView meshViewXZ2 = new PolygonMeshView(plane2);
meshViewXZ2.setDrawMode(DrawMode.LINE);
meshViewXZ2.setCullFace(CullFace.NONE);
meshViewXZ2.getTransforms().add(new Translate(size / 1000f, size / 1000f, 0));
meshViewXZ2.getTransforms().add(new Rotate(90, Rotate.X_AXIS));
PolygonMeshView meshViewYZ2 = new PolygonMeshView(plane2);
meshViewYZ2.setDrawMode(DrawMode.LINE);
meshViewYZ2.setCullFace(CullFace.NONE);
meshViewYZ2.getTransforms().add(new Translate(size / 1000f, size / 1000f, 0));
meshViewYZ2.getTransforms().add(new Rotate(90, Rotate.Y_AXIS));
return new Group(meshViewXY, meshViewXY2, meshViewXZ, meshViewXZ2 /*, meshViewYZ, meshViewYZ2 */);
}
Обратите внимание, что я продублировал плоскость, чтобы имитировать более широкий штрих каждые 5 строк.
Наконец добавление осей:
public Group getAxes(double scale) {
Cylinder axisX = new Cylinder(1, 200);
axisX.getTransforms().addAll(new Rotate(90, Rotate.Z_AXIS), new Translate(0, -100, 0));
axisX.setMaterial(new PhongMaterial(Color.RED));
Cylinder axisY = new Cylinder(1, 200);
axisY.getTransforms().add(new Translate(0, 100, 0));
axisY.setMaterial(new PhongMaterial(Color.GREEN));
Cylinder axisZ = new Cylinder(1, 200);
axisZ.setMaterial(new PhongMaterial(Color.BLUE));
axisZ.getTransforms().addAll(new Rotate(90, Rotate.X_AXIS), new Translate(0, 100, 0));
Group group = new Group(axisX, axisY, axisZ);
group.getTransforms().add(new Scale(scale, scale, scale));
return group;
}
Теперь у вас есть:
final Group axes = getAxes(0.5);
final Group grid = createGrid(200, 10);
final Sphere sphere = new Sphere(5);
sphere.getTransforms().add(new Translate(20, 15, 40));
Scene scene = new Scene(new Group(axes, grid, sphere), 800, 800, true, SceneAntialiasing.BALANCED);
Общее количество узлов этого образца равно 14.
Конечно, его можно улучшить, добавив метки и многие другие функции.
person
José Pereda
schedule
17.08.2018