Added support for extensions, implemented PBR spec gloss extension
This commit is contained in:
parent
e9869e5298
commit
f14acf305b
@ -55,8 +55,15 @@ varying vec3 wPosition;
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef SPECGLOSSPIPELINE
|
#ifdef SPECGLOSSPIPELINE
|
||||||
uniform sampler2D m_SpecularMap;
|
|
||||||
uniform sampler2D m_GlossMap;
|
uniform vec4 m_Specular;
|
||||||
|
uniform float m_Glossiness;
|
||||||
|
#ifdef USE_PACKED_SG
|
||||||
|
uniform sampler2D m_SpecularGlossinessMap;
|
||||||
|
#else
|
||||||
|
uniform sampler2D m_SpecularMap;
|
||||||
|
uniform sampler2D m_GlossinessMap;
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef PARALLAXMAP
|
#ifdef PARALLAXMAP
|
||||||
@ -160,9 +167,26 @@ void main(){
|
|||||||
|
|
||||||
float specular = 0.5;
|
float specular = 0.5;
|
||||||
#ifdef SPECGLOSSPIPELINE
|
#ifdef SPECGLOSSPIPELINE
|
||||||
vec4 specularColor = texture2D(m_SpecularMap, newTexCoord);
|
|
||||||
vec4 diffuseColor = albedo;
|
#ifdef USE_PACKED_SG
|
||||||
Roughness = 1.0 - texture2D(m_GlossMap, newTexCoord).r;
|
vec4 specularColor = texture2D(m_SpecularGlossinessMap, newTexCoord);
|
||||||
|
float glossiness = specularColor.a * m_Glossiness;
|
||||||
|
specularColor *= m_Specular;
|
||||||
|
#else
|
||||||
|
#ifdef SPECULARMAP
|
||||||
|
vec4 specularColor = texture2D(m_SpecularMap, newTexCoord);
|
||||||
|
#else
|
||||||
|
vec4 specularColor = vec4(1.0);
|
||||||
|
#endif
|
||||||
|
#ifdef GLOSSINESSMAP
|
||||||
|
float glossiness = texture2D(m_GlossinesMap, newTexCoord).r * m_Glossiness;
|
||||||
|
#else
|
||||||
|
float glossiness = m_Glossiness;
|
||||||
|
#endif
|
||||||
|
specularColor *= m_Specular;
|
||||||
|
#endif
|
||||||
|
vec4 diffuseColor = albedo * (1.0 - max(max(specularColor.r, specularColor.g), specularColor.b));
|
||||||
|
Roughness = 1.0 - glossiness;
|
||||||
#else
|
#else
|
||||||
float nonMetalSpec = 0.08 * specular;
|
float nonMetalSpec = 0.08 * specular;
|
||||||
vec4 specularColor = (nonMetalSpec - nonMetalSpec * Metallic) + albedo * Metallic;
|
vec4 specularColor = (nonMetalSpec - nonMetalSpec * Metallic) + albedo * Metallic;
|
||||||
|
@ -40,8 +40,12 @@ MaterialDef PBR Lighting {
|
|||||||
Float NormalType : -1.0
|
Float NormalType : -1.0
|
||||||
|
|
||||||
// For Spec gloss pipeline
|
// For Spec gloss pipeline
|
||||||
|
Boolean UseSpecGloss
|
||||||
Texture2D SpecularMap
|
Texture2D SpecularMap
|
||||||
Texture2D GlossMap
|
Texture2D GlossinessMap
|
||||||
|
Texture2D SpecularGlossinessMap
|
||||||
|
Color Specular : 1.0 1.0 1.0 1.0
|
||||||
|
Float Glossiness : 1.0
|
||||||
|
|
||||||
Vector4 ProbeData
|
Vector4 ProbeData
|
||||||
|
|
||||||
@ -135,7 +139,7 @@ MaterialDef PBR Lighting {
|
|||||||
ROUGHNESSMAP : RoughnessMap
|
ROUGHNESSMAP : RoughnessMap
|
||||||
EMISSIVEMAP : EmissiveMap
|
EMISSIVEMAP : EmissiveMap
|
||||||
EMISSIVE : Emissive
|
EMISSIVE : Emissive
|
||||||
SPECGLOSSPIPELINE : SpecularMap
|
SPECGLOSSPIPELINE : UseSpecGloss
|
||||||
PARALLAXMAP : ParallaxMap
|
PARALLAXMAP : ParallaxMap
|
||||||
NORMALMAP_PARALLAX : PackedNormalParallax
|
NORMALMAP_PARALLAX : PackedNormalParallax
|
||||||
STEEP_PARALLAX : SteepParallax
|
STEEP_PARALLAX : SteepParallax
|
||||||
@ -145,6 +149,9 @@ MaterialDef PBR Lighting {
|
|||||||
NUM_BONES : NumberOfBones
|
NUM_BONES : NumberOfBones
|
||||||
INSTANCING : UseInstancing
|
INSTANCING : UseInstancing
|
||||||
USE_PACKED_MR: MetallicRoughnessMap
|
USE_PACKED_MR: MetallicRoughnessMap
|
||||||
|
USE_PACKED_SG: SpecularGlossinessMap
|
||||||
|
SPECULARMAP : SpecularMap
|
||||||
|
GLOSSINESSMAP : GlossinessMap
|
||||||
NORMAL_TYPE: NormalType
|
NORMAL_TYPE: NormalType
|
||||||
VERTEX_COLOR : UseVertexColor
|
VERTEX_COLOR : UseVertexColor
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,89 @@
|
|||||||
|
package com.jme3.scene.plugins.gltf;
|
||||||
|
|
||||||
|
import com.google.gson.JsonArray;
|
||||||
|
import com.google.gson.JsonElement;
|
||||||
|
import com.jme3.asset.AssetLoadException;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Nehon on 20/08/2017.
|
||||||
|
*/
|
||||||
|
public class CustomContentManager {
|
||||||
|
|
||||||
|
private final static Logger logger = Logger.getLogger(CustomContentManager.class.getName());
|
||||||
|
|
||||||
|
private GltfModelKey key;
|
||||||
|
private GltfLoader gltfLoader;
|
||||||
|
|
||||||
|
private static Map<String, ExtensionLoader> defaultExtensionLoaders = new HashMap<>();
|
||||||
|
|
||||||
|
static {
|
||||||
|
defaultExtensionLoaders.put("KHR_materials_pbrSpecularGlossiness", new PBRSpecGlossExtensionLoader());
|
||||||
|
}
|
||||||
|
|
||||||
|
void init(GltfLoader gltfLoader) {
|
||||||
|
this.gltfLoader = gltfLoader;
|
||||||
|
|
||||||
|
if (gltfLoader.getInfo().getKey() instanceof GltfModelKey) {
|
||||||
|
this.key = (GltfModelKey) gltfLoader.getInfo().getKey();
|
||||||
|
}
|
||||||
|
|
||||||
|
JsonArray extensionUsed = gltfLoader.getDocRoot().getAsJsonArray("extensionsUsed");
|
||||||
|
if (extensionUsed != null) {
|
||||||
|
for (JsonElement extElem : extensionUsed) {
|
||||||
|
String ext = extElem.getAsString();
|
||||||
|
if (ext != null) {
|
||||||
|
if (defaultExtensionLoaders.get(ext) == null && (this.key != null && this.key.getExtensionLoader(ext) == null)) {
|
||||||
|
logger.log(Level.WARNING, "Extension " + ext + " is not supported, please provide your own implementation in the GltfModelKey");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
JsonArray extensionRequired = gltfLoader.getDocRoot().getAsJsonArray("extensionsRequired");
|
||||||
|
if (extensionRequired != null) {
|
||||||
|
for (JsonElement extElem : extensionRequired) {
|
||||||
|
String ext = extElem.getAsString();
|
||||||
|
if (ext != null) {
|
||||||
|
if (defaultExtensionLoaders.get(ext) == null && (this.key != null && this.key.getExtensionLoader(ext) == null)) {
|
||||||
|
logger.log(Level.SEVERE, "Extension " + ext + " is mandatory for this file, the loaded scene result will be unexpected.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T> T readExtension(JsonElement el, T input) throws AssetLoadException {
|
||||||
|
JsonElement extensions = el.getAsJsonObject().getAsJsonObject("extensions");
|
||||||
|
if (extensions == null) {
|
||||||
|
return input;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Map.Entry<String, JsonElement> ext : extensions.getAsJsonObject().entrySet()) {
|
||||||
|
ExtensionLoader loader = null;
|
||||||
|
if (key != null) {
|
||||||
|
loader = key.getExtensionLoader(ext.getKey());
|
||||||
|
}
|
||||||
|
if (loader == null) {
|
||||||
|
loader = defaultExtensionLoaders.get(ext.getKey());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (loader == null) {
|
||||||
|
logger.log(Level.WARNING, "Could not find loader for extension " + ext.getKey());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
return (T) loader.handleExtension(gltfLoader, 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return input;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,12 @@
|
|||||||
|
package com.jme3.scene.plugins.gltf;
|
||||||
|
|
||||||
|
import com.google.gson.JsonElement;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Nehon on 20/08/2017.
|
||||||
|
*/
|
||||||
|
public interface ExtensionLoader {
|
||||||
|
|
||||||
|
Object handleExtension(GltfLoader loader, JsonElement parent, JsonElement extension, Object input);
|
||||||
|
|
||||||
|
}
|
@ -48,12 +48,15 @@ public class GltfLoader implements AssetLoader {
|
|||||||
|
|
||||||
private Material defaultMat;
|
private Material defaultMat;
|
||||||
private AssetInfo info;
|
private AssetInfo info;
|
||||||
|
private JsonObject docRoot;
|
||||||
|
private Node rootNode;
|
||||||
|
|
||||||
private FloatArrayPopulator floatArrayPopulator = new FloatArrayPopulator();
|
private FloatArrayPopulator floatArrayPopulator = new FloatArrayPopulator();
|
||||||
private Vector3fArrayPopulator vector3fArrayPopulator = new Vector3fArrayPopulator();
|
private Vector3fArrayPopulator vector3fArrayPopulator = new Vector3fArrayPopulator();
|
||||||
private QuaternionArrayPopulator quaternionArrayPopulator = new QuaternionArrayPopulator();
|
private QuaternionArrayPopulator quaternionArrayPopulator = new QuaternionArrayPopulator();
|
||||||
private Matrix4fArrayPopulator matrix4fArrayPopulator = new Matrix4fArrayPopulator();
|
private Matrix4fArrayPopulator matrix4fArrayPopulator = new Matrix4fArrayPopulator();
|
||||||
private static Map<String, MaterialAdapter> defaultMaterialAdapters = new HashMap<>();
|
private static Map<String, MaterialAdapter> defaultMaterialAdapters = new HashMap<>();
|
||||||
|
private CustomContentManager customContentManager = new CustomContentManager();
|
||||||
private boolean useNormalsFlag = false;
|
private boolean useNormalsFlag = false;
|
||||||
private Quaternion tmpQuat = new Quaternion();
|
private Quaternion tmpQuat = new Quaternion();
|
||||||
private Transform tmpTransforms = new Transform();
|
private Transform tmpTransforms = new Transform();
|
||||||
@ -64,7 +67,7 @@ public class GltfLoader implements AssetLoader {
|
|||||||
IntMap<SkinBuffers> skinBuffers = new IntMap<>();
|
IntMap<SkinBuffers> skinBuffers = new IntMap<>();
|
||||||
|
|
||||||
static {
|
static {
|
||||||
defaultMaterialAdapters.put("pbrMetallicRoughness", new PBRMaterialAdapter());
|
defaultMaterialAdapters.put("pbrMetallicRoughness", new PBRMetalRoughMaterialAdapter());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -72,6 +75,7 @@ public class GltfLoader implements AssetLoader {
|
|||||||
try {
|
try {
|
||||||
dataCache.clear();
|
dataCache.clear();
|
||||||
info = assetInfo;
|
info = assetInfo;
|
||||||
|
rootNode = new Node();
|
||||||
|
|
||||||
if (defaultMat == null) {
|
if (defaultMat == null) {
|
||||||
defaultMat = new Material(assetInfo.getManager(), "Common/MatDefs/Light/PBRLighting.j3md");
|
defaultMat = new Material(assetInfo.getManager(), "Common/MatDefs/Light/PBRLighting.j3md");
|
||||||
@ -80,9 +84,9 @@ public class GltfLoader implements AssetLoader {
|
|||||||
defaultMat.setFloat("Roughness", 1f);
|
defaultMat.setFloat("Roughness", 1f);
|
||||||
}
|
}
|
||||||
|
|
||||||
JsonObject root = new JsonParser().parse(new JsonReader(new InputStreamReader(assetInfo.openStream()))).getAsJsonObject();
|
docRoot = new JsonParser().parse(new JsonReader(new InputStreamReader(assetInfo.openStream()))).getAsJsonObject();
|
||||||
|
|
||||||
JsonObject asset = root.getAsJsonObject().get("asset").getAsJsonObject();
|
JsonObject asset = docRoot.getAsJsonObject().get("asset").getAsJsonObject();
|
||||||
String generator = getAsString(asset, "generator");
|
String generator = getAsString(asset, "generator");
|
||||||
String version = getAsString(asset, "version");
|
String version = getAsString(asset, "version");
|
||||||
String minVersion = getAsString(asset, "minVersion");
|
String minVersion = getAsString(asset, "minVersion");
|
||||||
@ -91,51 +95,62 @@ public class GltfLoader implements AssetLoader {
|
|||||||
throw new AssetLoadException("Gltf Loader doesn't support this gltf version: " + version + (minVersion != null ? ("/" + minVersion) : ""));
|
throw new AssetLoadException("Gltf Loader doesn't support this gltf version: " + version + (minVersion != null ? ("/" + minVersion) : ""));
|
||||||
}
|
}
|
||||||
|
|
||||||
scenes = root.getAsJsonArray("scenes");
|
scenes = docRoot.getAsJsonArray("scenes");
|
||||||
nodes = root.getAsJsonArray("nodes");
|
nodes = docRoot.getAsJsonArray("nodes");
|
||||||
meshes = root.getAsJsonArray("meshes");
|
meshes = docRoot.getAsJsonArray("meshes");
|
||||||
accessors = root.getAsJsonArray("accessors");
|
accessors = docRoot.getAsJsonArray("accessors");
|
||||||
bufferViews = root.getAsJsonArray("bufferViews");
|
bufferViews = docRoot.getAsJsonArray("bufferViews");
|
||||||
buffers = root.getAsJsonArray("buffers");
|
buffers = docRoot.getAsJsonArray("buffers");
|
||||||
materials = root.getAsJsonArray("materials");
|
materials = docRoot.getAsJsonArray("materials");
|
||||||
textures = root.getAsJsonArray("textures");
|
textures = docRoot.getAsJsonArray("textures");
|
||||||
images = root.getAsJsonArray("images");
|
images = docRoot.getAsJsonArray("images");
|
||||||
samplers = root.getAsJsonArray("samplers");
|
samplers = docRoot.getAsJsonArray("samplers");
|
||||||
animations = root.getAsJsonArray("animations");
|
animations = docRoot.getAsJsonArray("animations");
|
||||||
skins = root.getAsJsonArray("skins");
|
skins = docRoot.getAsJsonArray("skins");
|
||||||
|
|
||||||
|
|
||||||
|
customContentManager.init(this);
|
||||||
|
|
||||||
readSkins();
|
readSkins();
|
||||||
|
|
||||||
JsonPrimitive defaultScene = root.getAsJsonPrimitive("scene");
|
JsonPrimitive defaultScene = docRoot.getAsJsonPrimitive("scene");
|
||||||
|
|
||||||
Node n = readScenes(defaultScene);
|
readScenes(defaultScene, rootNode);
|
||||||
|
|
||||||
|
rootNode = customContentManager.readExtension(docRoot, rootNode);
|
||||||
|
|
||||||
setupControls();
|
setupControls();
|
||||||
|
|
||||||
//only one scene let's not return the root.
|
//only one scene let's not return the root.
|
||||||
if (n.getChildren().size() == 1) {
|
if (rootNode.getChildren().size() == 1) {
|
||||||
n = (Node) n.getChild(0);
|
rootNode = (Node) rootNode.getChild(0);
|
||||||
}
|
}
|
||||||
//no name for the scene... let's set the file name.
|
//no name for the scene... let's set the file name.
|
||||||
if (n.getName() == null) {
|
if (rootNode.getName() == null) {
|
||||||
n.setName(assetInfo.getKey().getName());
|
rootNode.setName(assetInfo.getKey().getName());
|
||||||
}
|
}
|
||||||
return n;
|
return rootNode;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new AssetLoadException("An error occurred loading " + assetInfo.getKey().getName(), e);
|
throw new AssetLoadException("An error occurred loading " + assetInfo.getKey().getName(), e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void setDefaultParams(Material mat) {
|
||||||
|
mat.setColor("BaseColor", ColorRGBA.White);
|
||||||
|
mat.setFloat("Metallic", 0f);
|
||||||
|
mat.setFloat("Roughness", 1f);
|
||||||
|
}
|
||||||
|
|
||||||
private boolean isSupported(String version, String minVersion) {
|
private boolean isSupported(String version, String minVersion) {
|
||||||
return "2.0".equals(version);
|
return "2.0".equals(version);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Node readScenes(JsonPrimitive defaultScene) throws IOException {
|
public void readScenes(JsonPrimitive defaultScene, Node rootNode) throws IOException {
|
||||||
if (scenes == null) {
|
if (scenes == null) {
|
||||||
//no scene... lets handle this later...
|
//no scene... lets handle this later...
|
||||||
throw new AssetLoadException("Gltf files with no scene is not yet supported");
|
throw new AssetLoadException("Gltf files with no scene is not yet supported");
|
||||||
}
|
}
|
||||||
Node root = new Node();
|
|
||||||
for (JsonElement scene : scenes) {
|
for (JsonElement scene : scenes) {
|
||||||
Node sceneNode = new Node();
|
Node sceneNode = new Node();
|
||||||
//specs says that only the default scene should be rendered,
|
//specs says that only the default scene should be rendered,
|
||||||
@ -144,10 +159,12 @@ public class GltfLoader implements AssetLoader {
|
|||||||
|
|
||||||
sceneNode.setName(getAsString(scene.getAsJsonObject(), "name"));
|
sceneNode.setName(getAsString(scene.getAsJsonObject(), "name"));
|
||||||
JsonArray sceneNodes = scene.getAsJsonObject().getAsJsonArray("nodes");
|
JsonArray sceneNodes = scene.getAsJsonObject().getAsJsonArray("nodes");
|
||||||
root.attachChild(sceneNode);
|
sceneNode = customContentManager.readExtension(scene, sceneNode);
|
||||||
|
rootNode.attachChild(sceneNode);
|
||||||
for (JsonElement node : sceneNodes) {
|
for (JsonElement node : sceneNodes) {
|
||||||
readChild(sceneNode, node);
|
readChild(sceneNode, node);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//Loading animations
|
//Loading animations
|
||||||
@ -162,11 +179,10 @@ public class GltfLoader implements AssetLoader {
|
|||||||
if (defaultScene != null) {
|
if (defaultScene != null) {
|
||||||
activeChild = defaultScene.getAsInt();
|
activeChild = defaultScene.getAsInt();
|
||||||
}
|
}
|
||||||
root.getChild(activeChild).setCullHint(Spatial.CullHint.Inherit);
|
rootNode.getChild(activeChild).setCullHint(Spatial.CullHint.Inherit);
|
||||||
return root;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Object readNode(int nodeIndex) throws IOException {
|
public Object readNode(int nodeIndex) throws IOException {
|
||||||
Object obj = fetchFromCache("nodes", nodeIndex, Object.class);
|
Object obj = fetchFromCache("nodes", nodeIndex, Object.class);
|
||||||
if (obj != null) {
|
if (obj != null) {
|
||||||
if (obj instanceof BoneWrapper) {
|
if (obj instanceof BoneWrapper) {
|
||||||
@ -222,6 +238,8 @@ public class GltfLoader implements AssetLoader {
|
|||||||
spatial.setName(getAsString(nodeData.getAsJsonObject(), "name"));
|
spatial.setName(getAsString(nodeData.getAsJsonObject(), "name"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
spatial = customContentManager.readExtension(nodeData, spatial);
|
||||||
|
|
||||||
addToCache("nodes", nodeIndex, spatial, nodes.size());
|
addToCache("nodes", nodeIndex, spatial, nodes.size());
|
||||||
return spatial;
|
return spatial;
|
||||||
}
|
}
|
||||||
@ -248,7 +266,7 @@ public class GltfLoader implements AssetLoader {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Transform readTransforms(JsonObject nodeData) {
|
public Transform readTransforms(JsonObject nodeData) {
|
||||||
Transform transform = new Transform();
|
Transform transform = new Transform();
|
||||||
JsonArray matrix = nodeData.getAsJsonArray("matrix");
|
JsonArray matrix = nodeData.getAsJsonArray("matrix");
|
||||||
if (matrix != null) {
|
if (matrix != null) {
|
||||||
@ -288,7 +306,7 @@ public class GltfLoader implements AssetLoader {
|
|||||||
return transform;
|
return transform;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Geometry[] readMeshPrimitives(int meshIndex) throws IOException {
|
public Geometry[] readMeshPrimitives(int meshIndex) throws IOException {
|
||||||
Geometry[] geomArray = (Geometry[]) fetchFromCache("meshes", meshIndex, Object.class);
|
Geometry[] geomArray = (Geometry[]) fetchFromCache("meshes", meshIndex, Object.class);
|
||||||
if (geomArray != null) {
|
if (geomArray != null) {
|
||||||
//cloning the geoms.
|
//cloning the geoms.
|
||||||
@ -355,6 +373,8 @@ public class GltfLoader implements AssetLoader {
|
|||||||
mesh.generateBindPose();
|
mesh.generateBindPose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mesh = customContentManager.readExtension(meshObject, mesh);
|
||||||
|
|
||||||
Geometry geom = new Geometry(null, mesh);
|
Geometry geom = new Geometry(null, mesh);
|
||||||
|
|
||||||
Integer materialIndex = getAsInteger(meshObject, "material");
|
Integer materialIndex = getAsInteger(meshObject, "material");
|
||||||
@ -384,21 +404,12 @@ public class GltfLoader implements AssetLoader {
|
|||||||
//TODO targets(morph anim...)
|
//TODO targets(morph anim...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
geomArray = customContentManager.readExtension(meshData, geomArray);
|
||||||
|
|
||||||
addToCache("meshes", meshIndex, geomArray, meshes.size());
|
addToCache("meshes", meshIndex, geomArray, meshes.size());
|
||||||
return geomArray;
|
return geomArray;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class WeightData {
|
|
||||||
float value;
|
|
||||||
short index;
|
|
||||||
int componentSize;
|
|
||||||
|
|
||||||
public WeightData(float value, short index, int componentSize) {
|
|
||||||
this.value = value;
|
|
||||||
this.index = index;
|
|
||||||
this.componentSize = componentSize;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private SkinBuffers getSkinBuffers(String bufferType) {
|
private SkinBuffers getSkinBuffers(String bufferType) {
|
||||||
int bufIndex = getIndex(bufferType);
|
int bufIndex = getIndex(bufferType);
|
||||||
@ -410,7 +421,7 @@ public class GltfLoader implements AssetLoader {
|
|||||||
return buffs;
|
return buffs;
|
||||||
}
|
}
|
||||||
|
|
||||||
private <R> R readAccessorData(int accessorIndex, Populator<R> populator) throws IOException {
|
public <R> R readAccessorData(int accessorIndex, Populator<R> populator) throws IOException {
|
||||||
|
|
||||||
assertNotNull(accessors, "No accessor attribute in the gltf file");
|
assertNotNull(accessors, "No accessor attribute in the gltf file");
|
||||||
|
|
||||||
@ -432,10 +443,12 @@ public class GltfLoader implements AssetLoader {
|
|||||||
//TODO extensions?
|
//TODO extensions?
|
||||||
//TODO extras?
|
//TODO extras?
|
||||||
|
|
||||||
return populator.populate(bufferViewIndex, componentType, type, count, byteOffset);
|
R data = populator.populate(bufferViewIndex, componentType, type, count, byteOffset);
|
||||||
|
data = customContentManager.readExtension(accessor, data);
|
||||||
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void readBuffer(Integer bufferViewIndex, int byteOffset, int bufferSize, Object store, int numComponents, int componentSize) throws IOException {
|
public void readBuffer(Integer bufferViewIndex, int byteOffset, int bufferSize, Object store, int numComponents, int componentSize) throws IOException {
|
||||||
|
|
||||||
JsonObject bufferView = bufferViews.get(bufferViewIndex).getAsJsonObject();
|
JsonObject bufferView = bufferViews.get(bufferViewIndex).getAsJsonObject();
|
||||||
Integer bufferIndex = getAsInteger(bufferView, "buffer");
|
Integer bufferIndex = getAsInteger(bufferView, "buffer");
|
||||||
@ -450,14 +463,17 @@ public class GltfLoader implements AssetLoader {
|
|||||||
//int target = getAsInteger(bufferView, "target", 0);
|
//int target = getAsInteger(bufferView, "target", 0);
|
||||||
|
|
||||||
byte[] data = readData(bufferIndex);
|
byte[] data = readData(bufferIndex);
|
||||||
|
|
||||||
|
data = customContentManager.readExtension(bufferView, data);
|
||||||
|
|
||||||
populateBuffer(store, data, bufferSize, byteOffset + bvByteOffset, byteStride, numComponents, componentSize);
|
populateBuffer(store, data, bufferSize, byteOffset + bvByteOffset, byteStride, numComponents, componentSize);
|
||||||
|
|
||||||
//TODO extensions?
|
|
||||||
//TODO extras?
|
//TODO extras?
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private byte[] readData(int bufferIndex) throws IOException {
|
public byte[] readData(int bufferIndex) throws IOException {
|
||||||
|
|
||||||
assertNotNull(buffers, "No buffer defined");
|
assertNotNull(buffers, "No buffer defined");
|
||||||
|
|
||||||
@ -465,25 +481,23 @@ public class GltfLoader implements AssetLoader {
|
|||||||
String uri = getAsString(buffer, "uri");
|
String uri = getAsString(buffer, "uri");
|
||||||
Integer bufferLength = getAsInteger(buffer, "byteLength");
|
Integer bufferLength = getAsInteger(buffer, "byteLength");
|
||||||
assertNotNull(bufferLength, "No byteLength defined for buffer " + bufferIndex);
|
assertNotNull(bufferLength, "No byteLength defined for buffer " + bufferIndex);
|
||||||
|
byte[] data = (byte[]) fetchFromCache("buffers", bufferIndex, Object.class);
|
||||||
|
if (data != null) {
|
||||||
|
return data;
|
||||||
|
}
|
||||||
if (uri != null) {
|
if (uri != null) {
|
||||||
if (uri.startsWith("data:")) {
|
if (uri.startsWith("data:")) {
|
||||||
//base 64 embed data
|
//base 64 embed data
|
||||||
return DatatypeConverter.parseBase64Binary(uri.substring(uri.indexOf(",") + 1));
|
data = DatatypeConverter.parseBase64Binary(uri.substring(uri.indexOf(",") + 1));
|
||||||
} else {
|
} else {
|
||||||
//external file let's load it
|
//external file let's load it
|
||||||
if (!uri.endsWith(".bin")) {
|
if (!uri.endsWith(".bin")) {
|
||||||
throw new AssetLoadException("Cannot load " + uri + ", a .bin extension is required.");
|
throw new AssetLoadException("Cannot load " + uri + ", a .bin extension is required.");
|
||||||
}
|
}
|
||||||
byte[] data = (byte[]) fetchFromCache("buffers", bufferIndex, Object.class);
|
|
||||||
if (data != null) {
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
InputStream input = (InputStream) info.getManager().loadAsset(info.getKey().getFolder() + uri);
|
InputStream input = (InputStream) info.getManager().loadAsset(info.getKey().getFolder() + uri);
|
||||||
data = new byte[bufferLength];
|
data = new byte[bufferLength];
|
||||||
input.read(data);
|
input.read(data);
|
||||||
addToCache("buffers", bufferIndex, data, buffers.size());
|
|
||||||
|
|
||||||
return data;
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
//no URI we are in a binary file so the data is in the 2nd chunk
|
//no URI we are in a binary file so the data is in the 2nd chunk
|
||||||
@ -491,52 +505,73 @@ public class GltfLoader implements AssetLoader {
|
|||||||
throw new AssetLoadException("Binary gltf is not supported yet");
|
throw new AssetLoadException("Binary gltf is not supported yet");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
data = customContentManager.readExtension(buffer, data);
|
||||||
|
|
||||||
|
addToCache("buffers", bufferIndex, data, buffers.size());
|
||||||
|
return data;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Material readMaterial(int materialIndex) {
|
public Material readMaterial(int materialIndex) {
|
||||||
assertNotNull(materials, "There is no material defined yet a mesh references one");
|
assertNotNull(materials, "There is no material defined yet a mesh references one");
|
||||||
|
|
||||||
JsonObject matData = materials.get(materialIndex).getAsJsonObject();
|
JsonObject matData = materials.get(materialIndex).getAsJsonObject();
|
||||||
JsonObject pbrMat = matData.getAsJsonObject("pbrMetallicRoughness");
|
JsonObject pbrMat = matData.getAsJsonObject("pbrMetallicRoughness");
|
||||||
|
|
||||||
if (pbrMat == null) {
|
|
||||||
logger.log(Level.WARNING, "Unable to find any pbrMetallicRoughness material entry in material " + materialIndex + ". Only PBR material is supported for now");
|
MaterialAdapter adapter = null;
|
||||||
return defaultMat;
|
|
||||||
|
if (pbrMat != null) {
|
||||||
|
adapter = getAdapterForMaterial(info, "pbrMetallicRoughness");
|
||||||
|
if (adapter == null) {
|
||||||
|
adapter = defaultMaterialAdapters.get("pbrMetallicRoughness");
|
||||||
|
}
|
||||||
|
adapter.init(info.getManager());
|
||||||
}
|
}
|
||||||
|
|
||||||
MaterialAdapter adapter = getAdapterForMaterial(info, "pbrMetallicRoughness");
|
adapter = customContentManager.readExtension(matData, adapter);
|
||||||
|
|
||||||
if (adapter == null) {
|
if (adapter == null) {
|
||||||
|
logger.log(Level.WARNING, "Couldn't find any matching material definition for material " + materialIndex);
|
||||||
adapter = defaultMaterialAdapters.get("pbrMetallicRoughness");
|
adapter = defaultMaterialAdapters.get("pbrMetallicRoughness");
|
||||||
|
adapter.init(info.getManager());
|
||||||
|
setDefaultParams(adapter.getMaterial());
|
||||||
}
|
}
|
||||||
|
|
||||||
Material mat = adapter.getMaterial(info.getManager());
|
if (pbrMat != null) {
|
||||||
mat.setName(getAsString(matData, "name"));
|
adapter.setParam("baseColorFactor", getAsColor(pbrMat, "baseColorFactor", ColorRGBA.White));
|
||||||
|
adapter.setParam("metallicFactor", getAsFloat(pbrMat, "metallicFactor", 1f));
|
||||||
|
adapter.setParam("roughnessFactor", getAsFloat(pbrMat, "roughnessFactor", 1f));
|
||||||
|
adapter.setParam("baseColorTexture", readTexture(pbrMat.getAsJsonObject("baseColorTexture")));
|
||||||
|
adapter.setParam("metallicRoughnessTexture", readTexture(pbrMat.getAsJsonObject("metallicRoughnessTexture")));
|
||||||
|
}
|
||||||
|
|
||||||
adapter.setParam(mat, "baseColorFactor", getAsColor(pbrMat, "baseColorFactor", ColorRGBA.White));
|
adapter.getMaterial().setName(getAsString(matData, "name"));
|
||||||
adapter.setParam(mat, "metallicFactor", getAsFloat(pbrMat, "metallicFactor", 1f));
|
adapter.setParam("emissiveFactor", getAsColor(matData, "emissiveFactor", ColorRGBA.Black));
|
||||||
adapter.setParam(mat, "roughnessFactor", getAsFloat(pbrMat, "roughnessFactor", 1f));
|
|
||||||
adapter.setParam(mat, "emissiveFactor", getAsColor(matData, "emissiveFactor", ColorRGBA.Black));
|
|
||||||
String alphaMode = getAsString(matData, "alphaMode");
|
String alphaMode = getAsString(matData, "alphaMode");
|
||||||
adapter.setParam(mat, "alphaMode", alphaMode);
|
adapter.setParam("alphaMode", alphaMode);
|
||||||
if (alphaMode != null && alphaMode.equals("MASK")) {
|
if (alphaMode != null && alphaMode.equals("MASK")) {
|
||||||
adapter.setParam(mat, "alphaCutoff", getAsFloat(matData, "alphaCutoff"));
|
adapter.setParam("alphaCutoff", getAsFloat(matData, "alphaCutoff"));
|
||||||
}
|
}
|
||||||
adapter.setParam(mat, "doubleSided", getAsBoolean(matData, "doubleSided"));
|
adapter.setParam("doubleSided", getAsBoolean(matData, "doubleSided"));
|
||||||
|
|
||||||
adapter.setParam(mat, "baseColorTexture", readTexture(pbrMat.getAsJsonObject("baseColorTexture")));
|
|
||||||
adapter.setParam(mat, "metallicRoughnessTexture", readTexture(pbrMat.getAsJsonObject("metallicRoughnessTexture")));
|
|
||||||
Texture2D normal = readTexture(matData.getAsJsonObject("normalTexture"));
|
Texture2D normal = readTexture(matData.getAsJsonObject("normalTexture"));
|
||||||
adapter.setParam(mat, "normalTexture", normal);
|
adapter.setParam("normalTexture", normal);
|
||||||
if (normal != null) {
|
if (normal != null) {
|
||||||
useNormalsFlag = true;
|
useNormalsFlag = true;
|
||||||
}
|
}
|
||||||
adapter.setParam(mat, "occlusionTexture", readTexture(matData.getAsJsonObject("occlusionTexture")));
|
adapter.setParam("occlusionTexture", readTexture(matData.getAsJsonObject("occlusionTexture")));
|
||||||
adapter.setParam(mat, "emissiveTexture", readTexture(matData.getAsJsonObject("emissiveTexture")));
|
adapter.setParam("emissiveTexture", readTexture(matData.getAsJsonObject("emissiveTexture")));
|
||||||
|
|
||||||
return mat;
|
|
||||||
|
return adapter.getMaterial();
|
||||||
}
|
}
|
||||||
|
|
||||||
private Texture2D readTexture(JsonObject texture) {
|
public Texture2D readTexture(JsonObject texture) {
|
||||||
|
return readTexture(texture, false);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public Texture2D readTexture(JsonObject texture, boolean flip) {
|
||||||
if (texture == null) {
|
if (texture == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -548,19 +583,22 @@ public class GltfLoader implements AssetLoader {
|
|||||||
Integer sourceIndex = getAsInteger(textureData, "source");
|
Integer sourceIndex = getAsInteger(textureData, "source");
|
||||||
Integer samplerIndex = getAsInteger(textureData, "sampler");
|
Integer samplerIndex = getAsInteger(textureData, "sampler");
|
||||||
|
|
||||||
Texture2D texture2d = readImage(sourceIndex);
|
Texture2D texture2d = readImage(sourceIndex, flip);
|
||||||
readSampler(samplerIndex, texture2d);
|
readSampler(samplerIndex, texture2d);
|
||||||
|
|
||||||
|
texture2d = customContentManager.readExtension(texture, texture2d);
|
||||||
|
|
||||||
return texture2d;
|
return texture2d;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Texture2D readImage(int sourceIndex) {
|
public Texture2D readImage(int sourceIndex, boolean flip) {
|
||||||
if (images == null) {
|
if (images == null) {
|
||||||
throw new AssetLoadException("No image defined");
|
throw new AssetLoadException("No image defined");
|
||||||
}
|
}
|
||||||
|
|
||||||
JsonObject image = images.get(sourceIndex).getAsJsonObject();
|
JsonObject image = images.get(sourceIndex).getAsJsonObject();
|
||||||
String uri = getAsString(image, "uri");
|
String uri = getAsString(image, "uri");
|
||||||
|
Texture2D result;
|
||||||
if (uri == null) {
|
if (uri == null) {
|
||||||
//Image is embed in a buffer not supported yet
|
//Image is embed in a buffer not supported yet
|
||||||
//TODO support images embed in a buffer
|
//TODO support images embed in a buffer
|
||||||
@ -571,18 +609,22 @@ public class GltfLoader implements AssetLoader {
|
|||||||
byte[] data = DatatypeConverter.parseBase64Binary(uriInfo[1]);
|
byte[] data = DatatypeConverter.parseBase64Binary(uriInfo[1]);
|
||||||
String headerInfo = uriInfo[0].split(";")[0];
|
String headerInfo = uriInfo[0].split(";")[0];
|
||||||
String extension = headerInfo.split("/")[1];
|
String extension = headerInfo.split("/")[1];
|
||||||
TextureKey key = new TextureKey("image" + sourceIndex + "." + extension, false);
|
TextureKey key = new TextureKey("image" + sourceIndex + "." + extension, flip);
|
||||||
return (Texture2D) info.getManager().loadAssetFromStream(key, new ByteArrayInputStream(data));
|
result = (Texture2D) info.getManager().loadAssetFromStream(key, new ByteArrayInputStream(data));
|
||||||
} else {
|
} else {
|
||||||
//external file image
|
//external file image
|
||||||
TextureKey key = new TextureKey(info.getKey().getFolder() + uri, false);
|
TextureKey key = new TextureKey(info.getKey().getFolder() + uri, flip);
|
||||||
Texture tex = info.getManager().loadTexture(key);
|
Texture tex = info.getManager().loadTexture(key);
|
||||||
return (Texture2D) tex;
|
result = (Texture2D) tex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
result = customContentManager.readExtension(image, result);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void readAnimation(int animationIndex) throws IOException {
|
public void readAnimation(int animationIndex) throws IOException {
|
||||||
JsonObject animation = animations.get(animationIndex).getAsJsonObject();
|
JsonObject animation = animations.get(animationIndex).getAsJsonObject();
|
||||||
JsonArray channels = animation.getAsJsonArray("channels");
|
JsonArray channels = animation.getAsJsonArray("channels");
|
||||||
JsonArray samplers = animation.getAsJsonArray("samplers");
|
JsonArray samplers = animation.getAsJsonArray("samplers");
|
||||||
@ -705,6 +747,8 @@ public class GltfLoader implements AssetLoader {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
anim = customContentManager.readExtension(animation, anim);
|
||||||
|
|
||||||
if (skinIndex != -1) {
|
if (skinIndex != -1) {
|
||||||
//we have a bone animation.
|
//we have a bone animation.
|
||||||
SkinData skin = fetchFromCache("skins", skinIndex, SkinData.class);
|
SkinData skin = fetchFromCache("skins", skinIndex, SkinData.class);
|
||||||
@ -742,7 +786,7 @@ public class GltfLoader implements AssetLoader {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void readSampler(int samplerIndex, Texture2D texture) {
|
public void readSampler(int samplerIndex, Texture2D texture) {
|
||||||
if (samplers == null) {
|
if (samplers == null) {
|
||||||
throw new AssetLoadException("No samplers defined");
|
throw new AssetLoadException("No samplers defined");
|
||||||
}
|
}
|
||||||
@ -762,7 +806,7 @@ public class GltfLoader implements AssetLoader {
|
|||||||
texture.setWrap(Texture.WrapAxis.T, wrapT);
|
texture.setWrap(Texture.WrapAxis.T, wrapT);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void readSkins() throws IOException {
|
public void readSkins() throws IOException {
|
||||||
if (skins == null) {
|
if (skins == null) {
|
||||||
//no skins, no bone animation.
|
//no skins, no bone animation.
|
||||||
return;
|
return;
|
||||||
@ -870,7 +914,7 @@ public class GltfLoader implements AssetLoader {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Bone readNodeAsBone(int nodeIndex, int boneIndex, int skinIndex, Matrix4f modelBindMatrix) throws IOException {
|
public Bone readNodeAsBone(int nodeIndex, int boneIndex, int skinIndex, Matrix4f modelBindMatrix) throws IOException {
|
||||||
|
|
||||||
BoneWrapper boneWrapper = fetchFromCache("nodes", nodeIndex, BoneWrapper.class);
|
BoneWrapper boneWrapper = fetchFromCache("nodes", nodeIndex, BoneWrapper.class);
|
||||||
if (boneWrapper != null) {
|
if (boneWrapper != null) {
|
||||||
@ -927,8 +971,11 @@ public class GltfLoader implements AssetLoader {
|
|||||||
spatial.removeControl(animControl);
|
spatial.removeControl(animControl);
|
||||||
}
|
}
|
||||||
|
|
||||||
spatial.addControl(skinData.animControl);
|
if (skinData.animControl != null) {
|
||||||
spatial.addControl(skinData.skeletonControl);
|
spatial.addControl(skinData.animControl);
|
||||||
|
spatial.addControl(skinData.skeletonControl);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -937,7 +984,7 @@ public class GltfLoader implements AssetLoader {
|
|||||||
return getAsString(meshData, "name");
|
return getAsString(meshData, "name");
|
||||||
}
|
}
|
||||||
|
|
||||||
private <T> T fetchFromCache(String name, int index, Class<T> type) {
|
public <T> T fetchFromCache(String name, int index, Class<T> type) {
|
||||||
Object[] data = dataCache.get(name);
|
Object[] data = dataCache.get(name);
|
||||||
if (data == null) {
|
if (data == null) {
|
||||||
return null;
|
return null;
|
||||||
@ -945,7 +992,7 @@ public class GltfLoader implements AssetLoader {
|
|||||||
return type.cast(data[index]);
|
return type.cast(data[index]);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addToCache(String name, int index, Object object, int maxLength) {
|
public void addToCache(String name, int index, Object object, int maxLength) {
|
||||||
Object[] data = dataCache.get(name);
|
Object[] data = dataCache.get(name);
|
||||||
if (data == null) {
|
if (data == null) {
|
||||||
data = new Object[maxLength];
|
data = new Object[maxLength];
|
||||||
@ -954,6 +1001,30 @@ public class GltfLoader implements AssetLoader {
|
|||||||
data[index] = object;
|
data[index] = object;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public AssetInfo getInfo() {
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
|
||||||
|
public JsonObject getDocRoot() {
|
||||||
|
return docRoot;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Node getRootNode() {
|
||||||
|
return rootNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class WeightData {
|
||||||
|
float value;
|
||||||
|
short index;
|
||||||
|
int componentSize;
|
||||||
|
|
||||||
|
public WeightData(float value, short index, int componentSize) {
|
||||||
|
this.value = value;
|
||||||
|
this.index = index;
|
||||||
|
this.componentSize = componentSize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private class AnimData {
|
private class AnimData {
|
||||||
Float length;
|
Float length;
|
||||||
float[] times;
|
float[] times;
|
||||||
|
@ -11,6 +11,7 @@ import java.util.Map;
|
|||||||
public class GltfModelKey extends ModelKey {
|
public class GltfModelKey extends ModelKey {
|
||||||
|
|
||||||
private Map<String, MaterialAdapter> materialAdapters = new HashMap<>();
|
private Map<String, MaterialAdapter> materialAdapters = new HashMap<>();
|
||||||
|
private static Map<String, ExtensionLoader> extensionLoaders = new HashMap<>();
|
||||||
private boolean keepSkeletonPose = false;
|
private boolean keepSkeletonPose = false;
|
||||||
|
|
||||||
public GltfModelKey(String name) {
|
public GltfModelKey(String name) {
|
||||||
@ -24,10 +25,18 @@ public class GltfModelKey extends ModelKey {
|
|||||||
materialAdapters.put(gltfMaterialName, adapter);
|
materialAdapters.put(gltfMaterialName, adapter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void registerExtensionLoader(String extensionName, ExtensionLoader loader) {
|
||||||
|
extensionLoaders.put(extensionName, loader);
|
||||||
|
}
|
||||||
|
|
||||||
public MaterialAdapter getAdapterForMaterial(String gltfMaterialName) {
|
public MaterialAdapter getAdapterForMaterial(String gltfMaterialName) {
|
||||||
return materialAdapters.get(gltfMaterialName);
|
return materialAdapters.get(gltfMaterialName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ExtensionLoader getExtensionLoader(String extensionName) {
|
||||||
|
return extensionLoaders.get(extensionName);
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isKeepSkeletonPose() {
|
public boolean isKeepSkeletonPose() {
|
||||||
return keepSkeletonPose;
|
return keepSkeletonPose;
|
||||||
}
|
}
|
||||||
@ -35,4 +44,6 @@ public class GltfModelKey extends ModelKey {
|
|||||||
public void setKeepSkeletonPose(boolean keepSkeletonPose) {
|
public void setKeepSkeletonPose(boolean keepSkeletonPose) {
|
||||||
this.keepSkeletonPose = keepSkeletonPose;
|
this.keepSkeletonPose = keepSkeletonPose;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -20,6 +20,8 @@ import java.util.Map;
|
|||||||
public abstract class MaterialAdapter {
|
public abstract class MaterialAdapter {
|
||||||
|
|
||||||
private Map<String, String> paramsMapping = new HashMap<>();
|
private Map<String, String> paramsMapping = new HashMap<>();
|
||||||
|
private Material mat;
|
||||||
|
private AssetManager assetManager;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Should return the material definition used by this material adapter
|
* Should return the material definition used by this material adapter
|
||||||
@ -28,13 +30,24 @@ public abstract class MaterialAdapter {
|
|||||||
*/
|
*/
|
||||||
protected abstract String getMaterialDefPath();
|
protected abstract String getMaterialDefPath();
|
||||||
|
|
||||||
protected abstract MatParam adaptMatParam(Material mat, MatParam param);
|
protected abstract MatParam adaptMatParam(MatParam param);
|
||||||
|
|
||||||
public Material getMaterial(AssetManager assetManager) {
|
protected void init(AssetManager assetManager) {
|
||||||
return new Material(assetManager, getMaterialDefPath());
|
this.assetManager = assetManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setParam(Material mat, String gltfParamName, Object value) {
|
void reset() {
|
||||||
|
mat = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Material getMaterial() {
|
||||||
|
if (mat == null) {
|
||||||
|
mat = new Material(assetManager, getMaterialDefPath());
|
||||||
|
}
|
||||||
|
return mat;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setParam(String gltfParamName, Object value) {
|
||||||
String name = getJmeParamName(gltfParamName);
|
String name = getJmeParamName(gltfParamName);
|
||||||
if (name == null || value == null) {
|
if (name == null || value == null) {
|
||||||
//no mapping registered or value is null, let's ignore this param
|
//no mapping registered or value is null, let's ignore this param
|
||||||
@ -42,7 +55,7 @@ public abstract class MaterialAdapter {
|
|||||||
}
|
}
|
||||||
MatParam param;
|
MatParam param;
|
||||||
if (value instanceof Texture) {
|
if (value instanceof Texture) {
|
||||||
MatParam defParam = mat.getMaterialDef().getMaterialParam(name);
|
MatParam defParam = getMaterial().getMaterialDef().getMaterialParam(name);
|
||||||
if (defParam == null) {
|
if (defParam == null) {
|
||||||
throw new AssetLoadException("Material definition " + getMaterialDefPath() + " has not param with name" + name);
|
throw new AssetLoadException("Material definition " + getMaterialDefPath() + " has not param with name" + name);
|
||||||
}
|
}
|
||||||
@ -50,15 +63,15 @@ public abstract class MaterialAdapter {
|
|||||||
throw new AssetLoadException("param with name" + name + "in material definition " + getMaterialDefPath() + " should be a texture param");
|
throw new AssetLoadException("param with name" + name + "in material definition " + getMaterialDefPath() + " should be a texture param");
|
||||||
}
|
}
|
||||||
param = new MatParamTexture(VarType.Texture2D, name, (Texture) value, ((MatParamTexture) defParam).getColorSpace());
|
param = new MatParamTexture(VarType.Texture2D, name, (Texture) value, ((MatParamTexture) defParam).getColorSpace());
|
||||||
param = adaptMatParam(mat, param);
|
param = adaptMatParam(param);
|
||||||
if (param != null) {
|
if (param != null) {
|
||||||
mat.setTextureParam(param.getName(), param.getVarType(), (Texture) param.getValue());
|
getMaterial().setTextureParam(param.getName(), param.getVarType(), (Texture) param.getValue());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
param = new MatParam(getVarType(value), name, value);
|
param = new MatParam(getVarType(value), name, value);
|
||||||
param = adaptMatParam(mat, param);
|
param = adaptMatParam(param);
|
||||||
if (param != null) {
|
if (param != null) {
|
||||||
mat.setParam(param.getName(), param.getVarType(), param.getValue());
|
getMaterial().setParam(param.getName(), param.getVarType(), param.getValue());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,15 +5,10 @@ import com.jme3.material.*;
|
|||||||
/**
|
/**
|
||||||
* Created by Nehon on 08/08/2017.
|
* Created by Nehon on 08/08/2017.
|
||||||
*/
|
*/
|
||||||
public class PBRMaterialAdapter extends MaterialAdapter {
|
public abstract class PBRMaterialAdapter extends MaterialAdapter {
|
||||||
|
|
||||||
|
|
||||||
public PBRMaterialAdapter() {
|
public PBRMaterialAdapter() {
|
||||||
addParamMapping("baseColorFactor", "BaseColor");
|
|
||||||
addParamMapping("baseColorTexture", "BaseColorMap");
|
|
||||||
addParamMapping("metallicFactor", "Metallic");
|
|
||||||
addParamMapping("roughnessFactor", "Roughness");
|
|
||||||
addParamMapping("metallicRoughnessTexture", "MetallicRoughnessMap");
|
|
||||||
addParamMapping("normalTexture", "NormalMap");
|
addParamMapping("normalTexture", "NormalMap");
|
||||||
addParamMapping("occlusionTexture", "LightMap");
|
addParamMapping("occlusionTexture", "LightMap");
|
||||||
addParamMapping("emissiveTexture", "EmissiveMap");
|
addParamMapping("emissiveTexture", "EmissiveMap");
|
||||||
@ -29,13 +24,13 @@ public class PBRMaterialAdapter extends MaterialAdapter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected MatParam adaptMatParam(Material mat, MatParam param) {
|
protected MatParam adaptMatParam(MatParam param) {
|
||||||
if (param.getName().equals("alpha")) {
|
if (param.getName().equals("alpha")) {
|
||||||
String alphaMode = (String) param.getValue();
|
String alphaMode = (String) param.getValue();
|
||||||
switch (alphaMode) {
|
switch (alphaMode) {
|
||||||
case "MASK":
|
case "MASK":
|
||||||
case "BLEND":
|
case "BLEND":
|
||||||
mat.getAdditionalRenderState().setBlendMode(RenderState.BlendMode.Alpha);
|
getMaterial().getAdditionalRenderState().setBlendMode(RenderState.BlendMode.Alpha);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -43,13 +38,13 @@ public class PBRMaterialAdapter extends MaterialAdapter {
|
|||||||
boolean doubleSided = (boolean) param.getValue();
|
boolean doubleSided = (boolean) param.getValue();
|
||||||
if (doubleSided) {
|
if (doubleSided) {
|
||||||
//Note that this is not completely right as normals on the back side will be in the wrong direction.
|
//Note that this is not completely right as normals on the back side will be in the wrong direction.
|
||||||
mat.getAdditionalRenderState().setFaceCullMode(RenderState.FaceCullMode.Off);
|
getMaterial().getAdditionalRenderState().setFaceCullMode(RenderState.FaceCullMode.Off);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if (param.getName().equals("NormalMap")) {
|
if (param.getName().equals("NormalMap")) {
|
||||||
//Set the normal map type to OpenGl
|
//Set the normal map type to OpenGl
|
||||||
mat.setFloat("NormalType", 1.0f);
|
getMaterial().setFloat("NormalType", 1.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -0,0 +1,16 @@
|
|||||||
|
package com.jme3.scene.plugins.gltf;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Nehon on 20/08/2017.
|
||||||
|
*/
|
||||||
|
public class PBRMetalRoughMaterialAdapter extends PBRMaterialAdapter {
|
||||||
|
|
||||||
|
public PBRMetalRoughMaterialAdapter() {
|
||||||
|
super();
|
||||||
|
addParamMapping("baseColorFactor", "BaseColor");
|
||||||
|
addParamMapping("baseColorTexture", "BaseColorMap");
|
||||||
|
addParamMapping("metallicFactor", "Metallic");
|
||||||
|
addParamMapping("roughnessFactor", "Roughness");
|
||||||
|
addParamMapping("metallicRoughnessTexture", "MetallicRoughnessMap");
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,28 @@
|
|||||||
|
package com.jme3.scene.plugins.gltf;
|
||||||
|
|
||||||
|
import com.google.gson.JsonElement;
|
||||||
|
|
||||||
|
import static com.jme3.scene.plugins.gltf.GltfUtils.getAsColor;
|
||||||
|
import static com.jme3.scene.plugins.gltf.GltfUtils.getAsFloat;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Material adapter for PBR Specular Glossiness pipeline
|
||||||
|
* Created by Nehon on 20/08/2017.
|
||||||
|
*/
|
||||||
|
public class PBRSpecGlossExtensionLoader implements ExtensionLoader {
|
||||||
|
|
||||||
|
private PBRSpecGlossMaterialAdapter materialAdapter = new PBRSpecGlossMaterialAdapter();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object handleExtension(GltfLoader loader, JsonElement parent, JsonElement extension, Object input) {
|
||||||
|
materialAdapter.init(loader.getInfo().getManager());
|
||||||
|
|
||||||
|
materialAdapter.setParam("diffuseFactor", getAsColor(extension.getAsJsonObject(), "diffuseFactor"));
|
||||||
|
materialAdapter.setParam("specularFactor", getAsColor(extension.getAsJsonObject(), "specularFactor"));
|
||||||
|
materialAdapter.setParam("glossinessFactor", getAsFloat(extension.getAsJsonObject(), "glossinessFactor"));
|
||||||
|
materialAdapter.setParam("diffuseTexture", loader.readTexture(extension.getAsJsonObject().getAsJsonObject("diffuseTexture")));
|
||||||
|
materialAdapter.setParam("specularGlossinessTexture", loader.readTexture(extension.getAsJsonObject().getAsJsonObject("specularGlossinessTexture")));
|
||||||
|
|
||||||
|
return materialAdapter;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,24 @@
|
|||||||
|
package com.jme3.scene.plugins.gltf;
|
||||||
|
|
||||||
|
import com.jme3.material.MatParam;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Nehon on 20/08/2017.
|
||||||
|
*/
|
||||||
|
public class PBRSpecGlossMaterialAdapter extends PBRMaterialAdapter {
|
||||||
|
|
||||||
|
public PBRSpecGlossMaterialAdapter() {
|
||||||
|
super();
|
||||||
|
addParamMapping("diffuseFactor", "BaseColor");
|
||||||
|
addParamMapping("diffuseTexture", "BaseColorMap");
|
||||||
|
addParamMapping("specularFactor", "Specular");
|
||||||
|
addParamMapping("glossinessFactor", "Glossiness");
|
||||||
|
addParamMapping("specularGlossinessTexture", "SpecularGlossinessMap");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected MatParam adaptMatParam(MatParam param) {
|
||||||
|
getMaterial().setBoolean("UseSpecGloss", true);
|
||||||
|
return super.adaptMatParam(param);
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user