/* * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package meshviewer; import javafx.application.Application; import javafx.event.EventHandler; import javafx.scene.*; import javafx.scene.control.ScrollBar; import javafx.scene.image.Image; import javafx.scene.input.KeyEvent; import javafx.scene.light.PointLight; import javafx.scene.material.PhongMaterial; import javafx.scene.paint.Color; import javafx.scene.shape3d.*; import javafx.scene.transform.Rotate; import javafx.stage.Stage; public class MeshViewer extends Application { Group root; PointLight pointLight; MeshView meshView; TriangleMesh triMesh; PhongMaterial material; int divX = 120; int divY = 120; float rotateAngle = 0.0f; float funcValue = 0.0f; float resolution = 0.1f; boolean texture = false; boolean textureSwitch = false; // final Image diffuseMap = new Image("resources/cup_diffuseMap_1024.png"); // final Image bumpMap = new Image("resources/cup_normalMap_1024.png"); final static float minX = -10; final static float minY = -10; final static float maxX = 10; final static float maxY = 10; double getSinDivX(double x, double y) { double r = Math.sqrt(x*x + y*y); return funcValue * (r == 0 ? 1 : Math.sin(r) / r); } void computeMesh(int subDivX, int subDivY, float scale) { final int pointSize = 3; int numDivX = subDivX + 1; int numVerts = (subDivY + 1) * numDivX; float[] points = triMesh.getPoints(null); // Initial points and texCoords for (int y = 0; y <= subDivY; y++) { float dy = (float) y / subDivY; double fy = (1 - dy) * minY + dy * maxY; // System.err.println("dy = " + dy + ", fy = " + fy); for (int x = 0; x <= subDivX; x++) { float dx = (float) x / subDivX; double fx = (1 - dx) * minX + dx * maxX; // System.err.println("dx = " + dx + ", fx = " + fx); int index = y * numDivX * pointSize + (x * pointSize); // System.err.println("point index = " + index); points[index] = (float) fx * scale; points[index + 1] = (float) fy * scale; points[index + 2] = (float) getSinDivX(fx, fy) * scale; // System.err.println("points[" + (index + 2) + " = " + points[index + 2]); } } triMesh.setPoints(0, points, 0, points.length/3); } static TriangleMesh buildTriangleMesh(int subDivX, int subDivY, float scale, int smooth) { // System.err.println("subDivX = " + subDivX + ", subDivY = " + subDivY); final int pointSize = 3; final int texCoordSize = 2; final int faceSize = 6; // 3 point indices and 3 texCoord indices per triangle 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 * 2; int faces[] = new int[ faceCount * faceSize]; // Initial points and texCoords for (int y = 0; y <= subDivY; y++) { float dy = (float) y / subDivY; double fy = (1 - dy) * minY + dy * maxY; // System.err.println("dy = " + dy + ", fy = " + fy); for (int x = 0; x <= subDivX; x++) { float dx = (float) x / subDivX; double fx = (1 - dx) * minX + dx * maxX; // System.err.println("dx = " + dx + ", fx = " + fx); int index = y * numDivX * pointSize + (x * pointSize); // System.err.println("point index = " + index); points[index] = (float) fx * scale; points[index + 1] = (float) fy * scale; points[index + 2] = 0.0f; index = y * numDivX * texCoordSize + (x * texCoordSize); // System.err.println("texCoord index = " + index); texCoords[index] = dx; texCoords[index + 1] = dy; } } // Initial faces 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; int index = (y * subDivX * faceSize + (x * faceSize)) * 2; // System.err.println("face 0 index = " + index); 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; // System.err.println("face 1 index = " + index); faces[index + 0] = p11; faces[index + 1] = tc11; faces[index + 2] = p01; faces[index + 3] = tc01; faces[index + 4] = p00; faces[index + 5] = tc00; } } // for(int i = 0; i < points.length; i++) { // System.err.println("points[" + i + "] = " + points[i]); // } // for(int i = 0; i < texCoords.length; i++) { // System.err.println("texCoords[" + i + "] = " + texCoords[i]); // } // for(int i = 0; i < faces.length; i++) { // System.err.println("faces[" + i + "] = " + faces[i]); // } TriangleMesh triangleMesh = new TriangleMesh(points, texCoords, faces); // There is no need to initial face smoothing groups return triangleMesh; } private Group buildScene() { triMesh = buildTriangleMesh(divX, divY, 0.5f, 1); material = new PhongMaterial(); material.setDiffuseColor(Color.LIGHTGRAY); material.setSpecularColor(Color.rgb(30, 30, 30)); meshView = new MeshView(triMesh); meshView.setMaterial(material); //Set Wireframe mode meshView.setDrawMode(DrawMode.FILL); meshView.setCullFace(CullFace.BACK); final Group grp1 = new Group(meshView); grp1.setRotate(0); grp1.setRotationAxis(Rotate.X_AXIS); Group grp2 = new Group(grp1); grp2.setRotate(-60); grp2.setRotationAxis(Rotate.X_AXIS); Group grp3 = new Group(grp2); grp3.setTranslateZ(10); grp3.setTranslateY(2); pointLight = new PointLight(Color.ANTIQUEWHITE); pointLight.setTranslateX(15); pointLight.setTranslateY(-10); pointLight.setTranslateZ(-100); root = new Group(grp3, pointLight); root.setOnKeyTyped(new EventHandler() { @Override public void handle(KeyEvent e) { switch (e.getCharacter()) { case "[": funcValue -= resolution; if (funcValue < -20.0f) { funcValue = -20.0f; } computeMesh(divX, divY, 0.5f); break; case "]": funcValue += resolution; if (funcValue > 20.0f) { funcValue = 20.0f; } computeMesh(divX, divY, 0.5f); break; case "p": funcValue = 0; computeMesh(divX, divY, 0.5f); break; // case "i": // System.err.print("i "); // if (!textureSwitch) { // texture = texture ? false : true; // } else { // textureSwitch = false; // } // if (texture) { // material.setDiffuseMap(diffuseMap); // material.setBumpMap(bumpMap); // material.setDiffuseColor(Color.TRANSPARENT); // } else { // material.setDiffuseMap(null); // material.setBumpMap(null); // material.setDiffuseColor(Color.LIGHTGRAY); // } // break; // case "k": // System.err.print("k "); // if ((texture) || (!textureSwitch)) { // material.setDiffuseMap(diffuseMap); // material.setBumpMap(null); // material.setDiffuseColor(Color.TRANSPARENT); // texture = true; // textureSwitch = true; // } else { // material.setDiffuseMap(null); // material.setBumpMap(null); // material.setDiffuseColor(Color.LIGHTGRAY); // } // break; // case "u": // System.err.print("u "); // if (texture) { // material.setDiffuseMap(null); // material.setBumpMap(bumpMap); // material.setDiffuseColor(Color.LIGHTGRAY); // textureSwitch = true; // } else { // material.setDiffuseMap(null); // material.setBumpMap(null); // material.setDiffuseColor(Color.LIGHTGRAY); // } // break; case "l": System.err.print("l "); boolean wireframe = meshView.getDrawMode() == DrawMode.LINE; meshView.setDrawMode(wireframe ? DrawMode.FILL : DrawMode.LINE); break; case "<": grp1.setRotate(rotateAngle -= (resolution * 5)); break; case ">": grp1.setRotate(rotateAngle += (resolution * 5)); break; case "X": grp1.setRotationAxis(Rotate.X_AXIS); break; case "Y": grp1.setRotationAxis(Rotate.Y_AXIS); break; case "Z": grp1.setRotationAxis(Rotate.Z_AXIS); break; case "P": rotateAngle = 0; grp1.setRotate(rotateAngle); case "1": System.err.print("1 "); divX = 10; divY = 10; rotateAngle = 0.0f; funcValue = 0.0f; triMesh = buildTriangleMesh(divX, divY, 0.5f, 1); meshView.setMesh(triMesh); break; case "2": System.err.print("2 "); divX = 120; divY = 120; rotateAngle = 0.0f; funcValue = 0.0f; triMesh = buildTriangleMesh(divX, divY, 0.5f, 1); meshView.setMesh(triMesh); break; } } }); root.setFocusTraversable(true); return root; } @Override public void start(Stage primaryStage) { Scene scene = new Scene(buildScene(), 1024, 768, true); root.getChildren().add(new ScrollBar()); // scene.setFill(Color.rgb(10, 10, 40)); primaryStage.setTitle("SimpleMeshViewer"); primaryStage.setScene(scene); primaryStage.show(); } public static void main(String[] args) { System.setProperty("prism.dirtyopts", "false"); launch(args); } }