Created
March 28, 2023 19:29
-
-
Save Birdasaur/4364778971c134c93dc3bccabb599e54 to your computer and use it in GitHub Desktop.
Painting JavaFX 3D surface with crosshair
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public void updatePaintMesh() { | |
//in case the data grid dimensions have changed | |
//make the painting image the same dimension as the data grid for easy math | |
diffusePaintImage = new WritableImage( | |
Double.valueOf(xWidth*surfScale).intValue(), | |
Double.valueOf(zWidth*surfScale).intValue() | |
); | |
//if this is the first time .... | |
if(null == paintTriangleMesh) { | |
paintTriangleMesh = new TriangleMesh(); | |
paintMeshView = new MeshView(paintTriangleMesh); | |
paintMeshView.setMouseTransparent(true); | |
paintMeshView.setMesh(paintTriangleMesh); | |
paintMeshView.setCullFace(CullFace.NONE); | |
paintPhong = new PhongMaterial(Color.WHITE, | |
diffusePaintImage, null, null, null); | |
paintPhong.setSpecularColor(Color.WHITE); | |
paintPhong.setDiffuseColor(Color.WHITE); | |
paintMeshView.setMaterial(paintPhong); | |
sceneRoot.getChildren().add(paintMeshView); | |
//debug trick to change the color of the whole apint surface | |
surfPlot.addEventHandler(MouseEvent.MOUSE_CLICKED, e -> { | |
if(e.getClickCount() > 1 && e.isControlDown()) { | |
Color color = new Color(rando.nextDouble(), rando.nextDouble(), rando.nextDouble(), 1.0); | |
paintSingleColor(color); | |
} | |
}); | |
} | |
TriangleMesh surfMesh = (TriangleMesh)surfPlot.getMesh(); | |
// paintTriangleMesh.getTexCoords().setAll(surfMesh.getTexCoords()); | |
paintTriangleMesh.getPoints().setAll(surfMesh.getPoints()); | |
// paintTriangleMesh.getFaces().setAll(surfMesh.getFaces()); | |
paintTriangleMesh.getFaces().clear(); | |
paintTriangleMesh.getTexCoords().clear(); | |
final int texCoordSize = 2; | |
Float pSkip = 1.0f; | |
int pskip = pSkip.intValue(); | |
int subDivX = (int) diffusePaintImage.getWidth() / pskip; | |
int subDivZ = (int) diffusePaintImage.getHeight() / pskip; | |
int numDivX = subDivX + 1; | |
int numVerts = (subDivZ + 1) * numDivX; | |
float currZ, currX; | |
float texCoords[] = new float[numVerts * texCoordSize]; | |
int faceCount = subDivX * subDivZ * 2; | |
final int faceSize = 6; //should always be 6 for a triangle mesh | |
int faces[] = new int[faceCount * faceSize]; | |
int index, p00,p01,p10,p11,tc00,tc01,tc10,tc11; | |
//Map the 2D data grid to UV coordinates and paint a single color to test | |
for (int z = 0; z < subDivZ; z++) { | |
currZ = (float) z / subDivZ; | |
for (int x = 0; x < subDivX; x++) { | |
currX = (float) x / subDivX; | |
index = z * numDivX * texCoordSize + (x * texCoordSize); | |
texCoords[index] = currX; | |
texCoords[index + 1] = currZ; | |
// Create faces | |
p00 = z * numDivX + x; | |
p01 = p00 + 1; | |
p10 = p00 + numDivX; | |
p11 = p10 + 1; | |
tc00 = z * numDivX + x; | |
tc01 = tc00 + 1; | |
tc10 = tc00 + numDivX; | |
tc11 = tc10 + 1; | |
index = (z * subDivX * faceSize + (x * faceSize)) * 2; | |
faces[index + 0] = p00; | |
faces[index + 1] = tc00; | |
faces[index + 2] = p10; | |
faces[index + 3] = tc10; | |
faces[index + 4] = p11; | |
faces[index + 5] = tc11; | |
index += faceSize; | |
faces[index + 0] = p11; | |
faces[index + 1] = tc11; | |
faces[index + 2] = p01; | |
faces[index + 3] = tc01; | |
faces[index + 4] = p00; | |
faces[index + 5] = tc00; | |
diffusePaintImage.getPixelWriter().setColor(x, z, Color.TRANSPARENT); | |
} | |
} | |
paintTriangleMesh.getTexCoords().setAll(texCoords); | |
paintTriangleMesh.getFaces().setAll(faces); | |
//force update of the material (is this actually necessary?) | |
paintPhong.setDiffuseMap(diffusePaintImage); | |
paintMeshView.setTranslateZ(-1); | |
paintMeshView.setTranslateX(-(xWidth*surfScale)/2.0); | |
paintMeshView.setTranslateZ(-(zWidth*surfScale)/2.0); | |
} | |
public void paintSingleColor(Color color) { | |
//Map the 2D data grid to UV coordinates and paint a single color to test | |
for (int z = 0; z < diffusePaintImage.getHeight(); z++) { | |
for (int x = 0; x < diffusePaintImage.getWidth(); x++) { | |
diffusePaintImage.getPixelWriter().setColor(x, z, color); | |
} | |
} | |
} | |
public void illuminateCrosshair(Point3D center) { | |
if(null == diffusePaintImage) | |
return; | |
int x = (int) center.getX(); | |
int z = (int) center.getZ(); //Image Y is projected into Z | |
PixelWriter pw = diffusePaintImage.getPixelWriter(); | |
for(int i=0; i<diffusePaintImage.getWidth();i++) | |
pw.setColor(i, z, Color.WHITE); | |
for(int i=0; i<diffusePaintImage.getHeight();i++) | |
pw.setColor(x, i, Color.WHITE); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment