浏览代码

New RectangleMesh shape class (#1701)

* New RectangleMesh shape class

This RectangleMesh class was created based on the idea proposed at https://hub.jmonkeyengine.org/t/next-release-of-the-engine/44988/170

* Update RectangleMesh.java

* Update RectangleMesh.java

* Update Rectangle.java

* Update Rectangle.java

* Update RectangleMesh.java

* Update Rectangle.java

* Update RectangleMesh.java

* Update TestCameraNode.java

* Update TestChaseCamera.java

Modified to use RectangleMesh instead of Quad.

* Update TestTransparentShadow.java

Modified to use RectangleMesh instead of Quad.

* Update TestTransparentSSAO.java

Modified to use RectangleMesh instead of Quad.

* Update TestAnisotropicFilter.java

Modified to use RectangleMesh instead of Quad.

* Update TestTransparentCartoonEdge.java

Modified to use RectangleMesh instead of Quad.

* Update TestParallax.java

Modified to use RectangleMesh instead of Quad.

* Modified to use RectangleMesh instead of Quad

* Modified to use RectangleMesh instead of Quad

* Update Rectangle.java

* Rectangle:  javadoc improvements

* Rectangle:  correct formula for the normal vector

* Rectangle:  further clarification of the javadoc

* RectangleMesh:  improve the javadoc

* Rectangle:  correct the documentation of the normal formula

* Rename getD() to calculateD() and improve it

* Access modifier

Changed the access modifier of updateMesh() from public to protected.

* Removed setNormal() and created flip()

* Added texture to flip()

* Changes on flip() and its javadoc

* Fixed read() and write() methods

* Update RectangleMesh.java

Co-authored-by: Stephen Gold <[email protected]>
Francivan Bezerra 3 年之前
父节点
当前提交
789b1cf687

+ 52 - 2
jme3-core/src/main/java/com/jme3/math/Rectangle.java

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009-2020 jMonkeyEngine
+ * Copyright (c) 2009-2021 jMonkeyEngine
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -37,7 +37,21 @@ import java.io.IOException;
 /**
  * <code>Rectangle</code> defines a finite plane within three dimensional space
  * that is specified via three points (A, B, C). These three points define a
- * triangle with the fourth point defining the rectangle ((B + C) - A.
+ * triangle with the fourth point defining the rectangle (B + C) - A.
+ *
+ * <p>The corner points are named as follows:
+ *
+ * <pre>
+ *     C +---+ D
+ *       |   |
+ *       |   |
+ *       |   |
+ *       |   |
+ *     A +---+ B
+ * </pre>
+ *
+ * <p>If angle BAC isn't exactly 90 degrees, then the resulting shape is
+ * actually parallelogram, not a rectangle.
  *
  * @author Mark Powell
  * @author Joshua Slack
@@ -125,6 +139,42 @@ public final class Rectangle implements Savable, Cloneable, java.io.Serializable
         this.c = c;
     }
 
+    /**
+     * Returns the coordinates of the 4th corner, calculated by the formula
+     * D = (B + C) - A .
+     *
+     * @return the corner location (a new Vector3f)
+     */
+    public Vector3f calculateD() {
+        float x = b.x + c.x - a.x;
+        float y = b.y + c.y - a.y;
+        float z = b.z + c.z - a.z;
+        return new Vector3f(x, y, z);
+    }
+
+    /**
+     * Returns a normal vector, calculated by the formula
+     * <pre>
+     *      (C - B) x (B - A)
+     * N = -------------------
+     *     |(C - B) x (B - A)|
+     * </pre>
+     *
+     * @param normal storage for the normal, or null for a new Vector3f
+     * @return the normal direction (either {@code normal} or a new Vector3f)
+     */
+    public Vector3f calculateNormal(Vector3f normal) {
+        if (normal == null) {
+            normal = new Vector3f();
+        }
+
+        Vector3f v1 = c.subtract(b);
+        Vector3f v2 = a.subtract(b);
+        normal.set(v1.crossLocal(v2).normalizeLocal());
+
+        return normal;
+    }
+
     /**
      * <code>random</code> returns a random point within the plane defined by:
      * A, B, C, and (B + C) - A.

+ 277 - 0
jme3-core/src/main/java/com/jme3/scene/shape/RectangleMesh.java

@@ -0,0 +1,277 @@
+/*
+ * Copyright (c) 2021 jMonkeyEngine
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ *
+ * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
+ *   may be used to endorse or promote products derived from this software
+ *   without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package com.jme3.scene.shape;
+
+import java.io.IOException;
+
+import com.jme3.export.InputCapsule;
+import com.jme3.export.JmeExporter;
+import com.jme3.export.JmeImporter;
+import com.jme3.export.OutputCapsule;
+import com.jme3.math.Rectangle;
+import com.jme3.math.Vector2f;
+import com.jme3.math.Vector3f;
+import com.jme3.scene.Mesh;
+import com.jme3.scene.VertexBuffer.Type;
+import com.jme3.util.BufferUtils;
+import com.jme3.util.clone.Cloner;
+
+/**
+ * A static, indexed, Triangle-mode mesh that renders a rectangle or
+ * parallelogram, with customizable normals and texture coordinates.
+ *
+ * <p>It uses a {@link com.jme3.math.Rectangle} to locate its vertices, which
+ * are named as follows:
+ *
+ * <pre>
+ *     C +----+ D
+ *       |\   |
+ *       | \  |
+ *       |  \ |
+ *       |   \|
+ *     A +----+ B
+ * </pre>
+ *
+ * <p>In the vertex buffers, the order of the vertices is A, B, D, then C.
+ *
+ * <p>The default texture coordinates have:<ul>
+ * <li>U=0 at vertices A and C</li>
+ * <li>U=1 at vertices B and D</li>
+ * <li>V=0 at vertices A and B</li>
+ * <li>V=1 at vertices C and D</li</ul>
+ *
+ * @author Francivan Bezerra
+ */
+public class RectangleMesh extends Mesh {
+
+    /**
+     * Used to locate the vertices and calculate a default normal.
+     */
+    private Rectangle rectangle;
+
+    /**
+     * Texture coordinates in A-B-D-C order.
+     */
+    private Vector2f[] texCoords;
+
+    /**
+     * Normal direction for all 4 vertices.
+     */
+    private Vector3f normal;
+
+    /**
+     * Used to indicate whether this mesh is flipped.
+     */
+    private boolean flipped;
+
+    /**
+     * Instantiates a unit-square mesh in the X-Y plane, centered at (0.5, 0.5),
+     * with normals in the +Z direction.
+     *
+     */
+    public RectangleMesh() {
+        this(new Rectangle(new Vector3f(), new Vector3f(1, 0, 0), new Vector3f(0, 1, 0)));
+    }
+
+    /**
+     * Instantiates a rectangle or parallelogram mesh based on the specified
+     * {@link com.jme3.math.Rectangle}.
+     *
+     * @param rectangle to locate the vertices and set the normals (not null,
+     *     alias created)
+     */
+    public RectangleMesh(Rectangle rectangle) {
+        this.rectangle = rectangle;
+        this.texCoords = new Vector2f[] {
+                new Vector2f(0, 0),
+                new Vector2f(1, 0),
+                new Vector2f(1, 1),
+                new Vector2f(0, 1)
+        };
+        flipped = false;
+        updateMesh();
+    }
+
+    /**
+     * Instantiates a rectangle or parallelogram mesh based on 3 specified
+     * vertex positions.
+     *
+     * @param a the mesh position of vertex A (not null, alias created)
+     * @param b the mesh position of vertex B (not null, alias created)
+     * @param c the mesh position of vertex C (not null, alias created)
+     */
+    public RectangleMesh(Vector3f a, Vector3f b, Vector3f c) {
+        this(new Rectangle(a, b, c));
+    }
+
+    /**
+     * Provides access to the internal {@link com.jme3.math.Rectangle} on which
+     * the mesh is based.
+     *
+     * @return the pre-existing instance (do not modify!)
+     */
+    public Rectangle getRectangle() {
+        return rectangle;
+    }
+
+    /**
+     * Sets the {@link com.jme3.math.Rectangle} and updates the mesh
+     * accordingly.
+     *
+     * @param rectangle the desired Rectangle (not null, alias created)
+     */
+    public void setRectangle(Rectangle rectangle) {
+        this.rectangle = rectangle;
+        updateMesh();
+    }
+
+    /**
+     * Provides access to the internal texture-coordinate array.
+     *
+     * @return the pre-existing array of length 4 (do not modify!)
+     */
+    public Vector2f[] getTexCoords() {
+        return texCoords;
+    }
+
+    /**
+     * Sets the texture coordinates and updates the mesh accordingly.
+     *
+     * @param texCoords the desired texture coordinates for each vertex (not
+     *     null, alias created)
+     * @throws IllegalArgumentException if the array length isn't exactly 4
+     */
+    public void setTexCoords(Vector2f[] texCoords) throws IllegalArgumentException {
+        if (texCoords.length != 4) {
+            throw new IllegalArgumentException(
+                    "Texture coordinates are 4 vertices, therefore a Vector2f array of length 4 must be provided.");
+        }
+        this.texCoords = texCoords;
+        updateMesh();
+    }
+
+    /**
+     * Provides access to the internal normal-direction vector.
+     *
+     * @return the pre-existing vector (do not modify!)
+     */
+    public Vector3f getNormal() {
+        return normal;
+    }
+
+    /**
+     * Flips this mesh by reversing its normal vector direction and
+     * setting the {@code flipped} variable accordingly. This variable
+     * will be used by the {@code updateMesh()} method to rearrange
+     * the index buffer.
+     */
+    public void flip() {
+        normal.negateLocal();
+        flipped = !flipped;
+        updateMesh();
+    }
+
+    protected void updateMesh() {
+        Vector3f a = rectangle.getA();
+        Vector3f b = rectangle.getB();
+        Vector3f c = rectangle.getC();
+        Vector3f d = rectangle.calculateD();
+        setBuffer(Type.Position, 3, new float[] {
+                a.x, a.y, a.z,
+                b.x, b.y, b.z,
+                d.x, d.y, d.z,
+                c.x, c.y, c.z
+        });
+
+        setBuffer(Type.TexCoord, 2, BufferUtils.createFloatBuffer(texCoords));
+
+        if (normal == null) {
+            normal = rectangle.calculateNormal(null);
+        }
+        setBuffer(Type.Normal, 3, BufferUtils.createFloatBuffer(normal, normal, normal, normal));
+
+        if (flipped) {
+            setBuffer(Type.Index, 3, new short[]{1, 0, 3, 3, 2, 1});
+        } else {
+            setBuffer(Type.Index, 3, new short[]{3, 0, 1, 1, 2, 3});
+        }
+
+        updateBound();
+        setStatic();
+    }
+
+    /**
+     * Called internally by com.jme3.util.clone.Cloner. Do not call directly.
+     */
+    @Override
+    public void cloneFields(Cloner cloner, Object original) {
+        super.cloneFields(cloner, original);
+        this.rectangle = cloner.clone(rectangle);
+        this.texCoords = cloner.clone(texCoords);
+        this.normal = cloner.clone(normal);
+    }
+
+    @Override
+    public void read(JmeImporter e) throws IOException {
+        super.read(e);
+        final InputCapsule capsule = e.getCapsule(this);
+        rectangle = (Rectangle) capsule.readSavable("rectangle", new Rectangle(
+                new Vector3f(),
+                new Vector3f(1, 0, 0),
+                new Vector3f(0, 1, 0)));
+        texCoords = (Vector2f[]) capsule.readSavableArray("texCoords", new Vector2f[] {
+                new Vector2f(0, 0),
+                new Vector2f(1, 0),
+                new Vector2f(1, 1),
+                new Vector2f(0, 1) });
+        normal = (Vector3f) capsule.readSavable("normal", null);
+        flipped = capsule.readBoolean("flipped", false);
+    }
+
+    @Override
+    public void write(JmeExporter e) throws IOException {
+        super.write(e);
+        final OutputCapsule capsule = e.getCapsule(this);
+        capsule.write(rectangle, "rectangle", new Rectangle(
+                new Vector3f(),
+                new Vector3f(1, 0, 0),
+                new Vector3f(0, 1, 0)));
+        capsule.write(texCoords, "texCoords", new Vector2f[] {
+                new Vector2f(0, 0),
+                new Vector2f(1, 0),
+                new Vector2f(1, 1),
+                new Vector2f(0, 1)
+        });
+        capsule.write(normal, "normal", null);
+        capsule.write(flipped, "flipped", false);
+    }
+}

+ 5 - 6
jme3-examples/src/main/java/jme3test/input/TestCameraNode.java

@@ -36,14 +36,12 @@ import com.jme3.input.KeyInput;
 import com.jme3.input.MouseInput;
 import com.jme3.input.controls.*;
 import com.jme3.material.Material;
-import com.jme3.math.FastMath;
-import com.jme3.math.Quaternion;
 import com.jme3.math.Vector3f;
 import com.jme3.scene.CameraNode;
 import com.jme3.scene.Geometry;
 import com.jme3.scene.Node;
 import com.jme3.scene.control.CameraControl.ControlDirection;
-import com.jme3.scene.shape.Quad;
+import com.jme3.scene.shape.RectangleMesh;
 import com.jme3.system.AppSettings;
 
 /**
@@ -78,9 +76,10 @@ public class TestCameraNode extends SimpleApplication implements AnalogListener,
     // create a floor
     mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
     mat.setTexture("ColorMap", assetManager.loadTexture("Interface/Logo/Monkey.jpg"));
-    Geometry ground = new Geometry("ground", new Quad(50, 50));
-    ground.setLocalRotation(new Quaternion().fromAngleAxis(-FastMath.HALF_PI, Vector3f.UNIT_X));
-    ground.setLocalTranslation(-25, -1, 25);
+    Geometry ground = new Geometry("ground", new RectangleMesh(
+            new Vector3f(-25, -1, 25),
+            new Vector3f(25, -1, 25),
+            new Vector3f(-25, -1, -25)));
     ground.setMaterial(mat);
     rootNode.attachChild(ground);
 

+ 5 - 6
jme3-examples/src/main/java/jme3test/input/TestChaseCamera.java

@@ -38,11 +38,9 @@ import com.jme3.input.controls.ActionListener;
 import com.jme3.input.controls.AnalogListener;
 import com.jme3.input.controls.KeyTrigger;
 import com.jme3.material.Material;
-import com.jme3.math.FastMath;
-import com.jme3.math.Quaternion;
 import com.jme3.math.Vector3f;
 import com.jme3.scene.Geometry;
-import com.jme3.scene.shape.Quad;
+import com.jme3.scene.shape.RectangleMesh;
 
 /** A 3rd-person chase camera orbits a target (teapot). 
  * Follow the teapot with WASD keys, rotate by dragging the mouse. */
@@ -66,9 +64,10 @@ public class TestChaseCamera extends SimpleApplication implements AnalogListener
     // Load a floor model
     Material mat_ground = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
     mat_ground.setTexture("ColorMap", assetManager.loadTexture("Interface/Logo/Monkey.jpg"));
-    Geometry ground = new Geometry("ground", new Quad(50, 50));
-    ground.setLocalRotation(new Quaternion().fromAngleAxis(-FastMath.HALF_PI, Vector3f.UNIT_X));
-    ground.setLocalTranslation(-25, -1, 25);
+    Geometry ground = new Geometry("ground", new RectangleMesh(
+            new Vector3f(-25, -1, 25),
+            new Vector3f(25, -1, 25),
+            new Vector3f(-25, -1, -25)));
     ground.setMaterial(mat_ground);
     rootNode.attachChild(ground);
     

+ 10 - 8
jme3-examples/src/main/java/jme3test/light/TestTransparentShadow.java

@@ -45,7 +45,7 @@ import com.jme3.renderer.queue.RenderQueue.Bucket;
 import com.jme3.renderer.queue.RenderQueue.ShadowMode;
 import com.jme3.scene.Geometry;
 import com.jme3.scene.Spatial;
-import com.jme3.scene.shape.Quad;
+import com.jme3.scene.shape.RectangleMesh;
 import com.jme3.scene.shape.Sphere;
 import com.jme3.shadow.CompareMode;
 import com.jme3.shadow.DirectionalLightShadowRenderer;
@@ -66,15 +66,17 @@ public class TestTransparentShadow extends SimpleApplication {
 
         viewPort.setBackgroundColor(ColorRGBA.DarkGray);
 
-        Quad q = new Quad(20, 20);
-        q.scaleTextureCoordinates(Vector2f.UNIT_XY.mult(10));
-        TangentBinormalGenerator.generate(q);
-        Geometry geom = new Geometry("floor", q);
+        RectangleMesh rm = new RectangleMesh(
+                new Vector3f(-10, 0, 10),
+                new Vector3f(10, 0, 10),
+                new Vector3f(-10, 0, -10)
+        );
+        rm.scaleTextureCoordinates(Vector2f.UNIT_XY.mult(10));
+        TangentBinormalGenerator.generate(rm);
+
+        Geometry geom = new Geometry("floor", rm);
         Material mat = assetManager.loadMaterial("Textures/Terrain/Pond/Pond.j3m");
         geom.setMaterial(mat);
-
-        geom.rotate(-FastMath.HALF_PI, 0, 0);
-        geom.center();
         geom.setShadowMode(ShadowMode.CastAndReceive);
         rootNode.attachChild(geom);
 

+ 10 - 14
jme3-examples/src/main/java/jme3test/material/TestParallax.java

@@ -41,9 +41,8 @@ import com.jme3.material.Material;
 import com.jme3.math.*;
 import com.jme3.renderer.queue.RenderQueue.ShadowMode;
 import com.jme3.scene.Geometry;
-import com.jme3.scene.Node;
 import com.jme3.scene.Spatial;
-import com.jme3.scene.shape.Quad;
+import com.jme3.scene.shape.RectangleMesh;
 import com.jme3.util.SkyFactory;
 import com.jme3.util.TangentBinormalGenerator;
 
@@ -70,20 +69,17 @@ public class TestParallax extends SimpleApplication {
 
     public void setupFloor() {
         mat = assetManager.loadMaterial("Textures/Terrain/BrickWall/BrickWall.j3m");
-                
-        Node floorGeom = new Node("floorGeom");
-        Quad q = new Quad(100, 100);
-        q.scaleTextureCoordinates(new Vector2f(10, 10));
-        Geometry g = new Geometry("geom", q);
-        g.setLocalRotation(new Quaternion().fromAngleAxis(-FastMath.HALF_PI, Vector3f.UNIT_X));
-        floorGeom.attachChild(g);
-        
-        
+
+        RectangleMesh rm = new RectangleMesh(
+                new Vector3f(-50, 22, 60),
+                new Vector3f(50, 22, 60),
+                new Vector3f(-50, 22, -40));
+        rm.scaleTextureCoordinates(new Vector2f(10, 10));
+
+        Geometry floorGeom = new Geometry("floorGeom", rm);
         TangentBinormalGenerator.generate(floorGeom);
-        floorGeom.setLocalTranslation(-50, 22, 60);
-        //floorGeom.setLocalScale(100);
+        floorGeom.setMaterial(mat);
 
-        floorGeom.setMaterial(mat);        
         rootNode.attachChild(floorGeom);
     }
 

+ 10 - 13
jme3-examples/src/main/java/jme3test/material/TestParallaxPBR.java

@@ -41,9 +41,8 @@ import com.jme3.material.Material;
 import com.jme3.math.*;
 import com.jme3.renderer.queue.RenderQueue.ShadowMode;
 import com.jme3.scene.Geometry;
-import com.jme3.scene.Node;
 import com.jme3.scene.Spatial;
-import com.jme3.scene.shape.Quad;
+import com.jme3.scene.shape.RectangleMesh;
 import com.jme3.util.SkyFactory;
 import com.jme3.util.TangentBinormalGenerator;
 
@@ -73,20 +72,18 @@ public class TestParallaxPBR extends SimpleApplication {
     public void setupFloor() {
         mat = assetManager.loadMaterial("Textures/Terrain/BrickWall/BrickWallPBR.j3m");
         //mat = assetManager.loadMaterial("Textures/Terrain/BrickWall/BrickWallPBR2.j3m");
-                
-        Node floorGeom = new Node("floorGeom");
-        Quad q = new Quad(100, 100);
-        q.scaleTextureCoordinates(new Vector2f(10, 10));
-        Geometry g = new Geometry("geom", q);
-        g.setLocalRotation(new Quaternion().fromAngleAxis(-FastMath.HALF_PI, Vector3f.UNIT_X));
-        floorGeom.attachChild(g);
-        
-        
+
+        RectangleMesh rm = new RectangleMesh(
+                new Vector3f(-50, 22, 60),
+                new Vector3f(50, 22, 60),
+                new Vector3f(-50, 22, -40));
+        rm.scaleTextureCoordinates(new Vector2f(10, 10));
+
+        Geometry floorGeom = new Geometry("floorGeom", rm);
         TangentBinormalGenerator.generate(floorGeom);
-        floorGeom.setLocalTranslation(-50, 22, 60);
         //floorGeom.setLocalScale(100);
 
-        floorGeom.setMaterial(mat);        
+        floorGeom.setMaterial(mat);
         rootNode.attachChild(floorGeom);
     }
 

+ 7 - 7
jme3-examples/src/main/java/jme3test/post/TestTransparentCartoonEdge.java

@@ -12,7 +12,7 @@ import com.jme3.renderer.queue.RenderQueue.ShadowMode;
 import com.jme3.scene.Geometry;
 import com.jme3.scene.Node;
 import com.jme3.scene.Spatial;
-import com.jme3.scene.shape.Quad;
+import com.jme3.scene.shape.RectangleMesh;
 import com.jme3.texture.Texture;
 
 public class TestTransparentCartoonEdge extends SimpleApplication {
@@ -33,14 +33,14 @@ public class TestTransparentCartoonEdge extends SimpleApplication {
 
         viewPort.setBackgroundColor(ColorRGBA.DarkGray);
 
-        Quad q = new Quad(20, 20);
-        q.scaleTextureCoordinates(Vector2f.UNIT_XY.mult(5));
-        Geometry geom = new Geometry("floor", q);
+        RectangleMesh rm = new RectangleMesh(
+                new Vector3f(-10, 0, 10),
+                new Vector3f(10, 0, 10),
+                new Vector3f(-10, 0, -10));
+        rm.scaleTextureCoordinates(Vector2f.UNIT_XY.mult(5));
+        Geometry geom = new Geometry("floor", rm);
         Material mat = assetManager.loadMaterial("Textures/Terrain/Pond/Pond.j3m");
         geom.setMaterial(mat);
-        
-        geom.rotate(-FastMath.HALF_PI, 0, 0);
-        geom.center();
         geom.setShadowMode(ShadowMode.Receive);
         rootNode.attachChild(geom);
 

+ 7 - 6
jme3-examples/src/main/java/jme3test/post/TestTransparentSSAO.java

@@ -11,7 +11,7 @@ import com.jme3.renderer.queue.RenderQueue.Bucket;
 import com.jme3.renderer.queue.RenderQueue.ShadowMode;
 import com.jme3.scene.Geometry;
 import com.jme3.scene.Spatial;
-import com.jme3.scene.shape.Quad;
+import com.jme3.scene.shape.RectangleMesh;
 import com.jme3.util.TangentBinormalGenerator;
 
 public class TestTransparentSSAO extends SimpleApplication {
@@ -32,14 +32,15 @@ public class TestTransparentSSAO extends SimpleApplication {
 
         viewPort.setBackgroundColor(ColorRGBA.DarkGray);
 
-        Quad q = new Quad(20, 20);
-        q.scaleTextureCoordinates(Vector2f.UNIT_XY.mult(5));
-        Geometry geom = new Geometry("floor", q);
+        RectangleMesh rm = new RectangleMesh(
+                new Vector3f(-10, 0, 10),
+                new Vector3f(10, 0, 10),
+                new Vector3f(-10, 0, -10));
+        rm.scaleTextureCoordinates(Vector2f.UNIT_XY.mult(5));
+        Geometry geom = new Geometry("floor", rm);
         Material mat = assetManager.loadMaterial("Textures/Terrain/Pond/Pond.j3m");
         geom.setMaterial(mat);
 
-        geom.rotate(-FastMath.HALF_PI, 0, 0);
-        geom.center();
         geom.setShadowMode(ShadowMode.Receive);
         TangentBinormalGenerator.generate(geom);
         rootNode.attachChild(geom);

+ 8 - 6
jme3-examples/src/main/java/jme3test/texture/TestAnisotropicFilter.java

@@ -7,13 +7,12 @@ import com.jme3.input.controls.ActionListener;
 import com.jme3.input.controls.KeyTrigger;
 import com.jme3.material.Material;
 import com.jme3.math.ColorRGBA;
-import com.jme3.math.FastMath;
 import com.jme3.math.Quaternion;
 import com.jme3.math.Vector2f;
 import com.jme3.math.Vector3f;
 import com.jme3.renderer.Limits;
 import com.jme3.scene.Geometry;
-import com.jme3.scene.shape.Quad;
+import com.jme3.scene.shape.RectangleMesh;
 import com.jme3.texture.Image;
 import com.jme3.texture.Image.Format;
 import com.jme3.texture.Texture;
@@ -35,10 +34,13 @@ public class TestAnisotropicFilter extends SimpleApplication implements ActionLi
         flyCam.setMoveSpeed(100);
         cam.setLocation(new Vector3f(197.02617f, 4.6769195f, -194.89545f));
         cam.setRotation(new Quaternion(0.07921988f, 0.8992258f, -0.18292196f, 0.38943136f));
-        Quad q = new Quad(1000, 1000);
-        q.scaleTextureCoordinates(new Vector2f(1000, 1000));
-        Geometry geom = new Geometry("quad", q);
-        geom.rotate(-FastMath.HALF_PI, 0, 0);
+
+        RectangleMesh rm = new RectangleMesh(
+                new Vector3f(-500, 0, 500),
+                new Vector3f(500, 0, 500),
+                new Vector3f(-500, 0, -500));
+        rm.scaleTextureCoordinates(new Vector2f(1000, 1000));
+        Geometry geom = new Geometry("rectangle", rm);
         geom.setMaterial(createCheckerBoardMaterial(assetManager));
         rootNode.attachChild(geom);
 

+ 7 - 6
jme3-examples/src/main/java/jme3test/water/TestSceneWater.java

@@ -42,7 +42,7 @@ import com.jme3.renderer.queue.RenderQueue.ShadowMode;
 import com.jme3.scene.Geometry;
 import com.jme3.scene.Node;
 import com.jme3.scene.Spatial;
-import com.jme3.scene.shape.Quad;
+import com.jme3.scene.shape.RectangleMesh;
 import com.jme3.scene.shape.Sphere;
 import com.jme3.util.SkyFactory;
 import com.jme3.water.SimpleWaterProcessor;
@@ -125,16 +125,17 @@ public class TestSceneWater extends SimpleApplication {
         //lower the speed of the waves if they are too fast
 //        waterProcessor.setWaveSpeed(0.01f);
 
-        Quad quad = new Quad(400,400);
+        RectangleMesh rect = new RectangleMesh(
+                new Vector3f(-200, -20, 250),
+                new Vector3f(200, -20, 250),
+                new Vector3f(-200, -20, -150));
 
         //the texture coordinates define the general size of the waves
-        quad.scaleTextureCoordinates(new Vector2f(6f,6f));
+        rect.scaleTextureCoordinates(new Vector2f(6f, 6f));
 
-        Geometry water=new Geometry("water", quad);
+        Geometry water = new Geometry("water", rect);
         water.setShadowMode(ShadowMode.Receive);
-        water.setLocalRotation(new Quaternion().fromAngleAxis(-FastMath.HALF_PI, Vector3f.UNIT_X));
         water.setMaterial(waterProcessor.getMaterial());
-        water.setLocalTranslation(-200, -20, 250);
 
         rootNode.attachChild(water);