logger.warning("material not found: " + materialName);
return;
}
final String originalMaterial = mat.getAttributeValue("id");
MaterialInfo mInfo = null;
if (!_dataCache.getMaterialInfoMap().containsKey(originalMaterial)) {
mInfo = new MaterialInfo();
mInfo.setMaterialName(originalMaterial);
_dataCache.getMaterialInfoMap().put(originalMaterial, mInfo);
}
_dataCache.getMeshMaterialMap().put(mesh, originalMaterial);
final Element child = mat.getChild("instance_effect");
final Element effectNode = _colladaDOMUtil.findTargetWithId(child.getAttributeValue("url"));
if (effectNode == null) {
logger.warning("material effect not found: " + mat.getChild("instance_material").getAttributeValue("url"));
return;
}
if ("effect".equals(effectNode.getName())) {
/*
* temp cache for textures, we do not want to add textures twice (for example, transparant map might point
* to diffuse texture)
*/
final HashMap<String, Texture> loadedTextures = new HashMap<String, Texture>();
final Element effect = effectNode;
// XXX: For now, just grab the common technique:
final Element common = effect.getChild("profile_COMMON");
if (common != null) {
if (mInfo != null) {
mInfo.setProfile("COMMON");
}
final Element commonExtra = common.getChild("extra");
if (commonExtra != null) {
// process with any plugins
_importer.readExtra(commonExtra, mesh);
}
final Element technique = common.getChild("technique");
String type = "blinn";
if (technique.getChild(type) == null) {
type = "phong";
if (technique.getChild(type) == null) {
type = "lambert";
if (technique.getChild(type) == null) {
type = "constant";
if (technique.getChild(type) == null) {
ColladaMaterialUtils.logger.warning("COMMON material has unusuable techinque. "
+ child.getAttributeValue("url"));
return;
}
}
}
}
final Element blinnPhongLambert = technique.getChild(type);
if (mInfo != null) {
mInfo.setTechnique(type);
}
final MaterialState mState = new MaterialState();
// TODO: implement proper transparency handling
Texture diffuseTexture = null;
ColorRGBA transparent = new ColorRGBA(1.0f, 1.0f, 1.0f, 1.0f);
float transparency = 1.0f;
boolean useTransparency = false;
String opaqueMode = "A_ONE";
/*
* place holder for current property, we import material properties in fixed order (for texture order)
*/
Element property = null;
/* Diffuse property */
property = blinnPhongLambert.getChild("diffuse");
if (property != null) {
final Element propertyValue = property.getChildren().get(0);
if ("color".equals(propertyValue.getName())) {
final ColorRGBA color = _colladaDOMUtil.getColor(propertyValue.getText());
mState.setDiffuse(MaterialFace.FrontAndBack, color);
} else if ("texture".equals(propertyValue.getName()) && _loadTextures) {
diffuseTexture = populateTextureState(mesh, propertyValue, effect, loadedTextures, mInfo,
"diffuse");
}
}
/* Ambient property */
property = blinnPhongLambert.getChild("ambient");
if (property != null) {
final Element propertyValue = property.getChildren().get(0);
if ("color".equals(propertyValue.getName())) {
final ColorRGBA color = _colladaDOMUtil.getColor(propertyValue.getText());
mState.setAmbient(MaterialFace.FrontAndBack, color);
} else if ("texture".equals(propertyValue.getName()) && _loadTextures) {
populateTextureState(mesh, propertyValue, effect, loadedTextures, mInfo, "ambient");
}
}
/* Transparent property */
property = blinnPhongLambert.getChild("transparent");
if (property != null) {
final Element propertyValue = property.getChildren().get(0);
if ("color".equals(propertyValue.getName())) {
transparent = _colladaDOMUtil.getColor(propertyValue.getText());
// TODO: use this
useTransparency = true;
} else if ("texture".equals(propertyValue.getName()) && _loadTextures) {
populateTextureState(mesh, propertyValue, effect, loadedTextures, mInfo, "transparent");
}
opaqueMode = property.getAttributeValue("opaque", "A_ONE");
}
/* Transparency property */
property = blinnPhongLambert.getChild("transparency");
if (property != null) {
final Element propertyValue = property.getChildren().get(0);
if ("float".equals(propertyValue.getName())) {
transparency = Float.parseFloat(propertyValue.getText().replace(",", "."));
// TODO: use this
if (_flipTransparency) {
transparency = 1f - transparency;
}
useTransparency = true;
} else if ("texture".equals(propertyValue.getName()) && _loadTextures) {
populateTextureState(mesh, propertyValue, effect, loadedTextures, mInfo, "transparency");
}
}
/* Emission property */
property = blinnPhongLambert.getChild("emission");
if (property != null) {
final Element propertyValue = property.getChildren().get(0);
if ("color".equals(propertyValue.getName())) {
mState.setEmissive(MaterialFace.FrontAndBack, _colladaDOMUtil.getColor(propertyValue.getText()));
} else if ("texture".equals(propertyValue.getName()) && _loadTextures) {
populateTextureState(mesh, propertyValue, effect, loadedTextures, mInfo, "emissive");
}
}
/* Specular property */
property = blinnPhongLambert.getChild("specular");
if (property != null) {
final Element propertyValue = property.getChildren().get(0);
if ("color".equals(propertyValue.getName())) {
mState.setSpecular(MaterialFace.FrontAndBack, _colladaDOMUtil.getColor(propertyValue.getText()));
} else if ("texture".equals(propertyValue.getName()) && _loadTextures) {
populateTextureState(mesh, propertyValue, effect, loadedTextures, mInfo, "specular");
}
}
/* Shininess property */
property = blinnPhongLambert.getChild("shininess");
if (property != null) {
final Element propertyValue = property.getChildren().get(0);
if ("float".equals(propertyValue.getName())) {
float shininess = Float.parseFloat(propertyValue.getText().replace(",", "."));
if (shininess >= 0.0f && shininess <= 1.0f) {
final float oldShininess = shininess;
shininess *= 128;
logger.finest("Shininess - " + oldShininess
+ " - was in the [0,1] range. Scaling to [0, 128] - " + shininess);
} else if (shininess < 0 || shininess > 128) {
final float oldShininess = shininess;
shininess = MathUtils.clamp(shininess, 0, 128);
logger.warning("Shininess must be between 0 and 128. Shininess " + oldShininess
+ " was clamped to " + shininess);
}
mState.setShininess(MaterialFace.FrontAndBack, shininess);
} else if ("texture".equals(propertyValue.getName()) && _loadTextures) {
populateTextureState(mesh, propertyValue, effect, loadedTextures, mInfo, "shininess");
}
}
/* Reflectivity property */
float reflectivity = 1.0f;
property = blinnPhongLambert.getChild("reflectivity");
if (property != null) {
final Element propertyValue = property.getChildren().get(0);
if ("float".equals(propertyValue.getName())) {
reflectivity = Float.parseFloat(propertyValue.getText().replace(",", "."));
}
}
/* Reflective property. Texture only */
property = blinnPhongLambert.getChild("reflective");
if (property != null) {
final Element propertyValue = property.getChildren().get(0);
if ("texture".equals(propertyValue.getName()) && _loadTextures) {
final Texture reflectiveTexture = populateTextureState(mesh, propertyValue, effect,
loadedTextures, mInfo, "reflective");
reflectiveTexture.setEnvironmentalMapMode(Texture.EnvironmentalMapMode.SphereMap);
reflectiveTexture.setApply(ApplyMode.Combine);
reflectiveTexture.setCombineFuncRGB(CombinerFunctionRGB.Interpolate);
// color 1
reflectiveTexture.setCombineSrc0RGB(CombinerSource.CurrentTexture);
reflectiveTexture.setCombineOp0RGB(CombinerOperandRGB.SourceColor);
// color 2
reflectiveTexture.setCombineSrc1RGB(CombinerSource.Previous);
reflectiveTexture.setCombineOp1RGB(CombinerOperandRGB.SourceColor);
// interpolate param will come from alpha of constant color
reflectiveTexture.setCombineSrc2RGB(CombinerSource.Constant);
reflectiveTexture.setCombineOp2RGB(CombinerOperandRGB.SourceAlpha);
reflectiveTexture.setConstantColor(new ColorRGBA(1, 1, 1, reflectivity));
}
}
/*
* An extra tag defines some materials not part of the collada standard. Since we're not able to parse
* we simply extract the textures from the element (such that shaders etc can at least pick up on them)
*/
property = technique.getChild("extra");
if (property != null) {
// process with any plugins
if (!_importer.readExtra(property, mesh)) {
// no plugin processed our mesh, so process ourselves.
getTexturesFromElement(mesh, property, effect, loadedTextures, mInfo);
}
}
// XXX: There are some issues with clarity on how to use alpha blending in OpenGL FFP.
// The best interpretation I have seen is that if transparent has a texture == diffuse,
// Turn on alpha blending and use diffuse alpha.
// check to make sure we actually need this.
// testing separately for a transparency of 0.0 is to hack around erroneous exports, since usually
// there is no use in exporting something with 100% transparency.
if ("A_ONE".equals(opaqueMode) && ColorRGBA.WHITE.equals(transparent) && transparency == 1.0
|| transparency == 0.0) {
useTransparency = false;
}
if (useTransparency) {
if (diffuseTexture != null) {
final BlendState blend = new BlendState();
blend.setBlendEnabled(true);
blend.setTestEnabled(true);
blend.setSourceFunction(BlendState.SourceFunction.SourceAlpha);
blend.setDestinationFunction(BlendState.DestinationFunction.OneMinusSourceAlpha);
mesh.setRenderState(blend);
} else {
final BlendState blend = new BlendState();
blend.setBlendEnabled(true);
blend.setTestEnabled(true);
transparent.setAlpha(transparent.getAlpha() * transparency);
blend.setConstantColor(transparent);
blend.setSourceFunction(BlendState.SourceFunction.ConstantAlpha);
blend.setDestinationFunction(BlendState.DestinationFunction.OneMinusConstantAlpha);
mesh.setRenderState(blend);
}
mesh.getSceneHints().setRenderBucketType(RenderBucketType.Transparent);
}
if (mInfo != null) {
if (useTransparency) {
mInfo.setUseTransparency(useTransparency);
if (diffuseTexture == null) {
mInfo.setTransparency(transparent.getAlpha() * transparency);
}
}
mInfo.setMaterialState(mState);
}
mesh.setRenderState(mState);
}
} else {
ColladaMaterialUtils.logger.warning("material effect not found: "