Ver código fonte

Gltf unlit (#1463)

* Adds support for the Unlit material in the GLTF loader.

* Adds some author information.

* Removes an unnecessary test.

It was left over from development and inevitably fails. TestGLTFUnlit serves as a good enough test anyway.

* Adds the copyright notice to TestGltfUnlit.
Markil3 4 anos atrás
pai
commit
62dc29b948

+ 67 - 0
jme3-examples/src/main/java/jme3test/light/TestGltfUnlit.java

@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2009-2019 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.light;
+
+import com.jme3.app.SimpleApplication;
+import com.jme3.input.controls.ActionListener;
+import com.jme3.math.ColorRGBA;
+import com.jme3.math.Vector3f;
+
+/**
+ * Tests the GLTF scene containing an unlit material. If it works, it should use the
+ * Common/MatDefs/Misc/Unshaded.j3md material definition for those objects.
+ *
+ * @author Markil 3
+ * @version 3.3.0-SNAPSHOT
+ */
+public class TestGltfUnlit extends SimpleApplication implements ActionListener {
+    public static void main(String[] args) {
+        TestGltfUnlit testUnlit = new TestGltfUnlit();
+        testUnlit.start();
+    }
+
+    @Override
+    public void simpleInitApp() {
+
+        ColorRGBA skyColor = new ColorRGBA(0.5f, 0.6f, 0.7f, 0.0f);
+
+        flyCam.setMoveSpeed(20);
+        viewPort.setBackgroundColor(skyColor.mult(0.9f));
+
+        this.cam.setLocation(new Vector3f(0, 10, 20));
+        this.rootNode.attachChild(this.getAssetManager().loadModel("jme3test/scenes/unlit.gltf"));
+    }
+
+    @Override
+    public void onAction(String name, boolean isPressed, float tpf) {
+    }
+}

BIN
jme3-examples/src/main/resources/jme3test/scenes/unlit.bin


BIN
jme3-examples/src/main/resources/jme3test/scenes/unlit.blend


+ 236 - 0
jme3-examples/src/main/resources/jme3test/scenes/unlit.gltf

@@ -0,0 +1,236 @@
+{
+    "asset" : {
+        "generator" : "Khronos glTF Blender I/O v1.4.40",
+        "version" : "2.0",
+        "author" : "Markil 3"
+    },
+    "extensionsUsed" : [
+        "KHR_materials_unlit"
+    ],
+    "scene" : 0,
+    "scenes" : [
+        {
+            "name" : "Scene",
+            "nodes" : [
+                0,
+                1,
+                2,
+                3
+            ]
+        }
+    ],
+    "nodes" : [
+        {
+            "name" : "Light",
+            "rotation" : [
+                0.16907575726509094,
+                0.7558803558349609,
+                -0.27217137813568115,
+                0.570947527885437
+            ],
+            "translation" : [
+                0.851825475692749,
+                8.599525451660156,
+                -0.8687540292739868
+            ]
+        },
+        {
+            "name" : "Camera",
+            "rotation" : [
+                0.483536034822464,
+                0.33687159419059753,
+                -0.20870360732078552,
+                0.7804827094078064
+            ],
+            "translation" : [
+                7.358891487121582,
+                4.958309173583984,
+                6.925790786743164
+            ]
+        },
+        {
+            "mesh" : 0,
+            "name" : "Plane",
+            "scale" : [
+                13.14516544342041,
+                13.14516544342041,
+                13.14516544342041
+            ]
+        },
+        {
+            "mesh" : 1,
+            "name" : "Cylinder",
+            "translation" : [
+                0,
+                5.575394630432129,
+                0
+            ]
+        }
+    ],
+    "materials" : [
+        {
+            "doubleSided" : true,
+            "extensions" : {
+                "KHR_materials_unlit" : {}
+            },
+            "name" : "Shadeless",
+            "pbrMetallicRoughness" : {
+                "baseColorFactor" : [
+                    1,
+                    0.012044749222695827,
+                    0,
+                    1
+                ],
+                "metallicFactor" : 0,
+                "roughnessFactor" : 0.9
+            }
+        }
+    ],
+    "meshes" : [
+        {
+            "name" : "Plane",
+            "primitives" : [
+                {
+                    "attributes" : {
+                        "POSITION" : 0,
+                        "NORMAL" : 1,
+                        "TEXCOORD_0" : 2
+                    },
+                    "indices" : 3
+                }
+            ]
+        },
+        {
+            "name" : "Cylinder",
+            "primitives" : [
+                {
+                    "attributes" : {
+                        "POSITION" : 4,
+                        "NORMAL" : 5,
+                        "TEXCOORD_0" : 6
+                    },
+                    "indices" : 7,
+                    "material" : 0
+                }
+            ]
+        }
+    ],
+    "accessors" : [
+        {
+            "bufferView" : 0,
+            "componentType" : 5126,
+            "count" : 4,
+            "max" : [
+                1,
+                0,
+                1
+            ],
+            "min" : [
+                -1,
+                0,
+                -1
+            ],
+            "type" : "VEC3"
+        },
+        {
+            "bufferView" : 1,
+            "componentType" : 5126,
+            "count" : 4,
+            "type" : "VEC3"
+        },
+        {
+            "bufferView" : 2,
+            "componentType" : 5126,
+            "count" : 4,
+            "type" : "VEC2"
+        },
+        {
+            "bufferView" : 3,
+            "componentType" : 5123,
+            "count" : 6,
+            "type" : "SCALAR"
+        },
+        {
+            "bufferView" : 4,
+            "componentType" : 5126,
+            "count" : 192,
+            "max" : [
+                1,
+                1,
+                1
+            ],
+            "min" : [
+                -1,
+                -1,
+                -1
+            ],
+            "type" : "VEC3"
+        },
+        {
+            "bufferView" : 5,
+            "componentType" : 5126,
+            "count" : 192,
+            "type" : "VEC3"
+        },
+        {
+            "bufferView" : 6,
+            "componentType" : 5126,
+            "count" : 192,
+            "type" : "VEC2"
+        },
+        {
+            "bufferView" : 7,
+            "componentType" : 5123,
+            "count" : 372,
+            "type" : "SCALAR"
+        }
+    ],
+    "bufferViews" : [
+        {
+            "buffer" : 0,
+            "byteLength" : 48,
+            "byteOffset" : 0
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 48,
+            "byteOffset" : 48
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 32,
+            "byteOffset" : 96
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 12,
+            "byteOffset" : 128
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 2304,
+            "byteOffset" : 140
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 2304,
+            "byteOffset" : 2444
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 1536,
+            "byteOffset" : 4748
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 744,
+            "byteOffset" : 6284
+        }
+    ],
+    "buffers" : [
+        {
+            "byteLength" : 7028,
+            "uri" : "unlit.bin"
+        }
+    ]
+}

+ 1 - 0
jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/CustomContentManager.java

@@ -55,6 +55,7 @@ public class CustomContentManager {
 
     static {
         defaultExtensionLoaders.put("KHR_materials_pbrSpecularGlossiness", new PBRSpecGlossExtensionLoader());
+        defaultExtensionLoaders.put("KHR_materials_unlit", new UnlitExtensionLoader());
     }
 
     void init(GltfLoader gltfLoader) {

+ 67 - 0
jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/UnlitExtensionLoader.java

@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2009-2020 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.plugins.gltf;
+
+import com.google.gson.JsonElement;
+import com.jme3.asset.AssetKey;
+
+import java.io.IOException;
+
+import static com.jme3.scene.plugins.gltf.GltfUtils.getAsColor;
+import static com.jme3.scene.plugins.gltf.GltfUtils.getAsFloat;
+
+/**
+ * Material adapter for the Unlit pipeline
+ * @author Markil 3
+ */
+public class UnlitExtensionLoader implements ExtensionLoader {
+
+    private final UnlitMaterialAdapter materialAdapter = new UnlitMaterialAdapter();
+
+    @Override
+    public Object handleExtension(GltfLoader loader, String parentName, JsonElement parent, JsonElement extension, Object input) {
+        MaterialAdapter adapter = materialAdapter;
+        AssetKey key = loader.getInfo().getKey();
+        //check for a custom adapter for spec/gloss pipeline
+        if (key instanceof GltfModelKey) {
+            GltfModelKey gltfKey = (GltfModelKey) key;
+            MaterialAdapter ma = gltfKey.getAdapterForMaterial("unlit");
+            if (ma != null) {
+                adapter = ma;
+            }
+        }
+
+        adapter.init(loader.getInfo().getManager());
+
+        return adapter;
+    }
+}

+ 81 - 0
jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/UnlitMaterialAdapter.java

@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2009-2020 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.plugins.gltf;
+
+import com.jme3.material.MatParam;
+import com.jme3.material.RenderState;
+
+/**
+ * @author Markil 3
+ */
+public class UnlitMaterialAdapter extends MaterialAdapter {
+
+    public UnlitMaterialAdapter() {
+        addParamMapping("baseColorFactor", "Color");
+        addParamMapping("baseColorTexture", "ColorMap");
+        addParamMapping("emissiveFactor", "GlowColor");
+        addParamMapping("emissiveTexture", "GlowMap");
+        addParamMapping("alphaMode", "alpha");
+        addParamMapping("alphaCutoff", "AlphaDiscardThreshold");
+        addParamMapping("doubleSided", "doubleSided");
+    }
+
+    @Override
+    protected String getMaterialDefPath() {
+        return "Common/MatDefs/Misc/Unshaded.j3md";
+    }
+
+    @Override
+    protected MatParam adaptMatParam(MatParam param) {
+        if (param.getName().equals("alpha")) {
+            String alphaMode = (String) param.getValue();
+            switch (alphaMode) {
+                case "MASK": // fallthrough
+                case "BLEND":
+                    getMaterial().getAdditionalRenderState().setBlendMode(RenderState.BlendMode.Alpha);
+                    break;
+            }
+            // Alpha is a RenderState not a Material Parameter, so return null
+            return null;
+        }
+        if (param.getName().equals("doubleSided")) {
+            boolean doubleSided = (boolean) param.getValue();
+            if (doubleSided) {
+                //Note that this is not completely right as normals on the back side will be in the wrong direction.
+                getMaterial().getAdditionalRenderState().setFaceCullMode(RenderState.FaceCullMode.Off);
+            }
+            // FaceCulling is a RenderState not a Material Parameter, so return null
+            return null;
+        }
+        return param;
+    }
+}

+ 8 - 1
jme3-plugins/src/test/java/com/jme3/scene/plugins/gltf/GltfLoaderTest.java

@@ -34,9 +34,11 @@ package com.jme3.scene.plugins.gltf;
 import com.jme3.asset.AssetLoadException;
 import com.jme3.asset.AssetManager;
 import com.jme3.material.plugin.TestMaterialWrite;
+import com.jme3.scene.Geometry;
 import com.jme3.scene.Node;
 import com.jme3.scene.Spatial;
 import com.jme3.system.JmeSystem;
+
 import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
@@ -78,10 +80,15 @@ public class GltfLoaderTest {
     }
 
     private void dumpScene(Spatial s, int indent) {
-        System.err.println(indentString.substring(0, indent) + s.getName() + " (" + s.getClass().getSimpleName() + ") / " +
+        System.err.print(indentString.substring(0, indent) + s.getName() + " (" + s.getClass().getSimpleName() + ") / " +
                 s.getLocalTransform().getTranslation().toString() + ", " +
                 s.getLocalTransform().getRotation().toString() + ", " +
                 s.getLocalTransform().getScale().toString());
+        if (s instanceof Geometry)
+        {
+            System.err.print(" / " + ((Geometry) s).getMaterial());
+        }
+        System.err.println();
         if (s instanceof Node) {
             Node n = (Node) s;
             for (Spatial spatial : n.getChildren()) {