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
3.0
Kae..pl 13 years ago
parent a28d0d8baf
commit 846b569552
  1. 7
      engine/src/blender/com/jme3/scene/plugins/blender/cameras/CameraHelper.java
  2. 293
      engine/src/blender/com/jme3/scene/plugins/blender/materials/MaterialContext.java
  3. 258
      engine/src/blender/com/jme3/scene/plugins/blender/materials/MaterialHelper.java
  4. 18
      engine/src/blender/com/jme3/scene/plugins/blender/textures/TextureGenerator.java
  5. 7
      engine/src/blender/com/jme3/scene/plugins/blender/textures/TextureGeneratorBlend.java
  6. 8
      engine/src/blender/com/jme3/scene/plugins/blender/textures/TextureGeneratorClouds.java
  7. 9
      engine/src/blender/com/jme3/scene/plugins/blender/textures/TextureGeneratorDistnoise.java
  8. 12
      engine/src/blender/com/jme3/scene/plugins/blender/textures/TextureGeneratorMagic.java
  9. 7
      engine/src/blender/com/jme3/scene/plugins/blender/textures/TextureGeneratorMarble.java
  10. 7
      engine/src/blender/com/jme3/scene/plugins/blender/textures/TextureGeneratorMusgrave.java
  11. 9
      engine/src/blender/com/jme3/scene/plugins/blender/textures/TextureGeneratorNoise.java
  12. 8
      engine/src/blender/com/jme3/scene/plugins/blender/textures/TextureGeneratorStucci.java
  13. 9
      engine/src/blender/com/jme3/scene/plugins/blender/textures/TextureGeneratorVoronoi.java
  14. 7
      engine/src/blender/com/jme3/scene/plugins/blender/textures/TextureGeneratorWood.java
  15. 127
      engine/src/blender/com/jme3/scene/plugins/blender/textures/TextureHelper.java
  16. 95
      engine/src/blender/com/jme3/scene/plugins/blender/textures/TexturePixel.java

@ -17,8 +17,8 @@ import com.jme3.scene.plugins.blender.file.Structure;
public class CameraHelper extends AbstractBlenderHelper { public class CameraHelper extends AbstractBlenderHelper {
private static final Logger LOGGER = Logger.getLogger(CameraHelper.class.getName()); private static final Logger LOGGER = Logger.getLogger(CameraHelper.class.getName());
protected static final int DEFAULT_CAM_WIDTH = 100; protected static final int DEFAULT_CAM_WIDTH = 640;
protected static final int DEFAULT_CAM_HEIGHT = 100; protected static final int DEFAULT_CAM_HEIGHT = 480;
/** /**
* This constructor parses the given blender version and stores the result. Some functionalities may differ in * 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 //type==0 - perspective; type==1 - orthographic; perspective is used as default
result.setParallelProjection(type == 1); result.setParallelProjection(type == 1);
float angle = ((Number) structure.getFieldValue("angle")).floatValue();
float aspect = 0; float aspect = 0;
float clipsta = ((Number) structure.getFieldValue("clipsta")).floatValue(); float clipsta = ((Number) structure.getFieldValue("clipsta")).floatValue();
float clipend = ((Number) structure.getFieldValue("clipend")).floatValue(); float clipend = ((Number) structure.getFieldValue("clipend")).floatValue();
@ -107,7 +106,7 @@ public class CameraHelper extends AbstractBlenderHelper {
} else { } else {
aspect = ((Number) structure.getFieldValue("ortho_scale")).floatValue(); aspect = ((Number) structure.getFieldValue("ortho_scale")).floatValue();
} }
result.setFrustumPerspective(angle, aspect, clipsta, clipend); result.setFrustumPerspective(aspect, result.getWidth() / result.getHeight(), clipsta, clipend);
return result; return result;
} }

@ -1,31 +1,58 @@
package com.jme3.scene.plugins.blender.materials; package com.jme3.scene.plugins.blender.materials;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
import com.jme3.math.ColorRGBA;
import com.jme3.scene.plugins.blender.BlenderContext; import com.jme3.scene.plugins.blender.BlenderContext;
import com.jme3.scene.plugins.blender.exceptions.BlenderFileException; import com.jme3.scene.plugins.blender.exceptions.BlenderFileException;
import com.jme3.scene.plugins.blender.file.DynamicArray; import com.jme3.scene.plugins.blender.file.DynamicArray;
import com.jme3.scene.plugins.blender.file.Pointer; import com.jme3.scene.plugins.blender.file.Pointer;
import com.jme3.scene.plugins.blender.file.Structure; 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.scene.plugins.blender.textures.TextureHelper;
import com.jme3.texture.Texture;
import com.jme3.texture.Texture.Type; 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 { public final class MaterialContext {
private static final Logger LOGGER = Logger.getLogger(MaterialContext.class.getName()); 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 String name;
/* package */final List<Structure> mTexs; /* package */final List<Structure> mTexs;
/* package */final List<Structure> textures; /* package */final List<Structure> textures;
/* package */final Map<Number, Texture> loadedTextures;
/* package */final Map<Texture, Structure> textureToMTexMap;
/* package */final int texturesCount; /* package */final int texturesCount;
/* package */final Type textureType; /* 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 shadeless;
/* package */final boolean vertexColor; /* package */final boolean vertexColor;
/* package */final boolean transparent; /* package */final boolean transparent;
/* package */final boolean vtangent; /* package */final boolean vTangent;
/* package */int uvCoordinatesType = -1; /* package */int uvCoordinatesType = -1;
/* package */int projectionType; /* package */int projectionType;
@ -38,10 +65,37 @@ public final class MaterialContext {
shadeless = (mode & 0x4) != 0; shadeless = (mode & 0x4) != 0;
vertexColor = (mode & 0x80) != 0; vertexColor = (mode & 0x80) != 0;
transparent = (mode & 0x10000) != 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<Structure>(); mTexs = new ArrayList<Structure>();
textures = new ArrayList<Structure>(); textures = new ArrayList<Structure>();
DynamicArray<Pointer> mtexsArray = (DynamicArray<Pointer>) structure.getFieldValue("mtex"); DynamicArray<Pointer> mtexsArray = (DynamicArray<Pointer>) structure.getFieldValue("mtex");
int separatedTextures = ((Number) structure.getFieldValue("septex")).intValue(); int separatedTextures = ((Number) structure.getFieldValue("septex")).intValue();
Type firstTextureType = null; Type firstTextureType = null;
@ -79,10 +133,89 @@ public final class MaterialContext {
} }
} }
} }
//loading the textures and merging them
Map<Number, List<Structure[]>> sortedTextures = this.sortAndFilterTextures();
loadedTextures = new HashMap<Number, Texture>(sortedTextures.size());
textureToMTexMap = new HashMap<Texture, Structure>();
TextureHelper textureHelper = blenderContext.getHelper(TextureHelper.class);
for(Entry<Number, List<Structure[]>> entry : sortedTextures.entrySet()) {
if(entry.getValue().size()>0) {
List<Texture> textures = new ArrayList<Texture>(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.texturesCount = mTexs.size();
this.textureType = firstTextureType; 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<Number, List<Structure[]>> sortAndFilterTextures() {
Map<Number, List<Structure[]>> result = new HashMap<Number, List<Structure[]>>();
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<Structure[]> mtexs = result.get(mapto);
if(mtexs==null) {
mtexs = new ArrayList<Structure[]>();
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 <b>true</b> if the texture has no alpha channel and <b>false</b>
* 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. * This method returns the current material's texture UV coordinates type.
@ -133,6 +266,74 @@ public final class MaterialContext {
Structure mtex = mTexs.get(textureIndex); Structure mtex = mTexs.get(textureIndex);
return new int[] { ((Number) mtex.getFieldValue("projx")).intValue(), ((Number) mtex.getFieldValue("projy")).intValue(), ((Number) mtex.getFieldValue("projz")).intValue() }; 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. * This method determines the type of the texture.
@ -167,4 +368,92 @@ public final class MaterialContext {
throw new IllegalStateException("Unknown texture type: " + texType); 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 <b>true</b> if the material is shadeless and <b>false</b> otherwise
*/
public boolean isShadeless() {
return shadeless;
}
/**
* @return <b>true</b> if the material uses vertex color and <b>false</b> otherwise
*/
public boolean isVertexColor() {
return vertexColor;
}
/**
* @return <b>true</b> if the material is transparent and <b>false</b> otherwise
*/
public boolean isTransparent() {
return transparent;
}
/**
* @return <b>true</b> if the material uses tangents and <b>false</b> 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 <b>null</b> if none
* exists
*/
public Structure getMTex(Texture texture) {
return textureToMTexMap.get(texture);
}
} }

@ -40,7 +40,6 @@ import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
import com.jme3.asset.BlenderKey.FeaturesToLoad; import com.jme3.asset.BlenderKey.FeaturesToLoad;
import com.jme3.asset.GeneratedTextureKey;
import com.jme3.material.MatParam; import com.jme3.material.MatParam;
import com.jme3.material.MatParamTexture; import com.jme3.material.MatParamTexture;
import com.jme3.material.Material; import com.jme3.material.Material;
@ -59,9 +58,7 @@ import com.jme3.shader.VarType;
import com.jme3.texture.Image; import com.jme3.texture.Image;
import com.jme3.texture.Image.Format; import com.jme3.texture.Image.Format;
import com.jme3.texture.Texture; import com.jme3.texture.Texture;
import com.jme3.texture.Texture.MinFilter;
import com.jme3.texture.Texture.Type; import com.jme3.texture.Texture.Type;
import com.jme3.texture.Texture.WrapMode;
import com.jme3.util.BufferUtils; import com.jme3.util.BufferUtils;
public class MaterialHelper extends AbstractBlenderHelper { public class MaterialHelper extends AbstractBlenderHelper {
@ -204,124 +201,66 @@ public class MaterialHelper extends AbstractBlenderHelper {
if(materialContext.textures.size() > 0) { 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); 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 // texture
Type colorTextureType = null;
Map<String, Texture> texturesMap = new HashMap<String, Texture>(); Map<String, Texture> texturesMap = new HashMap<String, Texture>();
Type firstTextureType = null; TextureHelper textureHelper = blenderContext.getHelper(TextureHelper.class);
if ((blenderContext.getBlenderKey().getFeaturesToLoad() & FeaturesToLoad.TEXTURES) != 0) { for(Entry<Number, Texture> textureEntry : materialContext.loadedTextures.entrySet()) {
TextureHelper textureHelper = blenderContext.getHelper(TextureHelper.class); int mapto = textureEntry.getKey().intValue();
for (int i=0;i<materialContext.texturesCount;++i) { Texture texture = textureEntry.getValue();
Structure mtex = materialContext.mTexs.get(i); if ((mapto & MaterialContext.MTEX_COL) != 0) {
colorTextureType = texture.getType();
int texflag = ((Number) mtex.getFieldValue("texflag")).intValue(); if (materialContext.shadeless) {
boolean negateTexture = (texflag & 0x04) == 0; texturesMap.put(colorTextureType==Type.ThreeDimensional ? TEXTURE_TYPE_3D : TEXTURE_TYPE_COLOR, texture);
} else {
int mapto = ((Number) mtex.getFieldValue("mapto")).intValue(); texturesMap.put(colorTextureType==Type.ThreeDimensional ? TEXTURE_TYPE_3D : TEXTURE_TYPE_DIFFUSE, texture);
if (mapto != 0) { }
Structure tex = materialContext.textures.get(i); }
Texture texture = textureHelper.getTexture(tex, blenderContext); if(texture.getType()==Type.TwoDimensional) {//so far only 2D textures can be mapped in other way than color
if (texture != null) { if ((mapto & MaterialContext.MTEX_NOR) != 0 && !materialContext.shadeless) {
if(firstTextureType == null) { Structure mTex = materialContext.getMTex(texture);
firstTextureType = texture.getType(); Texture normalMapTexture = textureHelper.convertToNormalMapTexture(texture, ((Number) mTex.getFieldValue("norfac")).floatValue());
} else if(firstTextureType != texture.getType()) { texturesMap.put(TEXTURE_TYPE_NORMAL, normalMapTexture);
LOGGER.warning("The texture with the name: " + texture.getName() + " is of different type than the first applied texture! It will not be applied!"); }
continue; if ((mapto & MaterialContext.MTEX_EMIT) != 0) {
} texturesMap.put(TEXTURE_TYPE_GLOW, texture);
}
// NOTE: Enable mipmaps FOR ALL TEXTURES EVER if ((mapto & MaterialContext.MTEX_SPEC) != 0 && !materialContext.shadeless) {
texture.setMinFilter(MinFilter.Trilinear); texturesMap.put(TEXTURE_TYPE_SPECULAR, texture);
}
if ((mapto & 0x01) != 0) {// Col if ((mapto & MaterialContext.MTEX_ALPHA) != 0 && !materialContext.shadeless) {
mapto &= 0xFFFFFFFE;//this is temporary to force loading of one texture of a mapping type (will be removed when textures merging is created) texturesMap.put(TEXTURE_TYPE_ALPHA, texture);
// Map to COLOR channel or DIFFUSE
// Set diffuse to white so it doesn't get multiplied by texture
// result.setColor(shadeless ? "Color" : "Diffuse", ColorRGBA.White.clone());
// result.setBoolean("UseMaterialColors", Boolean.FALSE);
// blending the texture with material color and texture's defined color
int blendType = ((Number) mtex.getFieldValue("blendtype")).intValue();
float[] color = new float[] { ((Number) mtex.getFieldValue("r")).floatValue(), ((Number) mtex.getFieldValue("g")).floatValue(), ((Number) mtex.getFieldValue("b")).floatValue() };
float colfac = ((Number) mtex.getFieldValue("colfac")).floatValue();
texture = textureHelper.blendTexture(diffuseColorArray, texture, color, colfac, blendType, negateTexture, blenderContext);
texture.setWrap(WrapMode.Repeat);
//TODO: textures merging
if (materialContext.shadeless) {
texturesMap.put(firstTextureType==Type.ThreeDimensional ? TEXTURE_TYPE_3D : TEXTURE_TYPE_COLOR, texture);
} else {
texturesMap.put(firstTextureType==Type.ThreeDimensional ? TEXTURE_TYPE_3D : TEXTURE_TYPE_DIFFUSE, texture);
}
}
if(firstTextureType == Type.TwoDimensional) {//for now other mappings available for images only
if ((mapto & 0x02) != 0 && !materialContext.shadeless) {// Nor
mapto &= 0xFFFFFFFD;//this is temporary to force loading of one texture of a mapping type (will be removed when textures merging is created)
Texture normalMapTexture;
if (texture.getKey() instanceof GeneratedTextureKey) {
normalMapTexture = textureHelper.convertToNormalMapTexture(texture, ((Number) mtex.getFieldValue("norfac")).floatValue());
normalMapTexture.setMinFilter(MinFilter.Trilinear);
} else {
normalMapTexture = texture;
}
texturesMap.put(TEXTURE_TYPE_NORMAL, normalMapTexture);
}
if ((mapto & 0x04) != 0 && !materialContext.shadeless) {// Spec
mapto &= 0xFFFFFFFB;//this is temporary to force loading of one texture of a mapping type (will be removed when textures merging is created)
// Map to SPECULAR
texturesMap.put(TEXTURE_TYPE_SPECULAR, texture);
}
if ((mapto & 0x40) != 0) {// Emit
mapto &= 0xFFFFFFF8;//this is temporary to force loading of one texture of a mapping type (will be removed when textures merging is created)
texturesMap.put(TEXTURE_TYPE_GLOW, texture);
}
if ((mapto & 0x80) != 0 && !materialContext.shadeless) {// Alpha
mapto &= 0xFFFFFF7F;//this is temporary to force loading of one texture of a mapping type (will be removed when textures merging is created)
texturesMap.put(TEXTURE_TYPE_ALPHA, texture);
}
} else {
LOGGER.warning("The following mappings: [Nor, Spec, Alpha] are available for 2D textures only!");
}
} else {
LOGGER.log(Level.WARNING, "Texture not found!");
}
} }
} }
} }
//creating the material //creating the material
if(firstTextureType==Type.ThreeDimensional) { if(colorTextureType==Type.ThreeDimensional) {
result = new Material(blenderContext.getAssetManager(), "jme3test/texture/tex3D.j3md"); result = new Material(blenderContext.getAssetManager(), "jme3test/texture/tex3D.j3md");
} else { } else {
if (materialContext.shadeless) { if (materialContext.shadeless) {
result = new Material(blenderContext.getAssetManager(), "Common/MatDefs/Misc/Unshaded.j3md"); result = new Material(blenderContext.getAssetManager(), "Common/MatDefs/Misc/Unshaded.j3md");
} else { } else {
result = new Material(blenderContext.getAssetManager(), "Common/MatDefs/Light/Lighting.j3md"); 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); result.setBoolean("UseMaterialColors", Boolean.TRUE);
// setting the colors // setting the colors
result.setBoolean("Minnaert", diffuseShader == DiffuseShader.MINNAERT); result.setBoolean("Minnaert", materialContext.diffuseShader == DiffuseShader.MINNAERT);
if (!materialContext.transparent) { 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", materialContext.specularShader == SpecularShader.WARDISO);
result.setBoolean("WardIso", specularShader == SpecularShader.WARDISO); result.setColor("Specular", materialContext.specularColor);
result.setColor("Specular", this.getSpecularColor(structure, specularShader));
result.setColor("Ambient", this.getAmbientColor(structure)); result.setColor("Ambient", materialContext.ambientColor);
result.setFloat("Shininess", this.getShininess(structure)); 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; 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 * 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/ * curve) but needs to have 'mat' field/

@ -278,7 +278,7 @@ import com.jme3.texture.Texture;
* @param tex texture structure * @param tex texture structure
* @param texres * @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; texres.red = (texres.red - 0.5f) * bacd.contrast + bacd.brightness;
if (texres.red < 0.0f) { if (texres.red < 0.0f) {
texres.red = 0.0f; texres.red = 0.0f;
@ -299,7 +299,7 @@ import com.jme3.texture.Texture;
* @param contrast * @param contrast
* @param brightness * @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; texres.intensity = (texres.intensity - 0.5f) * contrast + brightness;
if (texres.intensity < 0.0f) { if (texres.intensity < 0.0f) {
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. * A class constaining the colorband data.
* *

@ -118,13 +118,13 @@ public final class TextureGeneratorBlend extends TextureGenerator {
protected Texture generate(Structure tex, int width, int height, int depth, BlenderContext blenderContext) { protected Texture generate(Structure tex, int width, int height, int depth, BlenderContext blenderContext) {
int flag = ((Number) tex.getFieldValue("flag")).intValue(); int flag = ((Number) tex.getFieldValue("flag")).intValue();
int stype = ((Number) tex.getFieldValue("stype")).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; 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 wDelta = 1.0f / halfW, hDelta = 1.0f / halfH, dDelta = 1.0f / halfD, x, y;
float[][] colorBand = this.computeColorband(tex, blenderContext); float[][] colorBand = this.computeColorband(tex, blenderContext);
BrightnessAndContrastData bacd = new BrightnessAndContrastData(tex); BrightnessAndContrastData bacd = new BrightnessAndContrastData(tex);
Format format = colorBand != null ? Format.RGB8 : Format.Luminance8; Format format = colorBand != null ? Format.RGBA8 : Format.Luminance8;
int bytesPerPixel = colorBand != null ? 3 : 1; int bytesPerPixel = colorBand != null ? 4 : 1;
boolean flipped = (flag & NoiseGenerator.TEX_FLIPBLEND) != 0; boolean flipped = (flag & NoiseGenerator.TEX_FLIPBLEND) != 0;
byte[] data = new byte[width * height * depth * bytesPerPixel]; 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.red * 255.0f);
data[index++] = (byte) (texres.green * 255.0f); data[index++] = (byte) (texres.green * 255.0f);
data[index++] = (byte) (texres.blue * 255.0f); data[index++] = (byte) (texres.blue * 255.0f);
data[index++] = (byte) (colorBand[colorbandIndex][3] * 255.0f);
} else { } else {
this.applyBrightnessAndContrast(texres, bacd.contrast, bacd.brightness); this.applyBrightnessAndContrast(texres, bacd.contrast, bacd.brightness);
data[index++] = (byte) (texres.intensity * 255.0f); data[index++] = (byte) (texres.intensity * 255.0f);

@ -68,7 +68,7 @@ public class TextureGeneratorClouds extends TextureGenerator {
@Override @Override
protected Texture generate(Structure tex, int width, int height, int depth, BlenderContext blenderContext) { protected Texture generate(Structure tex, int width, int height, int depth, BlenderContext blenderContext) {
float[] texvec = new float[] { 0, 0, 0 }; float[] texvec = new float[] { 0, 0, 0 };
TextureResult texres = new TextureResult(); TexturePixel texres = new TexturePixel();
// reading the data from the texture structure // reading the data from the texture structure
float noisesize = ((Number) tex.getFieldValue("noisesize")).floatValue(); 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; 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 wDelta = 1.0f / halfW, hDelta = 1.0f / halfH, dDelta = 1.0f / halfD;
float[][] colorBand = this.computeColorband(tex, blenderContext); float[][] colorBand = this.computeColorband(tex, blenderContext);
Format format = sType == TEX_COLOR || colorBand != null ? Format.RGB8 : Format.Luminance8; Format format = sType == TEX_COLOR || colorBand != null ? Format.RGBA8 : Format.Luminance8;
int bytesPerPixel = sType == TEX_COLOR || colorBand != null ? 3 : 1; int bytesPerPixel = sType == TEX_COLOR || colorBand != null ? 4 : 1;
BrightnessAndContrastData bacd = new BrightnessAndContrastData(tex); BrightnessAndContrastData bacd = new BrightnessAndContrastData(tex);
byte[] data = new byte[width * height * depth * bytesPerPixel]; 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.red * 255.0f);
data[index++] = (byte) (texres.green * 255.0f); data[index++] = (byte) (texres.green * 255.0f);
data[index++] = (byte) (texres.blue * 255.0f); data[index++] = (byte) (texres.blue * 255.0f);
data[index++] = (byte) (colorBand[colorbandIndex][3] * 255.0f);
} else if (sType == TEX_COLOR) { } else if (sType == TEX_COLOR) {
texres.red = texres.intensity; texres.red = texres.intensity;
texres.green = NoiseGenerator.NoiseFunctions.turbulence(texvec[1], texvec[0], texvec[2], noisesize, noiseDepth, noiseBasis, isHard); 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.red * 255.0f);
data[index++] = (byte) (texres.green * 255.0f); data[index++] = (byte) (texres.green * 255.0f);
data[index++] = (byte) (texres.blue * 255.0f); data[index++] = (byte) (texres.blue * 255.0f);
data[index++] = (byte) (255);//1.0f * 255.0f
} else { } else {
this.applyBrightnessAndContrast(texres, bacd.contrast, bacd.brightness); this.applyBrightnessAndContrast(texres, bacd.contrast, bacd.brightness);
data[index++] = (byte) (texres.intensity * 255.0f); data[index++] = (byte) (texres.intensity * 255.0f);

@ -34,6 +34,7 @@ package com.jme3.scene.plugins.blender.textures;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.util.ArrayList; import java.util.ArrayList;
import com.jme3.math.FastMath;
import com.jme3.scene.plugins.blender.BlenderContext; import com.jme3.scene.plugins.blender.BlenderContext;
import com.jme3.scene.plugins.blender.file.Structure; import com.jme3.scene.plugins.blender.file.Structure;
import com.jme3.scene.plugins.blender.textures.NoiseGenerator.NoiseFunction; 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 noisebasis = ((Number) tex.getFieldValue("noisebasis")).intValue();
int noisebasis2 = ((Number) tex.getFieldValue("noisebasis2")).intValue(); int noisebasis2 = ((Number) tex.getFieldValue("noisebasis2")).intValue();
TextureResult texres = new TextureResult(); TexturePixel texres = new TexturePixel();
float[] texvec = new float[] { 0, 0, 0 }; float[] texvec = new float[] { 0, 0, 0 };
int halfW = width >> 1, halfH = height >> 1, halfD = depth >> 1, index = 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 wDelta = 1.0f / halfW, hDelta = 1.0f / halfH, dDelta = 1.0f / halfD;
float[][] colorBand = this.computeColorband(tex, blenderContext); float[][] colorBand = this.computeColorband(tex, blenderContext);
Format format = colorBand != null ? Format.RGB8 : Format.Luminance8; Format format = colorBand != null ? Format.RGBA8 : Format.Luminance8;
int bytesPerPixel = colorBand != null ? 3 : 1; int bytesPerPixel = colorBand != null ? 4 : 1;
BrightnessAndContrastData bacd = new BrightnessAndContrastData(tex); BrightnessAndContrastData bacd = new BrightnessAndContrastData(tex);
byte[] data = new byte[width * height * depth * bytesPerPixel]; byte[] data = new byte[width * height * depth * bytesPerPixel];
@ -82,6 +83,7 @@ public class TextureGeneratorDistnoise extends TextureGenerator {
for (int k = -halfD; k < halfD; ++k) { for (int k = -halfD; k < halfD; ++k) {
texvec[2] = dDelta * k; texvec[2] = dDelta * k;
texres.intensity = this.musgraveVariableLunacrityNoise(texvec[0], texvec[1], texvec[2], distAmount, noisebasis, noisebasis2); 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) { if (colorBand != null) {
int colorbandIndex = (int) (texres.intensity * 1000.0f); int colorbandIndex = (int) (texres.intensity * 1000.0f);
texres.red = colorBand[colorbandIndex][0]; 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.red * 255.0f);
data[index++] = (byte) (texres.green * 255.0f); data[index++] = (byte) (texres.green * 255.0f);
data[index++] = (byte) (texres.blue * 255.0f); data[index++] = (byte) (texres.blue * 255.0f);
data[index++] = (byte) (colorBand[colorbandIndex][3] * 255.0f);
} else { } else {
this.applyBrightnessAndContrast(texres, bacd.contrast, bacd.brightness); this.applyBrightnessAndContrast(texres, bacd.contrast, bacd.brightness);
data[index++] = (byte) (texres.intensity * 255.0f); data[index++] = (byte) (texres.intensity * 255.0f);

@ -34,6 +34,7 @@ package com.jme3.scene.plugins.blender.textures;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.util.ArrayList; import java.util.ArrayList;
import com.jme3.math.FastMath;
import com.jme3.scene.plugins.blender.BlenderContext; import com.jme3.scene.plugins.blender.BlenderContext;
import com.jme3.scene.plugins.blender.file.Structure; import com.jme3.scene.plugins.blender.file.Structure;
import com.jme3.texture.Image; import com.jme3.texture.Image;
@ -126,13 +127,13 @@ public class TextureGeneratorMagic extends TextureGenerator {
int noisedepth = ((Number) tex.getFieldValue("noisedepth")).intValue(); int noisedepth = ((Number) tex.getFieldValue("noisedepth")).intValue();
float turbul = ((Number) tex.getFieldValue("turbul")).floatValue() / 5.0f; float turbul = ((Number) tex.getFieldValue("turbul")).floatValue() / 5.0f;
float[] texvec = new float[] { 0, 0, 0 }; 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; 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 wDelta = 1.0f / halfW, hDelta = 1.0f / halfH, dDelta = 1.0f / halfD;
float[][] colorBand = this.computeColorband(tex, blenderContext); float[][] colorBand = this.computeColorband(tex, blenderContext);
BrightnessAndContrastData bacd = new BrightnessAndContrastData(tex); 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) { for (int i = -halfW; i < halfW; ++i) {
texvec[0] = wDelta * i; texvec[0] = wDelta * i;
for (int j = -halfH; j < halfH; ++j) { 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); xyz[2] = -(float) Math.cos((-texvec[0] - texvec[1] + texvec[2]) * 5.0f);
if (colorBand != null) { 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); int colorbandIndex = (int) (texres.intensity * 1000.0f);
texres.red = colorBand[colorbandIndex][0]; texres.red = colorBand[colorbandIndex][0];
texres.green = colorBand[colorbandIndex][1]; texres.green = colorBand[colorbandIndex][1];
texres.blue = colorBand[colorbandIndex][2]; texres.blue = colorBand[colorbandIndex][2];
texres.alpha = colorBand[colorbandIndex][3];
} else { } else {
if (noisedepth > 0) { if (noisedepth > 0) {
xyz[0] *= turb; xyz[0] *= turb;
@ -169,17 +171,19 @@ public class TextureGeneratorMagic extends TextureGenerator {
texres.red = 0.5f - xyz[0]; texres.red = 0.5f - xyz[0];
texres.green = 0.5f - xyz[1]; texres.green = 0.5f - xyz[1];
texres.blue = 0.5f - xyz[2]; texres.blue = 0.5f - xyz[2];
texres.alpha = 1.0f;
} }
this.applyBrightnessAndContrast(bacd, texres); this.applyBrightnessAndContrast(bacd, texres);
data[index++] = (byte) (texres.red * 255.0f); data[index++] = (byte) (texres.red * 255.0f);
data[index++] = (byte) (texres.green * 255.0f); data[index++] = (byte) (texres.green * 255.0f);
data[index++] = (byte) (texres.blue * 255.0f); data[index++] = (byte) (texres.blue * 255.0f);
data[index++] = (byte) (texres.alpha * 255.0f);
} }
} }
} }
ArrayList<ByteBuffer> dataArray = new ArrayList<ByteBuffer>(1); ArrayList<ByteBuffer> dataArray = new ArrayList<ByteBuffer>(1);
dataArray.add(BufferUtils.createByteBuffer(data)); 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 { private static interface NoiseDepthFunction {

@ -64,12 +64,12 @@ public class TextureGeneratorMarble extends TextureGeneratorWood {
@Override @Override
protected Texture generate(Structure tex, int width, int height, int depth, BlenderContext blenderContext) { protected Texture generate(Structure tex, int width, int height, int depth, BlenderContext blenderContext) {
float[] texvec = new float[] { 0, 0, 0 }; 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; 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 wDelta = 1.0f / halfW, hDelta = 1.0f / halfH, dDelta = 1.0f / halfD;
float[][] colorBand = this.computeColorband(tex, blenderContext); float[][] colorBand = this.computeColorband(tex, blenderContext);
Format format = colorBand != null ? Format.RGB8 : Format.Luminance8; Format format = colorBand != null ? Format.RGBA8 : Format.Luminance8;
int bytesPerPixel = colorBand != null ? 3 : 1; int bytesPerPixel = colorBand != null ? 4 : 1;
BrightnessAndContrastData bacd = new BrightnessAndContrastData(tex); BrightnessAndContrastData bacd = new BrightnessAndContrastData(tex);
MarbleData marbleData = new MarbleData(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.red * 255.0f);
data[index++] = (byte) (texres.green * 255.0f); data[index++] = (byte) (texres.green * 255.0f);
data[index++] = (byte) (texres.blue * 255.0f); data[index++] = (byte) (texres.blue * 255.0f);
data[index++] = (byte) (colorBand[colorbandIndex][3] * 255.0f);
} else { } else {
this.applyBrightnessAndContrast(texres, bacd.contrast, bacd.brightness); this.applyBrightnessAndContrast(texres, bacd.contrast, bacd.brightness);
data[index++] = (byte) (texres.intensity * 255.0f); data[index++] = (byte) (texres.intensity * 255.0f);

@ -62,13 +62,13 @@ public class TextureGeneratorMusgrave extends TextureGenerator {
protected Texture generate(Structure tex, int width, int height, int depth, BlenderContext blenderContext) { protected Texture generate(Structure tex, int width, int height, int depth, BlenderContext blenderContext) {
int stype = ((Number) tex.getFieldValue("stype")).intValue(); int stype = ((Number) tex.getFieldValue("stype")).intValue();
float noisesize = ((Number) tex.getFieldValue("noisesize")).floatValue(); float noisesize = ((Number) tex.getFieldValue("noisesize")).floatValue();
TextureResult texres = new TextureResult(); TexturePixel texres = new TexturePixel();
float[] texvec = new float[] { 0, 0, 0 }; float[] texvec = new float[] { 0, 0, 0 };
int halfW = width >> 1, halfH = height >> 1, halfD = depth >> 1, index = 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 wDelta = 1.0f / halfW, hDelta = 1.0f / halfH, dDelta = 1.0f / halfD;
float[][] colorBand = this.computeColorband(tex, blenderContext); float[][] colorBand = this.computeColorband(tex, blenderContext);
Format format = colorBand != null ? Format.RGB8 : Format.Luminance8; Format format = colorBand != null ? Format.RGBA8 : Format.Luminance8;
int bytesPerPixel = colorBand != null ? 3 : 1; int bytesPerPixel = colorBand != null ? 4 : 1;
MusgraveData musgraveData = new MusgraveData(tex); MusgraveData musgraveData = new MusgraveData(tex);
MusgraveFunction musgraveFunction; MusgraveFunction musgraveFunction;
BrightnessAndContrastData bacd = new BrightnessAndContrastData(tex); 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.red * 255.0f);
data[index++] = (byte) (texres.green * 255.0f); data[index++] = (byte) (texres.green * 255.0f);
data[index++] = (byte) (texres.blue * 255.0f); data[index++] = (byte) (texres.blue * 255.0f);
data[index++] = (byte) (colorBand[colorbandIndex][3] * 255.0f);
} else { } else {
this.applyBrightnessAndContrast(bacd, texres); this.applyBrightnessAndContrast(bacd, texres);
data[index++] = (byte) (texres.intensity * 255.0f); data[index++] = (byte) (texres.intensity * 255.0f);

@ -62,11 +62,11 @@ public class TextureGeneratorNoise extends TextureGenerator {
protected Texture generate(Structure tex, int width, int height, int depth, BlenderContext blenderContext) { protected Texture generate(Structure tex, int width, int height, int depth, BlenderContext blenderContext) {
int val, random, loop; int val, random, loop;
int noisedepth = ((Number) tex.getFieldValue("noisedepth")).intValue(); 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; int halfW = width >> 1, halfH = height >> 1, halfD = depth >> 1, index = 0;
float[][] colorBand = this.computeColorband(tex, blenderContext); float[][] colorBand = this.computeColorband(tex, blenderContext);
Format format = colorBand != null ? Format.RGB8 : Format.Luminance8; Format format = colorBand != null ? Format.RGBA8 : Format.Luminance8;
int bytesPerPixel = colorBand != null ? 3 : 1; int bytesPerPixel = colorBand != null ? 4 : 1;
BrightnessAndContrastData bacd = new BrightnessAndContrastData(tex); BrightnessAndContrastData bacd = new BrightnessAndContrastData(tex);
byte[] data = new byte[width * height * depth * bytesPerPixel]; byte[] data = new byte[width * height * depth * bytesPerPixel];
@ -81,7 +81,7 @@ public class TextureGeneratorNoise extends TextureGenerator {
random >>= 2; random >>= 2;
val *= random & 3; val *= random & 3;
} }
texres.intensity = val; texres.intensity = FastMath.clamp(val, 0.0f, 1.0f);
if (colorBand != null) { if (colorBand != null) {
int colorbandIndex = (int) (texres.intensity * 1000.0f); int colorbandIndex = (int) (texres.intensity * 1000.0f);
texres.red = colorBand[colorbandIndex][0]; 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.red * 255.0f);
data[index++] = (byte) (texres.green * 255.0f); data[index++] = (byte) (texres.green * 255.0f);
data[index++] = (byte) (texres.blue * 255.0f); data[index++] = (byte) (texres.blue * 255.0f);
data[index++] = (byte) (colorBand[colorbandIndex][3] * 255.0f);
} else { } else {
this.applyBrightnessAndContrast(texres, bacd.contrast, bacd.brightness); this.applyBrightnessAndContrast(texres, bacd.contrast, bacd.brightness);
data[index++] = (byte) (texres.intensity * 255.0f); data[index++] = (byte) (texres.intensity * 255.0f);

@ -72,12 +72,12 @@ public class TextureGeneratorStucci extends TextureGenerator {
} }
float[] texvec = new float[] { 0, 0, 0 }; 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; 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 wDelta = 1.0f / halfW, hDelta = 1.0f / halfH, dDelta = 1.0f / halfD, noiseValue, ofs;;
float[][] colorBand = this.computeColorband(tex, blenderContext); float[][] colorBand = this.computeColorband(tex, blenderContext);
Format format = colorBand != null ? Format.RGB8 : Format.Luminance8; Format format = colorBand != null ? Format.RGBA8 : Format.Luminance8;
int bytesPerPixel = colorBand != null ? 3 : 1; int bytesPerPixel = colorBand != null ? 4 : 1;
byte[] data = new byte[width * height * depth * bytesPerPixel]; byte[] data = new byte[width * height * depth * bytesPerPixel];
for (int i = -halfW; i < halfW; ++i) { for (int i = -halfW; i < halfW; ++i) {
@ -98,6 +98,7 @@ public class TextureGeneratorStucci extends TextureGenerator {
texres.red = colorBand[colorbandIndex][0]; texres.red = colorBand[colorbandIndex][0];
texres.green = colorBand[colorbandIndex][1]; texres.green = colorBand[colorbandIndex][1];
texres.blue = colorBand[colorbandIndex][2]; texres.blue = colorBand[colorbandIndex][2];
texres.alpha = colorBand[colorbandIndex][3];
} }
if (stype == NoiseGenerator.TEX_WALLOUT) { 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.red * 255.0f);
data[index++] = (byte) (texres.green * 255.0f); data[index++] = (byte) (texres.green * 255.0f);
data[index++] = (byte) (texres.blue * 255.0f); data[index++] = (byte) (texres.blue * 255.0f);
data[index++] = (byte) (texres.alpha * 255.0f);
} else { } else {
data[index++] = (byte) (texres.intensity * 255.0f); data[index++] = (byte) (texres.intensity * 255.0f);
} }

@ -71,14 +71,14 @@ public class TextureGeneratorVoronoi extends TextureGenerator {
int distm = ((Number) tex.getFieldValue("vn_distm")).intValue(); int distm = ((Number) tex.getFieldValue("vn_distm")).intValue();
int voronoiColorType = ((Number) tex.getFieldValue("vn_coltype")).intValue(); int voronoiColorType = ((Number) tex.getFieldValue("vn_coltype")).intValue();
TextureResult texres = new TextureResult(); TexturePixel texres = new TexturePixel();
float[] texvec = new float[] { 0, 0, 0 }; float[] texvec = new float[] { 0, 0, 0 };
int halfW = width >> 1, halfH = height >> 1, halfD = depth >> 1, index = 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 wDelta = 1.0f / halfW, hDelta = 1.0f / halfH, dDelta = 1.0f / halfD;
float[][] colorBand = this.computeColorband(tex, blenderContext); float[][] colorBand = this.computeColorband(tex, blenderContext);
Format format = voronoiColorType != 0 || colorBand != null ? Format.RGB8 : Format.Luminance8; Format format = voronoiColorType != 0 || colorBand != null ? Format.RGBA8 : Format.Luminance8;
int bytesPerPixel = voronoiColorType != 0 || colorBand != null ? 3 : 1; int bytesPerPixel = voronoiColorType != 0 || colorBand != null ? 4 : 1;
BrightnessAndContrastData bacd = new BrightnessAndContrastData(tex); BrightnessAndContrastData bacd = new BrightnessAndContrastData(tex);
float[] da = new float[4], pa = new float[12]; float[] da = new float[4], pa = new float[12];
@ -111,8 +111,10 @@ public class TextureGeneratorVoronoi extends TextureGenerator {
texres.red = colorBand[colorbandIndex][0]; texres.red = colorBand[colorbandIndex][0];
texres.green = colorBand[colorbandIndex][1]; texres.green = colorBand[colorbandIndex][1];
texres.blue = colorBand[colorbandIndex][2]; texres.blue = colorBand[colorbandIndex][2];
texres.alpha = colorBand[colorbandIndex][3];
} else if (voronoiColorType != 0) { } else if (voronoiColorType != 0) {
texres.red = texres.green = texres.blue = 0.0f; texres.red = texres.green = texres.blue = 0.0f;
texres.alpha = 1.0f;
for(int m=0; m<12; m+=3) { for(int m=0; m<12; m+=3) {
weight = voronoiWeights[m/3]; weight = voronoiWeights[m/3];
this.cellNoiseV(pa[m], pa[m + 1], pa[m + 2], hashPoint); 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.red * 255.0f);
data[index++] = (byte) (texres.green * 255.0f); data[index++] = (byte) (texres.green * 255.0f);
data[index++] = (byte) (texres.blue * 255.0f); data[index++] = (byte) (texres.blue * 255.0f);
data[index++] = (byte) (texres.alpha * 255.0f);
} else { } else {
this.applyBrightnessAndContrast(texres, bacd.contrast, bacd.brightness); this.applyBrightnessAndContrast(texres, bacd.contrast, bacd.brightness);
data[index++] = (byte) (texres.intensity * 255.0f); data[index++] = (byte) (texres.intensity * 255.0f);

@ -73,15 +73,15 @@ public class TextureGeneratorWood extends TextureGenerator {
@Override @Override
protected Texture generate(Structure tex, int width, int height, int depth, BlenderContext blenderContext) { protected Texture generate(Structure tex, int width, int height, int depth, BlenderContext blenderContext) {
float[] texvec = new float[] { 0, 0, 0 }; float[] texvec = new float[] { 0, 0, 0 };
TextureResult texres = new TextureResult(); TexturePixel texres = new TexturePixel();
int halfW = width >> 1; int halfW = width >> 1;
int halfH = height >> 1; int halfH = height >> 1;
int halfD = depth >> 1; int halfD = depth >> 1;
float wDelta = 1.0f / halfW, hDelta = 1.0f / halfH, dDelta = 1.0f / halfD; float wDelta = 1.0f / halfW, hDelta = 1.0f / halfH, dDelta = 1.0f / halfD;
float[][] colorBand = this.computeColorband(tex, blenderContext); float[][] colorBand = this.computeColorband(tex, blenderContext);
Format format = colorBand != null ? Format.RGB8 : Format.Luminance8; Format format = colorBand != null ? Format.RGBA8 : Format.Luminance8;
int bytesPerPixel = colorBand != null ? 3 : 1; int bytesPerPixel = colorBand != null ? 4 : 1;
WoodIntensityData woodIntensityData = new WoodIntensityData(tex); WoodIntensityData woodIntensityData = new WoodIntensityData(tex);
BrightnessAndContrastData bacd = new BrightnessAndContrastData(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.red * 255.0f);
data[index++] = (byte) (texres.green * 255.0f); data[index++] = (byte) (texres.green * 255.0f);
data[index++] = (byte) (texres.blue * 255.0f); data[index++] = (byte) (texres.blue * 255.0f);
data[index++] = (byte) (colorBand[colorbandIndex][3] * 255.0f);
} else { } else {
this.applyBrightnessAndContrast(texres, bacd.contrast, bacd.brightness); this.applyBrightnessAndContrast(texres, bacd.contrast, bacd.brightness);
data[index++] = (byte) (texres.intensity * 255.0f); data[index++] = (byte) (texres.intensity * 255.0f);

@ -50,6 +50,7 @@ import com.jme3.asset.BlenderKey;
import com.jme3.asset.BlenderKey.FeaturesToLoad; import com.jme3.asset.BlenderKey.FeaturesToLoad;
import com.jme3.asset.GeneratedTextureKey; import com.jme3.asset.GeneratedTextureKey;
import com.jme3.asset.TextureKey; import com.jme3.asset.TextureKey;
import com.jme3.math.ColorRGBA;
import com.jme3.math.FastMath; import com.jme3.math.FastMath;
import com.jme3.math.Vector3f; import com.jme3.math.Vector3f;
import com.jme3.scene.plugins.blender.AbstractBlenderHelper; 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.FileBlockHeader;
import com.jme3.scene.plugins.blender.file.Pointer; import com.jme3.scene.plugins.blender.file.Pointer;
import com.jme3.scene.plugins.blender.file.Structure; 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.scene.plugins.blender.materials.MaterialHelper;
import com.jme3.texture.Image; import com.jme3.texture.Image;
import com.jme3.texture.Image.Format; import com.jme3.texture.Image.Format;
import com.jme3.texture.Texture; import com.jme3.texture.Texture;
import com.jme3.texture.Texture.MinFilter;
import com.jme3.texture.Texture.WrapMode; import com.jme3.texture.Texture.WrapMode;
import com.jme3.texture.Texture2D; import com.jme3.texture.Texture2D;
import com.jme3.texture.Texture3D; import com.jme3.texture.Texture3D;
@ -215,6 +218,8 @@ public class TextureHelper extends AbstractBlenderHelper {
if (result != null) { if (result != null) {
result.setName(tex.getName()); result.setName(tex.getName());
result.setWrap(WrapMode.Repeat); 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 if(type != TEX_IMAGE) {//only generated textures should have this key
result.setKey(new GeneratedTextureKey(tex.getName())); 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[0] * 255.0f));
newData.put(dataIndex++, (byte) (resultPixel[1] * 255.0f)); newData.put(dataIndex++, (byte) (resultPixel[1] * 255.0f));
newData.put(dataIndex++, (byte) (resultPixel[2] * 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) { if(texture.getType()==Texture.Type.TwoDimensional) {
return new Texture2D(new Image(Format.RGBA8, width, height, newData)); 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<Texture> 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<sources.size()-1) {
sources = sources.subList(lastTextureWithoutAlphaIndex, sources.size()-1);
}
int pixelsAmount = width * height * depth;
ByteBuffer data = BufferUtils.createByteBuffer(pixelsAmount * 3);
TexturePixel resultPixel = new TexturePixel();
TexturePixel sourcePixel = new TexturePixel();
ColorRGBA diffuseColor = materialContext.getDiffuseColor();
for (int i = 0; i < pixelsAmount; ++i) {
for (int j = 0; j < sources.size(); ++j) {
Image image = sources.get(j).getImage();
ByteBuffer sourceData = image.getData(0);
if(j==0) {
resultPixel.fromColor(diffuseColor);
sourcePixel.fromImage(image.getFormat(), sourceData, i);
resultPixel.merge(sourcePixel);
} else {
sourcePixel.fromImage(image.getFormat(), sourceData, i);
resultPixel.merge(sourcePixel);
}
}
data.put((byte)(255 * resultPixel.red));
data.put((byte)(255 * resultPixel.green));
data.put((byte)(255 * resultPixel.blue));
resultPixel.clear();
}
ArrayList<ByteBuffer> arrayData = new ArrayList<ByteBuffer>(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. * 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. * 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) { protected float setupMaterialColor(ByteBuffer data, Format imageFormat, boolean neg, float[] materialColor) {
float tin = 0.0f; float tin = 0.0f;
byte pixelValue = data.get();// at least one byte is always taken :) 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) { 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: case ABGR8:
materialColor[3] = firstPixelValue;
pixelValue = data.get(); 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(); 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(); 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; break;
case BGR8: case BGR8:
materialColor[2] = firstPixelValue; materialColor[2] = firstPixelValue;
pixelValue = data.get(); 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(); 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; break;
case RGB8: case RGB8:
materialColor[0] = firstPixelValue; materialColor[0] = firstPixelValue;
pixelValue = data.get(); 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(); 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;
break; materialColor[3] = 1.0f;
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
break; break;
case Luminance8Alpha8: case Luminance8Alpha8:
tin = neg ? 1.0f - firstPixelValue : firstPixelValue; tin = neg ? 1.0f - firstPixelValue : firstPixelValue;
neg = false;//do not negate the materialColor, it must be unchanged 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; break;
case Luminance16: case Luminance16:
case Luminance16Alpha16: case Luminance16Alpha16:

@ -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();
}
}
Loading…
Cancel
Save