1 /*
   2  * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 package test3d;
  26 
  27 import javafx.application.ConditionalFeature;
  28 import javafx.application.Platform;
  29 import javafx.scene.Group;
  30 import javafx.scene.PerspectiveCamera;
  31 import javafx.scene.Scene;
  32 import javafx.scene.paint.Color;
  33 import javafx.scene.paint.PhongMaterial;
  34 import javafx.scene.shape.MeshView;
  35 import javafx.scene.shape.TriangleMesh;
  36 import javafx.scene.shape.VertexFormat;
  37 import javafx.stage.Stage;
  38 import org.junit.Test;
  39 import testharness.VisualTestBase;
  40 
  41 /**
  42  * Basic TriangleMesh validation tests.
  43  */
  44 public class TriangleMeshPNTValidationTest extends VisualTestBase {
  45 
  46     private Stage testStage;
  47     private Scene testScene;
  48     private MeshView meshView;
  49     private TriangleMesh triMesh;
  50     private PhongMaterial material;
  51     private Group root;
  52 
  53     private static final double TOLERANCE = 0.07;
  54     private static final int WIDTH = 800;
  55     private static final int HEIGHT = 800;
  56     private Color bgColor = Color.rgb(10, 10, 40);
  57 
  58     @Test(timeout = 5000)
  59     public void testInvalidNormalsLength() {
  60         runAndWait(() -> {
  61             testStage = getStage();
  62             testStage.setTitle("TriangleMesh PNT Validation Test");
  63 
  64             // Intentionally set depth buffer to false to reduce test complexity
  65             testScene = new Scene(buildScene(), WIDTH, HEIGHT, true);
  66             testScene.setFill(bgColor);
  67             addCamera(testScene);
  68             buildSquare();
  69             // set invalid points
  70             triMesh.getNormals().setAll(0f, 0.0f /*, -1.0f */);
  71             testStage.setScene(testScene);
  72             testStage.show();
  73         });
  74         waitFirstFrame();
  75         runAndWait(() -> {
  76 
  77             if (!Platform.isSupported(ConditionalFeature.SCENE3D)) {
  78                 System.out.println("*************************************************************");
  79                 System.out.println("*      Platform isn't SCENE3D capable, skipping 3D test.    *");
  80                 System.out.println("*************************************************************");
  81                 return;
  82             }
  83             // Rendering nothing. Should receive warning from validatePoints
  84             Color color = getColor(testScene, WIDTH / 3, WIDTH / 3);
  85             assertColorEquals(bgColor, color, TOLERANCE);
  86         });
  87     }
  88 
  89     @Test(timeout = 5000)
  90     public void testNormalsLengthChange() {
  91         runAndWait(() -> {
  92             testStage = getStage();
  93             testStage.setTitle("TriangleMesh PNT Validation Test");
  94 
  95             // Intentionally set depth buffer to false to reduce test complexity
  96             testScene = new Scene(buildScene(), WIDTH, HEIGHT, true);
  97             testScene.setFill(bgColor);
  98             addCamera(testScene);
  99             buildSquare();
 100             testStage.setScene(testScene);
 101             testStage.show();
 102         });
 103         waitFirstFrame();
 104         runAndWait(() -> {
 105 
 106             if (!Platform.isSupported(ConditionalFeature.SCENE3D)) {
 107                 System.out.println("*************************************************************");
 108                 System.out.println("*      Platform isn't SCENE3D capable, skipping 3D test.    *");
 109                 System.out.println("*************************************************************");
 110                 return;
 111             }
 112             Color color = getColor(testScene, WIDTH / 3, WIDTH / 3);
 113             assertColorEquals(Color.RED, color, TOLERANCE);
 114 
 115             // Valid change of normal
 116             triMesh.getPoints().setAll(0, 0, 1);
 117         });
 118         waitFirstFrame();
 119         runAndWait(() -> {
 120             if (!Platform.isSupported(ConditionalFeature.SCENE3D)) {
 121                 System.out.println("*************************************************************");
 122                 System.out.println("*      Platform isn't SCENE3D capable, skipping 3D test.    *");
 123                 System.out.println("*************************************************************");
 124                 return;
 125             }
 126             // Rendering nothing because faces is invalid.
 127             // Should receive warning from validateFaces
 128             Color color = getColor(testScene, WIDTH / 3, WIDTH / 3);
 129             assertColorEquals(bgColor, color, TOLERANCE);
 130         });
 131     }
 132 
 133     @Test(timeout = 5000)
 134     public void testDegeneratedMeshUpdateNormals() {
 135         runAndWait(() -> {
 136             testStage = getStage();
 137             testStage.setTitle("TriangleMesh PNT Validation Test");
 138 
 139             // Intentionally set depth buffer to false to reduce test complexity
 140             testScene = new Scene(buildScene(), WIDTH, HEIGHT, true);
 141             testScene.setFill(bgColor);
 142             addCamera(testScene);
 143             buildSquare();
 144             testStage.setScene(testScene);
 145             testStage.show();
 146         });
 147         waitFirstFrame();
 148         runAndWait(() -> {
 149 
 150             if (!Platform.isSupported(ConditionalFeature.SCENE3D)) {
 151                 System.out.println("*************************************************************");
 152                 System.out.println("*      Platform isn't SCENE3D capable, skipping 3D test.    *");
 153                 System.out.println("*************************************************************");
 154                 return;
 155             }
 156             // Rendering 2 Triangles that form a square
 157             Color color = getColor(testScene, WIDTH / 3, WIDTH / 3);
 158             assertColorEquals(Color.RED, color, TOLERANCE);
 159 
 160             color = getColor(testScene, WIDTH / 2 + 10, WIDTH / 2 + 10);
 161             assertColorEquals(Color.RED, color, TOLERANCE);
 162             // set normal with degenerated triangle
 163             triMesh.getNormals().setAll(0, 0, 0);
 164         });
 165         waitFirstFrame();
 166         runAndWait(() -> {
 167             if (!Platform.isSupported(ConditionalFeature.SCENE3D)) {
 168                 System.out.println("*************************************************************");
 169                 System.out.println("*      Platform isn't SCENE3D capable, skipping 3D test.    *");
 170                 System.out.println("*************************************************************");
 171                 return;
 172             }
 173 
 174             Color color = getColor(testScene, WIDTH / 2 + 10, WIDTH / 2 + 10);
 175             assertColorEquals(Color.BLACK, color, TOLERANCE);
 176 
 177         });
 178     }
 179 
 180     @Test(timeout = 5000)
 181     public void testDegeneratedMeshUpdatePoints() {
 182         runAndWait(() -> {
 183             testStage = getStage();
 184             testStage.setTitle("TriangleMesh Validation Test");
 185 
 186             // Intentionally set depth buffer to false to reduce test complexity
 187             testScene = new Scene(buildScene(), WIDTH, HEIGHT, true);
 188             testScene.setFill(bgColor);
 189             addCamera(testScene);
 190             buildSquare();
 191             testStage.setScene(testScene);
 192             testStage.show();
 193         });
 194         waitFirstFrame();
 195         runAndWait(() -> {
 196 
 197             if (!Platform.isSupported(ConditionalFeature.SCENE3D)) {
 198                 System.out.println("*************************************************************");
 199                 System.out.println("*      Platform isn't SCENE3D capable, skipping 3D test.    *");
 200                 System.out.println("*************************************************************");
 201                 return;
 202             }
 203             // Rendering 2 Triangles that form a square
 204             Color color = getColor(testScene, WIDTH / 3, WIDTH / 3);
 205             assertColorEquals(Color.RED, color, TOLERANCE);
 206 
 207             color = getColor(testScene, WIDTH / 2 + 10, WIDTH / 2 + 10);
 208             assertColorEquals(Color.RED, color, TOLERANCE);
 209             // set points that casuses a degenerated triangle
 210             triMesh.getPoints().setAll(
 211                     0.5f, -1.5f, 0f,
 212                     0.5f, -1.5f, 0f,
 213                     0.5f, 1.5f, 0f,
 214                     0.5f, -1.5f, 0f);
 215         });
 216         waitFirstFrame();
 217         runAndWait(() -> {
 218             if (!Platform.isSupported(ConditionalFeature.SCENE3D)) {
 219                 System.out.println("*************************************************************");
 220                 System.out.println("*      Platform isn't SCENE3D capable, skipping 3D test.    *");
 221                 System.out.println("*************************************************************");
 222                 return;
 223             }
 224 
 225             Color color = getColor(testScene, WIDTH / 2 + 10, WIDTH / 2 + 10);
 226             assertColorEquals(bgColor, color, TOLERANCE);
 227 
 228         });
 229     }
 230 
 231     void buildSquare() {
 232 
 233         float points[] = {
 234             1.5f, 1.5f, 0f,
 235             1.5f, -1.5f, 0f,
 236             -1.5f, 1.5f, 0f,
 237             -1.5f, -1.5f, 0f
 238         };
 239 
 240         float normals[] = {
 241             0f, 0f, -1f, 0f, 0f, 1f // Only the first normal is refered.
 242         };
 243 
 244         float texCoords[] = {0, 0
 245         };
 246 
 247         int faces[] = {
 248             2, 0, 0, 1, 0, 0, 3, 0, 0,
 249             2, 0, 0, 0, 0, 0, 1, 0, 0,};
 250 
 251         triMesh.getPoints().setAll(points);
 252         triMesh.getNormals().setAll(normals);
 253         triMesh.getTexCoords().setAll(texCoords);
 254         triMesh.getFaces().setAll(faces);
 255     }
 256 
 257     private Group buildScene() {
 258         triMesh = new TriangleMesh(VertexFormat.POINT_NORMAL_TEXCOORD);
 259         material = new PhongMaterial();
 260         material.setDiffuseColor(Color.RED);
 261         meshView = new MeshView(triMesh);
 262         meshView.setMaterial(material);
 263         meshView.setScaleX(200);
 264         meshView.setScaleY(200);
 265         meshView.setScaleZ(200);
 266         meshView.setTranslateX(400);
 267         meshView.setTranslateY(400);
 268         meshView.setTranslateZ(10);
 269 
 270         root = new Group(meshView);
 271         return root;
 272     }
 273 
 274     private PerspectiveCamera addCamera(Scene scene) {
 275         PerspectiveCamera perspectiveCamera = new PerspectiveCamera(false);
 276         scene.setCamera(perspectiveCamera);
 277         return perspectiveCamera;
 278     }
 279 }