From ef067952b21f01806a96de0c938a1331b4669567 Mon Sep 17 00:00:00 2001
From: theMinka
Date: Sun, 19 Apr 2026 12:35:12 +0200
Subject: [PATCH 01/10] Fixed multiple extension handling in
CustomContentManager
If multiple GLTF extensions are present on an element, the CustomContentManager now processes all supported ones instead of just the first one.
---
.../java/com/jme3/scene/plugins/gltf/CustomContentManager.java | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/CustomContentManager.java b/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/CustomContentManager.java
index d9c4cbf7d8..5898887e58 100644
--- a/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/CustomContentManager.java
+++ b/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/CustomContentManager.java
@@ -214,7 +214,7 @@ private T readExtension(String name, JsonElement el, T input) throws AssetLo
continue;
}
try {
- return (T) loader.handleExtension(gltfLoader, name, el, ext.getValue(), input);
+ input = (T) loader.handleExtension(gltfLoader, name, el, ext.getValue(), input);
} catch (ClassCastException e) {
throw new AssetLoadException("Extension loader " + loader.getClass().getName() + " for extension " + ext.getKey() + " is incompatible with type " + input.getClass(), e);
}
From 317a56abf18e11a4dfccdd170b7ea29b43e5d085 Mon Sep 17 00:00:00 2001
From: theMinka
Date: Sun, 19 Apr 2026 20:28:24 +0200
Subject: [PATCH 02/10] Added a flag to GltfModelKey to switch between the old
and new material creation process
---
.../jme3/scene/plugins/gltf/GltfLoader.java | 10 +++++++++
.../jme3/scene/plugins/gltf/GltfModelKey.java | 21 +++++++++++++++++++
.../jme3/scene/plugins/gltf/GltfUtils.java | 5 +++++
3 files changed, 36 insertions(+)
diff --git a/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/GltfLoader.java b/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/GltfLoader.java
index 69b0696df3..8dd1f1d4dd 100644
--- a/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/GltfLoader.java
+++ b/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/GltfLoader.java
@@ -803,6 +803,16 @@ protected ByteBuffer getBytes(int bufferIndex, String uri, Integer bufferLength)
}
public Material readMaterial(int materialIndex) throws IOException {
+ // Fallback to the old material adapter system, if the legacy flag is set.
+ if (GltfUtils.isMaterialAdaptersEnabled(info)) {
+ return readMaterialUsingMaterialAdapters(materialIndex);
+ }
+
+ // TODO Implement new material factory system.
+ return defaultMat;
+ }
+
+ protected Material readMaterialUsingMaterialAdapters(int materialIndex) throws IOException {
assertNotNull(materials, "There is no material defined yet a mesh references one");
JsonObject matData = materials.get(materialIndex).getAsJsonObject();
diff --git a/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/GltfModelKey.java b/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/GltfModelKey.java
index 2490243a00..de66ffbc0a 100644
--- a/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/GltfModelKey.java
+++ b/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/GltfModelKey.java
@@ -52,6 +52,13 @@
*/
public class GltfModelKey extends ModelKey {
+ /**
+ * Enables or disables the legacy material adapter system.
+ * This should only be used in older projects for backward compatibility.
+ */
+ // TODO Set the default to false, after the new material creation process has been implemented
+ private boolean materialAdaptersEnabled = true;
+
private Map materialAdapters = new HashMap<>();
private static Map extensionLoaders = new HashMap<>();
private boolean keepSkeletonPose = false;
@@ -101,6 +108,20 @@ public boolean isStrict() {
return strictExtensionCheck;
}
+ public boolean isMaterialAdaptersEnabled() {
+ return materialAdaptersEnabled;
+ }
+
+ /**
+ * Enables or disables the legacy material adapter system.
+ * This should only be used in older projects for backward compatibility.
+ *
+ * @param materialAdaptersEnabled The value to set.
+ */
+ public void setMaterialAdaptersEnabled(boolean materialAdaptersEnabled) {
+ this.materialAdaptersEnabled = materialAdaptersEnabled;
+ }
+
/**
* Registers a MaterialAdapter for the given materialName.
* The materialName must be "pbrMetallicRoughness" or any name from KHR_materials glTF Extension (for example "pbrSpecularGlossiness" for "KHR_materials_pbrSpecularGlossiness" extension)
diff --git a/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/GltfUtils.java b/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/GltfUtils.java
index 677f15e6ea..6aff505079 100644
--- a/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/GltfUtils.java
+++ b/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/GltfUtils.java
@@ -716,6 +716,11 @@ public static GltfModelKey getKey(AssetInfo info) {
return null;
}
+ public static boolean isMaterialAdaptersEnabled(AssetInfo info) {
+ GltfModelKey key = getKey(info);
+ return key != null && key.isMaterialAdaptersEnabled();
+ }
+
public static MaterialAdapter getAdapterForMaterial(AssetInfo info, String defName) {
GltfModelKey key = getKey(info);
if (key == null) {
From c164633a22c4f5a1fbe6c04feeb8f5a72200c493 Mon Sep 17 00:00:00 2001
From: theMinka
Date: Sun, 19 Apr 2026 20:38:40 +0200
Subject: [PATCH 03/10] Implemented new material creation process in GltfLoader
* Step 1: Collect all material data in the new GltfMaterialData object
* Step 1.1: GltfLoader reads all standard GLTF parameters
* Step 1.2: ExtensionLoader and ExtrasLoader can read additional GLTF parameters
* Step 2: Find a matching GltfMaterialFactory and use it to create the material
---
.../jme3/scene/plugins/gltf/GltfLoader.java | 106 ++++++++++-
.../scene/plugins/gltf/GltfMaterialData.java | 176 ++++++++++++++++++
.../plugins/gltf/GltfMaterialFactory.java | 68 +++++++
.../jme3/scene/plugins/gltf/GltfModelKey.java | 3 +-
4 files changed, 350 insertions(+), 3 deletions(-)
create mode 100644 jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/GltfMaterialData.java
create mode 100644 jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/GltfMaterialFactory.java
diff --git a/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/GltfLoader.java b/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/GltfLoader.java
index 8dd1f1d4dd..77d2d4901a 100644
--- a/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/GltfLoader.java
+++ b/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/GltfLoader.java
@@ -31,6 +31,7 @@
*/
package com.jme3.scene.plugins.gltf;
+import static com.jme3.scene.plugins.gltf.GltfMaterialData.*;
import static com.jme3.scene.plugins.gltf.GltfUtils.assertNotNull;
import static com.jme3.scene.plugins.gltf.GltfUtils.findCommonAncestor;
import static com.jme3.scene.plugins.gltf.GltfUtils.getAdapterForMaterial;
@@ -109,6 +110,7 @@
import com.jme3.util.BufferInputStream;
import com.jme3.util.BufferUtils;
import com.jme3.util.IntMap;
+import com.jme3.util.SafeArrayList;
import com.jme3.util.mikktspace.MikktspaceTangentGenerator;
/**
@@ -150,6 +152,8 @@ public class GltfLoader implements AssetLoader {
Map> skinnedSpatials = new HashMap<>();
private final IntMap skinBuffers = new IntMap<>();
+ private static SafeArrayList materialFactoryList = new SafeArrayList<>(GltfMaterialFactory.class);
+
public GltfLoader() {
defaultMaterialAdapters.put("pbrMetallicRoughness", new PBRMetalRoughMaterialAdapter());
}
@@ -808,7 +812,63 @@ public Material readMaterial(int materialIndex) throws IOException {
return readMaterialUsingMaterialAdapters(materialIndex);
}
- // TODO Implement new material factory system.
+ assertNotNull(materials, "There is no material defined yet a mesh references one");
+ JsonObject materialJson = materials.get(materialIndex).getAsJsonObject();
+
+ GltfMaterialData gltfMaterialData = readStandardMaterialParameters(materialJson);
+ gltfMaterialData = customContentManager.readExtensionAndExtras("material", materialJson, gltfMaterialData);
+ return createMaterial(gltfMaterialData, materialIndex);
+ }
+
+ protected GltfMaterialData readStandardMaterialParameters(JsonObject materialJson) throws IOException {
+ GltfMaterialData gltfMaterialData = new GltfMaterialData();
+ gltfMaterialData.setGltfParam(MATERIAL_NAME_PARAM, getAsString(materialJson, "name"));
+
+ JsonObject pbrMetallicRoughnessJson = materialJson.getAsJsonObject("pbrMetallicRoughness");
+ if (pbrMetallicRoughnessJson != null) {
+ gltfMaterialData.setGltfParam(BASE_COLOR_PARAM, getAsColor(pbrMetallicRoughnessJson, "baseColorFactor", ColorRGBA.White));
+ gltfMaterialData.setGltfParam(BASE_COLOR_TEXTURE_PARAM, getAsTexture2D(pbrMetallicRoughnessJson, "baseColorTexture"));
+ gltfMaterialData.setGltfParam(METALLIC_FACTOR_PARAM, getAsFloat(pbrMetallicRoughnessJson, "metallicFactor", 1f));
+ gltfMaterialData.setGltfParam(ROUGHNESS_FACTOR_PARAM, getAsFloat(pbrMetallicRoughnessJson, "roughnessFactor", 1f));
+ gltfMaterialData.setGltfParam(METALLIC_ROUGHNESS_TEXTURE_PARAM, getAsTexture2D(pbrMetallicRoughnessJson, "metallicRoughnessTexture"));
+ }
+
+ JsonObject normalTextureJson = materialJson.getAsJsonObject("normalTexture");
+ if (normalTextureJson != null) {
+ gltfMaterialData.setGltfParam(NORMAL_TEXTURE_PARAM, readTexture(normalTextureJson));
+ gltfMaterialData.setGltfParam(NORMAL_SCALE_PARAM, getAsFloat(normalTextureJson, "scale"));
+ useNormalsFlag = true;
+ }
+
+ JsonObject occlusionTextureJson = materialJson.getAsJsonObject("occlusionTexture");
+ if (occlusionTextureJson != null) {
+ gltfMaterialData.setGltfParam(OCCLUSION_TEXTURE_PARAM, readTexture(occlusionTextureJson));
+ gltfMaterialData.setGltfParam(OCCLUSION_TEXTURE_STRENGTH_PARAM, getAsFloat(occlusionTextureJson, "strength"));
+ }
+
+ gltfMaterialData.setGltfParam(EMISSIV_TEXTURE_PARAM, getAsTexture2D(materialJson, "emissiveTexture"));
+ gltfMaterialData.setGltfParam(EMISSIV_COLOR_PARAM, getAsColor(materialJson, "emissiveFactor", ColorRGBA.Black));
+
+ String alphaMode = getAsString(materialJson, "alphaMode");
+ gltfMaterialData.setGltfParam(ALPHA_MODE_PARAM, alphaMode);
+ if ("MASK".equals(alphaMode)) {
+ gltfMaterialData.setGltfParam(ALPHA_CUTOFF_PARAM, getAsFloat(materialJson, "alphaCutoff"));
+ }
+
+ gltfMaterialData.setGltfParam(DOUBLE_SIDED_PARAM, getAsBoolean(materialJson, "doubleSided"));
+
+ return gltfMaterialData;
+ }
+
+ protected Material createMaterial(GltfMaterialData gltfMaterialData, int materialIndex) {
+ for (GltfMaterialFactory gltfMaterialFactory : materialFactoryList) {
+ if (gltfMaterialFactory.accepts(info.getKey(), gltfMaterialData)) {
+ return gltfMaterialFactory.createMaterial(info.getManager(), info.getKey(), gltfMaterialData);
+ }
+ }
+
+ logger.log(Level.WARNING, "Couldn't find any matching GltfMaterialFactory for material " + materialIndex);
+ useNormalsFlag = false;
return defaultMat;
}
@@ -932,6 +992,10 @@ public void readCameras() throws IOException {
}
}
+ protected Texture2D getAsTexture2D(JsonObject jsonObject, String textureName) throws IOException {
+ return readTexture(jsonObject.getAsJsonObject(textureName));
+ }
+
public Texture2D readTexture(JsonObject texture) throws IOException {
return readTexture(texture, false);
}
@@ -1725,4 +1789,44 @@ public static void registerDefaultExtrasLoader(Class extends ExtrasLoader> loa
public static void unregisterDefaultExtrasLoader() {
CustomContentManager.defaultExtraLoaderClass = UserDataLoader.class;
}
+
+ /**
+ * Registers a new material factory and places it before all existing factories.
+ * The ordering of these factories defines their priority. When a new material needs to be created,
+ * the loader searches for the first material factory that accepts the given material data.
+ *
+ * @param materialFactory The {@link GltfMaterialFactory} to register.
+ */
+ public static void registerMaterialFactoryFirst(GltfMaterialFactory materialFactory) {
+ unregisterMaterialFactory(materialFactory.getClass());
+ materialFactoryList.add(0, materialFactory);
+ }
+
+ /**
+ * Registers a new material factory and places it behind all existing factories.
+ * The ordering of these factories defines their priority. When a new material needs to be created,
+ * the loader searches for the first material factory that accepts the given material data.
+ *
+ * @param materialFactory The {@link GltfMaterialFactory} to register.
+ */
+ public static void registerMaterialFactoryLast(GltfMaterialFactory materialFactory) {
+ unregisterMaterialFactory(materialFactory.getClass());
+ materialFactoryList.add(materialFactory);
+ }
+
+ /**
+ * Unregisters a material factory by its class.
+ *
+ * @param materialFactoryClass The class of the {@link GltfMaterialFactory} to unregister.
+ */
+ public static void unregisterMaterialFactory(Class extends GltfMaterialFactory> materialFactoryClass) {
+ materialFactoryList.removeIf(materialFactoryClass::isInstance);
+ }
+
+ /**
+ * Unregisters all material factories.
+ */
+ public static void unregisterAllMaterialFactories() {
+ materialFactoryList.clear();
+ }
}
diff --git a/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/GltfMaterialData.java b/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/GltfMaterialData.java
new file mode 100644
index 0000000000..cac559e900
--- /dev/null
+++ b/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/GltfMaterialData.java
@@ -0,0 +1,176 @@
+/*
+ * Copyright (c) 2009-2026 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 java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Stores all data of a single material from a GLTF file.
+ * This data can then be used by a {@link GltfMaterialFactory} to create a new material.
+ *
+ *
Parameter naming convention
+ *
+ * -
+ * Parameter names should use single dots '.' as a separator.
+ *
+ * -
+ * All standard parameter names are directly taken from the
+ * GLTF specs document
+ * (ยง 5.19. Material and following).
+ *
+ * -
+ * All additional parameter names from GLTF extensions should start with {@link #MATERIAL_EXTENSION_PARAM_PREFIX}
+ * followed by the name of the extension (e.g. "KHR_materials_unlit") and finished by the parameter name.
+ *
+ * -
+ * All additional parameter names from GLTF extras should start with {@link #MATERIAL_EXTRA_PARAM_PREFIX}.
+ *
+ *
+ *
+ */
+public class GltfMaterialData {
+
+ public static final String MATERIAL_NAME_PARAM = "material.name";
+
+ public static final String BASE_COLOR_PARAM = "material.pbrMetallicRoughness.baseColorFactor";
+
+ public static final String BASE_COLOR_TEXTURE_PARAM = "material.pbrMetallicRoughness.baseColorTexture";
+
+ public static final String METALLIC_FACTOR_PARAM = "material.pbrMetallicRoughness.metallicFactor";
+
+ public static final String ROUGHNESS_FACTOR_PARAM = "material.pbrMetallicRoughness.roughnessFactor";
+
+ public static final String METALLIC_ROUGHNESS_TEXTURE_PARAM = "material.pbrMetallicRoughness.metallicRoughnessTexture";
+
+ public static final String NORMAL_TEXTURE_PARAM = "material.normalTexture";
+
+ public static final String NORMAL_SCALE_PARAM = "material.normalTextureInfo.scale";
+
+ public static final String OCCLUSION_TEXTURE_PARAM = "material.occlusionTexture";
+
+ public static final String OCCLUSION_TEXTURE_STRENGTH_PARAM = "material.occlusionTextureInfo.strength";
+
+ public static final String EMISSIV_TEXTURE_PARAM = "material.emissiveTexture";
+
+ public static final String EMISSIV_COLOR_PARAM = "material.emissiveFactor";
+
+ public static final String ALPHA_MODE_PARAM = "material.alphaMode";
+
+ public static final String ALPHA_CUTOFF_PARAM = "material.alphaCutoff";
+
+ public static final String DOUBLE_SIDED_PARAM = "material.doubleSided";
+
+ public static final String MATERIAL_EXTENSION_PARAM_PREFIX = "material.extension.";
+
+ public static final String MATERIAL_EXTRA_PARAM_PREFIX = "material.extra.";
+
+
+ private Map gltfParamMap = new HashMap<>();
+
+ private Set gltfExtensions = new HashSet<>();
+
+
+ /**
+ * Checks if the material provides the given GLTF extension.
+ *
+ * @param gltfExtension The GLTF extension name.
+ * @return true if the material provides the given GLTF extension, otherwise false.
+ */
+ public boolean hasGltfExtension(String gltfExtension) {
+ return gltfExtensions.contains(gltfExtension);
+ }
+
+ /**
+ * Adds the given GLTF extension name.
+ *
+ * @param gltfExtension The GLTF extension name.
+ */
+ public void addGltfExtension(String gltfExtension) {
+ gltfExtensions.add(gltfExtension);
+ }
+
+ /**
+ * Removes the given GLTF extension name.
+ *
+ * @param gltfExtension The GLTF extension name.
+ */
+ public void removeGltfExtension(String gltfExtension) {
+ gltfExtensions.remove(gltfExtension);
+ }
+
+
+ /**
+ * Checks if the material provides a material parameter with the given name.
+ *
+ * @param gltfParamName The GLTF parameter name.
+ * @return true if the material provides a material parameter with the given name, otherwise false.
+ */
+ public boolean containsGltfParam(String gltfParamName) {
+ return gltfParamMap.containsKey(gltfParamName);
+ }
+
+ /**
+ * Gets the material parameter with the given name.
+ *
+ * @param gltfParamName The GLTF parameter name.
+ * @return The value of the material parameter with the given name, or null if no such parameter exists.
+ */
+ public Object getGltfParam(String gltfParamName) {
+ return gltfParamMap.get(gltfParamName);
+ }
+
+ /**
+ * Adds a material parameter with the given name and value.
+ *
+ * @param gltfParamName The GLTF parameter name.
+ * @param value The value of the material parameter. Does nothing, if value is null.
+ */
+ public void setGltfParam(String gltfParamName, Object value) {
+ if (value != null) {
+ gltfParamMap.put(gltfParamName, value);
+ }
+ }
+
+ /**
+ * Removes the material parameter with the given name.
+ *
+ * @param gltfParamName The GLTF parameter name.
+ * @return The previous value of the material parameter, or null if there was no such parameter.
+ */
+ public Object removeGltfParam(String gltfParamName) {
+ return gltfParamMap.remove(gltfParamName);
+ }
+
+}
diff --git a/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/GltfMaterialFactory.java b/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/GltfMaterialFactory.java
new file mode 100644
index 0000000000..7d4eabf5f4
--- /dev/null
+++ b/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/GltfMaterialFactory.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2009-2026 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.asset.AssetKey;
+import com.jme3.asset.AssetManager;
+import com.jme3.material.Material;
+
+/**
+ * A material factory creates {@link Material}s based on the data of a single material from a GLTF file.
+ *
+ * All material factories have bo be registered at the {@link GltfLoader} by using one of its
+ * static register methods.
+ *
+ */
+public interface GltfMaterialFactory {
+
+ /**
+ * Checks, if the factory is able to create a new material from the given material data.
+ * If it accepts the material data, the {@link #createMaterial(AssetManager, AssetKey, GltfMaterialData)} method
+ * can be used to create a new material.
+ *
+ * @param assetKey The {@link AssetKey} used for loading the GLTF model.
+ * @param gltfMaterialData The {@link GltfMaterialData} containing all available GLTF material data.
+ * @return true if the factory is able to create a material from the given material data, otherwise false.
+ */
+ boolean accepts(AssetKey> assetKey, GltfMaterialData gltfMaterialData);
+
+ /**
+ * Creates a new material from the given material data.
+ *
+ * @param assetManager The {@link AssetManager} instance.
+ * @param assetKey The {@link AssetKey} used for loading the GLTF model.
+ * @param gltfMaterialData The {@link GltfMaterialData} containing all available GLTF material data.
+ * @return The new created {@link Material}.
+ */
+ Material createMaterial(AssetManager assetManager, AssetKey> assetKey, GltfMaterialData gltfMaterialData);
+
+}
diff --git a/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/GltfModelKey.java b/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/GltfModelKey.java
index de66ffbc0a..92b6dbe463 100644
--- a/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/GltfModelKey.java
+++ b/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/GltfModelKey.java
@@ -56,8 +56,7 @@ public class GltfModelKey extends ModelKey {
* Enables or disables the legacy material adapter system.
* This should only be used in older projects for backward compatibility.
*/
- // TODO Set the default to false, after the new material creation process has been implemented
- private boolean materialAdaptersEnabled = true;
+ private boolean materialAdaptersEnabled = false;
private Map materialAdapters = new HashMap<>();
private static Map extensionLoaders = new HashMap<>();
From fef2d6ef55244307efd8c575cce32a12b10c5c8e Mon Sep 17 00:00:00 2001
From: theMinka
Date: Sun, 19 Apr 2026 20:56:16 +0200
Subject: [PATCH 04/10] Added handling of GltfMaterialData objects for all
material-based ExtensionLoaders
* Retains the old MaterialAdapter handling for backward compatibility
---
.../PBREmissiveStrengthExtensionLoader.java | 34 ++++++++++++++-
.../gltf/PBRSpecGlossExtensionLoader.java | 41 +++++++++++++++++++
.../plugins/gltf/UnlitExtensionLoader.java | 21 ++++++++++
3 files changed, 94 insertions(+), 2 deletions(-)
diff --git a/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/PBREmissiveStrengthExtensionLoader.java b/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/PBREmissiveStrengthExtensionLoader.java
index 71ab1b84a4..3ad3c59d88 100644
--- a/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/PBREmissiveStrengthExtensionLoader.java
+++ b/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/PBREmissiveStrengthExtensionLoader.java
@@ -33,7 +33,13 @@
import com.jme3.asset.AssetKey;
import com.jme3.plugins.json.JsonElement;
+import com.jme3.plugins.json.JsonObject;
+
import java.io.IOException;
+import java.util.logging.Logger;
+
+import static com.jme3.scene.plugins.gltf.GltfMaterialData.MATERIAL_EXTENSION_PARAM_PREFIX;
+import static com.jme3.scene.plugins.gltf.GltfUtils.getAsFloat;
/**
* Extension loader for "KHR_materials_emissive_strength".
@@ -41,11 +47,35 @@
* @author codex
*/
public class PBREmissiveStrengthExtensionLoader implements ExtensionLoader {
-
+
+ public static final String EXTENSION_NAME = "KHR_materials_emissive_strength";
+
+ public static final String EMISSIVE_STRENGTH_PARAM = MATERIAL_EXTENSION_PARAM_PREFIX + EXTENSION_NAME + ".emissiveStrength";
+
+ private static final Logger logger = Logger.getLogger(PBREmissiveStrengthExtensionLoader.class.getName());
+
private PBREmissiveStrengthMaterialAdapter materialAdapter = new PBREmissiveStrengthMaterialAdapter();
-
+
@Override
public Object handleExtension(GltfLoader loader, String parentName, JsonElement parent, JsonElement extension, Object input) throws IOException {
+ if (input instanceof GltfMaterialData) {
+ GltfMaterialData gltfMaterialData = (GltfMaterialData) input;
+ gltfMaterialData.addGltfExtension(EXTENSION_NAME);
+
+ JsonObject extensionJson = extension.getAsJsonObject();
+ gltfMaterialData.setGltfParam(EMISSIVE_STRENGTH_PARAM, getAsFloat(extensionJson, "emissiveStrength"));
+
+ } else if (input instanceof MaterialAdapter) {
+ return handleExtensionForMaterialAdapter(loader, parentName, parent, extension, input);
+
+ } else {
+ logger.warning(EXTENSION_NAME + " extension added on unsupported element");
+ }
+
+ return input;
+ }
+
+ private Object handleExtensionForMaterialAdapter(GltfLoader loader, String parentName, JsonElement parent, JsonElement extension, Object input) throws IOException {
MaterialAdapter adapter = materialAdapter;
AssetKey key = loader.getInfo().getKey();
//check for a custom adapter for emissive strength
diff --git a/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/PBRSpecGlossExtensionLoader.java b/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/PBRSpecGlossExtensionLoader.java
index abeda10cd7..395982fd8e 100644
--- a/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/PBRSpecGlossExtensionLoader.java
+++ b/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/PBRSpecGlossExtensionLoader.java
@@ -34,7 +34,12 @@
import com.jme3.asset.AssetKey;
import java.io.IOException;
+import java.util.logging.Logger;
+
import com.jme3.plugins.json.JsonElement;
+import com.jme3.plugins.json.JsonObject;
+
+import static com.jme3.scene.plugins.gltf.GltfMaterialData.MATERIAL_EXTENSION_PARAM_PREFIX;
import static com.jme3.scene.plugins.gltf.GltfUtils.getAsColor;
import static com.jme3.scene.plugins.gltf.GltfUtils.getAsFloat;
@@ -44,10 +49,46 @@
*/
public class PBRSpecGlossExtensionLoader implements ExtensionLoader {
+ public static final String EXTENSION_NAME = "KHR_materials_pbrSpecularGlossiness";
+
+ public static final String DIFFUSE_COLOR_PARAM = MATERIAL_EXTENSION_PARAM_PREFIX + EXTENSION_NAME + ".diffuseFactor";
+
+ public static final String SPECULAR_COLOR_PARAM = MATERIAL_EXTENSION_PARAM_PREFIX + EXTENSION_NAME + ".specularFactor";
+
+ public static final String GLOSSINESS_FACTOR_PARAM = MATERIAL_EXTENSION_PARAM_PREFIX + EXTENSION_NAME + ".glossinessFactor";
+
+ public static final String DIFFUSE_TEXTURE_PARAM = MATERIAL_EXTENSION_PARAM_PREFIX + EXTENSION_NAME + ".diffuseTexture";
+
+ public static final String SPECULAR_GLOSSINESS_TEXTURE_PARAM = MATERIAL_EXTENSION_PARAM_PREFIX + EXTENSION_NAME + ".specularGlossinessTexture";
+
+ private static final Logger logger = Logger.getLogger(PBRSpecGlossExtensionLoader.class.getName());
+
private PBRSpecGlossMaterialAdapter materialAdapter = new PBRSpecGlossMaterialAdapter();
@Override
public Object handleExtension(GltfLoader loader, String parentName, JsonElement parent, JsonElement extension, Object input) throws IOException {
+ if (input instanceof GltfMaterialData) {
+ GltfMaterialData gltfMaterialData = (GltfMaterialData) input;
+ gltfMaterialData.addGltfExtension(EXTENSION_NAME);
+
+ JsonObject extensionJson = extension.getAsJsonObject();
+ gltfMaterialData.setGltfParam(DIFFUSE_COLOR_PARAM, getAsColor(extensionJson, "diffuseFactor"));
+ gltfMaterialData.setGltfParam(SPECULAR_COLOR_PARAM, getAsColor(extensionJson, "specularFactor"));
+ gltfMaterialData.setGltfParam(GLOSSINESS_FACTOR_PARAM, getAsFloat(extensionJson, "glossinessFactor"));
+ gltfMaterialData.setGltfParam(DIFFUSE_TEXTURE_PARAM, loader.getAsTexture2D(extensionJson,"diffuseTexture"));
+ gltfMaterialData.setGltfParam(SPECULAR_GLOSSINESS_TEXTURE_PARAM, loader.getAsTexture2D(extensionJson,"specularGlossinessTexture"));
+
+ } else if (input instanceof MaterialAdapter) {
+ return handleExtensionForMaterialAdapter(loader, parentName, parent, extension, input);
+
+ } else {
+ logger.warning(EXTENSION_NAME + " extension added on unsupported element");
+ }
+
+ return input;
+ }
+
+ private Object handleExtensionForMaterialAdapter(GltfLoader loader, String parentName, JsonElement parent, JsonElement extension, Object input) throws IOException {
MaterialAdapter adapter = materialAdapter;
AssetKey key = loader.getInfo().getKey();
//check for a custom adapter for spec/gloss pipeline
diff --git a/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/UnlitExtensionLoader.java b/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/UnlitExtensionLoader.java
index 790d70b0cf..0ec82c6aed 100644
--- a/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/UnlitExtensionLoader.java
+++ b/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/UnlitExtensionLoader.java
@@ -34,16 +34,37 @@
import com.jme3.plugins.json.JsonElement;
import com.jme3.asset.AssetKey;
+import java.util.logging.Logger;
+
/**
* Material adapter for the Unlit pipeline
* @author Markil 3
*/
public class UnlitExtensionLoader implements ExtensionLoader {
+ public static final String EXTENSION_NAME = "KHR_materials_unlit";
+
+ private static final Logger logger = Logger.getLogger(UnlitExtensionLoader.class.getName());
+
private final UnlitMaterialAdapter materialAdapter = new UnlitMaterialAdapter();
@Override
public Object handleExtension(GltfLoader loader, String parentName, JsonElement parent, JsonElement extension, Object input) {
+ if (input instanceof GltfMaterialData) {
+ GltfMaterialData gltfMaterialData = (GltfMaterialData) input;
+ gltfMaterialData.addGltfExtension(EXTENSION_NAME);
+
+ } else if (input instanceof MaterialAdapter) {
+ return handleExtensionForMaterialAdapter(loader, parentName, parent, extension, input);
+
+ } else {
+ logger.warning(EXTENSION_NAME + " extension added on unsupported element");
+ }
+
+ return input;
+ }
+
+ private Object handleExtensionForMaterialAdapter(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
From 11eded35be1c20c4ab9feb4dd2daaa6250577c32 Mon Sep 17 00:00:00 2001
From: theMinka
Date: Sun, 19 Apr 2026 21:18:33 +0200
Subject: [PATCH 05/10] Added GltfMaterialFactory implementations for
BPRLighting and Unshaded material
* Added both material factories as the default ones to the GltfLoader
---
.../jme3/scene/plugins/gltf/GltfLoader.java | 5 +
.../gltf/PBRLightingMaterialFactory.java | 149 ++++++++++++++++++
.../plugins/gltf/UnshadedMaterialFactory.java | 95 +++++++++++
3 files changed, 249 insertions(+)
create mode 100644 jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/PBRLightingMaterialFactory.java
create mode 100644 jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/UnshadedMaterialFactory.java
diff --git a/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/GltfLoader.java b/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/GltfLoader.java
index 77d2d4901a..e105e93052 100644
--- a/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/GltfLoader.java
+++ b/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/GltfLoader.java
@@ -154,6 +154,11 @@ public class GltfLoader implements AssetLoader {
private static SafeArrayList materialFactoryList = new SafeArrayList<>(GltfMaterialFactory.class);
+ static {
+ materialFactoryList.add(new UnshadedMaterialFactory());
+ materialFactoryList.add(new PBRLightingMaterialFactory());
+ }
+
public GltfLoader() {
defaultMaterialAdapters.put("pbrMetallicRoughness", new PBRMetalRoughMaterialAdapter());
}
diff --git a/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/PBRLightingMaterialFactory.java b/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/PBRLightingMaterialFactory.java
new file mode 100644
index 0000000000..1100dbb3e4
--- /dev/null
+++ b/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/PBRLightingMaterialFactory.java
@@ -0,0 +1,149 @@
+/*
+ * Copyright (c) 2009-2026 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.asset.AssetKey;
+import com.jme3.asset.AssetManager;
+import com.jme3.material.Material;
+import com.jme3.material.RenderState;
+import com.jme3.texture.Texture;
+
+import static com.jme3.scene.plugins.gltf.GltfMaterialData.*;
+import static com.jme3.scene.plugins.gltf.PBREmissiveStrengthExtensionLoader.EMISSIVE_STRENGTH_PARAM;
+import static com.jme3.scene.plugins.gltf.PBRSpecGlossExtensionLoader.*;
+
+/**
+ * This material factory creates jME3's standard "PBRLighting" materials.
+ */
+public class PBRLightingMaterialFactory implements GltfMaterialFactory {
+
+ @Override
+ public boolean accepts(AssetKey> assetKey, GltfMaterialData gltfMaterialData) {
+ // Since PBRLighting is the default material, it accepts all material data,
+ // making any subsequent material factories effectively unreachable.
+ return true;
+ }
+
+ @Override
+ public Material createMaterial(AssetManager assetManager, AssetKey> assetKey, GltfMaterialData gltfMaterialData) {
+ Material material = new Material(assetManager, getMaterialDefPath());
+ material.setName((String) gltfMaterialData.getGltfParam(MATERIAL_NAME_PARAM));
+
+ setStandardParams(material, gltfMaterialData);
+
+ if (gltfMaterialData.hasGltfExtension(PBRSpecGlossExtensionLoader.EXTENSION_NAME)) {
+ setSpecularGlossinessParams(material, gltfMaterialData);
+
+ } else {
+ setMetallicRoughnessParams(material, gltfMaterialData);
+ }
+
+ return material;
+ }
+
+ protected String getMaterialDefPath() {
+ return "Common/MatDefs/Light/PBRLighting.j3md";
+ }
+
+ protected void setStandardParams(Material material, GltfMaterialData gltfMaterialData) {
+ if (gltfMaterialData.containsGltfParam(NORMAL_TEXTURE_PARAM)) {
+ setParam(material, "NormalMap", gltfMaterialData.getGltfParam(NORMAL_TEXTURE_PARAM));
+ setParam(material, "NormalScale", gltfMaterialData.getGltfParam(NORMAL_SCALE_PARAM));
+ material.setFloat("NormalType", 1f);
+ }
+
+ if (gltfMaterialData.containsGltfParam(OCCLUSION_TEXTURE_PARAM)) {
+ // Gltf only supports AO maps (gray scales and only the r channel must be read)
+ material.setBoolean("LightMapAsAOMap", true);
+ setParam(material, "LightMap", gltfMaterialData.getGltfParam(OCCLUSION_TEXTURE_PARAM));
+ setParam(material, "AoStrength", gltfMaterialData.getGltfParam(OCCLUSION_TEXTURE_STRENGTH_PARAM));
+
+ // Check if the occlusion texture is actually the same instance as the metallic-roughness texture.
+ boolean isAoPackedInMRMap = false;
+ if (gltfMaterialData.containsGltfParam(METALLIC_ROUGHNESS_TEXTURE_PARAM)) {
+ Texture occlusionTexture = (Texture) gltfMaterialData.getGltfParam(OCCLUSION_TEXTURE_PARAM);
+ Texture metallicRoughnessTexture = (Texture) gltfMaterialData.getGltfParam(METALLIC_ROUGHNESS_TEXTURE_PARAM);
+ isAoPackedInMRMap = occlusionTexture == metallicRoughnessTexture;
+ }
+ material.setBoolean("AoPackedInMRMap", isAoPackedInMRMap);
+ }
+
+ setParam(material, "EmissiveMap", gltfMaterialData.getGltfParam(EMISSIV_TEXTURE_PARAM));
+ setParam(material, "Emissive", gltfMaterialData.getGltfParam(EMISSIV_COLOR_PARAM));
+ setParam(material, "EmissiveIntensity", gltfMaterialData.getGltfParam(EMISSIVE_STRENGTH_PARAM));
+
+ if (gltfMaterialData.containsGltfParam(ALPHA_MODE_PARAM)) {
+ String alphaMode = (String) gltfMaterialData.getGltfParam(ALPHA_MODE_PARAM);
+ switch (alphaMode) {
+ case "MASK":
+ // "MASK" -> BlendMode.Off
+ setParam(material, "AlphaDiscardThreshold", gltfMaterialData.getGltfParam(ALPHA_CUTOFF_PARAM));
+ break;
+ case "BLEND":
+ material.getAdditionalRenderState().setBlendMode(RenderState.BlendMode.Alpha);
+ break;
+ }
+ }
+
+ if (gltfMaterialData.containsGltfParam(DOUBLE_SIDED_PARAM)) {
+ boolean doubleSided = (boolean) gltfMaterialData.getGltfParam(DOUBLE_SIDED_PARAM);
+ if (doubleSided) {
+ //Note that this is not completely right as normals on the back side will be in the wrong direction.
+ material.getAdditionalRenderState().setFaceCullMode(RenderState.FaceCullMode.Off);
+ }
+ }
+ }
+
+ protected void setMetallicRoughnessParams(Material material, GltfMaterialData gltfMaterialData) {
+ setParam(material, "BaseColor", gltfMaterialData.getGltfParam(BASE_COLOR_PARAM));
+ setParam(material, "BaseColorMap", gltfMaterialData.getGltfParam(BASE_COLOR_TEXTURE_PARAM));
+ setParam(material, "Metallic", gltfMaterialData.getGltfParam(METALLIC_FACTOR_PARAM));
+ setParam(material, "Roughness", gltfMaterialData.getGltfParam(ROUGHNESS_FACTOR_PARAM));
+ setParam(material, "MetallicRoughnessMap", gltfMaterialData.getGltfParam(METALLIC_ROUGHNESS_TEXTURE_PARAM));
+ }
+
+ protected void setSpecularGlossinessParams(Material material, GltfMaterialData gltfMaterialData) {
+ material.setBoolean("UseSpecGloss", true);
+ setParam(material, "BaseColor", gltfMaterialData.getGltfParam(DIFFUSE_COLOR_PARAM));
+ setParam(material, "BaseColorMap", gltfMaterialData.getGltfParam(DIFFUSE_TEXTURE_PARAM));
+ setParam(material, "Specular", gltfMaterialData.getGltfParam(SPECULAR_COLOR_PARAM));
+ setParam(material, "Glossiness", gltfMaterialData.getGltfParam(GLOSSINESS_FACTOR_PARAM));
+ setParam(material, "SpecularGlossinessMap", gltfMaterialData.getGltfParam(SPECULAR_GLOSSINESS_TEXTURE_PARAM));
+ }
+
+ protected void setParam(Material material, String paramName, Object value) {
+ if (value != null) {
+ material.setParam(paramName, value);
+ }
+ }
+
+}
diff --git a/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/UnshadedMaterialFactory.java b/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/UnshadedMaterialFactory.java
new file mode 100644
index 0000000000..ae47824046
--- /dev/null
+++ b/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/UnshadedMaterialFactory.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2009-2026 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.asset.AssetKey;
+import com.jme3.asset.AssetManager;
+import com.jme3.material.Material;
+import com.jme3.material.RenderState;
+
+import static com.jme3.scene.plugins.gltf.GltfMaterialData.*;
+
+/**
+ * This material factory creates jME3's standard "Unshaded" materials.
+ */
+public class UnshadedMaterialFactory implements GltfMaterialFactory {
+
+ @Override
+ public boolean accepts(AssetKey> assetKey, GltfMaterialData gltfMaterialData) {
+ return gltfMaterialData.hasGltfExtension(UnlitExtensionLoader.EXTENSION_NAME);
+ }
+
+ @Override
+ public Material createMaterial(AssetManager assetManager, AssetKey> assetKey, GltfMaterialData gltfMaterialData) {
+ Material material = new Material(assetManager,getMaterialDefPath());
+ material.setName((String) gltfMaterialData.getGltfParam(MATERIAL_NAME_PARAM));
+
+ setParam(material, "Color", gltfMaterialData.getGltfParam(BASE_COLOR_PARAM));
+ setParam(material, "ColorMap", gltfMaterialData.getGltfParam(BASE_COLOR_TEXTURE_PARAM));
+ setParam(material, "GlowColor", gltfMaterialData.getGltfParam(EMISSIV_COLOR_PARAM));
+ setParam(material, "GlowMap", gltfMaterialData.getGltfParam(EMISSIV_TEXTURE_PARAM));
+
+ if (gltfMaterialData.containsGltfParam(ALPHA_MODE_PARAM)) {
+ String alphaMode = (String) gltfMaterialData.getGltfParam(ALPHA_MODE_PARAM);
+ switch (alphaMode) {
+ case "MASK":
+ // "MASK" -> BlendMode.Off
+ setParam(material, "AlphaDiscardThreshold", gltfMaterialData.getGltfParam(ALPHA_CUTOFF_PARAM));
+ break;
+ case "BLEND":
+ material.getAdditionalRenderState().setBlendMode(RenderState.BlendMode.Alpha);
+ break;
+ }
+ }
+
+ if (gltfMaterialData.containsGltfParam(DOUBLE_SIDED_PARAM)) {
+ boolean doubleSided = (boolean) gltfMaterialData.getGltfParam(DOUBLE_SIDED_PARAM);
+ if (doubleSided) {
+ //Note that this is not completely right as normals on the back side will be in the wrong direction.
+ material.getAdditionalRenderState().setFaceCullMode(RenderState.FaceCullMode.Off);
+ }
+ }
+
+ return material;
+ }
+
+ protected String getMaterialDefPath() {
+ return "Common/MatDefs/Misc/Unshaded.j3md";
+ }
+
+ protected void setParam(Material material, String paramName, Object value) {
+ if (value != null) {
+ material.setParam(paramName, value);
+ }
+ }
+
+}
From ae12167eed21c011bad876578c9b115e6a00fb38 Mon Sep 17 00:00:00 2001
From: theMinka
Date: Sun, 19 Apr 2026 22:20:48 +0200
Subject: [PATCH 06/10] Move default values for material parameters to material
factories
Reason: Setting default values directly in GltfMaterialData obscures whether a parameter is actually defined in the glTF material. The presence of material parameters may be relevant for some material factories. Therefore, default values should be set by the material factories themselves.
---
.../com/jme3/scene/plugins/gltf/GltfLoader.java | 8 ++++----
.../plugins/gltf/PBRLightingMaterialFactory.java | 15 ++++++++++-----
.../plugins/gltf/UnshadedMaterialFactory.java | 11 ++++++++---
3 files changed, 22 insertions(+), 12 deletions(-)
diff --git a/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/GltfLoader.java b/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/GltfLoader.java
index e105e93052..bb83f4f369 100644
--- a/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/GltfLoader.java
+++ b/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/GltfLoader.java
@@ -831,10 +831,10 @@ protected GltfMaterialData readStandardMaterialParameters(JsonObject materialJso
JsonObject pbrMetallicRoughnessJson = materialJson.getAsJsonObject("pbrMetallicRoughness");
if (pbrMetallicRoughnessJson != null) {
- gltfMaterialData.setGltfParam(BASE_COLOR_PARAM, getAsColor(pbrMetallicRoughnessJson, "baseColorFactor", ColorRGBA.White));
+ gltfMaterialData.setGltfParam(BASE_COLOR_PARAM, getAsColor(pbrMetallicRoughnessJson, "baseColorFactor"));
gltfMaterialData.setGltfParam(BASE_COLOR_TEXTURE_PARAM, getAsTexture2D(pbrMetallicRoughnessJson, "baseColorTexture"));
- gltfMaterialData.setGltfParam(METALLIC_FACTOR_PARAM, getAsFloat(pbrMetallicRoughnessJson, "metallicFactor", 1f));
- gltfMaterialData.setGltfParam(ROUGHNESS_FACTOR_PARAM, getAsFloat(pbrMetallicRoughnessJson, "roughnessFactor", 1f));
+ gltfMaterialData.setGltfParam(METALLIC_FACTOR_PARAM, getAsFloat(pbrMetallicRoughnessJson, "metallicFactor"));
+ gltfMaterialData.setGltfParam(ROUGHNESS_FACTOR_PARAM, getAsFloat(pbrMetallicRoughnessJson, "roughnessFactor"));
gltfMaterialData.setGltfParam(METALLIC_ROUGHNESS_TEXTURE_PARAM, getAsTexture2D(pbrMetallicRoughnessJson, "metallicRoughnessTexture"));
}
@@ -852,7 +852,7 @@ protected GltfMaterialData readStandardMaterialParameters(JsonObject materialJso
}
gltfMaterialData.setGltfParam(EMISSIV_TEXTURE_PARAM, getAsTexture2D(materialJson, "emissiveTexture"));
- gltfMaterialData.setGltfParam(EMISSIV_COLOR_PARAM, getAsColor(materialJson, "emissiveFactor", ColorRGBA.Black));
+ gltfMaterialData.setGltfParam(EMISSIV_COLOR_PARAM, getAsColor(materialJson, "emissiveFactor"));
String alphaMode = getAsString(materialJson, "alphaMode");
gltfMaterialData.setGltfParam(ALPHA_MODE_PARAM, alphaMode);
diff --git a/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/PBRLightingMaterialFactory.java b/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/PBRLightingMaterialFactory.java
index 1100dbb3e4..07d0f47f7b 100644
--- a/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/PBRLightingMaterialFactory.java
+++ b/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/PBRLightingMaterialFactory.java
@@ -35,6 +35,7 @@
import com.jme3.asset.AssetManager;
import com.jme3.material.Material;
import com.jme3.material.RenderState;
+import com.jme3.math.ColorRGBA;
import com.jme3.texture.Texture;
import static com.jme3.scene.plugins.gltf.GltfMaterialData.*;
@@ -98,7 +99,7 @@ protected void setStandardParams(Material material, GltfMaterialData gltfMateria
}
setParam(material, "EmissiveMap", gltfMaterialData.getGltfParam(EMISSIV_TEXTURE_PARAM));
- setParam(material, "Emissive", gltfMaterialData.getGltfParam(EMISSIV_COLOR_PARAM));
+ setParam(material, "Emissive", gltfMaterialData.getGltfParam(EMISSIV_COLOR_PARAM), ColorRGBA.Black);
setParam(material, "EmissiveIntensity", gltfMaterialData.getGltfParam(EMISSIVE_STRENGTH_PARAM));
if (gltfMaterialData.containsGltfParam(ALPHA_MODE_PARAM)) {
@@ -106,7 +107,7 @@ protected void setStandardParams(Material material, GltfMaterialData gltfMateria
switch (alphaMode) {
case "MASK":
// "MASK" -> BlendMode.Off
- setParam(material, "AlphaDiscardThreshold", gltfMaterialData.getGltfParam(ALPHA_CUTOFF_PARAM));
+ setParam(material, "AlphaDiscardThreshold", gltfMaterialData.getGltfParam(ALPHA_CUTOFF_PARAM), 0.5f);
break;
case "BLEND":
material.getAdditionalRenderState().setBlendMode(RenderState.BlendMode.Alpha);
@@ -124,10 +125,10 @@ protected void setStandardParams(Material material, GltfMaterialData gltfMateria
}
protected void setMetallicRoughnessParams(Material material, GltfMaterialData gltfMaterialData) {
- setParam(material, "BaseColor", gltfMaterialData.getGltfParam(BASE_COLOR_PARAM));
+ setParam(material, "BaseColor", gltfMaterialData.getGltfParam(BASE_COLOR_PARAM), ColorRGBA.White);
setParam(material, "BaseColorMap", gltfMaterialData.getGltfParam(BASE_COLOR_TEXTURE_PARAM));
- setParam(material, "Metallic", gltfMaterialData.getGltfParam(METALLIC_FACTOR_PARAM));
- setParam(material, "Roughness", gltfMaterialData.getGltfParam(ROUGHNESS_FACTOR_PARAM));
+ setParam(material, "Metallic", gltfMaterialData.getGltfParam(METALLIC_FACTOR_PARAM), 1f);
+ setParam(material, "Roughness", gltfMaterialData.getGltfParam(ROUGHNESS_FACTOR_PARAM), 1f);
setParam(material, "MetallicRoughnessMap", gltfMaterialData.getGltfParam(METALLIC_ROUGHNESS_TEXTURE_PARAM));
}
@@ -146,4 +147,8 @@ protected void setParam(Material material, String paramName, Object value) {
}
}
+ protected void setParam(Material material, String paramName, Object value, Object defaultValue) {
+ setParam(material, paramName, value != null ? value : defaultValue);
+ }
+
}
diff --git a/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/UnshadedMaterialFactory.java b/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/UnshadedMaterialFactory.java
index ae47824046..58443a95ec 100644
--- a/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/UnshadedMaterialFactory.java
+++ b/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/UnshadedMaterialFactory.java
@@ -35,6 +35,7 @@
import com.jme3.asset.AssetManager;
import com.jme3.material.Material;
import com.jme3.material.RenderState;
+import com.jme3.math.ColorRGBA;
import static com.jme3.scene.plugins.gltf.GltfMaterialData.*;
@@ -53,9 +54,9 @@ public Material createMaterial(AssetManager assetManager, AssetKey> assetKey,
Material material = new Material(assetManager,getMaterialDefPath());
material.setName((String) gltfMaterialData.getGltfParam(MATERIAL_NAME_PARAM));
- setParam(material, "Color", gltfMaterialData.getGltfParam(BASE_COLOR_PARAM));
+ setParam(material, "Color", gltfMaterialData.getGltfParam(BASE_COLOR_PARAM), ColorRGBA.White);
setParam(material, "ColorMap", gltfMaterialData.getGltfParam(BASE_COLOR_TEXTURE_PARAM));
- setParam(material, "GlowColor", gltfMaterialData.getGltfParam(EMISSIV_COLOR_PARAM));
+ setParam(material, "GlowColor", gltfMaterialData.getGltfParam(EMISSIV_COLOR_PARAM), ColorRGBA.Black);
setParam(material, "GlowMap", gltfMaterialData.getGltfParam(EMISSIV_TEXTURE_PARAM));
if (gltfMaterialData.containsGltfParam(ALPHA_MODE_PARAM)) {
@@ -63,7 +64,7 @@ public Material createMaterial(AssetManager assetManager, AssetKey> assetKey,
switch (alphaMode) {
case "MASK":
// "MASK" -> BlendMode.Off
- setParam(material, "AlphaDiscardThreshold", gltfMaterialData.getGltfParam(ALPHA_CUTOFF_PARAM));
+ setParam(material, "AlphaDiscardThreshold", gltfMaterialData.getGltfParam(ALPHA_CUTOFF_PARAM), 0.5f);
break;
case "BLEND":
material.getAdditionalRenderState().setBlendMode(RenderState.BlendMode.Alpha);
@@ -92,4 +93,8 @@ protected void setParam(Material material, String paramName, Object value) {
}
}
+ protected void setParam(Material material, String paramName, Object value, Object defaultValue) {
+ setParam(material, paramName, value != null ? value : defaultValue);
+ }
+
}
From 53b75ca00e3945b2e50c781bdb3786212474afc2 Mon Sep 17 00:00:00 2001
From: theMinka
Date: Sun, 19 Apr 2026 22:28:11 +0200
Subject: [PATCH 07/10] Deprecating most parts of the old MaterialAdapter
system
---
.../gltf/java/com/jme3/scene/plugins/gltf/GltfLoader.java | 3 ++-
.../java/com/jme3/scene/plugins/gltf/GltfModelKey.java | 7 +++++++
.../gltf/java/com/jme3/scene/plugins/gltf/GltfUtils.java | 1 +
.../java/com/jme3/scene/plugins/gltf/MaterialAdapter.java | 4 ++++
.../plugins/gltf/PBREmissiveStrengthExtensionLoader.java | 2 ++
.../plugins/gltf/PBREmissiveStrengthMaterialAdapter.java | 4 ++++
.../com/jme3/scene/plugins/gltf/PBRMaterialAdapter.java | 4 ++++
.../scene/plugins/gltf/PBRMetalRoughMaterialAdapter.java | 4 ++++
.../scene/plugins/gltf/PBRSpecGlossExtensionLoader.java | 2 ++
.../scene/plugins/gltf/PBRSpecGlossMaterialAdapter.java | 4 ++++
.../com/jme3/scene/plugins/gltf/UnlitExtensionLoader.java | 2 ++
.../com/jme3/scene/plugins/gltf/UnlitMaterialAdapter.java | 4 ++++
12 files changed, 40 insertions(+), 1 deletion(-)
diff --git a/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/GltfLoader.java b/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/GltfLoader.java
index bb83f4f369..69596e7f6a 100644
--- a/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/GltfLoader.java
+++ b/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/GltfLoader.java
@@ -145,7 +145,7 @@ public class GltfLoader implements AssetLoader {
private final Vector3fArrayPopulator vector3fArrayPopulator = new Vector3fArrayPopulator();
private final QuaternionArrayPopulator quaternionArrayPopulator = new QuaternionArrayPopulator();
private final Matrix4fArrayPopulator matrix4fArrayPopulator = new Matrix4fArrayPopulator();
- private final Map defaultMaterialAdapters = new HashMap<>();
+ @Deprecated private final Map defaultMaterialAdapters = new HashMap<>();
private final CustomContentManager customContentManager = new CustomContentManager();
private boolean useNormalsFlag = false;
@@ -877,6 +877,7 @@ protected Material createMaterial(GltfMaterialData gltfMaterialData, int materia
return defaultMat;
}
+ @Deprecated
protected Material readMaterialUsingMaterialAdapters(int materialIndex) throws IOException {
assertNotNull(materials, "There is no material defined yet a mesh references one");
diff --git a/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/GltfModelKey.java b/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/GltfModelKey.java
index 92b6dbe463..cea372e7df 100644
--- a/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/GltfModelKey.java
+++ b/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/GltfModelKey.java
@@ -58,7 +58,9 @@ public class GltfModelKey extends ModelKey {
*/
private boolean materialAdaptersEnabled = false;
+ @Deprecated
private Map materialAdapters = new HashMap<>();
+
private static Map extensionLoaders = new HashMap<>();
private boolean keepSkeletonPose = false;
private ExtrasLoader extrasLoader;
@@ -127,7 +129,11 @@ public void setMaterialAdaptersEnabled(boolean materialAdaptersEnabled) {
*
* @param gltfMaterialName the name of the gltf material
* @param adapter the material adapter
+ *
+ * @deprecated This will be removed in a future version of the engine. To migrate,
+ * create a custom {@link GltfMaterialFactory} and register it with the {@link GltfLoader}.
*/
+ @Deprecated
public void registerMaterialAdapter(String gltfMaterialName, MaterialAdapter adapter) {
materialAdapters.put(gltfMaterialName, adapter);
}
@@ -144,6 +150,7 @@ public void registerExtensionLoader(String extensionName, ExtensionLoader loader
extensionLoaders.put(extensionName, loader);
}
+ @Deprecated
public MaterialAdapter getAdapterForMaterial(String gltfMaterialName) {
return materialAdapters.get(gltfMaterialName);
}
diff --git a/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/GltfUtils.java b/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/GltfUtils.java
index 6aff505079..e8f0735f67 100644
--- a/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/GltfUtils.java
+++ b/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/GltfUtils.java
@@ -721,6 +721,7 @@ public static boolean isMaterialAdaptersEnabled(AssetInfo info) {
return key != null && key.isMaterialAdaptersEnabled();
}
+ @Deprecated
public static MaterialAdapter getAdapterForMaterial(AssetInfo info, String defName) {
GltfModelKey key = getKey(info);
if (key == null) {
diff --git a/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/MaterialAdapter.java b/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/MaterialAdapter.java
index b6b10f9c83..d94d1662fa 100644
--- a/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/MaterialAdapter.java
+++ b/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/MaterialAdapter.java
@@ -47,7 +47,11 @@
* It maps each gltf parameter to its matching parameter in the JME material,
* and allows for some conversion if the JME material model doesn't exactly match the gltf material model
* Created by Nehon on 08/08/2017.
+ *
+ * @deprecated This will be removed in a future version of the engine. To migrate,
+ * create a custom {@link GltfMaterialFactory} and register it with the {@link GltfLoader}.
*/
+@Deprecated
public abstract class MaterialAdapter {
private final Map paramsMapping = new HashMap<>();
diff --git a/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/PBREmissiveStrengthExtensionLoader.java b/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/PBREmissiveStrengthExtensionLoader.java
index 3ad3c59d88..a29691a669 100644
--- a/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/PBREmissiveStrengthExtensionLoader.java
+++ b/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/PBREmissiveStrengthExtensionLoader.java
@@ -54,6 +54,7 @@ public class PBREmissiveStrengthExtensionLoader implements ExtensionLoader {
private static final Logger logger = Logger.getLogger(PBREmissiveStrengthExtensionLoader.class.getName());
+ @Deprecated
private PBREmissiveStrengthMaterialAdapter materialAdapter = new PBREmissiveStrengthMaterialAdapter();
@Override
@@ -75,6 +76,7 @@ public Object handleExtension(GltfLoader loader, String parentName, JsonElement
return input;
}
+ @Deprecated
private Object handleExtensionForMaterialAdapter(GltfLoader loader, String parentName, JsonElement parent, JsonElement extension, Object input) throws IOException {
MaterialAdapter adapter = materialAdapter;
AssetKey key = loader.getInfo().getKey();
diff --git a/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/PBREmissiveStrengthMaterialAdapter.java b/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/PBREmissiveStrengthMaterialAdapter.java
index 5d078c97f7..59386c0a8b 100644
--- a/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/PBREmissiveStrengthMaterialAdapter.java
+++ b/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/PBREmissiveStrengthMaterialAdapter.java
@@ -35,7 +35,11 @@
* Adapter for converting GLTF emissive strength to JME emissive intensity.
*
* @author codex
+ *
+ * @deprecated This will be removed in a future version of the engine. To migrate,
+ * create a custom {@link GltfMaterialFactory} and register it with the {@link GltfLoader}.
*/
+@Deprecated
public class PBREmissiveStrengthMaterialAdapter extends PBRMaterialAdapter {
public PBREmissiveStrengthMaterialAdapter() {
diff --git a/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/PBRMaterialAdapter.java b/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/PBRMaterialAdapter.java
index 340cdb513b..6e73560548 100644
--- a/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/PBRMaterialAdapter.java
+++ b/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/PBRMaterialAdapter.java
@@ -37,7 +37,11 @@
* Adapts GLTF PBR materials to JME PBR materials.
*
* @author Nehon
+ *
+ * @deprecated This will be removed in a future version of the engine. To migrate,
+ * create a custom {@link GltfMaterialFactory} and register it with the {@link GltfLoader}.
*/
+@Deprecated
public abstract class PBRMaterialAdapter extends MaterialAdapter {
/**
diff --git a/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/PBRMetalRoughMaterialAdapter.java b/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/PBRMetalRoughMaterialAdapter.java
index fd744cffdd..c9c99c595f 100644
--- a/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/PBRMetalRoughMaterialAdapter.java
+++ b/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/PBRMetalRoughMaterialAdapter.java
@@ -33,7 +33,11 @@
/**
* Created by Nehon on 20/08/2017.
+ *
+ * @deprecated This will be removed in a future version of the engine. To migrate,
+ * create a custom {@link GltfMaterialFactory} and register it with the {@link GltfLoader}.
*/
+@Deprecated
public class PBRMetalRoughMaterialAdapter extends PBRMaterialAdapter {
public PBRMetalRoughMaterialAdapter() {
diff --git a/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/PBRSpecGlossExtensionLoader.java b/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/PBRSpecGlossExtensionLoader.java
index 395982fd8e..984e649fb4 100644
--- a/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/PBRSpecGlossExtensionLoader.java
+++ b/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/PBRSpecGlossExtensionLoader.java
@@ -63,6 +63,7 @@ public class PBRSpecGlossExtensionLoader implements ExtensionLoader {
private static final Logger logger = Logger.getLogger(PBRSpecGlossExtensionLoader.class.getName());
+ @Deprecated
private PBRSpecGlossMaterialAdapter materialAdapter = new PBRSpecGlossMaterialAdapter();
@Override
@@ -88,6 +89,7 @@ public Object handleExtension(GltfLoader loader, String parentName, JsonElement
return input;
}
+ @Deprecated
private Object handleExtensionForMaterialAdapter(GltfLoader loader, String parentName, JsonElement parent, JsonElement extension, Object input) throws IOException {
MaterialAdapter adapter = materialAdapter;
AssetKey key = loader.getInfo().getKey();
diff --git a/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/PBRSpecGlossMaterialAdapter.java b/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/PBRSpecGlossMaterialAdapter.java
index bd4c25c8af..df74552ea6 100644
--- a/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/PBRSpecGlossMaterialAdapter.java
+++ b/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/PBRSpecGlossMaterialAdapter.java
@@ -35,7 +35,11 @@
/**
* Created by Nehon on 20/08/2017.
+ *
+ * @deprecated This will be removed in a future version of the engine. To migrate,
+ * create a custom {@link GltfMaterialFactory} and register it with the {@link GltfLoader}.
*/
+@Deprecated
public class PBRSpecGlossMaterialAdapter extends PBRMaterialAdapter {
public PBRSpecGlossMaterialAdapter() {
diff --git a/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/UnlitExtensionLoader.java b/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/UnlitExtensionLoader.java
index 0ec82c6aed..a95eda8960 100644
--- a/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/UnlitExtensionLoader.java
+++ b/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/UnlitExtensionLoader.java
@@ -46,6 +46,7 @@ public class UnlitExtensionLoader implements ExtensionLoader {
private static final Logger logger = Logger.getLogger(UnlitExtensionLoader.class.getName());
+ @Deprecated
private final UnlitMaterialAdapter materialAdapter = new UnlitMaterialAdapter();
@Override
@@ -64,6 +65,7 @@ public Object handleExtension(GltfLoader loader, String parentName, JsonElement
return input;
}
+ @Deprecated
private Object handleExtensionForMaterialAdapter(GltfLoader loader, String parentName, JsonElement parent, JsonElement extension, Object input) {
MaterialAdapter adapter = materialAdapter;
AssetKey key = loader.getInfo().getKey();
diff --git a/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/UnlitMaterialAdapter.java b/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/UnlitMaterialAdapter.java
index 65acdf7f2b..9b32dc8fce 100644
--- a/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/UnlitMaterialAdapter.java
+++ b/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/UnlitMaterialAdapter.java
@@ -37,7 +37,11 @@
/**
* @author Markil 3
+ *
+ * @deprecated This will be removed in a future version of the engine. To migrate,
+ * create a custom {@link GltfMaterialFactory} and register it with the {@link GltfLoader}.
*/
+@Deprecated
public class UnlitMaterialAdapter extends MaterialAdapter {
public UnlitMaterialAdapter() {
From 13ad8ba5df51120280f48165f3dd227add898cae Mon Sep 17 00:00:00 2001
From: theMinka
Date: Sat, 25 Apr 2026 18:16:20 +0200
Subject: [PATCH 08/10] Fixed vertex color flag in GltfLoader
---
.../jme3/scene/plugins/gltf/GltfLoader.java | 9 +++-----
.../scene/plugins/gltf/GltfMaterialData.java | 22 +++++++++++++++++++
.../gltf/PBRLightingMaterialFactory.java | 2 ++
.../plugins/gltf/UnshadedMaterialFactory.java | 2 ++
4 files changed, 29 insertions(+), 6 deletions(-)
diff --git a/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/GltfLoader.java b/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/GltfLoader.java
index 69596e7f6a..ed8dca5d32 100644
--- a/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/GltfLoader.java
+++ b/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/GltfLoader.java
@@ -535,7 +535,7 @@ public Geometry[] readMeshPrimitives(int meshIndex) throws IOException {
geom.setMaterial(defaultMat);
} else {
useNormalsFlag = false;
- geom.setMaterial(readMaterial(materialIndex));
+ geom.setMaterial(readMaterial(materialIndex, useVertexColors));
if (geom.getMaterial().getAdditionalRenderState()
.getBlendMode() == RenderState.BlendMode.Alpha) {
// Alpha blending is enabled for this material. Let's place the geom in the
@@ -549,10 +549,6 @@ public Geometry[] readMeshPrimitives(int meshIndex) throws IOException {
}
}
- if (useVertexColors) {
- geom.getMaterial().setBoolean("UseVertexColor", useVertexColors);
- }
-
geom.setName(name + "_" + index);
geom.updateModelBound();
@@ -811,7 +807,7 @@ protected ByteBuffer getBytes(int bufferIndex, String uri, Integer bufferLength)
return data;
}
- public Material readMaterial(int materialIndex) throws IOException {
+ public Material readMaterial(int materialIndex, boolean usesVertexColors) throws IOException {
// Fallback to the old material adapter system, if the legacy flag is set.
if (GltfUtils.isMaterialAdaptersEnabled(info)) {
return readMaterialUsingMaterialAdapters(materialIndex);
@@ -821,6 +817,7 @@ public Material readMaterial(int materialIndex) throws IOException {
JsonObject materialJson = materials.get(materialIndex).getAsJsonObject();
GltfMaterialData gltfMaterialData = readStandardMaterialParameters(materialJson);
+ gltfMaterialData.setHasVertexColors(usesVertexColors);
gltfMaterialData = customContentManager.readExtensionAndExtras("material", materialJson, gltfMaterialData);
return createMaterial(gltfMaterialData, materialIndex);
}
diff --git a/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/GltfMaterialData.java b/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/GltfMaterialData.java
index cac559e900..989a612318 100644
--- a/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/GltfMaterialData.java
+++ b/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/GltfMaterialData.java
@@ -101,6 +101,11 @@ public class GltfMaterialData {
private Set gltfExtensions = new HashSet<>();
+ /**
+ * Indicates the existence of a vertex color buffer.
+ */
+ private boolean hasVertexColors;
+
/**
* Checks if the material provides the given GLTF extension.
@@ -173,4 +178,21 @@ public Object removeGltfParam(String gltfParamName) {
return gltfParamMap.remove(gltfParamName);
}
+
+ /**
+ * @return Indicates the existence of a vertex color buffer.
+ */
+ public boolean hasVertexColors() {
+ return hasVertexColors;
+ }
+
+ /**
+ * Sets the vertex color flag.
+ *
+ * @param hasVertexColors The value to set.
+ */
+ public void setHasVertexColors(boolean hasVertexColors) {
+ this.hasVertexColors = hasVertexColors;
+ }
+
}
diff --git a/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/PBRLightingMaterialFactory.java b/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/PBRLightingMaterialFactory.java
index 07d0f47f7b..fbde3c53e8 100644
--- a/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/PBRLightingMaterialFactory.java
+++ b/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/PBRLightingMaterialFactory.java
@@ -122,6 +122,8 @@ protected void setStandardParams(Material material, GltfMaterialData gltfMateria
material.getAdditionalRenderState().setFaceCullMode(RenderState.FaceCullMode.Off);
}
}
+
+ setParam(material, "UseVertexColor", gltfMaterialData.hasVertexColors());
}
protected void setMetallicRoughnessParams(Material material, GltfMaterialData gltfMaterialData) {
diff --git a/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/UnshadedMaterialFactory.java b/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/UnshadedMaterialFactory.java
index 58443a95ec..7dd384a9f2 100644
--- a/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/UnshadedMaterialFactory.java
+++ b/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/UnshadedMaterialFactory.java
@@ -80,6 +80,8 @@ public Material createMaterial(AssetManager assetManager, AssetKey> assetKey,
}
}
+ setParam(material, "VertexColor", gltfMaterialData.hasVertexColors());
+
return material;
}
From 58410b626d2fa290a32ac981c649e83a328250b0 Mon Sep 17 00:00:00 2001
From: theMinka
Date: Sat, 25 Apr 2026 19:03:21 +0200
Subject: [PATCH 09/10] Fixed QueueBucket for BlendMode.AlphaAdditive in
GltfLoader
---
.../gltf/java/com/jme3/scene/plugins/gltf/GltfLoader.java | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/GltfLoader.java b/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/GltfLoader.java
index ed8dca5d32..d011925e75 100644
--- a/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/GltfLoader.java
+++ b/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/GltfLoader.java
@@ -84,6 +84,7 @@
import com.jme3.asset.TextureKey;
import com.jme3.material.Material;
import com.jme3.material.RenderState;
+import com.jme3.material.RenderState.BlendMode;
import com.jme3.math.ColorRGBA;
import com.jme3.math.FastMath;
import com.jme3.math.Matrix4f;
@@ -535,9 +536,10 @@ public Geometry[] readMeshPrimitives(int meshIndex) throws IOException {
geom.setMaterial(defaultMat);
} else {
useNormalsFlag = false;
- geom.setMaterial(readMaterial(materialIndex, useVertexColors));
- if (geom.getMaterial().getAdditionalRenderState()
- .getBlendMode() == RenderState.BlendMode.Alpha) {
+ Material material = readMaterial(materialIndex, useVertexColors);
+ geom.setMaterial(material);
+ BlendMode blendMode = material.getAdditionalRenderState().getBlendMode();
+ if (blendMode == BlendMode.Alpha || blendMode == BlendMode.AlphaAdditive) {
// Alpha blending is enabled for this material. Let's place the geom in the
// transparent bucket.
geom.setQueueBucket(RenderQueue.Bucket.Transparent);
From 2921b830b686247f3a43fbac7c120d510218bf43 Mon Sep 17 00:00:00 2001
From: theMinka
Date: Tue, 28 Apr 2026 11:20:25 +0200
Subject: [PATCH 10/10] Fixed typo in emissive constants in GltfMaterialData
---
.../gltf/java/com/jme3/scene/plugins/gltf/GltfLoader.java | 5 ++---
.../java/com/jme3/scene/plugins/gltf/GltfMaterialData.java | 4 ++--
.../jme3/scene/plugins/gltf/PBRLightingMaterialFactory.java | 4 ++--
.../com/jme3/scene/plugins/gltf/UnshadedMaterialFactory.java | 4 ++--
4 files changed, 8 insertions(+), 9 deletions(-)
diff --git a/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/GltfLoader.java b/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/GltfLoader.java
index d011925e75..211ad735dd 100644
--- a/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/GltfLoader.java
+++ b/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/GltfLoader.java
@@ -83,7 +83,6 @@
import com.jme3.asset.AssetLoader;
import com.jme3.asset.TextureKey;
import com.jme3.material.Material;
-import com.jme3.material.RenderState;
import com.jme3.material.RenderState.BlendMode;
import com.jme3.math.ColorRGBA;
import com.jme3.math.FastMath;
@@ -850,8 +849,8 @@ protected GltfMaterialData readStandardMaterialParameters(JsonObject materialJso
gltfMaterialData.setGltfParam(OCCLUSION_TEXTURE_STRENGTH_PARAM, getAsFloat(occlusionTextureJson, "strength"));
}
- gltfMaterialData.setGltfParam(EMISSIV_TEXTURE_PARAM, getAsTexture2D(materialJson, "emissiveTexture"));
- gltfMaterialData.setGltfParam(EMISSIV_COLOR_PARAM, getAsColor(materialJson, "emissiveFactor"));
+ gltfMaterialData.setGltfParam(EMISSIVE_TEXTURE_PARAM, getAsTexture2D(materialJson, "emissiveTexture"));
+ gltfMaterialData.setGltfParam(EMISSIVE_COLOR_PARAM, getAsColor(materialJson, "emissiveFactor"));
String alphaMode = getAsString(materialJson, "alphaMode");
gltfMaterialData.setGltfParam(ALPHA_MODE_PARAM, alphaMode);
diff --git a/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/GltfMaterialData.java b/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/GltfMaterialData.java
index 989a612318..490bc2973f 100644
--- a/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/GltfMaterialData.java
+++ b/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/GltfMaterialData.java
@@ -82,9 +82,9 @@ public class GltfMaterialData {
public static final String OCCLUSION_TEXTURE_STRENGTH_PARAM = "material.occlusionTextureInfo.strength";
- public static final String EMISSIV_TEXTURE_PARAM = "material.emissiveTexture";
+ public static final String EMISSIVE_TEXTURE_PARAM = "material.emissiveTexture";
- public static final String EMISSIV_COLOR_PARAM = "material.emissiveFactor";
+ public static final String EMISSIVE_COLOR_PARAM = "material.emissiveFactor";
public static final String ALPHA_MODE_PARAM = "material.alphaMode";
diff --git a/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/PBRLightingMaterialFactory.java b/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/PBRLightingMaterialFactory.java
index fbde3c53e8..5dcf6761c2 100644
--- a/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/PBRLightingMaterialFactory.java
+++ b/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/PBRLightingMaterialFactory.java
@@ -98,8 +98,8 @@ protected void setStandardParams(Material material, GltfMaterialData gltfMateria
material.setBoolean("AoPackedInMRMap", isAoPackedInMRMap);
}
- setParam(material, "EmissiveMap", gltfMaterialData.getGltfParam(EMISSIV_TEXTURE_PARAM));
- setParam(material, "Emissive", gltfMaterialData.getGltfParam(EMISSIV_COLOR_PARAM), ColorRGBA.Black);
+ setParam(material, "EmissiveMap", gltfMaterialData.getGltfParam(EMISSIVE_TEXTURE_PARAM));
+ setParam(material, "Emissive", gltfMaterialData.getGltfParam(EMISSIVE_COLOR_PARAM), ColorRGBA.Black);
setParam(material, "EmissiveIntensity", gltfMaterialData.getGltfParam(EMISSIVE_STRENGTH_PARAM));
if (gltfMaterialData.containsGltfParam(ALPHA_MODE_PARAM)) {
diff --git a/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/UnshadedMaterialFactory.java b/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/UnshadedMaterialFactory.java
index 7dd384a9f2..0d89573392 100644
--- a/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/UnshadedMaterialFactory.java
+++ b/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/UnshadedMaterialFactory.java
@@ -56,8 +56,8 @@ public Material createMaterial(AssetManager assetManager, AssetKey> assetKey,
setParam(material, "Color", gltfMaterialData.getGltfParam(BASE_COLOR_PARAM), ColorRGBA.White);
setParam(material, "ColorMap", gltfMaterialData.getGltfParam(BASE_COLOR_TEXTURE_PARAM));
- setParam(material, "GlowColor", gltfMaterialData.getGltfParam(EMISSIV_COLOR_PARAM), ColorRGBA.Black);
- setParam(material, "GlowMap", gltfMaterialData.getGltfParam(EMISSIV_TEXTURE_PARAM));
+ setParam(material, "GlowColor", gltfMaterialData.getGltfParam(EMISSIVE_COLOR_PARAM), ColorRGBA.Black);
+ setParam(material, "GlowMap", gltfMaterialData.getGltfParam(EMISSIVE_TEXTURE_PARAM));
if (gltfMaterialData.containsGltfParam(ALPHA_MODE_PARAM)) {
String alphaMode = (String) gltfMaterialData.getGltfParam(ALPHA_MODE_PARAM);