Переглянути джерело

LineWidth is now a RenderState parameter, One can change the lineWidth used to render a mesh wireframe or a mesh in Lines mode by using material.getAdditionalRenderState().setLineWidth(value)

Nehon 9 роки тому
батько
коміт
493855bac9

+ 49 - 9
jme3-core/src/main/java/com/jme3/material/RenderState.java

@@ -311,6 +311,8 @@ public class RenderState implements Cloneable, Savable {
     boolean applyPolyOffset = true;
     boolean stencilTest = false;
     boolean applyStencilTest = false;
+    float lineWidth = 1;
+    boolean applyLineWidth = false;
     TestFunction depthFunc = TestFunction.LessOrEqual;
     //by default depth func will be applied anyway if depth test is applied
     boolean applyDepthFunc = false;    
@@ -350,6 +352,9 @@ public class RenderState implements Cloneable, Savable {
         oc.write(backStencilDepthPassOperation, "backStencilDepthPassOperation", StencilOperation.Keep);
         oc.write(frontStencilFunction, "frontStencilFunction", TestFunction.Always);
         oc.write(backStencilFunction, "backStencilFunction", TestFunction.Always);
+        oc.write(depthFunc, "depthFunc", TestFunction.LessOrEqual);
+        oc.write(alphaFunc, "alphaFunc", TestFunction.Greater);
+        oc.write(lineWidth, "lineWidth", 1);
 
         // Only "additional render state" has them set to false by default
         oc.write(applyPointSprite, "applyPointSprite", true);
@@ -364,8 +369,7 @@ public class RenderState implements Cloneable, Savable {
         oc.write(applyPolyOffset, "applyPolyOffset", true);
         oc.write(applyDepthFunc, "applyDepthFunc", true);
         oc.write(applyAlphaFunc, "applyAlphaFunc", false);
-        oc.write(depthFunc, "depthFunc", TestFunction.LessOrEqual);
-        oc.write(alphaFunc, "alphaFunc", TestFunction.Greater);  
+        oc.write(applyLineWidth, "applyLineWidth", true);
 
     }
 
@@ -394,6 +398,8 @@ public class RenderState implements Cloneable, Savable {
         backStencilFunction = ic.readEnum("backStencilFunction", TestFunction.class, TestFunction.Always);
         depthFunc = ic.readEnum("depthFunc", TestFunction.class, TestFunction.LessOrEqual);
         alphaFunc = ic.readEnum("alphaFunc", TestFunction.class, TestFunction.Greater);
+        lineWidth = ic.readFloat("lineWidth", 1);
+
 
         applyPointSprite = ic.readBoolean("applyPointSprite", true);
         applyWireFrame = ic.readBoolean("applyWireFrame", true);
@@ -407,6 +413,8 @@ public class RenderState implements Cloneable, Savable {
         applyPolyOffset = ic.readBoolean("applyPolyOffset", true);
         applyDepthFunc = ic.readBoolean("applyDepthFunc", true);
         applyAlphaFunc = ic.readBoolean("applyAlphaFunc", false);
+        applyLineWidth = ic.readBoolean("applyLineWidth", true);
+
         
     }
 
@@ -528,6 +536,10 @@ public class RenderState implements Cloneable, Savable {
             }
         }
 
+        if(lineWidth != rs.lineWidth){
+            return false;
+        }
+
         return true;
     }
 
@@ -803,8 +815,17 @@ public class RenderState implements Cloneable, Savable {
         this.alphaFunc = alphaFunc;
         cachedHashCode = -1;
     }
-    
-    
+
+    /**
+     * Sets the mesh line width.
+     * This is to use in conjunction with {@link #setWireframe(boolean)} or with a mesh in {@link Mesh.Mode#Lines} mode.
+     * @param lineWidth the line width.
+     */
+    public void setLineWidth(float lineWidth) {
+        this.lineWidth = lineWidth;
+        this.applyLineWidth = true;
+        cachedHashCode = -1;
+    }
 
     /**
      * Check if stencil test is enabled.
@@ -1118,8 +1139,16 @@ public class RenderState implements Cloneable, Savable {
     public TestFunction getAlphaFunc() {
         return alphaFunc;
     }
-    
-    
+
+    /**
+     * returns the wireframe line width
+     *
+     * @return the line width
+     */
+    public float getLineWidth() {
+        return lineWidth;
+    }
+
 
     public boolean isApplyAlphaFallOff() {
         return applyAlphaFallOff;
@@ -1168,8 +1197,10 @@ public class RenderState implements Cloneable, Savable {
     public boolean isApplyAlphaFunc() {
         return applyAlphaFunc;
     }
-    
-    
+
+    public boolean isApplyLineWidth() {
+        return applyLineWidth;
+    }
 
     /**
      *
@@ -1200,6 +1231,7 @@ public class RenderState implements Cloneable, Savable {
             hash = 79 * hash + (this.backStencilDepthPassOperation != null ? this.backStencilDepthPassOperation.hashCode() : 0);
             hash = 79 * hash + (this.frontStencilFunction != null ? this.frontStencilFunction.hashCode() : 0);
             hash = 79 * hash + (this.backStencilFunction != null ? this.backStencilFunction.hashCode() : 0);
+            hash = 79 * hash + Float.floatToIntBits(this.lineWidth);
             cachedHashCode = hash;
         }
         return cachedHashCode;
@@ -1324,6 +1356,11 @@ public class RenderState implements Cloneable, Savable {
             state.frontStencilFunction = frontStencilFunction;
             state.backStencilFunction = backStencilFunction;
         }
+        if (additionalState.applyLineWidth) {
+            state.lineWidth = additionalState.lineWidth;
+        } else {
+            state.lineWidth = lineWidth;
+        }
         state.cachedHashCode = -1;
         return state;
     }
@@ -1351,6 +1388,7 @@ public class RenderState implements Cloneable, Savable {
         backStencilFunction = state.backStencilFunction;
         depthFunc = state.depthFunc;
         alphaFunc = state.alphaFunc;
+        lineWidth = state.lineWidth;
 
         applyPointSprite = true;
         applyWireFrame =  true;
@@ -1364,6 +1402,7 @@ public class RenderState implements Cloneable, Savable {
         applyPolyOffset =  true;
         applyDepthFunc =  true;
         applyAlphaFunc =  false;
+        applyLineWidth = true;
     }
 
     @Override
@@ -1392,7 +1431,8 @@ public class RenderState implements Cloneable, Savable {
                 + "\noffsetEnabled=" + offsetEnabled
                 + "\napplyPolyOffset=" + applyPolyOffset
                 + "\noffsetFactor=" + offsetFactor
-                + "\noffsetUnits=" + offsetUnits      
+                + "\noffsetUnits=" + offsetUnits
+                + "\nlineWidth=" + lineWidth
                 + "\n]";
     }
 }

+ 1 - 1
jme3-core/src/main/java/com/jme3/renderer/RenderContext.java

@@ -101,7 +101,7 @@ public class RenderContext {
     public float pointSize = 1;
     
     /**
-     * @see Mesh#setLineWidth(float) 
+     * @see RenderState#setLineWidth(float)
      */
     public float lineWidth = 1;
 

+ 6 - 2
jme3-core/src/main/java/com/jme3/renderer/opengl/GLRenderer.java

@@ -779,6 +779,10 @@ public final class GLRenderer implements Renderer {
                 gl.glDisable(GL.GL_STENCIL_TEST);
             }
         }
+        if (context.lineWidth != state.getLineWidth()) {
+            gl.glLineWidth(state.getLineWidth());
+            context.lineWidth = state.getLineWidth();
+        }
     }
 
     private int convertStencilOperation(StencilOperation stencilOp) {
@@ -2681,8 +2685,8 @@ public final class GLRenderer implements Renderer {
             return;
         }
 
-
-        if (context.lineWidth != mesh.getLineWidth()) {
+        //this is kept for backward compatibility.
+        if (mesh.getLineWidth() != -1 && context.lineWidth != mesh.getLineWidth()) {
             gl.glLineWidth(mesh.getLineWidth());
             context.lineWidth = mesh.getLineWidth();
         }

+ 11 - 10
jme3-core/src/main/java/com/jme3/scene/BatchNode.java

@@ -383,7 +383,7 @@ public class BatchNode extends GeometryGroupNode {
                 maxVertCount = geom.getVertexCount();
             }
             Mesh.Mode listMode;
-            float listLineWidth = 1f;
+            //float listLineWidth = 1f;
             int components;
             switch (geom.getMesh().getMode()) {
                 case Points:
@@ -394,7 +394,7 @@ public class BatchNode extends GeometryGroupNode {
                 case LineStrip:
                 case Lines:
                     listMode = Mesh.Mode.Lines;
-                    listLineWidth = geom.getMesh().getLineWidth();
+                    //listLineWidth = geom.getMesh().getLineWidth();
                     components = 2;
                     break;
                 case TriangleFan:
@@ -426,19 +426,20 @@ public class BatchNode extends GeometryGroupNode {
                         + " primitive types: " + mode + " != " + listMode);
             }
             mode = listMode;
-            if (mode == Mesh.Mode.Lines) {
-                if (lineWidth != 1f && listLineWidth != lineWidth) {
-                    throw new UnsupportedOperationException("When using Mesh Line mode, cannot combine meshes with different line width "
-                            + lineWidth + " != " + listLineWidth);
-                }
-                lineWidth = listLineWidth;
-            }
+            //Not needed anymore as lineWidth is now in RenderState and will be taken into account when merging according to the material
+//            if (mode == Mesh.Mode.Lines) {
+//                if (lineWidth != 1f && listLineWidth != lineWidth) {
+//                    throw new UnsupportedOperationException("When using Mesh Line mode, cannot combine meshes with different line width "
+//                            + lineWidth + " != " + listLineWidth);
+//                }
+//                lineWidth = listLineWidth;
+//            }
             compsForBuf[VertexBuffer.Type.Index.ordinal()] = components;
         }
 
         outMesh.setMaxNumWeights(maxWeights);
         outMesh.setMode(mode);
-        outMesh.setLineWidth(lineWidth);
+        //outMesh.setLineWidth(lineWidth);
         if (totalVerts >= 65536) {
             // make sure we create an UnsignedInt buffer so we can fit all of the meshes
             formatForBuf[VertexBuffer.Type.Index.ordinal()] = VertexBuffer.Format.UnsignedInt;

+ 10 - 5
jme3-core/src/main/java/com/jme3/scene/Mesh.java

@@ -37,6 +37,7 @@ import com.jme3.collision.Collidable;
 import com.jme3.collision.CollisionResults;
 import com.jme3.collision.bih.BIHTree;
 import com.jme3.export.*;
+import com.jme3.material.Material;
 import com.jme3.material.RenderState;
 import com.jme3.math.Matrix4f;
 import com.jme3.math.Triangle;
@@ -65,7 +66,7 @@ import java.util.ArrayList;
  * Points can also be used for {@link RenderState#setPointSprite(boolean) point
  * sprite} mode.</li>
  * <li>Lines - 2 vertices represent a line segment, with the width specified
- * via {@link Mesh#setLineWidth(float) }.</li>
+ * via {@link Material#getAdditionalRenderState()} and {@link RenderState#setLineWidth(float)}.</li>
  * <li>Triangles - 3 vertices represent a solid triangle primitive. </li>
  * </ul>
  * 
@@ -86,7 +87,7 @@ public class Mesh implements Savable, Cloneable {
         
         /**
          * A primitive is a line segment. Every two vertices specify
-         * a single line. {@link Mesh#setLineWidth(float) } can be used 
+         * a single line. {@link Material#getAdditionalRenderState()} and {@link RenderState#setLineWidth(float)} can be used
          * to set the width of the lines.
          */
         Lines(true),
@@ -94,7 +95,7 @@ public class Mesh implements Savable, Cloneable {
         /**
          * A primitive is a line segment. The first two vertices specify
          * a single line, while subsequent vertices are combined with the 
-         * previous vertex to make a line. {@link Mesh#setLineWidth(float) } can 
+         * previous vertex to make a line. {@link Material#getAdditionalRenderState()} and {@link RenderState#setLineWidth(float)} can
          * be used to set the width of the lines.
          */
         LineStrip(false),
@@ -102,7 +103,7 @@ public class Mesh implements Savable, Cloneable {
         /**
          * Identical to {@link #LineStrip} except that at the end
          * the last vertex is connected with the first to form a line.
-         * {@link Mesh#setLineWidth(float) } can be used 
+         * {@link Material#getAdditionalRenderState()} and {@link RenderState#setLineWidth(float)} can be used
          * to set the width of the lines.
          */
         LineLoop(false),
@@ -172,7 +173,7 @@ public class Mesh implements Savable, Cloneable {
     private IntMap<VertexBuffer> buffers = new IntMap<VertexBuffer>();
     private VertexBuffer[] lodLevels;
     private float pointSize = 1;
-    private float lineWidth = 1;
+    private float lineWidth = -1;
 
     private transient int vertexArrayID = -1;
 
@@ -583,7 +584,9 @@ public class Mesh implements Savable, Cloneable {
      * Returns the line width for line meshes.
      * 
      * @return the line width
+     * @deprecated use {@link Material#getAdditionalRenderState()} and {@link RenderState#getLineWidth()}
      */
+    @Deprecated
     public float getLineWidth() {
         return lineWidth;
     }
@@ -594,7 +597,9 @@ public class Mesh implements Savable, Cloneable {
      * the default value is 1.0.
      * 
      * @param lineWidth The line width
+     * @deprecated use {@link Material#getAdditionalRenderState()} and {@link RenderState#setLineWidth(float)}
      */
+    @Deprecated
     public void setLineWidth(float lineWidth) {
         this.lineWidth = lineWidth;
     }

+ 2 - 0
jme3-core/src/plugins/java/com/jme3/material/plugins/J3MLoader.java

@@ -458,6 +458,8 @@ public class J3MLoader implements AssetLoader {
             renderState.setDepthFunc(RenderState.TestFunction.valueOf(split[1]));
         }else if (split[0].equals("AlphaFunc")){
             renderState.setAlphaFunc(RenderState.TestFunction.valueOf(split[1]));
+        }else if (split[0].equals("LineWidth")){
+            renderState.setLineWidth(Float.parseFloat(split[1]));
         } else {
             throw new MatParseException(null, split[0], statement);
         }

+ 1 - 1
jme3-examples/src/main/java/jme3test/collision/TestMousePick.java

@@ -128,12 +128,12 @@ public class TestMousePick extends SimpleApplication {
     /** A red ball that marks the last spot that was "hit" by the "shot". */
     protected void initMark() {
         Arrow arrow = new Arrow(Vector3f.UNIT_Z.mult(2f));
-        arrow.setLineWidth(3);
 
         //Sphere sphere = new Sphere(30, 30, 0.2f);
         mark = new Geometry("BOOM!", arrow);
         //mark = new Geometry("BOOM!", sphere);
         Material mark_mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
+        mark_mat.getAdditionalRenderState().setLineWidth(3);
         mark_mat.setColor("Color", ColorRGBA.Red);
         mark.setMaterial(mark_mat);
     }

+ 0 - 1
jme3-examples/src/main/java/jme3test/light/TestTangentGenBadModels.java

@@ -72,7 +72,6 @@ public class TestTangentGenBadModels extends SimpleApplication {
                     "debug tangents geom",
                     TangentBinormalGenerator.genTbnLines(g.getMesh(), 0.2f)
                 );
-                debug.getMesh().setLineWidth(1);
                 debug.setMaterial(debugMat);
                 debug.setCullHint(Spatial.CullHint.Never);
                 debug.setLocalTransform(g.getWorldTransform());

+ 6 - 6
jme3-examples/src/main/java/jme3test/model/shape/TestDebugShapes.java

@@ -50,10 +50,11 @@ public class TestDebugShapes extends SimpleApplication {
         app.start();
     }
 
-    public Geometry putShape(Mesh shape, ColorRGBA color){
+    public Geometry putShape(Mesh shape, ColorRGBA color, float lineWidth){
         Geometry g = new Geometry("shape", shape);
         Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
         mat.getAdditionalRenderState().setWireframe(true);
+        mat.getAdditionalRenderState().setLineWidth(lineWidth);
         mat.setColor("Color", color);
         g.setMaterial(mat);
         rootNode.attachChild(g);
@@ -62,20 +63,19 @@ public class TestDebugShapes extends SimpleApplication {
 
     public void putArrow(Vector3f pos, Vector3f dir, ColorRGBA color){
         Arrow arrow = new Arrow(dir);
-        arrow.setLineWidth(4); // make arrow thicker
-        putShape(arrow, color).setLocalTranslation(pos);
+        putShape(arrow, color, 4).setLocalTranslation(pos);
     }
 
     public void putBox(Vector3f pos, float size, ColorRGBA color){
-        putShape(new WireBox(size, size, size), color).setLocalTranslation(pos);
+        putShape(new WireBox(size, size, size), color, 1).setLocalTranslation(pos);
     }
 
     public void putGrid(Vector3f pos, ColorRGBA color){
-        putShape(new Grid(6, 6, 0.2f), color).center().move(pos);
+        putShape(new Grid(6, 6, 0.2f), color, 1).center().move(pos);
     }
 
     public void putSphere(Vector3f pos, ColorRGBA color){
-        putShape(new WireSphere(1), color).setLocalTranslation(pos);
+        putShape(new WireSphere(1), color, 1).setLocalTranslation(pos);
     }
 
     @Override

+ 87 - 0
jme3-examples/src/main/java/jme3test/scene/TestLineWidthRenderState.java

@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2009-2012 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 jme3test.scene;
+
+import com.jme3.app.SimpleApplication;
+import com.jme3.input.KeyInput;
+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.Quaternion;
+import com.jme3.math.Vector3f;
+import com.jme3.scene.Geometry;
+import com.jme3.scene.shape.Box;
+
+public class TestLineWidthRenderState extends SimpleApplication {
+
+    private Material mat;
+
+    public static void main(String[] args){
+        TestLineWidthRenderState app = new TestLineWidthRenderState();
+        app.start();
+    }
+
+
+
+    @Override
+    public void simpleInitApp() {
+        setDisplayFps(false);
+        setDisplayStatView(false);
+        cam.setLocation(new Vector3f(5.5826545f, 3.6192513f, 8.016988f));
+        cam.setRotation(new Quaternion(-0.04787097f, 0.9463123f, -0.16569641f, -0.27339742f));
+
+        Box b = new Box(1, 1, 1);
+        Geometry geom = new Geometry("Box", b);
+        mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
+        mat.setColor("Color", ColorRGBA.Blue);
+        mat.getAdditionalRenderState().setWireframe(true);
+        mat.getAdditionalRenderState().setLineWidth(2);
+        geom.setMaterial(mat);
+        rootNode.attachChild(geom);
+
+        inputManager.addListener(new ActionListener() {
+            @Override
+            public void onAction(String name, boolean isPressed, float tpf) {
+                if(name.equals("up") && isPressed){
+                    mat.getAdditionalRenderState().setLineWidth(mat.getAdditionalRenderState().getLineWidth() + 1);
+                }
+                if(name.equals("down") && isPressed){
+                    mat.getAdditionalRenderState().setLineWidth(Math.max(mat.getAdditionalRenderState().getLineWidth() - 1, 1));
+                }
+            }
+        }, "up", "down");
+        inputManager.addMapping("up", new KeyTrigger(KeyInput.KEY_U));
+        inputManager.addMapping("down", new KeyTrigger(KeyInput.KEY_J));
+    }
+}

+ 1 - 0
jme3-plugins/src/main/java/com/jme3/material/plugin/export/material/J3MRenderStateOutputCapsule.java

@@ -32,6 +32,7 @@ public class J3MRenderStateOutputCapsule extends J3MOutputCapsule {
         NAME_MAP.put( "pointSprite", "PointSprite");
         NAME_MAP.put( "depthFunc", "DepthFunc");
         NAME_MAP.put( "alphaFunc", "AlphaFunc");
+        NAME_MAP.put( "lineWidth", "LineWidth");
     }
     public J3MRenderStateOutputCapsule(J3MExporter exporter) {
         super(exporter);

+ 3 - 4
jme3-plugins/src/test/java/com/jme3/material/plugin/TestMaterialWrite.java

@@ -40,10 +40,7 @@ import com.jme3.material.plugin.export.material.J3MExporter;
 import com.jme3.material.plugins.J3MLoader;
 import com.jme3.math.ColorRGBA;
 import com.jme3.system.JmeSystem;
-import static org.junit.Assert.*;
-
 import com.jme3.texture.Texture;
-import com.jme3.texture.Texture2D;
 import org.junit.Before;
 import org.junit.Test;
 
@@ -51,7 +48,8 @@ import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
-import java.util.Scanner;
+
+import static org.junit.Assert.assertTrue;
 
 public class TestMaterialWrite {
 
@@ -87,6 +85,7 @@ public class TestMaterialWrite {
         mat.setTexture("DiffuseMap", tex);
         mat.getAdditionalRenderState().setDepthWrite(false);
         mat.getAdditionalRenderState().setDepthTest(false);
+        mat.getAdditionalRenderState().setLineWidth(5);
         mat.getAdditionalRenderState().setBlendMode(RenderState.BlendMode.Alpha);
 
         final ByteArrayOutputStream stream = new ByteArrayOutputStream();