Support for UV-coordinates mapping (only for the first texture at the moment).

git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@8234 75d07b2b-3a1a-0410-a2c5-0572b91ccdca
3.0
Kae..pl 13 years ago
parent 3383e2e086
commit 7c1c6dc065
  1. 90
      engine/src/blender/com/jme3/scene/plugins/blender/materials/MaterialContext.java
  2. 9
      engine/src/blender/com/jme3/scene/plugins/blender/materials/MaterialHelper.java
  3. 4
      engine/src/blender/com/jme3/scene/plugins/blender/meshes/MeshHelper.java
  4. 25
      engine/src/blender/com/jme3/scene/plugins/blender/textures/UVCoordinatesGenerator.java

@ -14,32 +14,32 @@ import com.jme3.scene.plugins.blender.textures.TextureHelper;
import com.jme3.texture.Texture.Type; import com.jme3.texture.Texture.Type;
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());
/*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 int texturesCount; /* package */final int texturesCount;
/*package*/ final Type textureType; /* package */final Type textureType;
/*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;
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
/*package*/ MaterialContext(Structure structure, DataRepository dataRepository) throws BlenderFileException { /* package */MaterialContext(Structure structure, DataRepository dataRepository) throws BlenderFileException {
name = structure.getName(); name = structure.getName();
int mode = ((Number) structure.getFieldValue("mode")).intValue(); int mode = ((Number) structure.getFieldValue("mode")).intValue();
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
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");
@ -49,41 +49,41 @@ public final class MaterialContext {
Pointer p = mtexsArray.get(i); Pointer p = mtexsArray.get(i);
if (p.isNotNull() && (separatedTextures & 1 << i) == 0) { if (p.isNotNull() && (separatedTextures & 1 << i) == 0) {
Structure mtex = p.fetchData(dataRepository.getInputStream()).get(0); Structure mtex = p.fetchData(dataRepository.getInputStream()).get(0);
//the first texture determines the texture coordinates type // the first texture determines the texture coordinates type
if(uvCoordinatesType == -1) { if (uvCoordinatesType == -1) {
uvCoordinatesType = ((Number) mtex.getFieldValue("texco")).intValue(); uvCoordinatesType = ((Number) mtex.getFieldValue("texco")).intValue();
projectionType = ((Number) mtex.getFieldValue("mapping")).intValue(); projectionType = ((Number) mtex.getFieldValue("mapping")).intValue();
} else if(uvCoordinatesType != ((Number) mtex.getFieldValue("texco")).intValue()) { } else if (uvCoordinatesType != ((Number) mtex.getFieldValue("texco")).intValue()) {
LOGGER.log(Level.WARNING, "The texture with index: {0} has different UV coordinates type than the first texture! This texture will NOT be loaded!", i+1); LOGGER.log(Level.WARNING, "The texture with index: {0} has different UV coordinates type than the first texture! This texture will NOT be loaded!", i + 1);
continue; continue;
} }
Pointer pTex = (Pointer) mtex.getFieldValue("tex"); Pointer pTex = (Pointer) mtex.getFieldValue("tex");
if(pTex.isNotNull()) { if (pTex.isNotNull()) {
Structure tex = pTex.fetchData(dataRepository.getInputStream()).get(0); Structure tex = pTex.fetchData(dataRepository.getInputStream()).get(0);
int type = ((Number) tex.getFieldValue("type")).intValue(); int type = ((Number) tex.getFieldValue("type")).intValue();
Type textureType = this.getType(type); Type textureType = this.getType(type);
if(textureType != null) { if (textureType != null) {
if(firstTextureType == null) { if (firstTextureType == null) {
firstTextureType = textureType; firstTextureType = textureType;
mTexs.add(mtex); mTexs.add(mtex);
textures.add(tex); textures.add(tex);
} else if(firstTextureType == textureType) { } else if (firstTextureType == textureType) {
mTexs.add(mtex); mTexs.add(mtex);
textures.add(tex); textures.add(tex);
} else { } else {
LOGGER.log(Level.WARNING, "The texture with index: {0} is of different dimension than the first one! This texture will NOT be loaded!", i+1); LOGGER.log(Level.WARNING, "The texture with index: {0} is of different dimension than the first one! This texture will NOT be loaded!", i + 1);
} }
} }
} }
} }
} }
this.texturesCount = mTexs.size(); this.texturesCount = mTexs.size();
this.textureType = firstTextureType; this.textureType = firstTextureType;
} }
/** /**
* This method returns the current material's texture UV coordinates type. * This method returns the current material's texture UV coordinates type.
* @return uv coordinates type * @return uv coordinates type
@ -91,7 +91,7 @@ public final class MaterialContext {
public int getUvCoordinatesType() { public int getUvCoordinatesType() {
return uvCoordinatesType; return uvCoordinatesType;
} }
/** /**
* This method returns the proper projection type for the material's texture. * This method returns the proper projection type for the material's texture.
* This applies only to 2D textures. * This applies only to 2D textures.
@ -108,7 +108,7 @@ public final class MaterialContext {
public int getTextureDimension() { public int getTextureDimension() {
return this.textureType == Type.TwoDimensional ? 2 : 3; return this.textureType == Type.TwoDimensional ? 2 : 3;
} }
/** /**
* This method returns the amount of textures applied for the current * This method returns the amount of textures applied for the current
* material. * material.
@ -118,10 +118,26 @@ public final class MaterialContext {
public int getTexturesCount() { public int getTexturesCount() {
return textures == null ? 0 : textures.size(); return textures == null ? 0 : textures.size();
} }
/**
* This method returns the projection array that indicates where the current coordinate factor X, Y or Z (represented
* by the index in the array) will be used where (indicated by the value in the array).
* For example the configuration: [1,2,3] means that X - coordinate will be used as X, Y as Y and Z as Z.
* The configuration [2,1,0] means that Z will be used instead of X coordinate, Y will be used as Y and
* Z will not be used at all (0 will be in its place).
* @param textureIndex
* the index of the texture
* @return texture projection array
*/
public int[] getProjection(int textureIndex) {
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 determines the type of the texture. * This method determines the type of the texture.
* @param texType texture type (from blender) * @param texType
* texture type (from blender)
* @return texture type (used by jme) * @return texture type (used by jme)
*/ */
private Type getType(int texType) { private Type getType(int texType) {
@ -142,7 +158,7 @@ public final class MaterialContext {
case TextureHelper.TEX_NONE:// No texture, do nothing case TextureHelper.TEX_NONE:// No texture, do nothing
return null; return null;
case TextureHelper.TEX_POINTDENSITY: case TextureHelper.TEX_POINTDENSITY:
case TextureHelper.TEX_VOXELDATA: case TextureHelper.TEX_VOXELDATA:
case TextureHelper.TEX_PLUGIN: case TextureHelper.TEX_PLUGIN:
case TextureHelper.TEX_ENVMAP: case TextureHelper.TEX_ENVMAP:
LOGGER.log(Level.WARNING, "Texture type NOT supported: {0}", texType); LOGGER.log(Level.WARNING, "Texture type NOT supported: {0}", texType);

@ -200,6 +200,10 @@ public class MaterialHelper extends AbstractBlenderHelper {
MaterialContext materialContext = new MaterialContext(structure, dataRepository); MaterialContext materialContext = new MaterialContext(structure, dataRepository);
LOGGER.log(Level.INFO, "Material's name: {0}", materialContext.name); LOGGER.log(Level.INFO, "Material's name: {0}", materialContext.name);
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); DiffuseShader diffuseShader = this.getDiffuseShader(structure);
ColorRGBA diffuseColor = this.getDiffuseColor(structure, diffuseShader); ColorRGBA diffuseColor = this.getDiffuseColor(structure, diffuseShader);
@ -232,6 +236,7 @@ public class MaterialHelper extends AbstractBlenderHelper {
texture.setMinFilter(MinFilter.Trilinear); texture.setMinFilter(MinFilter.Trilinear);
if ((mapto & 0x01) != 0) {// Col if ((mapto & 0x01) != 0) {// Col
mapto &= 0xFFFFFFFE;//this is temporary to force loading of one texture of a mapping type (will be removed when textures merging is created)
// Map to COLOR channel or DIFFUSE // Map to COLOR channel or DIFFUSE
// Set diffuse to white so it doesn't get multiplied by texture // Set diffuse to white so it doesn't get multiplied by texture
// result.setColor(shadeless ? "Color" : "Diffuse", ColorRGBA.White.clone()); // result.setColor(shadeless ? "Color" : "Diffuse", ColorRGBA.White.clone());
@ -251,6 +256,7 @@ public class MaterialHelper extends AbstractBlenderHelper {
} }
if(firstTextureType == Type.TwoDimensional) {//for now other mappings available for images only if(firstTextureType == Type.TwoDimensional) {//for now other mappings available for images only
if ((mapto & 0x02) != 0 && !materialContext.shadeless) {// Nor 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; Texture normalMapTexture;
if (texture.getKey() instanceof GeneratedTextureKey) { if (texture.getKey() instanceof GeneratedTextureKey) {
normalMapTexture = textureHelper.convertToNormalMapTexture(texture, ((Number) mtex.getFieldValue("norfac")).floatValue()); normalMapTexture = textureHelper.convertToNormalMapTexture(texture, ((Number) mtex.getFieldValue("norfac")).floatValue());
@ -261,13 +267,16 @@ public class MaterialHelper extends AbstractBlenderHelper {
texturesMap.put(TEXTURE_TYPE_NORMAL, normalMapTexture); texturesMap.put(TEXTURE_TYPE_NORMAL, normalMapTexture);
} }
if ((mapto & 0x04) != 0 && !materialContext.shadeless) {// Spec 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 // Map to SPECULAR
texturesMap.put(TEXTURE_TYPE_SPECULAR, texture); texturesMap.put(TEXTURE_TYPE_SPECULAR, texture);
} }
if ((mapto & 0x40) != 0) {// Emit 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); texturesMap.put(TEXTURE_TYPE_GLOW, texture);
} }
if ((mapto & 0x80) != 0 && !materialContext.shadeless) {// Alpha 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); texturesMap.put(TEXTURE_TYPE_ALPHA, texture);
} }
} else { } else {

@ -408,8 +408,8 @@ public class MeshHelper extends AbstractBlenderHelper {
MaterialContext materialContext = dataRepository.getMaterialContext(entry.getKey()); MaterialContext materialContext = dataRepository.getMaterialContext(entry.getKey());
if(materialContext != null && materialContext.getTexturesCount()>0) { if(materialContext != null && materialContext.getTexturesCount()>0) {
UVCoordinatesGenerator.generateUVCoordinates(materialContext.getUvCoordinatesType(), UVCoordinatesGenerator.generateUVCoordinates(materialContext.getUvCoordinatesType(),
materialContext.getProjectionType(), materialContext.getProjectionType(), materialContext.getTextureDimension(),
materialContext.getTextureDimension(), entry.getValue()); materialContext.getProjection(0), entry.getValue());
} }
} }
} }

@ -90,10 +90,12 @@ public class UVCoordinatesGenerator {
* the projection type for 2D textures * the projection type for 2D textures
* @param textureDimension * @param textureDimension
* the dimension of the texture (only 2D and 3D) * the dimension of the texture (only 2D and 3D)
* @param coordinatesSwappingIndexes
* an array that tells how UV-coordinates need to be swapped
* @param geometries * @param geometries
* a list of geometries the UV coordinates will be applied to * a list of geometries the UV coordinates will be applied to
*/ */
public static void generateUVCoordinates(int texco, int projection, int textureDimension, List<Geometry> geometries) { public static void generateUVCoordinates(int texco, int projection, int textureDimension, int[] coordinatesSwappingIndexes, List<Geometry> geometries) {
if (textureDimension != 2 && textureDimension != 3) { if (textureDimension != 2 && textureDimension != 3) {
throw new IllegalStateException("Unsupported texture dimension: " + textureDimension); throw new IllegalStateException("Unsupported texture dimension: " + textureDimension);
} }
@ -123,20 +125,14 @@ public class UVCoordinatesGenerator {
case TEXCO_NORM: case TEXCO_NORM:
inputData = BufferUtils.getFloatArray(mesh.getFloatBuffer(VertexBuffer.Type.Normal)); inputData = BufferUtils.getFloatArray(mesh.getFloatBuffer(VertexBuffer.Type.Normal));
break; break;
case TEXCO_REFL:
case TEXCO_GLOB: case TEXCO_GLOB:
break;
case TEXCO_TANGENT: case TEXCO_TANGENT:
break;
case TEXCO_STRESS: case TEXCO_STRESS:
break;
case TEXCO_LAVECTOR: case TEXCO_LAVECTOR:
case TEXCO_OBJECT: case TEXCO_OBJECT:
case TEXCO_OSA: case TEXCO_OSA:
case TEXCO_PARTICLE_OR_STRAND: case TEXCO_PARTICLE_OR_STRAND:
case TEXCO_REFL:
case TEXCO_SPEED: case TEXCO_SPEED:
case TEXCO_STICKY: case TEXCO_STICKY:
case TEXCO_VIEW: case TEXCO_VIEW:
@ -169,15 +165,20 @@ public class UVCoordinatesGenerator {
} }
} else { } else {
Vector3f min = bb.getMin(null); Vector3f min = bb.getMin(null);
float[] uvCoordsResults = new float[4];//used for coordinates swapping
float[] ext = new float[] { bb.getXExtent() * 2, bb.getYExtent() * 2, bb.getZExtent() * 2 }; float[] ext = new float[] { bb.getXExtent() * 2, bb.getYExtent() * 2, bb.getZExtent() * 2 };
// now transform the coordinates so that they are in the range of <0; 1> // now transform the coordinates so that they are in the range of <0; 1>
for (int i = 0; i < inputData.length; i += 3) { for (int i = 0; i < inputData.length; i += 3) {
inputData[i] = (inputData[i] - min.x) / ext[0]; uvCoordsResults[1] = (inputData[i] - min.x) / ext[0];
inputData[i + 1] = (inputData[i + 1] - min.y) / ext[1]; uvCoordsResults[2] = (inputData[i + 1] - min.y) / ext[1];
inputData[i + 2] = (inputData[i + 2] - min.z) / ext[2]; uvCoordsResults[3] = (inputData[i + 2] - min.z) / ext[2];
inputData[i] = uvCoordsResults[coordinatesSwappingIndexes[0]];
inputData[i + 1] = uvCoordsResults[coordinatesSwappingIndexes[1]];
inputData[i + 2] = uvCoordsResults[coordinatesSwappingIndexes[2]];
} }
result.setupData(Usage.Static, textureDimension, Format.Float, BufferUtils.createFloatBuffer(inputData));
} }
result.setupData(Usage.Static, textureDimension, Format.Float, BufferUtils.createFloatBuffer(inputData)); result.setupData(Usage.Static, textureDimension, Format.Float, BufferUtils.createFloatBuffer(inputData));
} }

Loading…
Cancel
Save