From 846b569552eb772eddde3bf68fa92fbfd8b648fc Mon Sep 17 00:00:00 2001 From: "Kae..pl" Date: Sat, 1 Oct 2011 12:27:41 +0000 Subject: [PATCH] Support for generated textures merging. Optimizations in textures loading when multiple textures are applied. Fixes in pixel blending. git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@8324 75d07b2b-3a1a-0410-a2c5-0572b91ccdca --- .../plugins/blender/cameras/CameraHelper.java | 7 +- .../blender/materials/MaterialContext.java | 293 +++++++++++++++++- .../blender/materials/MaterialHelper.java | 258 +++------------ .../blender/textures/TextureGenerator.java | 18 +- .../textures/TextureGeneratorBlend.java | 7 +- .../textures/TextureGeneratorClouds.java | 8 +- .../textures/TextureGeneratorDistnoise.java | 9 +- .../textures/TextureGeneratorMagic.java | 12 +- .../textures/TextureGeneratorMarble.java | 7 +- .../textures/TextureGeneratorMusgrave.java | 7 +- .../textures/TextureGeneratorNoise.java | 9 +- .../textures/TextureGeneratorStucci.java | 8 +- .../textures/TextureGeneratorVoronoi.java | 9 +- .../textures/TextureGeneratorWood.java | 7 +- .../blender/textures/TextureHelper.java | 127 ++++++-- .../blender/textures/TexturePixel.java | 95 ++++++ 16 files changed, 586 insertions(+), 295 deletions(-) create mode 100644 engine/src/blender/com/jme3/scene/plugins/blender/textures/TexturePixel.java diff --git a/engine/src/blender/com/jme3/scene/plugins/blender/cameras/CameraHelper.java b/engine/src/blender/com/jme3/scene/plugins/blender/cameras/CameraHelper.java index 19aae9676..e4a907731 100644 --- a/engine/src/blender/com/jme3/scene/plugins/blender/cameras/CameraHelper.java +++ b/engine/src/blender/com/jme3/scene/plugins/blender/cameras/CameraHelper.java @@ -17,8 +17,8 @@ import com.jme3.scene.plugins.blender.file.Structure; public class CameraHelper extends AbstractBlenderHelper { private static final Logger LOGGER = Logger.getLogger(CameraHelper.class.getName()); - protected static final int DEFAULT_CAM_WIDTH = 100; - protected static final int DEFAULT_CAM_HEIGHT = 100; + protected static final int DEFAULT_CAM_WIDTH = 640; + protected static final int DEFAULT_CAM_HEIGHT = 480; /** * This constructor parses the given blender version and stores the result. Some functionalities may differ in @@ -98,7 +98,6 @@ public class CameraHelper extends AbstractBlenderHelper { } //type==0 - perspective; type==1 - orthographic; perspective is used as default result.setParallelProjection(type == 1); - float angle = ((Number) structure.getFieldValue("angle")).floatValue(); float aspect = 0; float clipsta = ((Number) structure.getFieldValue("clipsta")).floatValue(); float clipend = ((Number) structure.getFieldValue("clipend")).floatValue(); @@ -107,7 +106,7 @@ public class CameraHelper extends AbstractBlenderHelper { } else { aspect = ((Number) structure.getFieldValue("ortho_scale")).floatValue(); } - result.setFrustumPerspective(angle, aspect, clipsta, clipend); + result.setFrustumPerspective(aspect, result.getWidth() / result.getHeight(), clipsta, clipend); return result; } diff --git a/engine/src/blender/com/jme3/scene/plugins/blender/materials/MaterialContext.java b/engine/src/blender/com/jme3/scene/plugins/blender/materials/MaterialContext.java index 1fc0bf503..57cccf4ed 100644 --- a/engine/src/blender/com/jme3/scene/plugins/blender/materials/MaterialContext.java +++ b/engine/src/blender/com/jme3/scene/plugins/blender/materials/MaterialContext.java @@ -1,31 +1,58 @@ package com.jme3.scene.plugins.blender.materials; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; +import java.util.Map.Entry; import java.util.logging.Level; import java.util.logging.Logger; +import com.jme3.math.ColorRGBA; import com.jme3.scene.plugins.blender.BlenderContext; import com.jme3.scene.plugins.blender.exceptions.BlenderFileException; import com.jme3.scene.plugins.blender.file.DynamicArray; import com.jme3.scene.plugins.blender.file.Pointer; import com.jme3.scene.plugins.blender.file.Structure; +import com.jme3.scene.plugins.blender.materials.MaterialHelper.DiffuseShader; +import com.jme3.scene.plugins.blender.materials.MaterialHelper.SpecularShader; import com.jme3.scene.plugins.blender.textures.TextureHelper; +import com.jme3.texture.Texture; import com.jme3.texture.Texture.Type; +import com.jme3.texture.Texture.WrapMode; +/** + * This class holds the data about the material. + * @author Marcin Roguski (Kaelthas) + */ public final class MaterialContext { private static final Logger LOGGER = Logger.getLogger(MaterialContext.class.getName()); + //texture mapping types + public static final int MTEX_COL = 0x01; + public static final int MTEX_NOR = 0x02; + public static final int MTEX_SPEC = 0x04; + public static final int MTEX_EMIT = 0x40; + public static final int MTEX_ALPHA = 0x80; + /* package */final String name; /* package */final List mTexs; /* package */final List textures; + /* package */final Map loadedTextures; + /* package */final Map textureToMTexMap; /* package */final int texturesCount; /* package */final Type textureType; + /* package */final ColorRGBA diffuseColor; + /* package */final DiffuseShader diffuseShader; + /* package */final SpecularShader specularShader; + /* package */final ColorRGBA specularColor; + /* package */final ColorRGBA ambientColor; + /* package */final float shininess; /* package */final boolean shadeless; /* package */final boolean vertexColor; /* package */final boolean transparent; - /* package */final boolean vtangent; + /* package */final boolean vTangent; /* package */int uvCoordinatesType = -1; /* package */int projectionType; @@ -38,10 +65,37 @@ public final class MaterialContext { shadeless = (mode & 0x4) != 0; vertexColor = (mode & 0x80) != 0; transparent = (mode & 0x10000) != 0; - vtangent = (mode & 0x4000000) != 0; // NOTE: Requires tangents + vTangent = (mode & 0x4000000) != 0; // NOTE: Requires tangents + int diff_shader = ((Number) structure.getFieldValue("diff_shader")).intValue(); + diffuseShader = DiffuseShader.values()[diff_shader]; + + if(this.shadeless) { + diffuseColor = ColorRGBA.White.clone(); + specularShader = null; + specularColor = ambientColor = null; + shininess = 0.0f; + } else { + diffuseColor = this.readDiffuseColor(structure, diffuseShader); + + int spec_shader = ((Number) structure.getFieldValue("spec_shader")).intValue(); + specularShader = SpecularShader.values()[spec_shader]; + specularColor = this.readSpecularColor(structure, specularShader); + + float r = ((Number) structure.getFieldValue("ambr")).floatValue(); + float g = ((Number) structure.getFieldValue("ambg")).floatValue(); + float b = ((Number) structure.getFieldValue("ambb")).floatValue(); + float alpha = ((Number) structure.getFieldValue("alpha")).floatValue(); + ambientColor = new ColorRGBA(r, g, b, alpha); + + float shininess = ((Number) structure.getFieldValue("emit")).floatValue(); + this.shininess = shininess > 0.0f ? shininess : MaterialHelper.DEFAULT_SHININESS; + } + float[] diffuseColorArray = new float[] {diffuseColor.r, diffuseColor.g, diffuseColor.b, diffuseColor.a};//TODO: czy trzeba wstawiac te dane? + mTexs = new ArrayList(); textures = new ArrayList(); + DynamicArray mtexsArray = (DynamicArray) structure.getFieldValue("mtex"); int separatedTextures = ((Number) structure.getFieldValue("septex")).intValue(); Type firstTextureType = null; @@ -79,10 +133,89 @@ public final class MaterialContext { } } } + + //loading the textures and merging them + Map> sortedTextures = this.sortAndFilterTextures(); + loadedTextures = new HashMap(sortedTextures.size()); + textureToMTexMap = new HashMap(); + TextureHelper textureHelper = blenderContext.getHelper(TextureHelper.class); + for(Entry> entry : sortedTextures.entrySet()) { + if(entry.getValue().size()>0) { + List textures = new ArrayList(entry.getValue().size()); + for(Structure[] mtexAndTex : entry.getValue()) { + int texflag = ((Number) mtexAndTex[0].getFieldValue("texflag")).intValue(); + boolean negateTexture = (texflag & 0x04) != 0; + Texture texture = textureHelper.getTexture(mtexAndTex[1], blenderContext); + int blendType = ((Number) mtexAndTex[0].getFieldValue("blendtype")).intValue(); + float[] color = new float[] { ((Number) mtexAndTex[0].getFieldValue("r")).floatValue(), + ((Number) mtexAndTex[0].getFieldValue("g")).floatValue(), + ((Number) mtexAndTex[0].getFieldValue("b")).floatValue() }; + float colfac = ((Number) mtexAndTex[0].getFieldValue("colfac")).floatValue(); + texture = textureHelper.blendTexture(diffuseColorArray, texture, color, colfac, blendType, negateTexture, blenderContext); + texture.setWrap(WrapMode.Repeat); + textures.add(texture); + textureToMTexMap.put(texture, mtexAndTex[0]); + } + loadedTextures.put(entry.getKey(), textureHelper.mergeTextures(textures, this)); + } + } this.texturesCount = mTexs.size(); this.textureType = firstTextureType; } + + /** + * This method sorts the textures by their mapping type. + * In each group only textures of one type are put (either two- or three-dimensional). + * If the mapping type is MTEX_COL then if the texture has no alpha channel then all textures before it are + * discarded and will not be loaded and merged because texture with no alpha will cover them anyway. + * @return a map with sorted and filtered textures + */ + private Map> sortAndFilterTextures() { + Map> result = new HashMap>(); + for (int i = 0; i < mTexs.size(); ++i) { + Structure mTex = mTexs.get(i); + Structure texture = textures.get(i); + Number mapto = (Number) mTex.getFieldValue("mapto"); + List mtexs = result.get(mapto); + if(mtexs==null) { + mtexs = new ArrayList(); + result.put(mapto, mtexs); + } + if(mapto.intValue() == MTEX_COL && this.isWithoutAlpha(textures.get(i))) { + mtexs.clear();//remove previous textures, they will be covered anyway + } + mtexs.add(new Structure[] {mTex, texture}); + } + return result; + } + + /** + * This method determines if the given texture has no alpha channel. + * + * @param texture + * the texture to check for alpha channel + * @return true if the texture has no alpha channel and false + * otherwise + */ + private boolean isWithoutAlpha(Structure texture) { + int flag = ((Number) texture.getFieldValue("flag")).intValue(); + if((flag & 0x01) == 0) {//the texture has no colorband + int type = ((Number) texture.getFieldValue("type")).intValue(); + if(type==TextureHelper.TEX_MAGIC) { + return true; + } + if(type==TextureHelper.TEX_VORONOI) { + int voronoiColorType = ((Number) texture.getFieldValue("vn_coltype")).intValue(); + return voronoiColorType != 0;//voronoiColorType == 0: intensity, voronoiColorType != 0: col1, col2 or col3 + } + if(type==TextureHelper.TEX_CLOUDS) { + int sType = ((Number) texture.getFieldValue("stype")).intValue(); + return sType == 1;//sType==0: without colors, sType==1: with colors + } + } + return false; + } /** * This method returns the current material's texture UV coordinates type. @@ -133,6 +266,74 @@ public final class MaterialContext { Structure mtex = mTexs.get(textureIndex); return new int[] { ((Number) mtex.getFieldValue("projx")).intValue(), ((Number) mtex.getFieldValue("projy")).intValue(), ((Number) mtex.getFieldValue("projz")).intValue() }; } + + /** + * This method returns the diffuse color. + * + * @param materialStructure the material structure + * @param diffuseShader the diffuse shader + * @return the diffuse color + */ + private ColorRGBA readDiffuseColor(Structure materialStructure, DiffuseShader diffuseShader) { + // bitwise 'or' of all textures mappings + int commonMapto = ((Number) materialStructure.getFieldValue("mapto")).intValue(); + + // diffuse color + float r = ((Number) materialStructure.getFieldValue("r")).floatValue(); + float g = ((Number) materialStructure.getFieldValue("g")).floatValue(); + float b = ((Number) materialStructure.getFieldValue("b")).floatValue(); + float alpha = ((Number) materialStructure.getFieldValue("alpha")).floatValue(); + if ((commonMapto & 0x01) == 0x01) {// Col + return new ColorRGBA(r, g, b, alpha); + } else { + switch (diffuseShader) { + case FRESNEL: + case ORENNAYAR: + case TOON: + break;// TODO: find what is the proper modification + case MINNAERT: + case LAMBERT:// TODO: check if that is correct + float ref = ((Number) materialStructure.getFieldValue("ref")).floatValue(); + r *= ref; + g *= ref; + b *= ref; + break; + default: + throw new IllegalStateException("Unknown diffuse shader type: " + diffuseShader.toString()); + } + return new ColorRGBA(r, g, b, alpha); + } + } + + /** + * This method returns a specular color used by the material. + * + * @param materialStructure + * the material structure filled with data + * @return a specular color used by the material + */ + private ColorRGBA readSpecularColor(Structure materialStructure, SpecularShader specularShader) { + float r = ((Number) materialStructure.getFieldValue("specr")).floatValue(); + float g = ((Number) materialStructure.getFieldValue("specg")).floatValue(); + float b = ((Number) materialStructure.getFieldValue("specb")).floatValue(); + float alpha = ((Number) materialStructure.getFieldValue("alpha")).floatValue(); + switch (specularShader) { + case BLINN: + case COOKTORRENCE: + case TOON: + case WARDISO:// TODO: find what is the proper modification + break; + case PHONG:// TODO: check if that is correct + float spec = ((Number) materialStructure.getFieldValue("spec")).floatValue(); + r *= spec * 0.5f; + g *= spec * 0.5f; + b *= spec * 0.5f; + break; + default: + throw new IllegalStateException("Unknown specular shader type: " + specularShader.toString()); + } + return new ColorRGBA(r, g, b, alpha); + } /** * This method determines the type of the texture. @@ -167,4 +368,92 @@ public final class MaterialContext { throw new IllegalStateException("Unknown texture type: " + texType); } } + + /** + * @return he material's name + */ + public String getName() { + return name; + } + + /** + * @return a copy of diffuse color + */ + public ColorRGBA getDiffuseColor() { + return diffuseColor.clone(); + } + + /** + * @return an enum describing the type of a diffuse shader used by this material + */ + public DiffuseShader getDiffuseShader() { + return diffuseShader; + } + + /** + * @return a copy of specular color + */ + public ColorRGBA getSpecularColor() { + return specularColor.clone(); + } + + /** + * @return an enum describing the type of a specular shader used by this material + */ + public SpecularShader getSpecularShader() { + return specularShader; + } + + /** + * @return an ambient color used by the material + */ + public ColorRGBA getAmbientColor() { + return ambientColor; + } + + /** + * @return the sihiness of this material + */ + public float getShininess() { + return shininess; + } + + /** + * @return true if the material is shadeless and false otherwise + */ + public boolean isShadeless() { + return shadeless; + } + + /** + * @return true if the material uses vertex color and false otherwise + */ + public boolean isVertexColor() { + return vertexColor; + } + + /** + * @return true if the material is transparent and false otherwise + */ + public boolean isTransparent() { + return transparent; + } + + /** + * @return true if the material uses tangents and false otherwise + */ + public boolean isvTangent() { + return vTangent; + } + + /** + * @param texture + * the texture for which its mtex structure definition will be + * fetched + * @return mtex structure of the current texture or null if none + * exists + */ + public Structure getMTex(Texture texture) { + return textureToMTexMap.get(texture); + } } diff --git a/engine/src/blender/com/jme3/scene/plugins/blender/materials/MaterialHelper.java b/engine/src/blender/com/jme3/scene/plugins/blender/materials/MaterialHelper.java index 4f4dcb5c3..05fe74210 100644 --- a/engine/src/blender/com/jme3/scene/plugins/blender/materials/MaterialHelper.java +++ b/engine/src/blender/com/jme3/scene/plugins/blender/materials/MaterialHelper.java @@ -40,7 +40,6 @@ import java.util.logging.Level; import java.util.logging.Logger; import com.jme3.asset.BlenderKey.FeaturesToLoad; -import com.jme3.asset.GeneratedTextureKey; import com.jme3.material.MatParam; import com.jme3.material.MatParamTexture; import com.jme3.material.Material; @@ -59,9 +58,7 @@ import com.jme3.shader.VarType; import com.jme3.texture.Image; import com.jme3.texture.Image.Format; import com.jme3.texture.Texture; -import com.jme3.texture.Texture.MinFilter; import com.jme3.texture.Texture.Type; -import com.jme3.texture.Texture.WrapMode; import com.jme3.util.BufferUtils; public class MaterialHelper extends AbstractBlenderHelper { @@ -204,124 +201,66 @@ public class MaterialHelper extends AbstractBlenderHelper { if(materialContext.textures.size() > 0) { LOGGER.log(Level.WARNING, "Attetion! Many textures found for material: {0}. Only the first of each supported mapping types will be used!", materialContext.name); } - - DiffuseShader diffuseShader = this.getDiffuseShader(structure); - ColorRGBA diffuseColor = this.getDiffuseColor(structure, diffuseShader); - float[] diffuseColorArray = new float[] {diffuseColor.r, diffuseColor.g, diffuseColor.b}; // texture + Type colorTextureType = null; Map texturesMap = new HashMap(); - Type firstTextureType = null; - if ((blenderContext.getBlenderKey().getFeaturesToLoad() & FeaturesToLoad.TEXTURES) != 0) { - TextureHelper textureHelper = blenderContext.getHelper(TextureHelper.class); - for (int i=0;i textureEntry : materialContext.loadedTextures.entrySet()) { + int mapto = textureEntry.getKey().intValue(); + Texture texture = textureEntry.getValue(); + if ((mapto & MaterialContext.MTEX_COL) != 0) { + colorTextureType = texture.getType(); + if (materialContext.shadeless) { + texturesMap.put(colorTextureType==Type.ThreeDimensional ? TEXTURE_TYPE_3D : TEXTURE_TYPE_COLOR, texture); + } else { + texturesMap.put(colorTextureType==Type.ThreeDimensional ? TEXTURE_TYPE_3D : TEXTURE_TYPE_DIFFUSE, texture); + } + } + if(texture.getType()==Type.TwoDimensional) {//so far only 2D textures can be mapped in other way than color + if ((mapto & MaterialContext.MTEX_NOR) != 0 && !materialContext.shadeless) { + Structure mTex = materialContext.getMTex(texture); + Texture normalMapTexture = textureHelper.convertToNormalMapTexture(texture, ((Number) mTex.getFieldValue("norfac")).floatValue()); + texturesMap.put(TEXTURE_TYPE_NORMAL, normalMapTexture); + } + if ((mapto & MaterialContext.MTEX_EMIT) != 0) { + texturesMap.put(TEXTURE_TYPE_GLOW, texture); + } + if ((mapto & MaterialContext.MTEX_SPEC) != 0 && !materialContext.shadeless) { + texturesMap.put(TEXTURE_TYPE_SPECULAR, texture); + } + if ((mapto & MaterialContext.MTEX_ALPHA) != 0 && !materialContext.shadeless) { + texturesMap.put(TEXTURE_TYPE_ALPHA, texture); } } } //creating the material - if(firstTextureType==Type.ThreeDimensional) { + if(colorTextureType==Type.ThreeDimensional) { result = new Material(blenderContext.getAssetManager(), "jme3test/texture/tex3D.j3md"); } else { if (materialContext.shadeless) { result = new Material(blenderContext.getAssetManager(), "Common/MatDefs/Misc/Unshaded.j3md"); } else { result = new Material(blenderContext.getAssetManager(), "Common/MatDefs/Light/Lighting.j3md"); - } - - if (materialContext.vertexColor) { - result.setBoolean(materialContext.shadeless ? "VertexColor" : "UseVertexColor", true); - } - - if (materialContext.shadeless) { - // color of shadeless? doesn't seem to work in blender .. - diffuseColor = ColorRGBA.White.clone(); - } else { result.setBoolean("UseMaterialColors", Boolean.TRUE); // setting the colors - result.setBoolean("Minnaert", diffuseShader == DiffuseShader.MINNAERT); + result.setBoolean("Minnaert", materialContext.diffuseShader == DiffuseShader.MINNAERT); if (!materialContext.transparent) { - diffuseColor.a = 1; + materialContext.diffuseColor.a = 1; } - result.setColor("Diffuse", diffuseColor); + result.setColor("Diffuse", materialContext.diffuseColor); - SpecularShader specularShader = this.getSpecularShader(structure); - result.setBoolean("WardIso", specularShader == SpecularShader.WARDISO); - result.setColor("Specular", this.getSpecularColor(structure, specularShader)); + result.setBoolean("WardIso", materialContext.specularShader == SpecularShader.WARDISO); + result.setColor("Specular", materialContext.specularColor); - result.setColor("Ambient", this.getAmbientColor(structure)); - result.setFloat("Shininess", this.getShininess(structure)); + result.setColor("Ambient", materialContext.ambientColor); + result.setFloat("Shininess", materialContext.shininess); + } + + if (materialContext.vertexColor) { + result.setBoolean(materialContext.shadeless ? "VertexColor" : "UseVertexColor", true); } } @@ -487,125 +426,6 @@ public class MaterialHelper extends AbstractBlenderHelper { return false; } - /** - * This method returns the diffuse color - * - * @param materialStructure - * @param diffuseShader - * @return - */ - public ColorRGBA getDiffuseColor(Structure materialStructure, DiffuseShader diffuseShader) { - // bitwise 'or' of all textures mappings - int commonMapto = ((Number) materialStructure.getFieldValue("mapto")).intValue(); - - // diffuse color - float r = ((Number) materialStructure.getFieldValue("r")).floatValue(); - float g = ((Number) materialStructure.getFieldValue("g")).floatValue(); - float b = ((Number) materialStructure.getFieldValue("b")).floatValue(); - float alpha = ((Number) materialStructure.getFieldValue("alpha")).floatValue(); - if ((commonMapto & 0x01) == 0x01) {// Col - return new ColorRGBA(r, g, b, alpha); - } else { - switch (diffuseShader) { - case FRESNEL: - case ORENNAYAR: - case TOON: - break;// TODO: find what is the proper modification - case MINNAERT: - case LAMBERT:// TODO: check if that is correct - float ref = ((Number) materialStructure.getFieldValue("ref")).floatValue(); - r *= ref; - g *= ref; - b *= ref; - break; - default: - throw new IllegalStateException("Unknown diffuse shader type: " + diffuseShader.toString()); - } - return new ColorRGBA(r, g, b, alpha); - } - } - - /** - * This method returns an enum describing the type of a diffuse shader used by this material. - * - * @param materialStructure - * the material structure filled with data - * @return an enum describing the type of a diffuse shader used by this material - */ - public DiffuseShader getDiffuseShader(Structure materialStructure) { - int diff_shader = ((Number) materialStructure.getFieldValue("diff_shader")).intValue(); - return DiffuseShader.values()[diff_shader]; - } - - /** - * This method returns an ambient color used by the material. - * - * @param materialStructure - * the material structure filled with data - * @return an ambient color used by the material - */ - public ColorRGBA getAmbientColor(Structure materialStructure) { - float r = ((Number) materialStructure.getFieldValue("ambr")).floatValue(); - float g = ((Number) materialStructure.getFieldValue("ambg")).floatValue(); - float b = ((Number) materialStructure.getFieldValue("ambb")).floatValue(); - float alpha = ((Number) materialStructure.getFieldValue("alpha")).floatValue(); - return new ColorRGBA(r, g, b, alpha); - } - - /** - * This method returns an enum describing the type of a specular shader used by this material. - * - * @param materialStructure - * the material structure filled with data - * @return an enum describing the type of a specular shader used by this material - */ - public SpecularShader getSpecularShader(Structure materialStructure) { - int spec_shader = ((Number) materialStructure.getFieldValue("spec_shader")).intValue(); - return SpecularShader.values()[spec_shader]; - } - - /** - * This method returns a specular color used by the material. - * - * @param materialStructure - * the material structure filled with data - * @return a specular color used by the material - */ - public ColorRGBA getSpecularColor(Structure materialStructure, SpecularShader specularShader) { - float r = ((Number) materialStructure.getFieldValue("specr")).floatValue(); - float g = ((Number) materialStructure.getFieldValue("specg")).floatValue(); - float b = ((Number) materialStructure.getFieldValue("specb")).floatValue(); - float alpha = ((Number) materialStructure.getFieldValue("alpha")).floatValue(); - switch (specularShader) { - case BLINN: - case COOKTORRENCE: - case TOON: - case WARDISO:// TODO: find what is the proper modification - break; - case PHONG:// TODO: check if that is correct - float spec = ((Number) materialStructure.getFieldValue("spec")).floatValue(); - r *= spec * 0.5f; - g *= spec * 0.5f; - b *= spec * 0.5f; - break; - default: - throw new IllegalStateException("Unknown specular shader type: " + specularShader.toString()); - } - return new ColorRGBA(r, g, b, alpha); - } - - /** - * This method returns the sihiness of this material or DEFAULT_SHININESS value if not present. - * - * @param materialStructure - * the material structure filled with data - * @return the sihiness of this material or DEFAULT_SHININESS value if not present - */ - public float getShininess(Structure materialStructure) { - float shininess = ((Number) materialStructure.getFieldValue("emit")).floatValue(); - return shininess > 0.0f ? shininess : DEFAULT_SHININESS; - } - /** * This method returns the table of materials connected to the specified structure. The given structure can be of any type (ie. mesh or * curve) but needs to have 'mat' field/ diff --git a/engine/src/blender/com/jme3/scene/plugins/blender/textures/TextureGenerator.java b/engine/src/blender/com/jme3/scene/plugins/blender/textures/TextureGenerator.java index 5176ed4cd..8bf852c49 100644 --- a/engine/src/blender/com/jme3/scene/plugins/blender/textures/TextureGenerator.java +++ b/engine/src/blender/com/jme3/scene/plugins/blender/textures/TextureGenerator.java @@ -278,7 +278,7 @@ import com.jme3.texture.Texture; * @param tex texture structure * @param texres */ - protected void applyBrightnessAndContrast(BrightnessAndContrastData bacd, TextureResult texres) { + protected void applyBrightnessAndContrast(BrightnessAndContrastData bacd, TexturePixel texres) { texres.red = (texres.red - 0.5f) * bacd.contrast + bacd.brightness; if (texres.red < 0.0f) { texres.red = 0.0f; @@ -299,7 +299,7 @@ import com.jme3.texture.Texture; * @param contrast * @param brightness */ - protected void applyBrightnessAndContrast(TextureResult texres, float contrast, float brightness) { + protected void applyBrightnessAndContrast(TexturePixel texres, float contrast, float brightness) { texres.intensity = (texres.intensity - 0.5f) * contrast + brightness; if (texres.intensity < 0.0f) { texres.intensity = 0.0f; @@ -308,20 +308,6 @@ import com.jme3.texture.Texture; } } - /** - * The result pixel of generated texture computations; - * - * @author Marcin Roguski (Kaelthas) - */ - protected static class TextureResult implements Cloneable { - public float intensity, red, green, blue, alpha; - - @Override - public Object clone() throws CloneNotSupportedException { - return super.clone(); - } - } - /** * A class constaining the colorband data. * diff --git a/engine/src/blender/com/jme3/scene/plugins/blender/textures/TextureGeneratorBlend.java b/engine/src/blender/com/jme3/scene/plugins/blender/textures/TextureGeneratorBlend.java index 3528f3be9..aa31fb055 100644 --- a/engine/src/blender/com/jme3/scene/plugins/blender/textures/TextureGeneratorBlend.java +++ b/engine/src/blender/com/jme3/scene/plugins/blender/textures/TextureGeneratorBlend.java @@ -118,13 +118,13 @@ public final class TextureGeneratorBlend extends TextureGenerator { protected Texture generate(Structure tex, int width, int height, int depth, BlenderContext blenderContext) { int flag = ((Number) tex.getFieldValue("flag")).intValue(); int stype = ((Number) tex.getFieldValue("stype")).intValue(); - TextureResult texres = new TextureResult(); + TexturePixel texres = new TexturePixel(); int halfW = width >> 1, halfH = height >> 1, halfD = depth >> 1, index = 0; float wDelta = 1.0f / halfW, hDelta = 1.0f / halfH, dDelta = 1.0f / halfD, x, y; float[][] colorBand = this.computeColorband(tex, blenderContext); BrightnessAndContrastData bacd = new BrightnessAndContrastData(tex); - Format format = colorBand != null ? Format.RGB8 : Format.Luminance8; - int bytesPerPixel = colorBand != null ? 3 : 1; + Format format = colorBand != null ? Format.RGBA8 : Format.Luminance8; + int bytesPerPixel = colorBand != null ? 4 : 1; boolean flipped = (flag & NoiseGenerator.TEX_FLIPBLEND) != 0; byte[] data = new byte[width * height * depth * bytesPerPixel]; @@ -150,6 +150,7 @@ public final class TextureGeneratorBlend extends TextureGenerator { data[index++] = (byte) (texres.red * 255.0f); data[index++] = (byte) (texres.green * 255.0f); data[index++] = (byte) (texres.blue * 255.0f); + data[index++] = (byte) (colorBand[colorbandIndex][3] * 255.0f); } else { this.applyBrightnessAndContrast(texres, bacd.contrast, bacd.brightness); data[index++] = (byte) (texres.intensity * 255.0f); diff --git a/engine/src/blender/com/jme3/scene/plugins/blender/textures/TextureGeneratorClouds.java b/engine/src/blender/com/jme3/scene/plugins/blender/textures/TextureGeneratorClouds.java index fdd3cf78f..8be396831 100644 --- a/engine/src/blender/com/jme3/scene/plugins/blender/textures/TextureGeneratorClouds.java +++ b/engine/src/blender/com/jme3/scene/plugins/blender/textures/TextureGeneratorClouds.java @@ -68,7 +68,7 @@ public class TextureGeneratorClouds extends TextureGenerator { @Override protected Texture generate(Structure tex, int width, int height, int depth, BlenderContext blenderContext) { float[] texvec = new float[] { 0, 0, 0 }; - TextureResult texres = new TextureResult(); + TexturePixel texres = new TexturePixel(); // reading the data from the texture structure float noisesize = ((Number) tex.getFieldValue("noisesize")).floatValue(); @@ -80,8 +80,8 @@ public class TextureGeneratorClouds extends TextureGenerator { int halfW = width >> 1, halfH = height >> 1, halfD = depth >> 1, index = 0; float wDelta = 1.0f / halfW, hDelta = 1.0f / halfH, dDelta = 1.0f / halfD; float[][] colorBand = this.computeColorband(tex, blenderContext); - Format format = sType == TEX_COLOR || colorBand != null ? Format.RGB8 : Format.Luminance8; - int bytesPerPixel = sType == TEX_COLOR || colorBand != null ? 3 : 1; + Format format = sType == TEX_COLOR || colorBand != null ? Format.RGBA8 : Format.Luminance8; + int bytesPerPixel = sType == TEX_COLOR || colorBand != null ? 4 : 1; BrightnessAndContrastData bacd = new BrightnessAndContrastData(tex); byte[] data = new byte[width * height * depth * bytesPerPixel]; @@ -103,6 +103,7 @@ public class TextureGeneratorClouds extends TextureGenerator { data[index++] = (byte) (texres.red * 255.0f); data[index++] = (byte) (texres.green * 255.0f); data[index++] = (byte) (texres.blue * 255.0f); + data[index++] = (byte) (colorBand[colorbandIndex][3] * 255.0f); } else if (sType == TEX_COLOR) { texres.red = texres.intensity; texres.green = NoiseGenerator.NoiseFunctions.turbulence(texvec[1], texvec[0], texvec[2], noisesize, noiseDepth, noiseBasis, isHard); @@ -115,6 +116,7 @@ public class TextureGeneratorClouds extends TextureGenerator { data[index++] = (byte) (texres.red * 255.0f); data[index++] = (byte) (texres.green * 255.0f); data[index++] = (byte) (texres.blue * 255.0f); + data[index++] = (byte) (255);//1.0f * 255.0f } else { this.applyBrightnessAndContrast(texres, bacd.contrast, bacd.brightness); data[index++] = (byte) (texres.intensity * 255.0f); diff --git a/engine/src/blender/com/jme3/scene/plugins/blender/textures/TextureGeneratorDistnoise.java b/engine/src/blender/com/jme3/scene/plugins/blender/textures/TextureGeneratorDistnoise.java index 4f7d07b0d..f4a549ec2 100644 --- a/engine/src/blender/com/jme3/scene/plugins/blender/textures/TextureGeneratorDistnoise.java +++ b/engine/src/blender/com/jme3/scene/plugins/blender/textures/TextureGeneratorDistnoise.java @@ -34,6 +34,7 @@ package com.jme3.scene.plugins.blender.textures; import java.nio.ByteBuffer; import java.util.ArrayList; +import com.jme3.math.FastMath; import com.jme3.scene.plugins.blender.BlenderContext; import com.jme3.scene.plugins.blender.file.Structure; import com.jme3.scene.plugins.blender.textures.NoiseGenerator.NoiseFunction; @@ -65,13 +66,13 @@ public class TextureGeneratorDistnoise extends TextureGenerator { int noisebasis = ((Number) tex.getFieldValue("noisebasis")).intValue(); int noisebasis2 = ((Number) tex.getFieldValue("noisebasis2")).intValue(); - TextureResult texres = new TextureResult(); + TexturePixel texres = new TexturePixel(); float[] texvec = new float[] { 0, 0, 0 }; int halfW = width >> 1, halfH = height >> 1, halfD = depth >> 1, index = 0; float wDelta = 1.0f / halfW, hDelta = 1.0f / halfH, dDelta = 1.0f / halfD; float[][] colorBand = this.computeColorband(tex, blenderContext); - Format format = colorBand != null ? Format.RGB8 : Format.Luminance8; - int bytesPerPixel = colorBand != null ? 3 : 1; + Format format = colorBand != null ? Format.RGBA8 : Format.Luminance8; + int bytesPerPixel = colorBand != null ? 4 : 1; BrightnessAndContrastData bacd = new BrightnessAndContrastData(tex); byte[] data = new byte[width * height * depth * bytesPerPixel]; @@ -82,6 +83,7 @@ public class TextureGeneratorDistnoise extends TextureGenerator { for (int k = -halfD; k < halfD; ++k) { texvec[2] = dDelta * k; texres.intensity = this.musgraveVariableLunacrityNoise(texvec[0], texvec[1], texvec[2], distAmount, noisebasis, noisebasis2); + texres.intensity = FastMath.clamp(texres.intensity, 0.0f, 1.0f); if (colorBand != null) { int colorbandIndex = (int) (texres.intensity * 1000.0f); texres.red = colorBand[colorbandIndex][0]; @@ -92,6 +94,7 @@ public class TextureGeneratorDistnoise extends TextureGenerator { data[index++] = (byte) (texres.red * 255.0f); data[index++] = (byte) (texres.green * 255.0f); data[index++] = (byte) (texres.blue * 255.0f); + data[index++] = (byte) (colorBand[colorbandIndex][3] * 255.0f); } else { this.applyBrightnessAndContrast(texres, bacd.contrast, bacd.brightness); data[index++] = (byte) (texres.intensity * 255.0f); diff --git a/engine/src/blender/com/jme3/scene/plugins/blender/textures/TextureGeneratorMagic.java b/engine/src/blender/com/jme3/scene/plugins/blender/textures/TextureGeneratorMagic.java index a6d051a47..3b8c009d7 100644 --- a/engine/src/blender/com/jme3/scene/plugins/blender/textures/TextureGeneratorMagic.java +++ b/engine/src/blender/com/jme3/scene/plugins/blender/textures/TextureGeneratorMagic.java @@ -34,6 +34,7 @@ package com.jme3.scene.plugins.blender.textures; import java.nio.ByteBuffer; import java.util.ArrayList; +import com.jme3.math.FastMath; import com.jme3.scene.plugins.blender.BlenderContext; import com.jme3.scene.plugins.blender.file.Structure; import com.jme3.texture.Image; @@ -126,13 +127,13 @@ public class TextureGeneratorMagic extends TextureGenerator { int noisedepth = ((Number) tex.getFieldValue("noisedepth")).intValue(); float turbul = ((Number) tex.getFieldValue("turbul")).floatValue() / 5.0f; float[] texvec = new float[] { 0, 0, 0 }; - TextureResult texres = new TextureResult(); + TexturePixel texres = new TexturePixel(); int halfW = width >> 1, halfH = height >> 1, halfD = depth >> 1, index = 0; float wDelta = 1.0f / halfW, hDelta = 1.0f / halfH, dDelta = 1.0f / halfD; float[][] colorBand = this.computeColorband(tex, blenderContext); BrightnessAndContrastData bacd = new BrightnessAndContrastData(tex); - byte[] data = new byte[width * height * depth * 3]; + byte[] data = new byte[width * height * depth * 4]; for (int i = -halfW; i < halfW; ++i) { texvec[0] = wDelta * i; for (int j = -halfH; j < halfH; ++j) { @@ -145,11 +146,12 @@ public class TextureGeneratorMagic extends TextureGenerator { xyz[2] = -(float) Math.cos((-texvec[0] - texvec[1] + texvec[2]) * 5.0f); if (colorBand != null) { - texres.intensity = 0.3333f * (xyz[0] + xyz[1] + xyz[2]); + texres.intensity = FastMath.clamp(0.3333f * (xyz[0] + xyz[1] + xyz[2]), 0.0f, 1.0f); int colorbandIndex = (int) (texres.intensity * 1000.0f); texres.red = colorBand[colorbandIndex][0]; texres.green = colorBand[colorbandIndex][1]; texres.blue = colorBand[colorbandIndex][2]; + texres.alpha = colorBand[colorbandIndex][3]; } else { if (noisedepth > 0) { xyz[0] *= turb; @@ -169,17 +171,19 @@ public class TextureGeneratorMagic extends TextureGenerator { texres.red = 0.5f - xyz[0]; texres.green = 0.5f - xyz[1]; texres.blue = 0.5f - xyz[2]; + texres.alpha = 1.0f; } this.applyBrightnessAndContrast(bacd, texres); data[index++] = (byte) (texres.red * 255.0f); data[index++] = (byte) (texres.green * 255.0f); data[index++] = (byte) (texres.blue * 255.0f); + data[index++] = (byte) (texres.alpha * 255.0f); } } } ArrayList dataArray = new ArrayList(1); dataArray.add(BufferUtils.createByteBuffer(data)); - return new Texture3D(new Image(Format.RGB8, width, height, depth, dataArray)); + return new Texture3D(new Image(Format.RGBA8, width, height, depth, dataArray)); } private static interface NoiseDepthFunction { diff --git a/engine/src/blender/com/jme3/scene/plugins/blender/textures/TextureGeneratorMarble.java b/engine/src/blender/com/jme3/scene/plugins/blender/textures/TextureGeneratorMarble.java index 47148564f..45b56fa31 100644 --- a/engine/src/blender/com/jme3/scene/plugins/blender/textures/TextureGeneratorMarble.java +++ b/engine/src/blender/com/jme3/scene/plugins/blender/textures/TextureGeneratorMarble.java @@ -64,12 +64,12 @@ public class TextureGeneratorMarble extends TextureGeneratorWood { @Override protected Texture generate(Structure tex, int width, int height, int depth, BlenderContext blenderContext) { float[] texvec = new float[] { 0, 0, 0 }; - TextureResult texres = new TextureResult(); + TexturePixel texres = new TexturePixel(); int halfW = width >> 1, halfH = height >> 1, halfD = depth >> 1, index = 0; float wDelta = 1.0f / halfW, hDelta = 1.0f / halfH, dDelta = 1.0f / halfD; float[][] colorBand = this.computeColorband(tex, blenderContext); - Format format = colorBand != null ? Format.RGB8 : Format.Luminance8; - int bytesPerPixel = colorBand != null ? 3 : 1; + Format format = colorBand != null ? Format.RGBA8 : Format.Luminance8; + int bytesPerPixel = colorBand != null ? 4 : 1; BrightnessAndContrastData bacd = new BrightnessAndContrastData(tex); MarbleData marbleData = new MarbleData(tex); @@ -91,6 +91,7 @@ public class TextureGeneratorMarble extends TextureGeneratorWood { data[index++] = (byte) (texres.red * 255.0f); data[index++] = (byte) (texres.green * 255.0f); data[index++] = (byte) (texres.blue * 255.0f); + data[index++] = (byte) (colorBand[colorbandIndex][3] * 255.0f); } else { this.applyBrightnessAndContrast(texres, bacd.contrast, bacd.brightness); data[index++] = (byte) (texres.intensity * 255.0f); diff --git a/engine/src/blender/com/jme3/scene/plugins/blender/textures/TextureGeneratorMusgrave.java b/engine/src/blender/com/jme3/scene/plugins/blender/textures/TextureGeneratorMusgrave.java index 94479aeee..6b794ff8c 100644 --- a/engine/src/blender/com/jme3/scene/plugins/blender/textures/TextureGeneratorMusgrave.java +++ b/engine/src/blender/com/jme3/scene/plugins/blender/textures/TextureGeneratorMusgrave.java @@ -62,13 +62,13 @@ public class TextureGeneratorMusgrave extends TextureGenerator { protected Texture generate(Structure tex, int width, int height, int depth, BlenderContext blenderContext) { int stype = ((Number) tex.getFieldValue("stype")).intValue(); float noisesize = ((Number) tex.getFieldValue("noisesize")).floatValue(); - TextureResult texres = new TextureResult(); + TexturePixel texres = new TexturePixel(); float[] texvec = new float[] { 0, 0, 0 }; int halfW = width >> 1, halfH = height >> 1, halfD = depth >> 1, index = 0; float wDelta = 1.0f / halfW, hDelta = 1.0f / halfH, dDelta = 1.0f / halfD; float[][] colorBand = this.computeColorband(tex, blenderContext); - Format format = colorBand != null ? Format.RGB8 : Format.Luminance8; - int bytesPerPixel = colorBand != null ? 3 : 1; + Format format = colorBand != null ? Format.RGBA8 : Format.Luminance8; + int bytesPerPixel = colorBand != null ? 4 : 1; MusgraveData musgraveData = new MusgraveData(tex); MusgraveFunction musgraveFunction; BrightnessAndContrastData bacd = new BrightnessAndContrastData(tex); @@ -101,6 +101,7 @@ public class TextureGeneratorMusgrave extends TextureGenerator { data[index++] = (byte) (texres.red * 255.0f); data[index++] = (byte) (texres.green * 255.0f); data[index++] = (byte) (texres.blue * 255.0f); + data[index++] = (byte) (colorBand[colorbandIndex][3] * 255.0f); } else { this.applyBrightnessAndContrast(bacd, texres); data[index++] = (byte) (texres.intensity * 255.0f); diff --git a/engine/src/blender/com/jme3/scene/plugins/blender/textures/TextureGeneratorNoise.java b/engine/src/blender/com/jme3/scene/plugins/blender/textures/TextureGeneratorNoise.java index cadba7c8e..832532156 100644 --- a/engine/src/blender/com/jme3/scene/plugins/blender/textures/TextureGeneratorNoise.java +++ b/engine/src/blender/com/jme3/scene/plugins/blender/textures/TextureGeneratorNoise.java @@ -62,11 +62,11 @@ public class TextureGeneratorNoise extends TextureGenerator { protected Texture generate(Structure tex, int width, int height, int depth, BlenderContext blenderContext) { int val, random, loop; int noisedepth = ((Number) tex.getFieldValue("noisedepth")).intValue(); - TextureResult texres = new TextureResult(); + TexturePixel texres = new TexturePixel(); int halfW = width >> 1, halfH = height >> 1, halfD = depth >> 1, index = 0; float[][] colorBand = this.computeColorband(tex, blenderContext); - Format format = colorBand != null ? Format.RGB8 : Format.Luminance8; - int bytesPerPixel = colorBand != null ? 3 : 1; + Format format = colorBand != null ? Format.RGBA8 : Format.Luminance8; + int bytesPerPixel = colorBand != null ? 4 : 1; BrightnessAndContrastData bacd = new BrightnessAndContrastData(tex); byte[] data = new byte[width * height * depth * bytesPerPixel]; @@ -81,7 +81,7 @@ public class TextureGeneratorNoise extends TextureGenerator { random >>= 2; val *= random & 3; } - texres.intensity = val; + texres.intensity = FastMath.clamp(val, 0.0f, 1.0f); if (colorBand != null) { int colorbandIndex = (int) (texres.intensity * 1000.0f); texres.red = colorBand[colorbandIndex][0]; @@ -92,6 +92,7 @@ public class TextureGeneratorNoise extends TextureGenerator { data[index++] = (byte) (texres.red * 255.0f); data[index++] = (byte) (texres.green * 255.0f); data[index++] = (byte) (texres.blue * 255.0f); + data[index++] = (byte) (colorBand[colorbandIndex][3] * 255.0f); } else { this.applyBrightnessAndContrast(texres, bacd.contrast, bacd.brightness); data[index++] = (byte) (texres.intensity * 255.0f); diff --git a/engine/src/blender/com/jme3/scene/plugins/blender/textures/TextureGeneratorStucci.java b/engine/src/blender/com/jme3/scene/plugins/blender/textures/TextureGeneratorStucci.java index 3fd4e54e8..50651c405 100644 --- a/engine/src/blender/com/jme3/scene/plugins/blender/textures/TextureGeneratorStucci.java +++ b/engine/src/blender/com/jme3/scene/plugins/blender/textures/TextureGeneratorStucci.java @@ -72,12 +72,12 @@ public class TextureGeneratorStucci extends TextureGenerator { } float[] texvec = new float[] { 0, 0, 0 }; - TextureResult texres = new TextureResult(); + TexturePixel texres = new TexturePixel(); int halfW = width >> 1, halfH = height >> 1, halfD = depth >> 1, index = 0; float wDelta = 1.0f / halfW, hDelta = 1.0f / halfH, dDelta = 1.0f / halfD, noiseValue, ofs;; float[][] colorBand = this.computeColorband(tex, blenderContext); - Format format = colorBand != null ? Format.RGB8 : Format.Luminance8; - int bytesPerPixel = colorBand != null ? 3 : 1; + Format format = colorBand != null ? Format.RGBA8 : Format.Luminance8; + int bytesPerPixel = colorBand != null ? 4 : 1; byte[] data = new byte[width * height * depth * bytesPerPixel]; for (int i = -halfW; i < halfW; ++i) { @@ -98,6 +98,7 @@ public class TextureGeneratorStucci extends TextureGenerator { texres.red = colorBand[colorbandIndex][0]; texres.green = colorBand[colorbandIndex][1]; texres.blue = colorBand[colorbandIndex][2]; + texres.alpha = colorBand[colorbandIndex][3]; } if (stype == NoiseGenerator.TEX_WALLOUT) { @@ -111,6 +112,7 @@ public class TextureGeneratorStucci extends TextureGenerator { data[index++] = (byte) (texres.red * 255.0f); data[index++] = (byte) (texres.green * 255.0f); data[index++] = (byte) (texres.blue * 255.0f); + data[index++] = (byte) (texres.alpha * 255.0f); } else { data[index++] = (byte) (texres.intensity * 255.0f); } diff --git a/engine/src/blender/com/jme3/scene/plugins/blender/textures/TextureGeneratorVoronoi.java b/engine/src/blender/com/jme3/scene/plugins/blender/textures/TextureGeneratorVoronoi.java index fe1b40dd9..ffc96d882 100644 --- a/engine/src/blender/com/jme3/scene/plugins/blender/textures/TextureGeneratorVoronoi.java +++ b/engine/src/blender/com/jme3/scene/plugins/blender/textures/TextureGeneratorVoronoi.java @@ -71,14 +71,14 @@ public class TextureGeneratorVoronoi extends TextureGenerator { int distm = ((Number) tex.getFieldValue("vn_distm")).intValue(); int voronoiColorType = ((Number) tex.getFieldValue("vn_coltype")).intValue(); - TextureResult texres = new TextureResult(); + TexturePixel texres = new TexturePixel(); float[] texvec = new float[] { 0, 0, 0 }; int halfW = width >> 1, halfH = height >> 1, halfD = depth >> 1, index = 0; float wDelta = 1.0f / halfW, hDelta = 1.0f / halfH, dDelta = 1.0f / halfD; float[][] colorBand = this.computeColorband(tex, blenderContext); - Format format = voronoiColorType != 0 || colorBand != null ? Format.RGB8 : Format.Luminance8; - int bytesPerPixel = voronoiColorType != 0 || colorBand != null ? 3 : 1; + Format format = voronoiColorType != 0 || colorBand != null ? Format.RGBA8 : Format.Luminance8; + int bytesPerPixel = voronoiColorType != 0 || colorBand != null ? 4 : 1; BrightnessAndContrastData bacd = new BrightnessAndContrastData(tex); float[] da = new float[4], pa = new float[12]; @@ -111,8 +111,10 @@ public class TextureGeneratorVoronoi extends TextureGenerator { texres.red = colorBand[colorbandIndex][0]; texres.green = colorBand[colorbandIndex][1]; texres.blue = colorBand[colorbandIndex][2]; + texres.alpha = colorBand[colorbandIndex][3]; } else if (voronoiColorType != 0) { texres.red = texres.green = texres.blue = 0.0f; + texres.alpha = 1.0f; for(int m=0; m<12; m+=3) { weight = voronoiWeights[m/3]; this.cellNoiseV(pa[m], pa[m + 1], pa[m + 2], hashPoint); @@ -145,6 +147,7 @@ public class TextureGeneratorVoronoi extends TextureGenerator { data[index++] = (byte) (texres.red * 255.0f); data[index++] = (byte) (texres.green * 255.0f); data[index++] = (byte) (texres.blue * 255.0f); + data[index++] = (byte) (texres.alpha * 255.0f); } else { this.applyBrightnessAndContrast(texres, bacd.contrast, bacd.brightness); data[index++] = (byte) (texres.intensity * 255.0f); diff --git a/engine/src/blender/com/jme3/scene/plugins/blender/textures/TextureGeneratorWood.java b/engine/src/blender/com/jme3/scene/plugins/blender/textures/TextureGeneratorWood.java index c7ed8946f..51ee5b48d 100644 --- a/engine/src/blender/com/jme3/scene/plugins/blender/textures/TextureGeneratorWood.java +++ b/engine/src/blender/com/jme3/scene/plugins/blender/textures/TextureGeneratorWood.java @@ -73,15 +73,15 @@ public class TextureGeneratorWood extends TextureGenerator { @Override protected Texture generate(Structure tex, int width, int height, int depth, BlenderContext blenderContext) { float[] texvec = new float[] { 0, 0, 0 }; - TextureResult texres = new TextureResult(); + TexturePixel texres = new TexturePixel(); int halfW = width >> 1; int halfH = height >> 1; int halfD = depth >> 1; float wDelta = 1.0f / halfW, hDelta = 1.0f / halfH, dDelta = 1.0f / halfD; float[][] colorBand = this.computeColorband(tex, blenderContext); - Format format = colorBand != null ? Format.RGB8 : Format.Luminance8; - int bytesPerPixel = colorBand != null ? 3 : 1; + Format format = colorBand != null ? Format.RGBA8 : Format.Luminance8; + int bytesPerPixel = colorBand != null ? 4 : 1; WoodIntensityData woodIntensityData = new WoodIntensityData(tex); BrightnessAndContrastData bacd = new BrightnessAndContrastData(tex); @@ -106,6 +106,7 @@ public class TextureGeneratorWood extends TextureGenerator { data[index++] = (byte) (texres.red * 255.0f); data[index++] = (byte) (texres.green * 255.0f); data[index++] = (byte) (texres.blue * 255.0f); + data[index++] = (byte) (colorBand[colorbandIndex][3] * 255.0f); } else { this.applyBrightnessAndContrast(texres, bacd.contrast, bacd.brightness); data[index++] = (byte) (texres.intensity * 255.0f); diff --git a/engine/src/blender/com/jme3/scene/plugins/blender/textures/TextureHelper.java b/engine/src/blender/com/jme3/scene/plugins/blender/textures/TextureHelper.java index bb1d47912..ff5b27415 100644 --- a/engine/src/blender/com/jme3/scene/plugins/blender/textures/TextureHelper.java +++ b/engine/src/blender/com/jme3/scene/plugins/blender/textures/TextureHelper.java @@ -50,6 +50,7 @@ import com.jme3.asset.BlenderKey; import com.jme3.asset.BlenderKey.FeaturesToLoad; import com.jme3.asset.GeneratedTextureKey; import com.jme3.asset.TextureKey; +import com.jme3.math.ColorRGBA; import com.jme3.math.FastMath; import com.jme3.math.Vector3f; import com.jme3.scene.plugins.blender.AbstractBlenderHelper; @@ -59,10 +60,12 @@ import com.jme3.scene.plugins.blender.exceptions.BlenderFileException; import com.jme3.scene.plugins.blender.file.FileBlockHeader; import com.jme3.scene.plugins.blender.file.Pointer; import com.jme3.scene.plugins.blender.file.Structure; +import com.jme3.scene.plugins.blender.materials.MaterialContext; import com.jme3.scene.plugins.blender.materials.MaterialHelper; import com.jme3.texture.Image; import com.jme3.texture.Image.Format; import com.jme3.texture.Texture; +import com.jme3.texture.Texture.MinFilter; import com.jme3.texture.Texture.WrapMode; import com.jme3.texture.Texture2D; import com.jme3.texture.Texture3D; @@ -215,6 +218,8 @@ public class TextureHelper extends AbstractBlenderHelper { if (result != null) { result.setName(tex.getName()); result.setWrap(WrapMode.Repeat); + // NOTE: Enable mipmaps FOR ALL TEXTURES EVER + result.setMinFilter(MinFilter.Trilinear); if(type != TEX_IMAGE) {//only generated textures should have this key result.setKey(new GeneratedTextureKey(tex.getName())); } @@ -261,7 +266,7 @@ public class TextureHelper extends AbstractBlenderHelper { newData.put(dataIndex++, (byte) (resultPixel[0] * 255.0f)); newData.put(dataIndex++, (byte) (resultPixel[1] * 255.0f)); newData.put(dataIndex++, (byte) (resultPixel[2] * 255.0f)); - newData.put(dataIndex++, (byte) 255.0f);//1.0f * 255.0f + newData.put(dataIndex++, (byte) (materialColorClone[3] * 255.0f)); } if(texture.getType()==Texture.Type.TwoDimensional) { return new Texture2D(new Image(Format.RGBA8, width, height, newData)); @@ -272,6 +277,78 @@ public class TextureHelper extends AbstractBlenderHelper { } } + /** + * This method merges the given textures. The result texture has no alpha + * factor (is always opaque). + * + * @param sources + * the textures to be merged + * @param materialContext + * the context of the material + * @return merged textures + */ + public Texture mergeTextures(List sources, MaterialContext materialContext) { + Texture result = null; + if(sources!=null && sources.size()>0) { + //checking the sizes of the textures (tehy should perfectly match) + int lastTextureWithoutAlphaIndex = 0; + int width = sources.get(0).getImage().getWidth(); + int height = sources.get(0).getImage().getHeight(); + int depth = sources.get(0).getImage().getDepth(); + + for(Texture source : sources) { + if(source.getImage().getWidth() != width) { + throw new IllegalArgumentException("The texture " + source.getName() + " has invalid width! It should be: " + width + '!'); + } + if(source.getImage().getHeight() != height) { + throw new IllegalArgumentException("The texture " + source.getName() + " has invalid height! It should be: " + height + '!'); + } + if(source.getImage().getDepth() != depth) { + throw new IllegalArgumentException("The texture " + source.getName() + " has invalid depth! It should be: " + depth + '!'); + } + //support for more formats is not necessary at the moment + if(source.getImage().getFormat()!=Format.RGB8 && source.getImage().getFormat()!=Format.BGR8) { + ++lastTextureWithoutAlphaIndex; + } + } + + //remove textures before the one without alpha (they will be covered anyway) + if(lastTextureWithoutAlphaIndex > 0 && lastTextureWithoutAlphaIndex arrayData = new ArrayList(1); + arrayData.add(data); + //TODO: add different texture types + result = new Texture3D(new Image(Format.RGB8, width, height, depth, arrayData)); + } + return result; + } + /** * This method alters the material color in a way dependent on the type of the image. * For example the color remains untouched if the texture is of Luminance type. @@ -293,46 +370,52 @@ public class TextureHelper extends AbstractBlenderHelper { protected float setupMaterialColor(ByteBuffer data, Format imageFormat, boolean neg, float[] materialColor) { float tin = 0.0f; byte pixelValue = data.get();// at least one byte is always taken :) - float firstPixelValue = pixelValue >= 0 ? 1.0f - pixelValue / 255.0f : (~pixelValue + 1) / 255.0f; + float firstPixelValue = pixelValue >= 0 ? pixelValue / 255.0f : 1.0f - (~pixelValue) / 255.0f; switch (imageFormat) { + case Luminance8: + tin = neg ? 1.0f - firstPixelValue : firstPixelValue; + materialColor[3] = tin; + neg = false;//do not negate the materialColor, it must be unchanged + break; + case RGBA8: + materialColor[0] = firstPixelValue; + pixelValue = data.get(); + materialColor[1] = pixelValue >= 0 ? pixelValue / 255.0f : 1.0f - (~pixelValue) / 255.0f; + pixelValue = data.get(); + materialColor[2] = pixelValue >= 0 ? pixelValue / 255.0f : 1.0f - (~pixelValue) / 255.0f; + pixelValue = data.get(); + materialColor[3] = pixelValue >= 0 ? pixelValue / 255.0f : 1.0f - (~pixelValue) / 255.0f; + break; case ABGR8: + materialColor[3] = firstPixelValue; pixelValue = data.get(); - materialColor[2] = pixelValue >= 0 ? 1.0f - pixelValue / 255.0f : (~pixelValue + 1) / 255.0f; + materialColor[2] = pixelValue >= 0 ? pixelValue / 255.0f : 1.0f - (~pixelValue) / 255.0f; pixelValue = data.get(); - materialColor[1] = pixelValue >= 0 ? 1.0f - pixelValue / 255.0f : (~pixelValue + 1) / 255.0f; + materialColor[1] = pixelValue >= 0 ? pixelValue / 255.0f : 1.0f - (~pixelValue) / 255.0f; pixelValue = data.get(); - materialColor[0] = pixelValue >= 0 ? 1.0f - pixelValue / 255.0f : (~pixelValue + 1) / 255.0f; + materialColor[0] = pixelValue >= 0 ? pixelValue / 255.0f : 1.0f - (~pixelValue) / 255.0f; break; case BGR8: materialColor[2] = firstPixelValue; pixelValue = data.get(); - materialColor[1] = pixelValue >= 0 ? 1.0f - pixelValue / 255.0f : (~pixelValue + 1) / 255.0f; + materialColor[1] = pixelValue >= 0 ? pixelValue / 255.0f : 1.0f - (~pixelValue) / 255.0f; pixelValue = data.get(); - materialColor[0] = pixelValue >= 0 ? 1.0f - pixelValue / 255.0f : (~pixelValue + 1) / 255.0f; + materialColor[0] = pixelValue >= 0 ? pixelValue / 255.0f : 1.0f - (~pixelValue) / 255.0f; + materialColor[3] = 1.0f; break; case RGB8: materialColor[0] = firstPixelValue; pixelValue = data.get(); - materialColor[1] = pixelValue >= 0 ? 1.0f - pixelValue / 255.0f : (~pixelValue + 1) / 255.0f; + materialColor[1] = pixelValue >= 0 ? pixelValue / 255.0f : 1.0f - (~pixelValue) / 255.0f; pixelValue = data.get(); - materialColor[2] = pixelValue >= 0 ? 1.0f - pixelValue / 255.0f : (~pixelValue + 1) / 255.0f; - break; - case RGBA8: - materialColor[0] = firstPixelValue; - pixelValue = data.get(); - materialColor[1] = pixelValue >= 0 ? 1.0f - pixelValue / 255.0f : (~pixelValue + 1) / 255.0f; - pixelValue = data.get(); - materialColor[2] = pixelValue >= 0 ? 1.0f - pixelValue / 255.0f : (~pixelValue + 1) / 255.0f; - data.get(); // ignore alpha - break; - case Luminance8: - tin = neg ? 1.0f - firstPixelValue : firstPixelValue; - neg = false;//do not negate the materialColor, it must be unchanged + materialColor[2] = pixelValue >= 0 ? pixelValue / 255.0f : 1.0f - (~pixelValue) / 255.0f; + materialColor[3] = 1.0f; break; case Luminance8Alpha8: tin = neg ? 1.0f - firstPixelValue : firstPixelValue; neg = false;//do not negate the materialColor, it must be unchanged - data.get(); // ignore alpha + pixelValue = data.get(); // ignore alpha + materialColor[3] = pixelValue >= 0 ? pixelValue / 255.0f : 1.0f - (~pixelValue) / 255.0f; break; case Luminance16: case Luminance16Alpha16: diff --git a/engine/src/blender/com/jme3/scene/plugins/blender/textures/TexturePixel.java b/engine/src/blender/com/jme3/scene/plugins/blender/textures/TexturePixel.java new file mode 100644 index 000000000..2481ace10 --- /dev/null +++ b/engine/src/blender/com/jme3/scene/plugins/blender/textures/TexturePixel.java @@ -0,0 +1,95 @@ +package com.jme3.scene.plugins.blender.textures; + +import java.nio.ByteBuffer; +import java.util.logging.Level; +import java.util.logging.Logger; + +import com.jme3.math.ColorRGBA; +import com.jme3.texture.Image.Format; + +/*package*/ class TexturePixel implements Cloneable { + private static final Logger LOGGER = Logger.getLogger(TexturePixel.class.getName()); + + public float intensity, red, green, blue, alpha; + + public void fromColor(ColorRGBA colorRGBA) { + this.intensity = 0; + this.red = colorRGBA.r; + this.green = colorRGBA.g; + this.blue = colorRGBA.b; + this.alpha = colorRGBA.a; + } + + public void fromImage(Format imageFormat, ByteBuffer data, int pixelIndex) { + int firstByteIndex; + byte pixelValue; + switch(imageFormat) { + case ABGR8: + firstByteIndex = pixelIndex << 2; + pixelValue = data.get(firstByteIndex); + this.alpha = pixelValue >= 0 ? pixelValue / 255.0f : 1.0f - (~pixelValue) / 255.0f; + pixelValue = data.get(firstByteIndex + 1); + this.blue = pixelValue >= 0 ? pixelValue / 255.0f : 1.0f - (~pixelValue) / 255.0f; + pixelValue = data.get(firstByteIndex + 2); + this.green = pixelValue >= 0 ? pixelValue / 255.0f : 1.0f - (~pixelValue) / 255.0f; + pixelValue = data.get(firstByteIndex + 3); + this.red = pixelValue >= 0 ? pixelValue / 255.0f : 1.0f - (~pixelValue) / 255.0f; + break; + case RGBA8: + firstByteIndex = pixelIndex << 2; + pixelValue = data.get(firstByteIndex); + this.red = pixelValue >= 0 ? pixelValue / 255.0f : 1.0f - (~pixelValue) / 255.0f; + pixelValue = data.get(firstByteIndex + 1); + this.green = pixelValue >= 0 ? pixelValue / 255.0f : 1.0f - (~pixelValue) / 255.0f; + pixelValue = data.get(firstByteIndex + 2); + this.blue = pixelValue >= 0 ? pixelValue / 255.0f : 1.0f - (~pixelValue) / 255.0f; + pixelValue = data.get(firstByteIndex + 3); + this.alpha = pixelValue >= 0 ? pixelValue / 255.0f : 1.0f - (~pixelValue) / 255.0f; + break; + case BGR8: + firstByteIndex = pixelIndex * 3; + pixelValue = data.get(firstByteIndex); + this.blue = pixelValue >= 0 ? pixelValue / 255.0f : 1.0f - (~pixelValue) / 255.0f; + pixelValue = data.get(firstByteIndex + 1); + this.green = pixelValue >= 0 ? pixelValue / 255.0f : 1.0f - (~pixelValue) / 255.0f; + pixelValue = data.get(firstByteIndex + 2); + this.red = pixelValue >= 0 ? pixelValue / 255.0f : 1.0f - (~pixelValue) / 255.0f; + this.alpha = 1.0f; + break; + case RGB8: + firstByteIndex = pixelIndex * 3; + pixelValue = data.get(firstByteIndex); + this.red = pixelValue >= 0 ? pixelValue / 255.0f : 1.0f - (~pixelValue) / 255.0f; + pixelValue = data.get(firstByteIndex + 1); + this.green = pixelValue >= 0 ? pixelValue / 255.0f : 1.0f - (~pixelValue) / 255.0f; + pixelValue = data.get(firstByteIndex + 2); + this.blue = pixelValue >= 0 ? pixelValue / 255.0f : 1.0f - (~pixelValue) / 255.0f; + this.alpha = 1.0f; + break; + case Luminance8: + pixelValue = data.get(pixelIndex); + this.intensity = pixelValue >= 0 ? pixelValue / 255.0f : 1.0f - (~pixelValue) / 255.0f; + break; + default: + LOGGER.log(Level.FINEST, "Unknown type of texture: {0}. Black pixel used!", imageFormat); + this.intensity = this.blue = this.red = this.green = this.alpha = 0.0f; + } + } + + public void merge(TexturePixel pixel) { + float oneMinusAlpha = 1 - pixel.alpha; + this.red = oneMinusAlpha * this.red + pixel.alpha*pixel.red; + this.green = oneMinusAlpha * this.green + pixel.alpha*pixel.green; + this.blue = oneMinusAlpha * this.blue + pixel.alpha*pixel.blue; + //alpha should be always 1.0f as a result + } + + public void clear() { + this.intensity = this.blue = this.red = this.green = this.alpha = 0.0f; + } + + @Override + public Object clone() throws CloneNotSupportedException { + return super.clone(); + } +}