/* * Copyright (c) 2009-2015 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.fbx.material; import com.jme3.math.ColorRGBA; import com.jme3.scene.plugins.fbx.file.FbxElement; import java.util.HashMap; import java.util.Map; import java.util.logging.Level; import java.util.logging.Logger; public class FbxMaterialProperties { private static final Logger logger = Logger.getLogger(FbxMaterialProperties.class.getName()); private static final Map<String, FBXMaterialProperty> propertyMetaMap = new HashMap<String, FBXMaterialProperty>(); private final Map<String, Object> propertyValueMap = new HashMap<String, Object>(); private static enum Type { Color, Alpha, Factor, Texture2DOrColor, Texture2DOrAlpha, Texture2DOrFactor, Texture2D, TextureCubeMap, Ignore; } private static class FBXMaterialProperty { private final String name; private final Type type; public FBXMaterialProperty(String name, Type type) { this.name = name; this.type = type; } } private static boolean isValueAcceptable(Type type, Object value) { if (type == Type.Ignore) { return true; } if (value instanceof FbxTexture) { switch (type) { case Texture2D: case Texture2DOrAlpha: case Texture2DOrColor: case Texture2DOrFactor: return true; } } else if (value instanceof ColorRGBA) { switch (type) { case Color: case Texture2DOrColor: return true; } } else if (value instanceof Float) { switch (type) { case Alpha: case Factor: case Texture2DOrAlpha: case Texture2DOrFactor: return true; } } return false; } private static void defineProp(String name, Type type) { propertyMetaMap.put(name, new FBXMaterialProperty(name, type)); } private static void defineAlias(String alias, String name) { propertyMetaMap.put(alias, propertyMetaMap.get(name)); } static { // Lighting->Ambient // TODO: Add support for AmbientMap?? defineProp("AmbientColor", Type.Color); defineProp("AmbientFactor", Type.Factor); defineAlias("Ambient", "AmbientColor"); // Lighting->DiffuseMap/Diffuse defineProp("DiffuseColor", Type.Texture2DOrColor); defineProp("DiffuseFactor", Type.Factor); defineAlias("Diffuse", "DiffuseColor"); // Lighting->SpecularMap/Specular defineProp("SpecularColor", Type.Texture2DOrColor); defineProp("SpecularFactor", Type.Factor); defineAlias("Specular", "SpecularColor"); // Lighting->AlphaMap/Diffuse defineProp("TransparentColor", Type.Texture2DOrAlpha); // Lighting->Diffuse defineProp("TransparencyFactor", Type.Alpha); defineAlias("Opacity", "TransparencyFactor"); // Lighting->GlowMap/GlowColor defineProp("EmissiveColor", Type.Texture2DOrColor); defineProp("EmissiveFactor", Type.Factor); defineAlias("Emissive", "EmissiveColor"); // Lighting->Shininess defineProp("Shininess", Type.Factor); defineAlias("ShininessExponent", "Shininess"); // Lighting->NormalMap defineProp("NormalMap", Type.Texture2D); defineAlias("Normal", "NormalMap"); // Lighting->EnvMap defineProp("ReflectionColor", Type.Texture2DOrColor); // Lighting->FresnelParams defineProp("Reflectivity", Type.Factor); defineAlias("ReflectionFactor", "Reflectivity"); // ShadingModel is no longer specified under Properties element. defineProp("ShadingModel", Type.Ignore); // MultiLayer materials aren't supported anyway.. defineProp("MultiLayer", Type.Ignore); // Not sure what this is.. NormalMap again?? defineProp("Bump", Type.Texture2DOrColor); defineProp("BumpFactor", Type.Factor); defineProp("DisplacementColor", Type.Color); defineProp("DisplacementFactor", Type.Factor); } public void setPropertyTexture(String name, FbxTexture texture) { FBXMaterialProperty prop = propertyMetaMap.get(name); if (prop == null) { logger.log(Level.WARNING, "Unknown FBX material property '{0}'", name); return; } if (propertyValueMap.get(name) instanceof FbxTexture) { // Multiple / layered textures .. // Just write into 2nd slot for now (maybe will use for lightmaps). name = name + "2"; } propertyValueMap.put(name, texture); } public void setPropertyFromElement(FbxElement propertyElement) { String name = (String) propertyElement.properties.get(0); FBXMaterialProperty prop = propertyMetaMap.get(name); if (prop == null) { logger.log(Level.WARNING, "Unknown FBX material property ''{0}''", name); return; } // It is either a color, alpha, or factor. // Textures can only be set via setPropertyTexture. // If it is an alias, get the real name of the property. String realName = prop.name; switch (prop.type) { case Alpha: case Factor: case Texture2DOrFactor: case Texture2DOrAlpha: double value = (Double) propertyElement.properties.get(4); propertyValueMap.put(realName, (float)value); break; case Color: case Texture2DOrColor: double x = (Double) propertyElement.properties.get(4); double y = (Double) propertyElement.properties.get(5); double z = (Double) propertyElement.properties.get(6); ColorRGBA color = new ColorRGBA((float)x, (float)y, (float)z, 1f); propertyValueMap.put(realName, color); break; default: logger.log(Level.WARNING, "FBX material property ''{0}'' requires a texture.", name); break; } } public Object getProperty(String name) { return propertyValueMap.get(name); } public static Type getPropertyType(String name) { FBXMaterialProperty prop = propertyMetaMap.get(name); if (prop == null) { return null; } else { return prop.type; } } }