Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@ private <T> 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);
}
Expand Down
138 changes: 128 additions & 10 deletions jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/GltfLoader.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -82,7 +83,7 @@
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;
import com.jme3.math.Matrix4f;
Expand All @@ -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;

/**
Expand Down Expand Up @@ -143,13 +145,20 @@ 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<String, MaterialAdapter> defaultMaterialAdapters = new HashMap<>();
@Deprecated private final Map<String, MaterialAdapter> defaultMaterialAdapters = new HashMap<>();
private final CustomContentManager customContentManager = new CustomContentManager();
private boolean useNormalsFlag = false;

Map<SkinData, List<Spatial>> skinnedSpatials = new HashMap<>();
private final IntMap<SkinBuffers> skinBuffers = new IntMap<>();

private static SafeArrayList<GltfMaterialFactory> materialFactoryList = new SafeArrayList<>(GltfMaterialFactory.class);

static {
materialFactoryList.add(new UnshadedMaterialFactory());
materialFactoryList.add(new PBRLightingMaterialFactory());
}

public GltfLoader() {
defaultMaterialAdapters.put("pbrMetallicRoughness", new PBRMetalRoughMaterialAdapter());
}
Expand Down Expand Up @@ -526,9 +535,10 @@ public Geometry[] readMeshPrimitives(int meshIndex) throws IOException {
geom.setMaterial(defaultMat);
} else {
useNormalsFlag = false;
geom.setMaterial(readMaterial(materialIndex));
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);
Expand All @@ -540,10 +550,6 @@ public Geometry[] readMeshPrimitives(int meshIndex) throws IOException {
}
}

if (useVertexColors) {
geom.getMaterial().setBoolean("UseVertexColor", useVertexColors);
}

geom.setName(name + "_" + index);

geom.updateModelBound();
Expand Down Expand Up @@ -802,7 +808,75 @@ 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);
}

assertNotNull(materials, "There is no material defined yet a mesh references one");
JsonObject materialJson = materials.get(materialIndex).getAsJsonObject();

GltfMaterialData gltfMaterialData = readStandardMaterialParameters(materialJson);
gltfMaterialData.setHasVertexColors(usesVertexColors);
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"));
gltfMaterialData.setGltfParam(BASE_COLOR_TEXTURE_PARAM, getAsTexture2D(pbrMetallicRoughnessJson, "baseColorTexture"));
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"));
}

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(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);
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;
}

@Deprecated
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();
Expand Down Expand Up @@ -922,6 +996,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);
}
Expand Down Expand Up @@ -1715,4 +1793,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.<br/>
* 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.<br/>
* 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();
}
}
Loading