I am adding 16 cubes as a TriangleMesh
to a MeshView
. Somehow the cube faces look broken, even though I followed the counter clockwise rules. Maybe having more than one cube in the 3D mesh makes the cubes look broken?
My cube code are two classes in a larger program:
class Cubes
and
class Chart3DItem
import common.Common;
import entities.Location;
import javafx.scene.paint.Color;
import javafx.scene.paint.PhongMaterial;
import javafx.scene.shape.DrawMode;
import javafx.scene.shape.MeshView;
import javafx.scene.shape.TriangleMesh;
public class Cubes extends TriangleMesh
{
public Cubes ()
{
float size = 50;
// /Z
// /
// /
// 0 -------->X
// |
// |
// |
// Y
int count = Common.getCurrentGame()
.getVisitedSolarsystemsMap().keySet().size();
float[] allCorners = new float[count*24];
int index = 0;
for (Location location : Common.getCurrentGame()
.getVisitedSolarsystemsMap().keySet())
{
float deltaX = location.getX().floatValue()*120; // factor is to scale the range [0 to 10} to [0 to 600]
float deltaY = location.getY().floatValue()*120;
float deltaZ = location.getZ().floatValue()*120;
float[] corners = new float[]{
// X, Y, Z
deltaX,deltaY,deltaZ+size,
deltaX+size,deltaY,deltaZ+size,
deltaX,deltaY+size,deltaZ+size,
deltaX+size,deltaY+size,deltaZ+size,
deltaX,deltaY,deltaZ,
deltaX-size,deltaY,deltaZ,
deltaX,deltaY+size,deltaZ,
deltaX+size,deltaY+size,deltaZ
};
for (int i = 0; i < corners.length; i++)
{
allCorners[i+index] = corners[i];
}
index += 24;
}
// 0--------->1
// |
// |
// |
// |
// 1
float[] textureCoordinateOnImage = new float[]{
0,0
};
// 4---------5
// /| /|
// / | / |
// 0--------->1 |
// | 6------|--7
// | / | /
// |/ |/
// 2---------3
int[] allTriangles = new int[count*72];
index = 0;
int a = 0;
for(int i = 0; i < count; i++)
{
int triangles[] = new int[]{
a+5,0,a+4,0,a+0,0, // top
a+5,0,a+0,0,a+1,0, // top
a+0,0,a+4,0,a+6,0, // left
a+0,0,a+6,0,a+2,0, // left
a+1,0,a+0,0,a+2,0, // front
a+1,0,a+2,0,a+3,0, // front
a+5,0,a+1,0,a+3,0, // right
a+5,0,a+3,0,a+7,0, // right
a+4,0,a+5,0,a+7,0, // back
a+4,0,a+7,0,a+6,0, // back
a+3,0,a+2,0,a+6,0, // bottom
a+3,0,a+6,0,a+7,0 // bottom
};
for (int j = 0; j < triangles.length; j++)
{
allTriangles[j+index] = triangles[j];
}
a += 8;
index += 72;
}
this.getPoints().addAll(allCorners);
this.getTexCoords().addAll(textureCoordinateOnImage);
this.getFaces().addAll(allTriangles);
}
public static MeshView getSolarsystems()
{
MeshView cube = new MeshView(new Cubes());
cube.setDrawMode(DrawMode.FILL);
PhongMaterial material = new PhongMaterial();
material.setSpecularColor(Color.ORANGE);
cube.setMaterial(material);
return cube;
}
}
import javafx.geometry.Pos;
import javafx.scene.Group;
import javafx.scene.PerspectiveCamera;
import javafx.scene.PointLight;
import javafx.scene.SceneAntialiasing;
import javafx.scene.SubScene;
import javafx.scene.layout.StackPane;
import javafx.scene.shape.MeshView;
import javafx.scene.transform.Rotate;
import scences.Cubes;
public class Chart3DItem extends StackPane
{
private Group group = new Group();
private SubScene scene3d;
public Chart3DItem()
{
initContent();
}
private void initContent()
{
this.setAlignment(Pos.CENTER);
this.getStyleClass().add("solarsystem-pane");
this.setPrefHeight(600.0);
this.setMinHeight(600.0);
this.setMaxHeight(600.0);
this.setPrefWidth(600.0);
this.setMinWidth(600.0);
this.setMaxWidth(600.0);
this.getChildren().add(new PointLight());
PerspectiveCamera camera = new PerspectiveCamera();
camera.setTranslateZ(-2000);
this.getChildren().add(camera);
scene3d = new SubScene(group, 600, 600, true, SceneAntialiasing.DISABLED);
scene3d.setCamera(camera);
this.getChildren().add(scene3d);
}
public void update()
{
group.getChildren().clear();
MeshView view = Cubes.getSolarsystems();
group.getChildren().add(view);
this.setOnMouseDragged(event -> {
Rotate rotX = new Rotate(event.getX()/1000f);
rotX.axisProperty().set(Rotate.X_AXIS);
view.getTransforms().add(0,rotX);
Rotate rotY = new Rotate(event.getY()/1000f);
rotY.axisProperty().set(Rotate.Y_AXIS);
view.getTransforms().add(1,rotY);
/*Rotate rotZ = new Rotate(event.getZ()/1000f);
rotZ.axisProperty().set(Rotate.Z_AXIS);
view.getTransforms().add(rotZ);*/
});
}
}
The 16 cubes, representing 15 solar systems and 1 spaceship in a 3D-grid, are added to a group, which is added to a subscene, which is added to a StackPane
(which is added in the program as a node to a menu-item).
In the menu-item the broken cubes can be seen. Also they show up black and white, even though I choose to add Color.ORANGE to the PhongMaterial
.
All ideas are welcome. I Googled and searched the Internet but could not find this problem of having multiple cubes in one mesh and losing color.
There was a little - minus sign, instead of a + plus sign.
float[] corners = new float[]{
// X, Y, Z
deltaX,deltaY,deltaZ+size,
deltaX+size,deltaY,deltaZ+size,
deltaX,deltaY+size,deltaZ+size,
deltaX+size,deltaY+size,deltaZ+size,
deltaX,deltaY,deltaZ,
deltaX+size,deltaY,deltaZ,
deltaX,deltaY+size,deltaZ,
deltaX+size,deltaY+size,deltaZ
};
Now it displays correctly.
To get the orange color, the diffuseColor needs to be set.
public static MeshView getSolarsystems()
{
MeshView cube = new MeshView(new Cubes());
cube.setDrawMode(DrawMode.FILL);
PhongMaterial material = new PhongMaterial();
material.setDiffuseColor(Color.ORANGE);
cube.setMaterial(material);
return cube;
}
I also fixed the rotation. Therefore I post the class Chart3DItem.
import javafx.geometry.Pos;
import javafx.scene.AmbientLight;
import javafx.scene.Group;
import javafx.scene.PerspectiveCamera;
import javafx.scene.SceneAntialiasing;
import javafx.scene.SubScene;
import javafx.scene.layout.StackPane;
import javafx.scene.shape.MeshView;
import javafx.scene.transform.Rotate;
import scences.Cubes;
public class Chart3DItem extends StackPane
{
private double mouseOldX, mouseOldY = 0;
private Rotate rotateX = new Rotate(0, Rotate.X_AXIS);
private Rotate rotateY = new Rotate(0, Rotate.Y_AXIS);
private Rotate rotateZ = new Rotate(0, Rotate.Z_AXIS);
private final double VIEWPORT_SIZE = 600;
private Group group = new Group();
private SubScene scene3d;
public Chart3DItem()
{
initContent();
}
private void initContent()
{
this.setAlignment(Pos.CENTER);
this.getStyleClass().add("chart3d-pane");
this.setPrefHeight(600.0);
this.setMinHeight(600.0);
this.setMaxHeight(600.0);
this.setPrefWidth(600.0);
this.setMinWidth(600.0);
this.setMaxWidth(600.0);
this.getChildren().add(new AmbientLight());
PerspectiveCamera camera = new PerspectiveCamera();
camera.setTranslateZ(-300);
this.getChildren().add(camera);
scene3d = new SubScene(group, VIEWPORT_SIZE, VIEWPORT_SIZE, true, SceneAntialiasing.BALANCED);
scene3d.setCamera(camera);
this.getChildren().add(scene3d);
}
public void update()
{
group.getChildren().clear();
MeshView view = Cubes.getSolarsystems();
view.setTranslateX(VIEWPORT_SIZE / 2);
view.setTranslateY(VIEWPORT_SIZE / 2);
view.setTranslateZ(VIEWPORT_SIZE / 2);
view.getTransforms().add(0,rotateX);
view.getTransforms().add(1,rotateY);
view.getTransforms().add(2,rotateZ);
group.getChildren().add(view);
rotateX.setPivotX(VIEWPORT_SIZE / 2);
rotateX.setPivotY(VIEWPORT_SIZE / 2);
rotateX.setPivotZ(VIEWPORT_SIZE / 2);
rotateY.setPivotX(VIEWPORT_SIZE / 2);
rotateY.setPivotY(VIEWPORT_SIZE / 2);
rotateY.setPivotZ(VIEWPORT_SIZE / 2);
rotateZ.setPivotX(VIEWPORT_SIZE / 2);
rotateZ.setPivotY(VIEWPORT_SIZE / 2);
rotateZ.setPivotZ(VIEWPORT_SIZE / 2);
this.setOnMousePressed(event -> {
mouseOldX = event.getSceneX();
mouseOldY = event.getSceneY();
});
this.setOnMouseDragged(event -> {
rotateX.setAngle(rotateX.getAngle() - (event.getSceneY() - mouseOldY));
rotateY.setAngle(rotateY.getAngle() + (event.getSceneX() - mouseOldX));
mouseOldX = event.getSceneX();
mouseOldY = event.getSceneY();
});
}
}
As you can see I added axis, which are also cubes. Therefore here the Cubes class again:
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import business.Solarsystem;
import common.Common;
import javafx.scene.image.Image;
import javafx.scene.paint.PhongMaterial;
import javafx.scene.shape.DrawMode;
import javafx.scene.shape.MeshView;
import javafx.scene.shape.TriangleMesh;
import resources.images.Images;
public class Cubes extends TriangleMesh
{
public Cubes ()
{
float size = 50;
// /Z
// /
// /
// 0 -------->X
// |
// |
// |
// Y
// 0---------1
// /| /|
// / | / |
// 4--------->5 |
// | 2------|--3
// | / | /
// |/ |/
// 6---------7
int count = Common.getCurrentGame().getAllSolarsystemsList().size();
float[] allCorners = new float[(count+4)*24]; // +1 for spaceship cube +3 for grid cubes
int index = 0;
ArrayList<Solarsystem> systems = Common.getCurrentGame().getAllSolarsystemsList();
Collections.sort(systems, new Comparator<business.Solarsystem>() {
@Override
public int compare(business.Solarsystem system1, business.Solarsystem system2)
{
return system2.getName().compareTo(system1.getName());
}
});
for (Solarsystem system : systems)
{
float deltaX = system.getLocation().getX().floatValue()*60; // factor is to scale the range [0 to 10} to [0 to 600]
float deltaY = system.getLocation().getY().floatValue()*60;
float deltaZ = system.getLocation().getZ().floatValue()*60;
float[] corners = new float[]{
// X, Y, Z
deltaX,deltaY,deltaZ+size, // 0
deltaX+size,deltaY,deltaZ+size, // 1
deltaX,deltaY+size,deltaZ+size, // 2
deltaX+size,deltaY+size,deltaZ+size, // 3
deltaX,deltaY,deltaZ, // 4
deltaX+size,deltaY,deltaZ, // 5
deltaX,deltaY+size,deltaZ, // 6
deltaX+size,deltaY+size,deltaZ // 7
};
for (int i = 0; i < corners.length; i++)
{
allCorners[i+index] = corners[i];
}
index += 24;
}
float deltaX = Common.getCurrentGame().getCurrentSpaceship().getLocation().getX().floatValue()*60;
float deltaY = Common.getCurrentGame().getCurrentSpaceship().getLocation().getY().floatValue()*60;
float deltaZ = Common.getCurrentGame().getCurrentSpaceship().getLocation().getZ().floatValue()*60;
float[] corners = new float[]{
// X, Y, Z
deltaX,deltaY,deltaZ+size, // 0
deltaX+size,deltaY,deltaZ+size, // 1
deltaX,deltaY+size,deltaZ+size, // 2
deltaX+size,deltaY+size,deltaZ+size, // 3
deltaX,deltaY,deltaZ, // 4
deltaX+size,deltaY,deltaZ, // 5
deltaX,deltaY+size,deltaZ, // 6
deltaX+size,deltaY+size,deltaZ // 7
};
for (int i = 0; i < corners.length; i++)
{
allCorners[i+index] = corners[i];
}
index += 24;
deltaX = 0.0f;
deltaY = 5.0f*60;
deltaZ = 5.0f*60;
size = 5.0f;
corners = new float[]{
// X, Y, Z
deltaX,deltaY,deltaZ+size, // 0
deltaX+600f,deltaY,deltaZ+size, // 1
deltaX,deltaY+size,deltaZ+size, // 2
deltaX+600f,deltaY+size,deltaZ+size, // 3
deltaX,deltaY,deltaZ, // 4
deltaX+600f,deltaY,deltaZ, // 5
deltaX,deltaY+size,deltaZ, // 6
deltaX+600f,deltaY+size,deltaZ // 7
};
for (int i = 0; i < corners.length; i++)
{
allCorners[i+index] = corners[i];
}
index += 24;
deltaX = 5.0f*60;
deltaY = 0.0f;
deltaZ = 5.0f*60;
size = 5.0f;
corners = new float[]{
// X, Y, Z
deltaX,deltaY,deltaZ+size, // 0
deltaX+size,deltaY,deltaZ+size, // 1
deltaX,deltaY+600f,deltaZ+size, // 2
deltaX+size,deltaY+600f,deltaZ+size, // 3
deltaX,deltaY,deltaZ, // 4
deltaX+size,deltaY,deltaZ, // 5
deltaX,deltaY+600f,deltaZ, // 6
deltaX+size,deltaY+600f,deltaZ // 7
};
for (int i = 0; i < corners.length; i++)
{
allCorners[i+index] = corners[i];
}
index += 24;
deltaX = 5.0f*60;
deltaY = 5.0f*60;
deltaZ = 0.0f;
size = 5.0f;
corners = new float[]{
// X, Y, Z
deltaX,deltaY,deltaZ+600f, // 0
deltaX+size,deltaY,deltaZ+600f, // 1
deltaX,deltaY+size,deltaZ+600f, // 2
deltaX+size,deltaY+size,deltaZ+600f, // 3
deltaX,deltaY,deltaZ, // 4
deltaX+size,deltaY,deltaZ, // 5
deltaX,deltaY+size,deltaZ, // 6
deltaX+size,deltaY+size,deltaZ // 7
};
for (int i = 0; i < corners.length; i++)
{
allCorners[i+index] = corners[i];
}
// 0--------->1
// |
// |
// |
// |
// 1
int[][] textureNumbers = new int[][] {
{0,1,2},
{3,4,5},
{6,7,8},
{9,10,11},
{12,13,14},
{15,16,17},
{18,19,20},
{21,22,23},
{24,25,26},
{27,28,29},
{30,31,32},
{33,34,35},
{36,37,38},
{39,40,41},
{42,43,44},
{45,46,47},
{48,49,50},
{51,52,53},
{54,55,56}
};
float[] textureCoordinateOnImage = new float[]{
// sort backwards also
0.5f,0.75f, // 42
0.75f,0.75f, // 43
0.5f,1, // 44 => 42,43,44 light violet Zells
0.25f,0.75f, // 39
0.5f,0.75f, // 40
0.25f,1, // 41 => 39,40,41 dark violet Xoquam
0,0.75f, // 36
0.25f,0.75f, // 37
0,1f, // 38 => 36,37,38 dark brown Treblar
0.75f,0.5f, // 33
1,0.5f, // 34
0.75f,0.75f, // 35 => 33,34,35 medium brown Singuis
0.5f,0.5f, // 30
0.75f,0.5f, // 31
0.5f,0.75f, // 32 => 30,31,32 light brown Razor
0.25f,0.5f, // 27
0.5f,0.5f, // 28
0.25f,0.75f, // 29 => 27,28,29 turquoise Pot
0,0.5f, // 24
0.25f,0.5f, // 25
0,0.75f, // 26 => 24,25,26 dark blue Olam
0.75f,0.25f, // 21
1,0.25f, // 22
0.75f,0.5f, // 23 => 21,22,23 light blue Meichu
0.5f,0.25f, // 18
0.75f,0.25f, // 19
0.5f,0.5f, // 20 => 18,19,20 dark green Kantell
0.25f,0.25f, // 15
0.5f,0.25f, // 16
0.25f,0.5f, // 17 => 15,16,17 light green Irisa
0,0.25f, // 12
0.25f,0.25f, // 13
0,0.5f, // 14 => 12,13,14 dark red Holm
0.75f,0, // 9
1,0, // 10
0.75f,0.25f, // 11 => 9,10,11 pink Fantus
0.5f,0, // 6
0.75f,0, // 7
0.5f,0.25f, // 8 => 6,7,8 light red Dora
0.25f,0, // 3
0.5f,0, // 4
0.25f,0.25f, // 5 => 3,4,5 orange Bini
0,0, // 0
0.25f,0, // 1
0,0.25f, // 2 => 0,1,2 yellow Aglena
0.75f,0.75f, // 45
1,0.75f, // 46
0.75f,1, // 47 => 45,46,47 white Spaceship
0.75f,0.75f, // 48
1,0.75f, // 49
0.75f,1, // 50 => 48,49,50 white axis
0.75f,0.75f, // 51
1,0.75f, // 52
0.75f,1, // 53 => 51,52,53 white axis
0.75f,0.75f, // 54
1,0.75f, // 55
0.75f,1 // 56 => 54,55,56 white axis
};
// 3---------2
// /| /|
// / | / |
// 0--------->1 |
// | 7------|--6
// | / | /
// |/ |/
// 4---------5
int[] allTriangles = new int[(count+4)*72];
index = 0;
int a = 0;
for(int i = 0; i < count; i++)
{
int[]t = textureNumbers[i];
int triangles[] = new int[]{
a+5,t[0],a+4,t[1],a+0,t[2], // top
a+5,t[0],a+0,t[1],a+1,t[2], // top
a+0,t[0],a+4,t[1],a+6,t[2], // left
a+0,t[0],a+6,t[1],a+2,t[2], // left
a+1,t[0],a+0,t[1],a+2,t[2], // front
a+1,t[0],a+2,t[1],a+3,t[2], // front
a+5,t[0],a+1,t[1],a+3,t[2], // right
a+5,t[0],a+3,t[1],a+7,t[2], // right
a+4,t[0],a+5,t[1],a+7,t[2], // back
a+4,t[0],a+7,t[1],a+6,t[2], // back
a+3,t[0],a+2,t[1],a+6,t[2], // bottom
a+3,t[0],a+6,t[1],a+7,t[2] // bottom
};
for (int j = 0; j < triangles.length; j++)
{
allTriangles[j+index] = triangles[j];
}
a += 8;
index += 72;
}
// spaceship
int[]t = textureNumbers[count];
int triangles[] = new int[]{
a+5,t[0],a+4,t[1],a+0,t[2], // top
a+5,t[0],a+0,t[1],a+1,t[2], // top
a+0,t[0],a+4,t[1],a+6,t[2], // left
a+0,t[0],a+6,t[1],a+2,t[2], // left
a+1,t[0],a+0,t[1],a+2,t[2], // front
a+1,t[0],a+2,t[1],a+3,t[2], // front
a+5,t[0],a+1,t[1],a+3,t[2], // right
a+5,t[0],a+3,t[1],a+7,t[2], // right
a+4,t[0],a+5,t[1],a+7,t[2], // back
a+4,t[0],a+7,t[1],a+6,t[2], // back
a+3,t[0],a+2,t[1],a+6,t[2], // bottom
a+3,t[0],a+6,t[1],a+7,t[2] // bottom
};
for (int j = 0; j < triangles.length; j++)
{
allTriangles[j+index] = triangles[j];
}
a += 8;
index += 72;
t = textureNumbers[count+1];
// axis
triangles = new int[]{
a+5,t[0],a+4,t[1],a+0,t[2], // top
a+5,t[0],a+0,t[1],a+1,t[2], // top
a+0,t[0],a+4,t[1],a+6,t[2], // left
a+0,t[0],a+6,t[1],a+2,t[2], // left
a+1,t[0],a+0,t[1],a+2,t[2], // front
a+1,t[0],a+2,t[1],a+3,t[2], // front
a+5,t[0],a+1,t[1],a+3,t[2], // right
a+5,t[0],a+3,t[1],a+7,t[2], // right
a+4,t[0],a+5,t[1],a+7,t[2], // back
a+4,t[0],a+7,t[1],a+6,t[2], // back
a+3,t[0],a+2,t[1],a+6,t[2], // bottom
a+3,t[0],a+6,t[1],a+7,t[2] // bottom
};
for (int j = 0; j < triangles.length; j++)
{
allTriangles[j+index] = triangles[j];
}
a += 8;
index += 72;
t = textureNumbers[count+2];
// axis
triangles = new int[]{
a+5,t[0],a+4,t[1],a+0,t[2], // top
a+5,t[0],a+0,t[1],a+1,t[2], // top
a+0,t[0],a+4,t[1],a+6,t[2], // left
a+0,t[0],a+6,t[1],a+2,t[2], // left
a+1,t[0],a+0,t[1],a+2,t[2], // front
a+1,t[0],a+2,t[1],a+3,t[2], // front
a+5,t[0],a+1,t[1],a+3,t[2], // right
a+5,t[0],a+3,t[1],a+7,t[2], // right
a+4,t[0],a+5,t[1],a+7,t[2], // back
a+4,t[0],a+7,t[1],a+6,t[2], // back
a+3,t[0],a+2,t[1],a+6,t[2], // bottom
a+3,t[0],a+6,t[1],a+7,t[2] // bottom
};
for (int j = 0; j < triangles.length; j++)
{
allTriangles[j+index] = triangles[j];
}
a += 8;
index += 72;
t = textureNumbers[count+3];
// axis
triangles = new int[]{
a+5,t[0],a+4,t[1],a+0,t[2], // top
a+5,t[0],a+0,t[1],a+1,t[2], // top
a+0,t[0],a+4,t[1],a+6,t[2], // left
a+0,t[0],a+6,t[1],a+2,t[2], // left
a+1,t[0],a+0,t[1],a+2,t[2], // front
a+1,t[0],a+2,t[1],a+3,t[2], // front
a+5,t[0],a+1,t[1],a+3,t[2], // right
a+5,t[0],a+3,t[1],a+7,t[2], // right
a+4,t[0],a+5,t[1],a+7,t[2], // back
a+4,t[0],a+7,t[1],a+6,t[2], // back
a+3,t[0],a+2,t[1],a+6,t[2], // bottom
a+3,t[0],a+6,t[1],a+7,t[2] // bottom
};
for (int j = 0; j < triangles.length; j++)
{
allTriangles[j+index] = triangles[j];
}
this.getPoints().addAll(allCorners);
this.getTexCoords().addAll(textureCoordinateOnImage);
this.getFaces().addAll(allTriangles);
this.getFaceSmoothingGroups().addAll(0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0);
}
public static MeshView getSolarsystems()
{
MeshView cube = new MeshView(new Cubes());
cube.setDrawMode(DrawMode.FILL);
PhongMaterial material = new PhongMaterial();
material.setDiffuseMap(new Image(
Images.class.getResource("colors.png").toExternalForm()));
cube.setMaterial(material);
return cube;
}
}