Importing generated textures as 3D textures.

UV coordinates generator added (will handle different UV coordinates generation methods in the future).
MaterialHelper refactoring.

git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@8039 75d07b2b-3a1a-0410-a2c5-0572b91ccdca
3.0
Kae..pl 13 years ago
parent cc27b5bcf6
commit d6574a8cc7
  1. 22
      engine/src/blender/com/jme3/asset/BlenderKey.java
  2. 26
      engine/src/blender/com/jme3/scene/plugins/blender/materials/IAlphaMask.java
  3. 113
      engine/src/blender/com/jme3/scene/plugins/blender/materials/MaterialContext.java
  4. 298
      engine/src/blender/com/jme3/scene/plugins/blender/materials/MaterialHelper.java
  5. 75
      engine/src/blender/com/jme3/scene/plugins/blender/meshes/MeshHelper.java
  6. 16
      engine/src/blender/com/jme3/scene/plugins/blender/textures/TextureGenerator.java
  7. 114
      engine/src/blender/com/jme3/scene/plugins/blender/textures/TextureGeneratorBlend.java
  8. 83
      engine/src/blender/com/jme3/scene/plugins/blender/textures/TextureGeneratorClouds.java
  9. 59
      engine/src/blender/com/jme3/scene/plugins/blender/textures/TextureGeneratorDistnoise.java
  10. 114
      engine/src/blender/com/jme3/scene/plugins/blender/textures/TextureGeneratorMagic.java
  11. 58
      engine/src/blender/com/jme3/scene/plugins/blender/textures/TextureGeneratorMarble.java
  12. 68
      engine/src/blender/com/jme3/scene/plugins/blender/textures/TextureGeneratorMusgrave.java
  13. 57
      engine/src/blender/com/jme3/scene/plugins/blender/textures/TextureGeneratorNoise.java
  14. 88
      engine/src/blender/com/jme3/scene/plugins/blender/textures/TextureGeneratorStucci.java
  15. 137
      engine/src/blender/com/jme3/scene/plugins/blender/textures/TextureGeneratorVoronoi.java
  16. 49
      engine/src/blender/com/jme3/scene/plugins/blender/textures/TextureGeneratorWood.java
  17. 23
      engine/src/blender/com/jme3/scene/plugins/blender/textures/TextureHelper.java
  18. 324
      engine/src/blender/com/jme3/scene/plugins/blender/textures/UVCoordinatesGenerator.java

@ -78,10 +78,12 @@ public class BlenderKey extends ModelKey {
* between the frames.
*/
protected int fps = DEFAULT_FPS;
/** Width of generated textures (in pixels). Blender uses 140x140 by default. */
protected int generatedTextureWidth = 140;
/** Height of generated textures (in pixels). Blender uses 140x140 by default. */
protected int generatedTextureHeight = 140;
/** Width of generated textures (in pixels). */
protected int generatedTextureWidth = 20;
/** Height of generated textures (in pixels). */
protected int generatedTextureHeight = 20;
/** Depth of generated textures (in pixels). */
protected int generatedTextureDepth = 20;
/**
* This variable is a bitwise flag of FeatureToLoad interface values; By default everything is being loaded.
*/
@ -228,7 +230,7 @@ public class BlenderKey extends ModelKey {
}
/**
* This method sets the height of generated texture (in pixels). By default the value is 140 px.
* This method sets the height of generated texture (in pixels). By default the value is 20 px.
* @param generatedTextureHeight
* the height of generated texture
*/
@ -237,12 +239,20 @@ public class BlenderKey extends ModelKey {
}
/**
* This method returns the height of generated texture (in pixels). By default the value is 140 px.
* This method returns the height of generated texture (in pixels). By default the value is 20 px.
* @return the height of generated texture
*/
public int getGeneratedTextureHeight() {
return generatedTextureHeight;
}
/**
* This method returns the depth of generated texture (in pixels). By default the value is 20 px.
* @return the depth of generated texture
*/
public int getGeneratedTextureDepth() {
return generatedTextureDepth;
}
/**
* This method returns the face cull mode.

@ -0,0 +1,26 @@
package com.jme3.scene.plugins.blender.materials;
/**
* An interface used in calculating alpha mask during particles' texture calculations.
* @author Marcin Roguski (Kaelthas)
*/
/*package*/ interface IAlphaMask {
/**
* This method sets the size of the texture's image.
* @param width
* the width of the image
* @param height
* the height of the image
*/
void setImageSize(int width, int height);
/**
* This method returns the alpha value for the specified texture position.
* @param x
* the X coordinate of the texture position
* @param y
* the Y coordinate of the texture position
* @return the alpha value for the specified texture position
*/
byte getAlpha(float x, float y);
}

@ -0,0 +1,113 @@
package com.jme3.scene.plugins.blender.materials;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.jme3.scene.plugins.blender.DataRepository;
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.textures.TextureHelper;
import com.jme3.texture.Texture.Type;
/*package*/final class MaterialContext {
private static final Logger LOGGER = Logger.getLogger(MaterialContext.class.getName());
public final String name;
public final List<Structure> mTexs;
public final List<Structure> textures;
public final int texturesCount;
public final Type textureType;
public final int textureCoordinatesType;
public final boolean shadeless;
public final boolean vertexColor;
public final boolean transparent;
public final boolean vtangent;
@SuppressWarnings("unchecked")
public MaterialContext(Structure structure, DataRepository dataRepository) throws BlenderFileException {
name = structure.getName();
int mode = ((Number) structure.getFieldValue("mode")).intValue();
shadeless = (mode & 0x4) != 0;
vertexColor = (mode & 0x80) != 0;
transparent = (mode & 0x10000) != 0;
vtangent = (mode & 0x4000000) != 0; // NOTE: Requires tangents
mTexs = new ArrayList<Structure>();
textures = new ArrayList<Structure>();
DynamicArray<Pointer> mtexsArray = (DynamicArray<Pointer>) structure.getFieldValue("mtex");
int separatedTextures = ((Number) structure.getFieldValue("septex")).intValue();
Type firstTextureType = null;
int texco = -1;
for (int i = 0; i < mtexsArray.getTotalSize(); ++i) {
Pointer p = mtexsArray.get(i);
if (p.isNotNull() && (separatedTextures & 1 << i) == 0) {
Structure mtex = p.fetchData(dataRepository.getInputStream()).get(0);
//the first texture determines the texture coordinates type
if(texco == -1) {
texco = ((Number) mtex.getFieldValue("texco")).intValue();
} else if(texco != ((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);
continue;
}
Pointer pTex = (Pointer) mtex.getFieldValue("tex");
if(pTex.isNotNull()) {
Structure tex = pTex.fetchData(dataRepository.getInputStream()).get(0);
int type = ((Number) tex.getFieldValue("type")).intValue();
Type textureType = this.getType(type);
if(textureType != null) {
if(firstTextureType == null) {
firstTextureType = textureType;
mTexs.add(mtex);
textures.add(tex);
} else if(firstTextureType == textureType) {
mTexs.add(mtex);
textures.add(tex);
} 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);
}
}
}
}
}
this.texturesCount = mTexs.size();
this.textureCoordinatesType = texco;
this.textureType = firstTextureType;
}
private Type getType(int texType) {
switch (texType) {
case TextureHelper.TEX_IMAGE:// (it is first because probably this will be most commonly used)
return Type.TwoDimensional;
case TextureHelper.TEX_CLOUDS:
case TextureHelper.TEX_WOOD:
case TextureHelper.TEX_MARBLE:
case TextureHelper.TEX_MAGIC:
case TextureHelper.TEX_BLEND:
case TextureHelper.TEX_STUCCI:
case TextureHelper.TEX_NOISE:
case TextureHelper.TEX_MUSGRAVE:
case TextureHelper.TEX_VORONOI:
case TextureHelper.TEX_DISTNOISE:
return Type.ThreeDimensional;
case TextureHelper.TEX_NONE:// No texture, do nothing
return null;
case TextureHelper.TEX_POINTDENSITY:
case TextureHelper.TEX_VOXELDATA:
case TextureHelper.TEX_PLUGIN:
case TextureHelper.TEX_ENVMAP:
LOGGER.log(Level.WARNING, "Texture type NOT supported: {0}", texType);
return null;
default:
throw new IllegalStateException("Unknown texture type: " + texType);
}
}
}

@ -52,7 +52,6 @@ import com.jme3.scene.plugins.blender.AbstractBlenderHelper;
import com.jme3.scene.plugins.blender.DataRepository;
import com.jme3.scene.plugins.blender.DataRepository.LoadedFeatureDataType;
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.textures.TextureHelper;
@ -61,6 +60,7 @@ 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;
@ -68,6 +68,7 @@ public class MaterialHelper extends AbstractBlenderHelper {
private static final Logger LOGGER = Logger.getLogger(MaterialHelper.class.getName());
protected static final float DEFAULT_SHININESS = 20.0f;
public static final String TEXTURE_TYPE_3D = "Texture";
public static final String TEXTURE_TYPE_COLOR = "ColorMap";
public static final String TEXTURE_TYPE_DIFFUSE = "DiffuseMap";
public static final String TEXTURE_TYPE_NORMAL = "NormalMap";
@ -177,7 +178,6 @@ public class MaterialHelper extends AbstractBlenderHelper {
this.faceCullMode = faceCullMode;
}
@SuppressWarnings("unchecked")
public Material toMaterial(Structure structure, DataRepository dataRepository) throws BlenderFileException {
LOGGER.log(Level.INFO, "Loading material.");
if (structure == null) {
@ -187,153 +187,139 @@ public class MaterialHelper extends AbstractBlenderHelper {
if (result != null) {
return result;
}
int mode = ((Number) structure.getFieldValue("mode")).intValue();
boolean shadeless = (mode & 0x4) != 0;
boolean vertexColor = (mode & 0x80) != 0;
boolean transparent = (mode & 0x10000) != 0;
boolean vtangent = (mode & 0x4000000) != 0; // NOTE: Requires tangents
if (shadeless) {
result = new Material(dataRepository.getAssetManager(), "Common/MatDefs/Misc/Unshaded.j3md");
} else {
result = new Material(dataRepository.getAssetManager(), "Common/MatDefs/Light/Lighting.j3md");
}
//System.out.println("Mode: \n" +
// "Shadeless: " + shadeless + "\n" +
// "VColor: " + vertexColor + "\n" +
// "ZTrans: " + transparent + "\n" +
// "VTangent: " + vtangent);
result.getAdditionalRenderState().setFaceCullMode(faceCullMode);
if (transparent) {
result.setTransparent(true);
result.getAdditionalRenderState().setBlendMode(BlendMode.Alpha);
}
String name = structure.getName();
LOGGER.log(Level.INFO, "Material's name: {0}", name);
if (vertexColor) {
result.setBoolean(shadeless ? "VertexColor" : "UseVertexColor", true);
}
MaterialHelper materialHelper = dataRepository.getHelper(MaterialHelper.class);
ColorRGBA diffuseColor = null;
if (shadeless) {
// color of shadeless? doesn't seem to work in blender ..
diffuseColor = ColorRGBA.White.clone();
} else {
result.setBoolean("UseMaterialColors", Boolean.TRUE);
// setting the colors
DiffuseShader diffuseShader = materialHelper.getDiffuseShader(structure);
result.setBoolean("Minnaert", diffuseShader == DiffuseShader.MINNAERT);
diffuseColor = materialHelper.getDiffuseColor(structure, diffuseShader);
if (!transparent){
diffuseColor.a = 1;
}
result.setColor("Diffuse", diffuseColor);
SpecularShader specularShader = materialHelper.getSpecularShader(structure);
result.setBoolean("WardIso", specularShader == SpecularShader.WARDISO);
result.setColor("Specular", materialHelper.getSpecularColor(structure, specularShader));
result.setColor("Ambient", materialHelper.getAmbientColor(structure));
result.setFloat("Shininess", materialHelper.getShininess(structure));
}
MaterialContext materialContext = new MaterialContext(structure, dataRepository);
LOGGER.log(Level.INFO, "Material's name: {0}", materialContext.name);
// texture
Map<String, Texture> texturesMap = new HashMap<String, Texture>();
Type firstTextureType = null;
if ((dataRepository.getBlenderKey().getFeaturesToLoad() & FeaturesToLoad.TEXTURES) != 0) {
TextureHelper textureHelper = dataRepository.getHelper(TextureHelper.class);
DynamicArray<Pointer> mtexs = (DynamicArray<Pointer>) structure.getFieldValue("mtex");
int separatedTextures = ((Number)structure.getFieldValue("septex")).intValue();
for (int i = 0; i < mtexs.getTotalSize(); ++i) {
Pointer p = mtexs.get(i);
if (p.isNotNull() && (separatedTextures & (1 << i)) == 0) {
List<Structure> mtex = p.fetchData(dataRepository.getInputStream());
if (mtex.size() == 1) {
Structure textureLink = mtex.get(0);
int texflag = ((Number) textureLink.getFieldValue("texflag")).intValue();
// int texco = ((Number) textureLink.getFieldValue("texco")).intValue();
boolean negateTexture = (texflag & 0x04) == 0;
// if(texco == 0x10) {//TEXCO_UV (this is only supported now)
int mapto = ((Number) textureLink.getFieldValue("mapto")).intValue();
if (mapto != 0) {
Pointer pTex = (Pointer) textureLink.getFieldValue("tex");
Structure tex = pTex.fetchData(dataRepository.getInputStream()).get(0);
Texture texture = textureHelper.getTexture(tex, dataRepository);
if (texture != null) {
// NOTE: Enable mipmaps FOR ALL TEXTURES EVER
texture.setMinFilter(MinFilter.Trilinear);
if ((mapto & 0x01) != 0) {// Col
// Map to COLOR channel or DIFFUSE
// Set diffuse to white so it doesn't get multiplied by texture
diffuseColor.r = diffuseColor.g = diffuseColor.b = 1.0f;
result.setColor(shadeless ? "Color" : "Diffuse", diffuseColor);
//result.setBoolean("UseMaterialColors", Boolean.FALSE);
// blending the texture with material color and texture's defined color
int blendType = ((Number) textureLink.getFieldValue("blendtype")).intValue();
float[] color = new float[] { ((Number) textureLink.getFieldValue("r")).floatValue(), ((Number) textureLink.getFieldValue("g")).floatValue(), ((Number) textureLink.getFieldValue("b")).floatValue() };
float colfac = ((Number) textureLink.getFieldValue("colfac")).floatValue();
texture = textureHelper.blendTexture(diffuseColor.getColorArray(), texture, color, colfac, blendType, negateTexture, dataRepository);
texture.setMinFilter(MinFilter.Trilinear);
texture.setWrap(WrapMode.Repeat);
if (shadeless) {
result.setTexture(TEXTURE_TYPE_COLOR, texture);
} else {
result.setTexture(TEXTURE_TYPE_DIFFUSE, texture);
}
}
if ((mapto & 0x02) != 0 && !shadeless) {// Nor
Texture normalMapTexture;
if(texture.getKey() instanceof GeneratedTextureKey) {
normalMapTexture = textureHelper.convertToNormalMapTexture(texture, ((Number)textureLink.getFieldValue("norfac")).floatValue());
normalMapTexture.setMinFilter(MinFilter.Trilinear);
} else {
normalMapTexture = texture;
}
result.setTexture(TEXTURE_TYPE_NORMAL, normalMapTexture);
if (vertexColor) {
result.setBoolean(shadeless ? "VertexColor" : "UseVertexColor", false);
}
}
if ((mapto & 0x04) != 0 && !shadeless) {// Spec
// Map to SPECULAR
result.setTexture(TEXTURE_TYPE_SPECULAR, texture);
}
if ((mapto & 0x40) != 0) {// Emit
result.setTexture(TEXTURE_TYPE_GLOW, texture);
}
if ((mapto & 0x80) != 0 && !shadeless) {// Alpha
result.setTexture(TEXTURE_TYPE_ALPHA, texture);
}
for (int i=0;i<materialContext.texturesCount;++i) {
Structure mtex = materialContext.mTexs.get(i);
int texflag = ((Number) mtex.getFieldValue("texflag")).intValue();
boolean negateTexture = (texflag & 0x04) == 0;
int mapto = ((Number) mtex.getFieldValue("mapto")).intValue();
if (mapto != 0) {
Structure tex = materialContext.textures.get(i);
Texture texture = textureHelper.getTexture(tex, dataRepository);
if (texture != null) {
if(firstTextureType == null) {
firstTextureType = texture.getType();
} else if(firstTextureType != texture.getType()) {
LOGGER.warning("The texture with the name: " + texture.getName() + " is of different type than the first applied texture! It will not be applied!");
continue;
}
// NOTE: Enable mipmaps FOR ALL TEXTURES EVER
texture.setMinFilter(MinFilter.Trilinear);
//TODO: textures merging
if ((mapto & 0x01) != 0) {// Col
// 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(new float[] {1, 1, 1}, texture, color, colfac, blendType, negateTexture, dataRepository);
texture.setWrap(WrapMode.Repeat);
if (materialContext.shadeless) {
texturesMap.put(firstTextureType==Type.ThreeDimensional ? TEXTURE_TYPE_3D : TEXTURE_TYPE_COLOR, texture);
} else {
LOGGER.log(Level.WARNING, "Texture not found!");
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
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
// Map to SPECULAR
texturesMap.put(TEXTURE_TYPE_SPECULAR, texture);
}
if ((mapto & 0x40) != 0) {// Emit
texturesMap.put(TEXTURE_TYPE_GLOW, texture);
}
if ((mapto & 0x80) != 0 && !materialContext.shadeless) {// Alpha
texturesMap.put(TEXTURE_TYPE_ALPHA, texture);
}
} else {
LOGGER.warning("The following mappings: [Nor, Spec, Alpha] are available for 2D textures only!");
}
// } else {
// Pointer pTex = (Pointer)textureLink.getFieldValue("tex");
// List<Structure> texs = pTex.fetchData(dataRepository.getInputStream());
// Structure tex = texs.get(0);
// LOGGER.log(Level.WARNING, "Unsupported texture type: " + texco);
// }
} else {
LOGGER.log(Level.WARNING, "Many textures. Not solved yet!");// TODO
LOGGER.log(Level.WARNING, "Texture not found!");
}
}
}
}
//creating the material
if(firstTextureType==Type.ThreeDimensional) {
result = new Material(dataRepository.getAssetManager(), "jme3test/texture/tex3D.j3md");
} else {
if (materialContext.shadeless) {
result = new Material(dataRepository.getAssetManager(), "Common/MatDefs/Misc/Unshaded.j3md");
} else {
result = new Material(dataRepository.getAssetManager(), "Common/MatDefs/Light/Lighting.j3md");
}
if (materialContext.vertexColor) {
result.setBoolean(materialContext.shadeless ? "VertexColor" : "UseVertexColor", true);
}
ColorRGBA diffuseColor = null;
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
DiffuseShader diffuseShader = this.getDiffuseShader(structure);
result.setBoolean("Minnaert", diffuseShader == DiffuseShader.MINNAERT);
diffuseColor = this.getDiffuseColor(structure, diffuseShader);
if (!materialContext.transparent) {
diffuseColor.a = 1;
}
result.setColor("Diffuse", diffuseColor);
SpecularShader specularShader = this.getSpecularShader(structure);
result.setBoolean("WardIso", specularShader == SpecularShader.WARDISO);
result.setColor("Specular", this.getSpecularColor(structure, specularShader));
result.setColor("Ambient", this.getAmbientColor(structure));
result.setFloat("Shininess", this.getShininess(structure));
}
}
//applying textures
for(Entry<String, Texture> textureEntry : texturesMap.entrySet()) {
result.setTexture(textureEntry.getKey(), textureEntry.getValue());
}
//applying other data
result.getAdditionalRenderState().setFaceCullMode(faceCullMode);
if (materialContext.transparent) {
result.setTransparent(true);
result.getAdditionalRenderState().setBlendMode(BlendMode.Alpha);
}
dataRepository.addLoadedFeatures(structure.getOldMemoryAddress(), structure.getName(), structure, result);
return result;
}
/**
* This method returns a material similar to the one given but without textures. If the material has no textures it is not cloned but
* returned itself.
@ -428,7 +414,7 @@ public class MaterialHelper extends AbstractBlenderHelper {
}
return result;
}
/**
* This method indicates if the material has any kind of texture.
*
@ -438,22 +424,25 @@ public class MaterialHelper extends AbstractBlenderHelper {
*/
public boolean hasTexture(Material material) {
if (material != null) {
if(material.getTextureParam(TEXTURE_TYPE_ALPHA) != null) {
if (material.getTextureParam(TEXTURE_TYPE_3D) != null) {
return true;
}
if (material.getTextureParam(TEXTURE_TYPE_ALPHA) != null) {
return true;
}
if(material.getTextureParam(TEXTURE_TYPE_COLOR) != null) {
if (material.getTextureParam(TEXTURE_TYPE_COLOR) != null) {
return true;
}
if(material.getTextureParam(TEXTURE_TYPE_DIFFUSE) != null) {
if (material.getTextureParam(TEXTURE_TYPE_DIFFUSE) != null) {
return true;
}
if(material.getTextureParam(TEXTURE_TYPE_GLOW) != null) {
if (material.getTextureParam(TEXTURE_TYPE_GLOW) != null) {
return true;
}
if(material.getTextureParam(TEXTURE_TYPE_NORMAL) != null) {
if (material.getTextureParam(TEXTURE_TYPE_NORMAL) != null) {
return true;
}
if(material.getTextureParam(TEXTURE_TYPE_SPECULAR) != null) {
if (material.getTextureParam(TEXTURE_TYPE_SPECULAR) != null) {
return true;
}
}
@ -475,7 +464,7 @@ public class MaterialHelper extends AbstractBlenderHelper {
}
return false;
}
/**
* This method returns the diffuse color
*
@ -743,29 +732,4 @@ public class MaterialHelper extends AbstractBlenderHelper {
public boolean shouldBeLoaded(Structure structure, DataRepository dataRepository) {
return (dataRepository.getBlenderKey().getFeaturesToLoad() & FeaturesToLoad.MATERIALS) != 0;
}
/**
* An interface used in calculating alpha mask during particles' texture calculations.
* @author Marcin Roguski (Kaelthas)
*/
protected static interface IAlphaMask {
/**
* This method sets the size of the texture's image.
* @param width
* the width of the image
* @param height
* the height of the image
*/
void setImageSize(int width, int height);
/**
* This method returns the alpha value for the specified texture position.
* @param x
* the X coordinate of the texture position
* @param y
* the Y coordinate of the texture position
* @return the alpha value for the specified texture position
*/
byte getAlpha(float x, float y);
}
}

@ -44,10 +44,8 @@ import com.jme3.asset.BlenderKey.FeaturesToLoad;
import com.jme3.bounding.BoundingBox;
import com.jme3.bounding.BoundingSphere;
import com.jme3.bounding.BoundingVolume;
import com.jme3.collision.CollisionResults;
import com.jme3.material.Material;
import com.jme3.math.FastMath;
import com.jme3.math.Ray;
import com.jme3.math.Vector2f;
import com.jme3.math.Vector3f;
import com.jme3.renderer.queue.RenderQueue.Bucket;
@ -68,6 +66,7 @@ import com.jme3.scene.plugins.blender.file.Structure;
import com.jme3.scene.plugins.blender.materials.MaterialHelper;
import com.jme3.scene.plugins.blender.objects.Properties;
import com.jme3.scene.plugins.blender.textures.TextureHelper;
import com.jme3.scene.plugins.blender.textures.UVCoordinatesGenerator;
import com.jme3.texture.Texture;
import com.jme3.util.BufferUtils;
@ -127,10 +126,13 @@ public class MeshHelper extends AbstractBlenderHelper {
// the following map sorts faces by material number (because in jme Mesh can have only one material)
Map<Integer, List<Integer>> meshesMap = new HashMap<Integer, List<Integer>>();
Pointer pMFace = (Pointer) structure.getFieldValue("mface");
List<Structure> mFaces = null;
if (pMFace.isNotNull()){
mFaces = pMFace.fetchData(dataRepository.getInputStream());
}
List<Structure> mFaces = null;
if (pMFace.isNotNull()){
mFaces = pMFace.fetchData(dataRepository.getInputStream());
if(mFaces==null || mFaces.size()==0) {
return new ArrayList<Geometry>(0);
}
}
Pointer pMTFace = (Pointer) structure.getFieldValue("mtface");
List<Vector2f> uvCoordinates = null;
@ -142,7 +144,7 @@ public class MeshHelper extends AbstractBlenderHelper {
if (mtFaces.size() != facesAmount) {
throw new BlenderFileException("The amount of faces uv coordinates is not equal to faces amount!");
}
uvCoordinates = new ArrayList<Vector2f>();// TODO: calculate the amount of coordinates if possible
uvCoordinates = new ArrayList<Vector2f>();
}
// normalMap merges normals of faces that will be rendered smooth
@ -156,9 +158,6 @@ public class MeshHelper extends AbstractBlenderHelper {
// positions (it simply tells which vertex is referenced where in the result list)
Map<Integer, List<Integer>> vertexReferenceMap = new HashMap<Integer, List<Integer>>(verticesAmount);
int vertexColorIndex = 0;
if (mFaces == null){
return null;
}
for (int i = 0; i < mFaces.size(); ++i) {
Structure mFace = mFaces.get(i);
boolean smooth = (((Number) mFace.getFieldValue("flag")).byteValue() & 0x01) != 0x00;
@ -392,54 +391,9 @@ public class MeshHelper extends AbstractBlenderHelper {
for(Geometry geom : geometries) {
geom.getMesh().setBuffer(uvCoordsBuffer);
}
} else {
Vector2f[] uvTable = new Vector2f[vertexList.size()];
Ray ray = new Ray();
CollisionResults cr = new CollisionResults();
Vector3f yVec = new Vector3f();
Vector3f zVec = new Vector3f();
for(Geometry geom : geometries) {
if(materialHelper.hasTexture(geom.getMaterial())) {//generate only when material has a texture
geom.getMesh().updateBound();
BoundingSphere bs = this.getBoundingSphere(geom.getMesh());
float r2 = bs.getRadius() * bs.getRadius();
yVec.set(0, -bs.getRadius(), 0);
zVec.set(0, 0, -bs.getRadius());
Vector3f center = bs.getCenter();
ray.setOrigin(center);
//we cast each vertex of the current mesh on the bounding box to determine the UV-coordinates
for(int i=0;i<geom.getMesh().getIndexBuffer().size();++i) {
int index = geom.getMesh().getIndexBuffer().get(i);
ray.setOrigin(vertexList.get(index));
ray.setDirection(normalList.get(index));
//finding collision point
cr.clear();
bs.collideWith(ray, cr);//there is ALWAYS one collision
Vector3f p = cr.getCollision(0).getContactPoint();
p.subtractLocal(center);
//arcLength = FastMath.acos(p.dot(yVec)/(p.length * yVec.length)) * r <- an arc length on the sphere (from top to the point on the sphere)
//but yVec.length == r and p.length == r so: arcLength = FastMath.acos(p.dot(yVec)/r^2)/r
//U coordinate is as follows: u = arcLength / PI*r
//so to compute it faster we just write: u = FastMath.acos(p.dot(yVec)/r^2) / PI;
float u = FastMath.acos(p.dot(yVec)/r2) / FastMath.PI;
//we use similiar method to compute v
//the only difference is that we need to cast the p vector on ZX plane
//and use its length instead of r
p.y = 0;
float v = FastMath.acos(p.dot(zVec)/(bs.getRadius()*p.length())) / FastMath.PI;
uvTable[index] = new Vector2f(u, v);
}
}
}
//creating and applying the buffer
uvCoordsBuffer = new VertexBuffer(Type.TexCoord);
uvCoordsBuffer.setupData(Usage.Static, 2, Format.Float, BufferUtils.createFloatBuffer(uvTable));
for(Geometry geom : geometries) {
geom.getMesh().setBuffer(uvCoordsBuffer);
}
} else {//TODO: get the proper texture coordinates type
UVCoordinatesGenerator.generateUVCoordinates(UVCoordinatesGenerator.TEXCO_ORCO,
com.jme3.texture.Texture.Type.ThreeDimensional, geometries);
}
dataRepository.addLoadedFeatures(structure.getOldMemoryAddress(), structure.getName(), structure, geometries);
@ -550,8 +504,9 @@ public class MeshHelper extends AbstractBlenderHelper {
public Vector3f[] getVertices(Structure meshStructure, DataRepository dataRepository) throws BlenderFileException {
int verticesAmount = ((Number) meshStructure.getFieldValue("totvert")).intValue();
Vector3f[] vertices = new Vector3f[verticesAmount];
if (verticesAmount == 0)
return vertices;
if (verticesAmount == 0) {
return vertices;
}
Pointer pMVert = (Pointer) meshStructure.getFieldValue("mvert");
List<Structure> mVerts = pMVert.fetchData(dataRepository.getInputStream());

@ -14,14 +14,14 @@ import com.jme3.texture.Texture;
* @author Marcin Roguski (Kaelthas)
*/
/* package */abstract class TextureGenerator {
private static final Logger LOGGER = Logger.getLogger(TextureGenerator.class.getName());
protected NoiseGenerator noiseGenerator;
private static final Logger LOGGER = Logger.getLogger(TextureGenerator.class.getName());
protected NoiseGenerator noiseGenerator;
public TextureGenerator(NoiseGenerator noiseGenerator) {
this.noiseGenerator = noiseGenerator;
}
/**
* This method generates the texture.
* @param tex
@ -30,12 +30,14 @@ import com.jme3.texture.Texture;
* the width of the result texture
* @param height
* the height of the result texture
* @param depth
* the depth of the texture
* @param dataRepository
* the data repository
* @return newly generated texture
*/
protected abstract Texture generate(Structure tex, int width, int height, DataRepository dataRepository);
protected abstract Texture generate(Structure tex, int width, int height, int depth, DataRepository dataRepository);
/**
* This method reads the colorband data from the given texture structure.
*

@ -1,6 +1,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.DataRepository;
@ -8,9 +9,9 @@ import com.jme3.scene.plugins.blender.file.Structure;
import com.jme3.scene.plugins.blender.textures.TextureHelper.ColorBand;
import com.jme3.scene.plugins.blender.textures.TextureHelper.TexResult;
import com.jme3.texture.Image;
import com.jme3.texture.Texture;
import com.jme3.texture.Texture2D;
import com.jme3.texture.Image.Format;
import com.jme3.texture.Texture;
import com.jme3.texture.Texture3D;
import com.jme3.util.BufferUtils;
/**
@ -21,85 +22,92 @@ public final class TextureGeneratorBlend extends TextureGenerator {
/**
* Constructor stores the given noise generator.
* @param noiseGenerator the noise generator
* @param noiseGenerator
* the noise generator
*/
public TextureGeneratorBlend(NoiseGenerator noiseGenerator) {
super(noiseGenerator);
}
@Override
protected Texture generate(Structure tex, int width, int height, DataRepository dataRepository) {
protected Texture generate(Structure tex, int width, int height, int depth, DataRepository dataRepository) {
int flag = ((Number) tex.getFieldValue("flag")).intValue();
int stype = ((Number) tex.getFieldValue("stype")).intValue();
float contrast = ((Number) tex.getFieldValue("contrast")).floatValue();
float brightness = ((Number) tex.getFieldValue("bright")).floatValue();
float wDelta = 1.0f / width, hDelta = 1.0f / height, x, y, t;
float wDelta = 1.0f / width, hDelta = 1.0f / height, dDelta = 1.0f / depth, x, y, t;
float[] texvec = new float[] { 0, 0, 0 };
TexResult texres = new TexResult();
int halfW = width, halfH = height;
int halfW = width, halfH = height, halfD = depth;
width <<= 1;
height <<= 1;
depth <<= 1;
ColorBand colorBand = this.readColorband(tex, dataRepository);
Format format = colorBand != null ? Format.RGB8 : Format.Luminance8;
int bytesPerPixel = colorBand != null ? 3 : 1;
ByteBuffer data = BufferUtils.createByteBuffer(width * height * bytesPerPixel);
ByteBuffer data = BufferUtils.createByteBuffer(width * height * depth * bytesPerPixel);
for (int i = -halfW; i < halfW; ++i) {
texvec[0] = wDelta * i;
for (int j = -halfH; j < halfH; ++j) {
texvec[1] = hDelta * j;
if ((flag & NoiseGenerator.TEX_FLIPBLEND) != 0) {
x = texvec[1];
y = texvec[0];
} else {
x = texvec[0];
y = texvec[1];
}
if (stype == NoiseGenerator.TEX_LIN) { /* lin */
texres.tin = (1.0f + x) / 2.0f;
} else if (stype == NoiseGenerator.TEX_QUAD) { /* quad */
texres.tin = (1.0f + x) / 2.0f;
if (texres.tin < 0.0f) {
texres.tin = 0.0f;
for (int k = -halfD; k < halfD; ++k) {
texvec[2] = dDelta * k;
if ((flag & NoiseGenerator.TEX_FLIPBLEND) != 0) {
x = texvec[1];
y = texvec[0];
} else {
texres.tin *= texres.tin;
x = texvec[0];
y = texvec[1];
}
} else if (stype == NoiseGenerator.TEX_EASE) { /* ease */
texres.tin = (1.0f + x) / 2.0f;
if (texres.tin <= 0.0f) {
texres.tin = 0.0f;
} else if (texres.tin >= 1.0f) {
texres.tin = 1.0f;
} else {
t = texres.tin * texres.tin;
texres.tin = 3.0f * t - 2.0f * t * texres.tin;
if (stype == NoiseGenerator.TEX_LIN) { /* lin */
texres.tin = (1.0f + x) / 2.0f;
} else if (stype == NoiseGenerator.TEX_QUAD) { /* quad */
texres.tin = (1.0f + x) / 2.0f;
if (texres.tin < 0.0f) {
texres.tin = 0.0f;
} else {
texres.tin *= texres.tin;
}
} else if (stype == NoiseGenerator.TEX_EASE) { /* ease */
texres.tin = (1.0f + x) / 2.0f;
if (texres.tin <= 0.0f) {
texres.tin = 0.0f;
} else if (texres.tin >= 1.0f) {
texres.tin = 1.0f;
} else {
t = texres.tin * texres.tin;
texres.tin = 3.0f * t - 2.0f * t * texres.tin;
}
} else if (stype == NoiseGenerator.TEX_DIAG) { /* diag */
texres.tin = (2.0f + x + y) / 4.0f;
} else if (stype == NoiseGenerator.TEX_RAD) { /* radial */
texres.tin = (float) Math.atan2(y, x) / FastMath.TWO_PI + 0.5f;
} else { /* sphere TEX_SPHERE */
texres.tin = 1.0f - (float) Math.sqrt(x * x + y * y + texvec[2] * texvec[2]);
if (texres.tin < 0.0f) {
texres.tin = 0.0f;
}
if (stype == NoiseGenerator.TEX_HALO) {
texres.tin *= texres.tin;
} /* halo */
}
} else if (stype == NoiseGenerator.TEX_DIAG) { /* diag */
texres.tin = (2.0f + x + y) / 4.0f;
} else if (stype == NoiseGenerator.TEX_RAD) { /* radial */
texres.tin = (float) Math.atan2(y, x) / FastMath.TWO_PI + 0.5f;
} else { /* sphere TEX_SPHERE */
texres.tin = 1.0f - (float) Math.sqrt(x * x + y * y + texvec[2] * texvec[2]);
if (texres.tin < 0.0f) {
texres.tin = 0.0f;
if (colorBand != null) {
noiseGenerator.doColorband(colorBand, texres, dataRepository);
noiseGenerator.brightnesAndContrastRGB(tex, texres);
data.put((byte) (texres.tr * 255.0f));
data.put((byte) (texres.tg * 255.0f));
data.put((byte) (texres.tb * 255.0f));
} else {
noiseGenerator.brightnesAndContrast(texres, contrast, brightness);
data.put((byte) (texres.tin * 255.0f));
}
if (stype == NoiseGenerator.TEX_HALO) {
texres.tin *= texres.tin;
} /* halo */
}
if (colorBand != null) {
noiseGenerator.doColorband(colorBand, texres, dataRepository);
noiseGenerator.brightnesAndContrastRGB(tex, texres);
data.put((byte) (texres.tr * 255.0f));
data.put((byte) (texres.tg * 255.0f));
data.put((byte) (texres.tb * 255.0f));
} else {
noiseGenerator.brightnesAndContrast(texres, contrast, brightness);
data.put((byte) (texres.tin * 255.0f));
}
}
}
return new Texture2D(new Image(format, width, height, data));
ArrayList<ByteBuffer> dataArray = new ArrayList<ByteBuffer>(1);
dataArray.add(data);
return new Texture3D(new Image(format, width, height, depth, dataArray));
}
}

@ -1,15 +1,16 @@
package com.jme3.scene.plugins.blender.textures;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import com.jme3.scene.plugins.blender.DataRepository;
import com.jme3.scene.plugins.blender.file.Structure;
import com.jme3.scene.plugins.blender.textures.TextureHelper.ColorBand;
import com.jme3.scene.plugins.blender.textures.TextureHelper.TexResult;
import com.jme3.texture.Image;
import com.jme3.texture.Texture;
import com.jme3.texture.Texture2D;
import com.jme3.texture.Image.Format;
import com.jme3.texture.Texture;
import com.jme3.texture.Texture3D;
import com.jme3.util.BufferUtils;
/**
@ -20,16 +21,17 @@ public class TextureGeneratorClouds extends TextureGenerator {
/**
* Constructor stores the given noise generator.
* @param noiseGenerator the noise generator
* @param noiseGenerator
* the noise generator
*/
public TextureGeneratorClouds(NoiseGenerator noiseGenerator) {
super(noiseGenerator);
}
@Override
protected Texture generate(Structure tex, int width, int height, DataRepository dataRepository) {
protected Texture generate(Structure tex, int width, int height, int depth, DataRepository dataRepository) {
// preparing the proper data
float wDelta = 1.0f / width, hDelta = 1.0f / height;
float wDelta = 1.0f / width, hDelta = 1.0f / height, dDelta = 1.0f / depth;
float[] texvec = new float[] { 0, 0, 0 };
TexResult texres = new TexResult();
@ -42,50 +44,55 @@ public class TextureGeneratorClouds extends TextureGenerator {
float bright = ((Number) tex.getFieldValue("bright")).floatValue();
boolean isHard = noiseType != NoiseGenerator.TEX_NOISESOFT;
int sType = ((Number) tex.getFieldValue("stype")).intValue();
int halfW = width, halfH = height;
int halfW = width, halfH = height, halfD = depth;
width <<= 1;
height <<= 1;
depth <<= 1;
ColorBand colorBand = this.readColorband(tex, dataRepository);
Format format = sType == NoiseGenerator.TEX_COLOR || colorBand != null ? Format.RGB8 : Format.Luminance8;
int bytesPerPixel = sType == NoiseGenerator.TEX_COLOR || colorBand != null ? 3 : 1;
ByteBuffer data = BufferUtils.createByteBuffer(width * height * bytesPerPixel);
ByteBuffer data = BufferUtils.createByteBuffer(width * height * depth * bytesPerPixel);
for (int i = -halfW; i < halfW; ++i) {
texvec[0] = wDelta * i;// x
texvec[0] = wDelta * i;
for (int j = -halfH; j < halfH; ++j) {
texvec[1] = hDelta * j;// y (z is always = 0)
texres.tin = noiseGenerator.bliGTurbulence(noisesize, texvec[0], texvec[1], texvec[2], noiseDepth, isHard, noiseBasis);
if (colorBand != null) {
noiseGenerator.doColorband(colorBand, texres, dataRepository);
if (texres.nor != null) {
float nabla = ((Number) tex.getFieldValue("nabla")).floatValue();
// calculate bumpnormal
texres.nor[0] = noiseGenerator.bliGTurbulence(noisesize, texvec[0] + nabla, texvec[1], texvec[2], noiseDepth, isHard, noiseBasis);
texres.nor[1] = noiseGenerator.bliGTurbulence(noisesize, texvec[0], texvec[1] + nabla, texvec[2], noiseDepth, isHard, noiseBasis);
texres.nor[2] = noiseGenerator.bliGTurbulence(noisesize, texvec[0], texvec[1], texvec[2] + nabla, noiseDepth, isHard, noiseBasis);
noiseGenerator.texNormalDerivate(colorBand, texres, dataRepository);
texvec[1] = hDelta * j;
for (int k = -halfD; k < halfD; ++k) {
texvec[2] = dDelta * k;
texres.tin = noiseGenerator.bliGTurbulence(noisesize, texvec[0], texvec[1], texvec[2], noiseDepth, isHard, noiseBasis);
if (colorBand != null) {
noiseGenerator.doColorband(colorBand, texres, dataRepository);
if (texres.nor != null) {
float nabla = ((Number) tex.getFieldValue("nabla")).floatValue();
// calculate bumpnormal
texres.nor[0] = noiseGenerator.bliGTurbulence(noisesize, texvec[0] + nabla, texvec[1], texvec[2], noiseDepth, isHard, noiseBasis);
texres.nor[1] = noiseGenerator.bliGTurbulence(noisesize, texvec[0], texvec[1] + nabla, texvec[2], noiseDepth, isHard, noiseBasis);
texres.nor[2] = noiseGenerator.bliGTurbulence(noisesize, texvec[0], texvec[1], texvec[2] + nabla, noiseDepth, isHard, noiseBasis);
noiseGenerator.texNormalDerivate(colorBand, texres, dataRepository);
}
noiseGenerator.brightnesAndContrastRGB(tex, texres);
data.put((byte) (texres.tr * 255.0f));
data.put((byte) (texres.tg * 255.0f));
data.put((byte) (texres.tb * 255.0f));
} else if (sType == NoiseGenerator.TEX_COLOR) {
// in this case, int. value should really be computed from color,
// and bumpnormal from that, would be too slow, looks ok as is
texres.tr = texres.tin;
texres.tg = noiseGenerator.bliGTurbulence(noisesize, texvec[1], texvec[0], texvec[2], noiseDepth, isHard, noiseBasis);
texres.tb = noiseGenerator.bliGTurbulence(noisesize, texvec[1], texvec[2], texvec[0], noiseDepth, isHard, noiseBasis);
noiseGenerator.brightnesAndContrastRGB(tex, texres);
data.put((byte) (texres.tr * 255.0f));
data.put((byte) (texres.tg * 255.0f));
data.put((byte) (texres.tb * 255.0f));
} else {
noiseGenerator.brightnesAndContrast(texres, contrast, bright);
data.put((byte) (texres.tin * 255));
}
noiseGenerator.brightnesAndContrastRGB(tex, texres);
data.put((byte) (texres.tr * 255.0f));
data.put((byte) (texres.tg * 255.0f));
data.put((byte) (texres.tb * 255.0f));
} else if (sType == NoiseGenerator.TEX_COLOR) {
// in this case, int. value should really be computed from color,
// and bumpnormal from that, would be too slow, looks ok as is
texres.tr = texres.tin;
texres.tg = noiseGenerator.bliGTurbulence(noisesize, texvec[1], texvec[0], texvec[2], noiseDepth, isHard, noiseBasis);
texres.tb = noiseGenerator.bliGTurbulence(noisesize, texvec[1], texvec[2], texvec[0], noiseDepth, isHard, noiseBasis);
noiseGenerator.brightnesAndContrastRGB(tex, texres);
data.put((byte) (texres.tr * 255.0f));
data.put((byte) (texres.tg * 255.0f));
data.put((byte) (texres.tb * 255.0f));
} else {
noiseGenerator.brightnesAndContrast(texres, contrast, bright);
data.put((byte) (texres.tin * 255));
}
}
}
return new Texture2D(new Image(format, width, height, data));
ArrayList<ByteBuffer> dataArray = new ArrayList<ByteBuffer>(1);
dataArray.add(data);
return new Texture3D(new Image(format, width, height, depth, dataArray));
}
}

@ -1,15 +1,16 @@
package com.jme3.scene.plugins.blender.textures;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import com.jme3.scene.plugins.blender.DataRepository;
import com.jme3.scene.plugins.blender.file.Structure;
import com.jme3.scene.plugins.blender.textures.TextureHelper.ColorBand;
import com.jme3.scene.plugins.blender.textures.TextureHelper.TexResult;
import com.jme3.texture.Image;
import com.jme3.texture.Texture;
import com.jme3.texture.Texture2D;
import com.jme3.texture.Image.Format;
import com.jme3.texture.Texture;
import com.jme3.texture.Texture3D;
import com.jme3.util.BufferUtils;
/**
@ -20,14 +21,15 @@ public class TextureGeneratorDistnoise extends TextureGenerator {
/**
* Constructor stores the given noise generator.
* @param noiseGenerator the noise generator
* @param noiseGenerator
* the noise generator
*/
public TextureGeneratorDistnoise(NoiseGenerator noiseGenerator) {
super(noiseGenerator);
}
@Override
protected Texture generate(Structure tex, int width, int height, DataRepository dataRepository) {
protected Texture generate(Structure tex, int width, int height, int depth, DataRepository dataRepository) {
float noisesize = ((Number) tex.getFieldValue("noisesize")).floatValue();
float nabla = ((Number) tex.getFieldValue("nabla")).floatValue();
float distAmount = ((Number) tex.getFieldValue("dist_amount")).floatValue();
@ -38,42 +40,47 @@ public class TextureGeneratorDistnoise extends TextureGenerator {
TexResult texres = new TexResult();
float[] texvec = new float[] { 0, 0, 0 };
float wDelta = 1.0f / width, hDelta = 1.0f / height;
int halfW = width, halfH = height;
float wDelta = 1.0f / width, hDelta = 1.0f / height, dDelta = 1.0f / depth;
int halfW = width, halfH = height, halfD = depth;
width <<= 1;
height <<= 1;
depth <<= 1;
ColorBand colorBand = this.readColorband(tex, dataRepository);
Format format = colorBand != null ? Format.RGB8 : Format.Luminance8;
int bytesPerPixel = colorBand != null ? 3 : 1;
ByteBuffer data = BufferUtils.createByteBuffer(width * height * bytesPerPixel);
ByteBuffer data = BufferUtils.createByteBuffer(width * height * depth * bytesPerPixel);
for (int i = -halfW; i < halfW; ++i) {
texvec[0] = wDelta * i / noisesize;
for (int j = -halfH; j < halfH; ++j) {
texvec[1] = hDelta * j / noisesize;
for (int k = -halfD; k < halfD; ++k) {
texvec[2] = dDelta * k;// z
texres.tin = noiseGenerator.mgVLNoise(texvec[0], texvec[1], texvec[2], distAmount, noisebasis, noisebasis2);
if (colorBand != null) {
noiseGenerator.doColorband(colorBand, texres, dataRepository);
if (texres.nor != null) {
float offs = nabla / noisesize; // also scaling of texvec
/* calculate bumpnormal */
texres.nor[0] = noiseGenerator.mgVLNoise(texvec[0] + offs, texvec[1], texvec[2], distAmount, noisebasis, noisebasis2);
texres.nor[1] = noiseGenerator.mgVLNoise(texvec[0], texvec[1] + offs, texvec[2], distAmount, noisebasis, noisebasis2);
texres.nor[2] = noiseGenerator.mgVLNoise(texvec[0], texvec[1], texvec[2] + offs, distAmount, noisebasis, noisebasis2);
noiseGenerator.texNormalDerivate(colorBand, texres, dataRepository);
}
texres.tin = noiseGenerator.mgVLNoise(texvec[0], texvec[1], texvec[2], distAmount, noisebasis, noisebasis2);
if (colorBand != null) {
noiseGenerator.doColorband(colorBand, texres, dataRepository);
if (texres.nor != null) {
float offs = nabla / noisesize; // also scaling of texvec
/* calculate bumpnormal */
texres.nor[0] = noiseGenerator.mgVLNoise(texvec[0] + offs, texvec[1], texvec[2], distAmount, noisebasis, noisebasis2);
texres.nor[1] = noiseGenerator.mgVLNoise(texvec[0], texvec[1] + offs, texvec[2], distAmount, noisebasis, noisebasis2);
texres.nor[2] = noiseGenerator.mgVLNoise(texvec[0], texvec[1], texvec[2] + offs, distAmount, noisebasis, noisebasis2);
noiseGenerator.texNormalDerivate(colorBand, texres, dataRepository);
noiseGenerator.brightnesAndContrastRGB(tex, texres);
data.put((byte) (texres.tr * 255.0f));
data.put((byte) (texres.tg * 255.0f));
data.put((byte) (texres.tb * 255.0f));
} else {
noiseGenerator.brightnesAndContrast(texres, contrast, brightness);
data.put((byte) (texres.tin * 255.0f));
}
noiseGenerator.brightnesAndContrastRGB(tex, texres);
data.put((byte) (texres.tr * 255.0f));
data.put((byte) (texres.tg * 255.0f));
data.put((byte) (texres.tb * 255.0f));
} else {
noiseGenerator.brightnesAndContrast(texres, contrast, brightness);
data.put((byte) (texres.tin * 255.0f));
}
}
}
return new Texture2D(new Image(format, width, height, data));
ArrayList<ByteBuffer> dataArray = new ArrayList<ByteBuffer>(1);
dataArray.add(data);
return new Texture3D(new Image(format, width, height, depth, dataArray));
}
}

@ -1,15 +1,16 @@
package com.jme3.scene.plugins.blender.textures;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import com.jme3.scene.plugins.blender.DataRepository;
import com.jme3.scene.plugins.blender.file.Structure;
import com.jme3.scene.plugins.blender.textures.TextureHelper.ColorBand;
import com.jme3.scene.plugins.blender.textures.TextureHelper.TexResult;
import com.jme3.texture.Image;
import com.jme3.texture.Texture;
import com.jme3.texture.Texture2D;
import com.jme3.texture.Image.Format;
import com.jme3.texture.Texture;
import com.jme3.texture.Texture3D;
import com.jme3.util.BufferUtils;
/**
@ -20,62 +21,67 @@ public class TextureGeneratorMagic extends TextureGenerator {
/**
* Constructor stores the given noise generator.
* @param noiseGenerator the noise generator
* @param noiseGenerator
* the noise generator
*/
public TextureGeneratorMagic(NoiseGenerator noiseGenerator) {
super(noiseGenerator);
}
@Override
protected Texture generate(Structure tex, int width, int height, DataRepository dataRepository) {
protected Texture generate(Structure tex, int width, int height, int depth, DataRepository dataRepository) {
float x, y, z, turb;
int noisedepth = ((Number) tex.getFieldValue("noisedepth")).intValue();
float turbul = ((Number) tex.getFieldValue("turbul")).floatValue() / 5.0f;
float[] texvec = new float[] { 0, 0, 0 };
TexResult texres = new TexResult();
float wDelta = 1.0f / width, hDelta = 1.0f / height;
int halfW = width, halfH = height;
float wDelta = 1.0f / width, hDelta = 1.0f / height, dDelta = 1.0f / depth;
int halfW = width, halfH = height, halfD = depth;
width <<= 1;
height <<= 1;
depth <<= 1;
ColorBand colorBand = this.readColorband(tex, dataRepository);
ByteBuffer data = BufferUtils.createByteBuffer(width * height * 4);
ByteBuffer data = BufferUtils.createByteBuffer(width * height * depth * 4);
for (int i = -halfW; i < halfW; ++i) {
texvec[0] = wDelta * i;
for (int j = -halfH; j < halfH; ++j) {
turb = turbul;
texvec[1] = hDelta * j;
x = (float) Math.sin((texvec[0] + texvec[1]) * 5.0f);// in blender: Math.sin((texvec[0] + texvec[1] + texvec[2]) * 5.0f);
y = (float) Math.cos((-texvec[0] + texvec[1]) * 5.0f);// in blender: Math.cos((-texvec[0] + texvec[1] - texvec[2]) * 5.0f);
z = -(float) Math.cos((-texvec[0] - texvec[1]) * 5.0f);// in blender: Math.cos((-texvec[0] - texvec[1] + texvec[2]) * 5.0f);
for (int k = -halfD; k < halfD; ++k) {
turb = turbul;
texvec[2] = dDelta * k;// z
x = (float) Math.sin((texvec[0] + texvec[1] + texvec[2]) * 5.0f);
y = (float) Math.cos((-texvec[0] + texvec[1] - texvec[2]) * 5.0f);
z = -(float) Math.cos((-texvec[0] - texvec[1] + texvec[2]) * 5.0f);
if (colorBand != null) {
texres.tin = 0.3333f * (x + y + z);
noiseGenerator.doColorband(colorBand, texres, dataRepository);
} else {
if (noisedepth > 0) {
x *= turb;
y *= turb;
z *= turb;
y = -(float) Math.cos(x - y + z) * turb;
if (noisedepth > 1) {
x = (float) Math.cos(x - y - z) * turb;
if (noisedepth > 2) {
z = (float) Math.sin(-x - y - z) * turb;
if (noisedepth > 3) {
x = -(float) Math.cos(-x + y - z) * turb;
if (noisedepth > 4) {
y = -(float) Math.sin(-x + y + z) * turb;
if (noisedepth > 5) {
y = -(float) Math.cos(-x + y + z) * turb;
if (noisedepth > 6) {
x = (float) Math.cos(x + y + z) * turb;
if (noisedepth > 7) {
z = (float) Math.sin(x + y - z) * turb;
if (noisedepth > 8) {
x = -(float) Math.cos(-x - y + z) * turb;
if (noisedepth > 9) {
y = -(float) Math.sin(x - y + z) * turb;
if (colorBand != null) {
texres.tin = 0.3333f * (x + y + z);
noiseGenerator.doColorband(colorBand, texres, dataRepository);
} else {
if (noisedepth > 0) {
x *= turb;
y *= turb;
z *= turb;
y = -(float) Math.cos(x - y + z) * turb;
if (noisedepth > 1) {
x = (float) Math.cos(x - y - z) * turb;
if (noisedepth > 2) {
z = (float) Math.sin(-x - y - z) * turb;
if (noisedepth > 3) {
x = -(float) Math.cos(-x + y - z) * turb;
if (noisedepth > 4) {
y = -(float) Math.sin(-x + y + z) * turb;
if (noisedepth > 5) {
y = -(float) Math.cos(-x + y + z) * turb;
if (noisedepth > 6) {
x = (float) Math.cos(x + y + z) * turb;
if (noisedepth > 7) {
z = (float) Math.sin(x + y - z) * turb;
if (noisedepth > 8) {
x = -(float) Math.cos(-x - y + z) * turb;
if (noisedepth > 9) {
y = -(float) Math.sin(x - y + z) * turb;
}
}
}
}
@ -85,25 +91,27 @@ public class TextureGeneratorMagic extends TextureGenerator {
}
}
}
}
if (turb != 0.0f) {
turb *= 2.0f;
x /= turb;
y /= turb;
z /= turb;
if (turb != 0.0f) {
turb *= 2.0f;
x /= turb;
y /= turb;
z /= turb;
}
texres.tr = 0.5f - x;
texres.tg = 0.5f - y;
texres.tb = 0.5f - z;
}
texres.tr = 0.5f - x;
texres.tg = 0.5f - y;
texres.tb = 0.5f - z;
noiseGenerator.brightnesAndContrastRGB(tex, texres);
data.put((byte) (texres.tin * 255));
data.put((byte) (texres.tb * 255));
data.put((byte) (texres.tg * 255));
data.put((byte) (texres.tr * 255));
}
noiseGenerator.brightnesAndContrastRGB(tex, texres);
data.put((byte) (texres.tin * 255));
data.put((byte) (texres.tb * 255));
data.put((byte) (texres.tg * 255));
data.put((byte) (texres.tr * 255));
}
}
return new Texture2D(new Image(Format.ABGR8, width, height, data));
ArrayList<ByteBuffer> dataArray = new ArrayList<ByteBuffer>(1);
dataArray.add(data);
return new Texture3D(new Image(Format.ABGR8, width, height, depth, dataArray));
}
}

@ -1,15 +1,16 @@
package com.jme3.scene.plugins.blender.textures;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import com.jme3.scene.plugins.blender.DataRepository;
import com.jme3.scene.plugins.blender.file.Structure;
import com.jme3.scene.plugins.blender.textures.TextureHelper.ColorBand;
import com.jme3.scene.plugins.blender.textures.TextureHelper.TexResult;
import com.jme3.texture.Image;
import com.jme3.texture.Texture;
import com.jme3.texture.Texture2D;
import com.jme3.texture.Image.Format;
import com.jme3.texture.Texture;
import com.jme3.texture.Texture3D;
import com.jme3.util.BufferUtils;
/**
@ -17,56 +18,63 @@ import com.jme3.util.BufferUtils;
* @author Marcin Roguski (Kaelthas)
*/
public class TextureGeneratorMarble extends TextureGenerator {
/**
* Constructor stores the given noise generator.
* @param noiseGenerator the noise generator
* @param noiseGenerator
* the noise generator
*/
public TextureGeneratorMarble(NoiseGenerator noiseGenerator) {
super(noiseGenerator);
}
@Override
protected Texture generate(Structure tex, int width, int height, DataRepository dataRepository) {
protected Texture generate(Structure tex, int width, int height, int depth, DataRepository dataRepository) {
// preparing the proper data
float contrast = ((Number) tex.getFieldValue("contrast")).floatValue();
float bright = ((Number) tex.getFieldValue("bright")).floatValue();
float nabla = ((Number) tex.getFieldValue("nabla")).floatValue();
float wDelta = 1.0f / width, hDelta = 1.0f / height;
float wDelta = 1.0f / width, hDelta = 1.0f / height, dDelta = 1.0f / depth;
float[] texvec = new float[] { 0, 0, 0 };
TexResult texres = new TexResult();
int halfW = width, halfH = height;
int halfW = width, halfH = height, halfD = depth;
width <<= 1;
height <<= 1;
depth <<= 1;
ColorBand colorBand = this.readColorband(tex, dataRepository);
Format format = colorBand != null ? Format.RGB8 : Format.Luminance8;
int bytesPerPixel = colorBand != null ? 3 : 1;
ByteBuffer data = BufferUtils.createByteBuffer(width * height * bytesPerPixel);
ByteBuffer data = BufferUtils.createByteBuffer(width * height * depth * bytesPerPixel);
for (int i = -halfW; i < halfW; ++i) {
texvec[0] = wDelta * i;
for (int j = -halfH; j < halfH; ++j) {
texvec[1] = hDelta * j;
texres.tin = noiseGenerator.marbleInt(tex, texvec[0], texvec[1], texvec[2], dataRepository);
if (colorBand != null) {
noiseGenerator.doColorband(colorBand, texres, dataRepository);
if (texres.nor != null) {// calculate bumpnormal
texres.nor[0] = noiseGenerator.marbleInt(tex, texvec[0] + nabla, texvec[1], texvec[2], dataRepository);
texres.nor[1] = noiseGenerator.marbleInt(tex, texvec[0], texvec[1] + nabla, texvec[2], dataRepository);
texres.nor[2] = noiseGenerator.marbleInt(tex, texvec[0], texvec[1], texvec[2] + nabla, dataRepository);
noiseGenerator.texNormalDerivate(colorBand, texres, dataRepository);
}
for (int k = -halfD; k < halfD; ++k) {
texvec[2] = dDelta * k;
texres.tin = noiseGenerator.marbleInt(tex, texvec[0], texvec[1], texvec[2], dataRepository);
if (colorBand != null) {
noiseGenerator.doColorband(colorBand, texres, dataRepository);
if (texres.nor != null) {// calculate bumpnormal
texres.nor[0] = noiseGenerator.marbleInt(tex, texvec[0] + nabla, texvec[1], texvec[2], dataRepository);
texres.nor[1] = noiseGenerator.marbleInt(tex, texvec[0], texvec[1] + nabla, texvec[2], dataRepository);
texres.nor[2] = noiseGenerator.marbleInt(tex, texvec[0], texvec[1], texvec[2] + nabla, dataRepository);
noiseGenerator.texNormalDerivate(colorBand, texres, dataRepository);
}
noiseGenerator.brightnesAndContrastRGB(tex, texres);
data.put((byte) (texres.tr * 255.0f));
data.put((byte) (texres.tg * 255.0f));
data.put((byte) (texres.tb * 255.0f));
} else {
noiseGenerator.brightnesAndContrast(texres, contrast, bright);
data.put((byte) (texres.tin * 255.0f));
noiseGenerator.brightnesAndContrastRGB(tex, texres);
data.put((byte) (texres.tr * 255.0f));
data.put((byte) (texres.tg * 255.0f));
data.put((byte) (texres.tb * 255.0f));
} else {
noiseGenerator.brightnesAndContrast(texres, contrast, bright);
data.put((byte) (texres.tin * 255.0f));
}
}
}
}
return new Texture2D(new Image(format, width, height, data));
ArrayList<ByteBuffer> dataArray = new ArrayList<ByteBuffer>(1);
dataArray.add(data);
return new Texture3D(new Image(format, width, height, depth, dataArray));
}
}

@ -1,15 +1,16 @@
package com.jme3.scene.plugins.blender.textures;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import com.jme3.scene.plugins.blender.DataRepository;
import com.jme3.scene.plugins.blender.file.Structure;
import com.jme3.scene.plugins.blender.textures.TextureHelper.ColorBand;
import com.jme3.scene.plugins.blender.textures.TextureHelper.TexResult;
import com.jme3.texture.Image;
import com.jme3.texture.Texture;
import com.jme3.texture.Texture2D;
import com.jme3.texture.Image.Format;
import com.jme3.texture.Texture;
import com.jme3.texture.Texture3D;
import com.jme3.util.BufferUtils;
/**
@ -20,56 +21,63 @@ public class TextureGeneratorMusgrave extends TextureGenerator {
/**
* Constructor stores the given noise generator.
* @param noiseGenerator the noise generator
* @param noiseGenerator
* the noise generator
*/
public TextureGeneratorMusgrave(NoiseGenerator noiseGenerator) {
super(noiseGenerator);
}
@Override
protected Texture generate(Structure tex, int width, int height, DataRepository dataRepository) {
protected Texture generate(Structure tex, int width, int height, int depth, DataRepository dataRepository) {
int stype = ((Number) tex.getFieldValue("stype")).intValue();
float noisesize = ((Number) tex.getFieldValue("noisesize")).floatValue();
TexResult texres = new TexResult();
float[] texvec = new float[] { 0, 0, 0 };
float wDelta = 1.0f / width, hDelta = 1.0f / height;
int halfW = width, halfH = height;
float wDelta = 1.0f / width, hDelta = 1.0f / height, dDelta = 1.0f / depth;
int halfW = width, halfH = height, halfD = depth;
width <<= 1;
height <<= 1;
depth <<= 1;
ColorBand colorBand = this.readColorband(tex, dataRepository);
Format format = colorBand != null ? Format.RGB8 : Format.Luminance8;
int bytesPerPixel = colorBand != null ? 3 : 1;
ByteBuffer data = BufferUtils.createByteBuffer(width * height * bytesPerPixel);
ByteBuffer data = BufferUtils.createByteBuffer(width * height * depth * bytesPerPixel);
for (int i = -halfW; i < halfW; ++i) {
texvec[0] = wDelta * i / noisesize;
for (int j = -halfH; j < halfH; ++j) {
texvec[1] = hDelta * j / noisesize;
switch (stype) {
case NoiseGenerator.TEX_MFRACTAL:
case NoiseGenerator.TEX_FBM:
noiseGenerator.mgMFractalOrfBmTex(tex, texvec, colorBand, texres, dataRepository);
break;
case NoiseGenerator.TEX_RIDGEDMF:
case NoiseGenerator.TEX_HYBRIDMF:
noiseGenerator.mgRidgedOrHybridMFTex(tex, texvec, colorBand, texres, dataRepository);
break;
case NoiseGenerator.TEX_HTERRAIN:
noiseGenerator.mgHTerrainTex(tex, texvec, colorBand, texres, dataRepository);
break;
default:
throw new IllegalStateException("Unknown type of musgrave texture: " + stype);
}
if (colorBand != null) {
noiseGenerator.doColorband(colorBand, texres, dataRepository);
data.put((byte) (texres.tr * 255.0f));
data.put((byte) (texres.tg * 255.0f));
data.put((byte) (texres.tb * 255.0f));
} else {
data.put((byte) (texres.tin * 255.0f));
for (int k = -halfD; k < halfD; ++k) {
texvec[2] = dDelta * k;
switch (stype) {
case NoiseGenerator.TEX_MFRACTAL:
case NoiseGenerator.TEX_FBM:
noiseGenerator.mgMFractalOrfBmTex(tex, texvec, colorBand, texres, dataRepository);
break;
case NoiseGenerator.TEX_RIDGEDMF:
case NoiseGenerator.TEX_HYBRIDMF:
noiseGenerator.mgRidgedOrHybridMFTex(tex, texvec, colorBand, texres, dataRepository);
break;
case NoiseGenerator.TEX_HTERRAIN:
noiseGenerator.mgHTerrainTex(tex, texvec, colorBand, texres, dataRepository);
break;
default:
throw new IllegalStateException("Unknown type of musgrave texture: " + stype);
}
if (colorBand != null) {
noiseGenerator.doColorband(colorBand, texres, dataRepository);
data.put((byte) (texres.tr * 255.0f));
data.put((byte) (texres.tg * 255.0f));
data.put((byte) (texres.tb * 255.0f));
} else {
data.put((byte) (texres.tin * 255.0f));
}
}
}
}
return new Texture2D(new Image(format, width, height, data));
ArrayList<ByteBuffer> dataArray = new ArrayList<ByteBuffer>(1);
dataArray.add(data);
return new Texture3D(new Image(format, width, height, depth, dataArray));
}
}

@ -1,6 +1,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.DataRepository;
@ -8,9 +9,9 @@ import com.jme3.scene.plugins.blender.file.Structure;
import com.jme3.scene.plugins.blender.textures.TextureHelper.ColorBand;
import com.jme3.scene.plugins.blender.textures.TextureHelper.TexResult;
import com.jme3.texture.Image;
import com.jme3.texture.Texture;
import com.jme3.texture.Texture2D;
import com.jme3.texture.Image.Format;
import com.jme3.texture.Texture;
import com.jme3.texture.Texture3D;
import com.jme3.util.BufferUtils;
/**
@ -21,52 +22,58 @@ public class TextureGeneratorNoise extends TextureGenerator {
/**
* Constructor stores the given noise generator.
* @param noiseGenerator the noise generator
* @param noiseGenerator
* the noise generator
*/
public TextureGeneratorNoise(NoiseGenerator noiseGenerator) {
super(noiseGenerator);
}
@Override
protected Texture generate(Structure tex, int width, int height, DataRepository dataRepository) {
protected Texture generate(Structure tex, int width, int height, int depth, DataRepository dataRepository) {
float div = 3.0f;
int val, ran, loop;
int noisedepth = ((Number) tex.getFieldValue("noisedepth")).intValue();
float contrast = ((Number) tex.getFieldValue("contrast")).floatValue();
float brightness = ((Number) tex.getFieldValue("bright")).floatValue();
TexResult texres = new TexResult();
int halfW = width, halfH = height;
int halfW = width, halfH = height, halfD = depth;
width <<= 1;
height <<= 1;
depth <<= 1;
ColorBand colorBand = this.readColorband(tex, dataRepository);
Format format = colorBand != null ? Format.RGB8 : Format.Luminance8;
int bytesPerPixel = colorBand != null ? 3 : 1;
ByteBuffer data = BufferUtils.createByteBuffer(width * height * bytesPerPixel);
ByteBuffer data = BufferUtils.createByteBuffer(width * height * depth * bytesPerPixel);
for (int i = -halfW; i < halfW; ++i) {
for (int j = -halfH; j < halfH; ++j) {
ran = FastMath.rand.nextInt();// BLI_rand();
val = ran & 3;
for (int k = -halfD; k < halfD; ++k) {
ran = FastMath.rand.nextInt();// BLI_rand();
val = ran & 3;
loop = noisedepth;
while (loop-- != 0) {
ran = ran >> 2;
val *= ran & 3;
div *= 3.0f;
}
texres.tin = val;// / div;
if (colorBand != null) {
noiseGenerator.doColorband(colorBand, texres, dataRepository);
noiseGenerator.brightnesAndContrastRGB(tex, texres);
data.put((byte) (texres.tr * 255.0f));
data.put((byte) (texres.tg * 255.0f));
data.put((byte) (texres.tb * 255.0f));
} else {
noiseGenerator.brightnesAndContrast(texres, contrast, brightness);
data.put((byte) (texres.tin * 255.0f));
loop = noisedepth;
while (loop-- != 0) {
ran = ran >> 2;
val *= ran & 3;
div *= 3.0f;
}
texres.tin = val;// / div;
if (colorBand != null) {
noiseGenerator.doColorband(colorBand, texres, dataRepository);
noiseGenerator.brightnesAndContrastRGB(tex, texres);
data.put((byte) (texres.tr * 255.0f));
data.put((byte) (texres.tg * 255.0f));
data.put((byte) (texres.tb * 255.0f));
} else {
noiseGenerator.brightnesAndContrast(texres, contrast, brightness);
data.put((byte) (texres.tin * 255.0f));
}
}
}
}
return new Texture2D(new Image(format, width, height, data));
ArrayList<ByteBuffer> dataArray = new ArrayList<ByteBuffer>(1);
dataArray.add(data);
return new Texture3D(new Image(format, width, height, depth, dataArray));
}
}

@ -1,15 +1,16 @@
package com.jme3.scene.plugins.blender.textures;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import com.jme3.scene.plugins.blender.DataRepository;
import com.jme3.scene.plugins.blender.file.Structure;
import com.jme3.scene.plugins.blender.textures.TextureHelper.ColorBand;
import com.jme3.scene.plugins.blender.textures.TextureHelper.TexResult;
import com.jme3.texture.Image;
import com.jme3.texture.Texture;
import com.jme3.texture.Texture2D;
import com.jme3.texture.Image.Format;
import com.jme3.texture.Texture;
import com.jme3.texture.Texture3D;
import com.jme3.util.BufferUtils;
/**
@ -20,14 +21,15 @@ public class TextureGeneratorStucci extends TextureGenerator {
/**
* Constructor stores the given noise generator.
* @param noiseGenerator the noise generator
* @param noiseGenerator
* the noise generator
*/
public TextureGeneratorStucci(NoiseGenerator noiseGenerator) {
super(noiseGenerator);
}
@Override
protected Texture generate(Structure tex, int width, int height, DataRepository dataRepository) {
protected Texture generate(Structure tex, int width, int height, int depth, DataRepository dataRepository) {
float noisesize = ((Number) tex.getFieldValue("noisesize")).floatValue();
int noisebasis = ((Number) tex.getFieldValue("noisebasis")).intValue();
int noisetype = ((Number) tex.getFieldValue("noisetype")).intValue();
@ -37,59 +39,65 @@ public class TextureGeneratorStucci extends TextureGenerator {
float[] texvec = new float[] { 0, 0, 0 };
TexResult texres = new TexResult();
float wDelta = 1.0f / width, hDelta = 1.0f / height, b2, ofs;
int halfW = width, halfH = height;
float wDelta = 1.0f / width, hDelta = 1.0f / height, dDelta = 1.0f / depth, b2, ofs;
int halfW = width, halfH = height, halfD = depth;
width <<= 1;
height <<= 1;
depth <<= 1;
ColorBand colorBand = this.readColorband(tex, dataRepository);
Format format = colorBand != null ? Format.RGB8 : Format.Luminance8;
int bytesPerPixel = colorBand != null ? 3 : 1;
ByteBuffer data = BufferUtils.createByteBuffer(width * height * bytesPerPixel);
ByteBuffer data = BufferUtils.createByteBuffer(width * height * depth * bytesPerPixel);
for (int i = -halfW; i < halfW; ++i) {
texvec[0] = wDelta * i;// x
texvec[0] = wDelta * i;
for (int j = -halfH; j < halfH; ++j) {
texvec[1] = hDelta * j;// y (z is always = 0)
b2 = noiseGenerator.bliGNoise(noisesize, texvec[0], texvec[1], texvec[2], isHard, noisebasis);
texvec[1] = hDelta * j;
for (int k = -halfD; k < halfD; ++k) {
texvec[2] = dDelta * k;
b2 = noiseGenerator.bliGNoise(noisesize, texvec[0], texvec[1], texvec[2], isHard, noisebasis);
ofs = turbul / 200.0f;
ofs = turbul / 200.0f;
if (stype != 0) {
ofs *= b2 * b2;
}
if (stype != 0) {
ofs *= b2 * b2;
}
texres.tin = noiseGenerator.bliGNoise(noisesize, texvec[0], texvec[1], texvec[2] + ofs, isHard, noisebasis);// ==nor[2]
if (colorBand != null) {
noiseGenerator.doColorband(colorBand, texres, dataRepository);
if (texres.nor != null) {
texres.nor[0] = noiseGenerator.bliGNoise(noisesize, texvec[0] + ofs, texvec[1], texvec[2], isHard, noisebasis);
texres.nor[1] = noiseGenerator.bliGNoise(noisesize, texvec[0], texvec[1] + ofs, texvec[2], isHard, noisebasis);
texres.nor[2] = texres.tin;
noiseGenerator.texNormalDerivate(colorBand, texres, dataRepository);
texres.tin = noiseGenerator.bliGNoise(noisesize, texvec[0], texvec[1], texvec[2] + ofs, isHard, noisebasis);// ==nor[2]
if (colorBand != null) {
noiseGenerator.doColorband(colorBand, texres, dataRepository);
if (texres.nor != null) {
texres.nor[0] = noiseGenerator.bliGNoise(noisesize, texvec[0] + ofs, texvec[1], texvec[2], isHard, noisebasis);
texres.nor[1] = noiseGenerator.bliGNoise(noisesize, texvec[0], texvec[1] + ofs, texvec[2], isHard, noisebasis);
texres.nor[2] = texres.tin;
noiseGenerator.texNormalDerivate(colorBand, texres, dataRepository);
if (stype == NoiseGenerator.TEX_WALLOUT) {
texres.nor[0] = -texres.nor[0];
texres.nor[1] = -texres.nor[1];
texres.nor[2] = -texres.nor[2];
if (stype == NoiseGenerator.TEX_WALLOUT) {
texres.nor[0] = -texres.nor[0];
texres.nor[1] = -texres.nor[1];
texres.nor[2] = -texres.nor[2];
}
}
}
}
if (stype == NoiseGenerator.TEX_WALLOUT) {
texres.tin = 1.0f - texres.tin;
}
if (texres.tin < 0.0f) {
texres.tin = 0.0f;
}
if (colorBand != null) {
data.put((byte) (texres.tr * 255.0f));
data.put((byte) (texres.tg * 255.0f));
data.put((byte) (texres.tb * 255.0f));
} else {
data.put((byte) (texres.tin * 255.0f));
if (stype == NoiseGenerator.TEX_WALLOUT) {
texres.tin = 1.0f - texres.tin;
}
if (texres.tin < 0.0f) {
texres.tin = 0.0f;
}
if (colorBand != null) {
data.put((byte) (texres.tr * 255.0f));
data.put((byte) (texres.tg * 255.0f));
data.put((byte) (texres.tb * 255.0f));
} else {
data.put((byte) (texres.tin * 255.0f));
}
}
}
}
return new Texture2D(new Image(format, width, height, data));
ArrayList<ByteBuffer> dataArray = new ArrayList<ByteBuffer>(1);
dataArray.add(data);
return new Texture3D(new Image(format, width, height, depth, dataArray));
}
}

@ -1,6 +1,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.DataRepository;
@ -8,9 +9,9 @@ import com.jme3.scene.plugins.blender.file.Structure;
import com.jme3.scene.plugins.blender.textures.TextureHelper.ColorBand;
import com.jme3.scene.plugins.blender.textures.TextureHelper.TexResult;
import com.jme3.texture.Image;
import com.jme3.texture.Texture;
import com.jme3.texture.Texture2D;
import com.jme3.texture.Image.Format;
import com.jme3.texture.Texture;
import com.jme3.texture.Texture3D;
import com.jme3.util.BufferUtils;
/**
@ -21,14 +22,15 @@ public class TextureGeneratorVoronoi extends TextureGenerator {
/**
* Constructor stores the given noise generator.
* @param noiseGenerator the noise generator
* @param noiseGenerator
* the noise generator
*/
public TextureGeneratorVoronoi(NoiseGenerator noiseGenerator) {
super(noiseGenerator);
}
@Override
protected Texture generate(Structure tex, int width, int height, DataRepository dataRepository) {
protected Texture generate(Structure tex, int width, int height, int depth, DataRepository dataRepository) {
float vn_w1 = ((Number) tex.getFieldValue("vn_w1")).floatValue();
float vn_w2 = ((Number) tex.getFieldValue("vn_w2")).floatValue();
float vn_w3 = ((Number) tex.getFieldValue("vn_w3")).floatValue();
@ -44,10 +46,11 @@ public class TextureGeneratorVoronoi extends TextureGenerator {
TexResult texres = new TexResult();
float[] texvec = new float[] { 0, 0, 0 };
float wDelta = 1.0f / width, hDelta = 1.0f / height;
int halfW = width, halfH = height;
float wDelta = 1.0f / width, hDelta = 1.0f / height, dDelta = 1.0f / depth;
int halfW = width, halfH = height, halfD = depth;
width <<= 1;
height <<= 1;
depth <<= 1;
ColorBand colorBand = this.readColorband(tex, dataRepository);
Format format = vn_coltype != 0 || colorBand != null ? Format.RGB8 : Format.Luminance8;
int bytesPerPixel = vn_coltype != 0 || colorBand != null ? 3 : 1;
@ -63,76 +66,80 @@ public class TextureGeneratorVoronoi extends TextureGenerator {
sc = ns_outscale / sc;
}
ByteBuffer data = BufferUtils.createByteBuffer(width * height * bytesPerPixel);
ByteBuffer data = BufferUtils.createByteBuffer(width * height * depth * bytesPerPixel);
for (int i = -halfW; i < halfW; ++i) {
texvec[0] = wDelta * i / noisesize;
for (int j = -halfH; j < halfH; ++j) {
texvec[1] = hDelta * j / noisesize;
noiseGenerator.voronoi(texvec[0], texvec[1], texvec[2], da, pa, vn_mexp, vn_distm);
texres.tin = sc * FastMath.abs(vn_w1 * da[0] + vn_w2 * da[1] + vn_w3 * da[2] + vn_w4 * da[3]);
if (vn_coltype != 0) {
noiseGenerator.cellNoiseV(pa[0], pa[1], pa[2], ca);
texres.tr = aw1 * ca[0];
texres.tg = aw1 * ca[1];
texres.tb = aw1 * ca[2];
noiseGenerator.cellNoiseV(pa[3], pa[4], pa[5], ca);
texres.tr += aw2 * ca[0];
texres.tg += aw2 * ca[1];
texres.tb += aw2 * ca[2];
noiseGenerator.cellNoiseV(pa[6], pa[7], pa[8], ca);
texres.tr += aw3 * ca[0];
texres.tg += aw3 * ca[1];
texres.tb += aw3 * ca[2];
noiseGenerator.cellNoiseV(pa[9], pa[10], pa[11], ca);
texres.tr += aw4 * ca[0];
texres.tg += aw4 * ca[1];
texres.tb += aw4 * ca[2];
if (vn_coltype >= 2) {
float t1 = (da[1] - da[0]) * 10.0f;
if (t1 > 1) {
t1 = 1.0f;
}
if (vn_coltype == 3) {
t1 *= texres.tin;
for (int k = -halfD; k < halfD; ++k) {
texvec[2] = dDelta * k;
noiseGenerator.voronoi(texvec[0], texvec[1], texvec[2], da, pa, vn_mexp, vn_distm);
texres.tin = sc * FastMath.abs(vn_w1 * da[0] + vn_w2 * da[1] + vn_w3 * da[2] + vn_w4 * da[3]);
if (vn_coltype != 0) {
noiseGenerator.cellNoiseV(pa[0], pa[1], pa[2], ca);
texres.tr = aw1 * ca[0];
texres.tg = aw1 * ca[1];
texres.tb = aw1 * ca[2];
noiseGenerator.cellNoiseV(pa[3], pa[4], pa[5], ca);
texres.tr += aw2 * ca[0];
texres.tg += aw2 * ca[1];
texres.tb += aw2 * ca[2];
noiseGenerator.cellNoiseV(pa[6], pa[7], pa[8], ca);
texres.tr += aw3 * ca[0];
texres.tg += aw3 * ca[1];
texres.tb += aw3 * ca[2];
noiseGenerator.cellNoiseV(pa[9], pa[10], pa[11], ca);
texres.tr += aw4 * ca[0];
texres.tg += aw4 * ca[1];
texres.tb += aw4 * ca[2];
if (vn_coltype >= 2) {
float t1 = (da[1] - da[0]) * 10.0f;
if (t1 > 1) {
t1 = 1.0f;
}
if (vn_coltype == 3) {
t1 *= texres.tin;
} else {
t1 *= sc;
}
texres.tr *= t1;
texres.tg *= t1;
texres.tb *= t1;
} else {
t1 *= sc;
texres.tr *= sc;
texres.tg *= sc;
texres.tb *= sc;
}
texres.tr *= t1;
texres.tg *= t1;
texres.tb *= t1;
} else {
texres.tr *= sc;
texres.tg *= sc;
texres.tb *= sc;
}
}
if (colorBand != null) {
noiseGenerator.doColorband(colorBand, texres, dataRepository);
if (texres.nor != null) {
float offs = nabla / noisesize; // also scaling of texvec
// calculate bumpnormal
noiseGenerator.voronoi(texvec[0] + offs, texvec[1], texvec[2], da, pa, vn_mexp, vn_distm);
texres.nor[0] = sc * FastMath.abs(vn_w1 * da[0] + vn_w2 * da[1] + vn_w3 * da[2] + vn_w4 * da[3]);
noiseGenerator.voronoi(texvec[0], texvec[1] + offs, texvec[2], da, pa, vn_mexp, vn_distm);
texres.nor[1] = sc * FastMath.abs(vn_w1 * da[0] + vn_w2 * da[1] + vn_w3 * da[2] + vn_w4 * da[3]);
noiseGenerator.voronoi(texvec[0], texvec[1], texvec[2] + offs, da, pa, vn_mexp, vn_distm);
texres.nor[2] = sc * FastMath.abs(vn_w1 * da[0] + vn_w2 * da[1] + vn_w3 * da[2] + vn_w4 * da[3]);
noiseGenerator.texNormalDerivate(colorBand, texres, dataRepository);
if (colorBand != null) {
noiseGenerator.doColorband(colorBand, texres, dataRepository);
if (texres.nor != null) {
float offs = nabla / noisesize; // also scaling of texvec
// calculate bumpnormal
noiseGenerator.voronoi(texvec[0] + offs, texvec[1], texvec[2], da, pa, vn_mexp, vn_distm);
texres.nor[0] = sc * FastMath.abs(vn_w1 * da[0] + vn_w2 * da[1] + vn_w3 * da[2] + vn_w4 * da[3]);
noiseGenerator.voronoi(texvec[0], texvec[1] + offs, texvec[2], da, pa, vn_mexp, vn_distm);
texres.nor[1] = sc * FastMath.abs(vn_w1 * da[0] + vn_w2 * da[1] + vn_w3 * da[2] + vn_w4 * da[3]);
noiseGenerator.voronoi(texvec[0], texvec[1], texvec[2] + offs, da, pa, vn_mexp, vn_distm);
texres.nor[2] = sc * FastMath.abs(vn_w1 * da[0] + vn_w2 * da[1] + vn_w3 * da[2] + vn_w4 * da[3]);
noiseGenerator.texNormalDerivate(colorBand, texres, dataRepository);
}
}
}
if (vn_coltype != 0 || colorBand != null) {
noiseGenerator.brightnesAndContrastRGB(tex, texres);
data.put((byte) (texres.tr * 255.0f));// tin or tr??
data.put((byte) (texres.tg * 255.0f));
data.put((byte) (texres.tb * 255.0f));
} else {
noiseGenerator.brightnesAndContrast(texres, contrast, brightness);
data.put((byte) (texres.tin * 255.0f));
if (vn_coltype != 0 || colorBand != null) {
noiseGenerator.brightnesAndContrastRGB(tex, texres);
data.put((byte) (texres.tr * 255.0f));// tin or tr??
data.put((byte) (texres.tg * 255.0f));
data.put((byte) (texres.tb * 255.0f));
} else {
noiseGenerator.brightnesAndContrast(texres, contrast, brightness);
data.put((byte) (texres.tin * 255.0f));
}
}
}
}
return new Texture2D(new Image(format, width, height, data));
ArrayList<ByteBuffer> dataArray = new ArrayList<ByteBuffer>(1);
dataArray.add(data);
return new Texture3D(new Image(format, width, height, depth, dataArray));
}
}

@ -1,6 +1,7 @@
package com.jme3.scene.plugins.blender.textures;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import com.jme3.scene.plugins.blender.DataRepository;
import com.jme3.scene.plugins.blender.file.Structure;
@ -9,7 +10,7 @@ import com.jme3.scene.plugins.blender.textures.TextureHelper.TexResult;
import com.jme3.texture.Image;
import com.jme3.texture.Image.Format;
import com.jme3.texture.Texture;
import com.jme3.texture.Texture2D;
import com.jme3.texture.Texture3D;
import com.jme3.util.BufferUtils;
/**
@ -27,46 +28,54 @@ public class TextureGeneratorWood extends TextureGenerator {
}
@Override
protected Texture generate(Structure tex, int width, int height, DataRepository dataRepository) {
protected Texture generate(Structure tex, int width, int height, int depth, DataRepository dataRepository) {
// preparing the proper data
float contrast = ((Number) tex.getFieldValue("contrast")).floatValue();
float bright = ((Number) tex.getFieldValue("bright")).floatValue();
float nabla = ((Number) tex.getFieldValue("nabla")).floatValue();
float wDelta = 1.0f / width, hDelta = 1.0f / height;
float wDelta = 1.0f / width, hDelta = 1.0f / height, dDelta = 1.0f / depth;
float[] texvec = new float[] { 0, 0, 0 };
TexResult texres = new TexResult();
int halfW = width;
int halfH = height;
int halfD = depth;
width <<= 1;
height <<= 1;
depth <<= 1;
ColorBand colorBand = this.readColorband(tex, dataRepository);
Format format = colorBand != null ? Format.RGB8 : Format.Luminance8;
int bytesPerPixel = colorBand != null ? 3 : 1;
ByteBuffer data = BufferUtils.createByteBuffer(width * height * bytesPerPixel);
ByteBuffer data = BufferUtils.createByteBuffer(width * height * depth * bytesPerPixel);
for (int i = -halfW; i < halfW; ++i) {
texvec[0] = wDelta * i;
for (int j = -halfH; j < halfH; ++j) {
texvec[1] = hDelta * j;
texres.tin = noiseGenerator.woodInt(tex, texvec[0], texvec[1], texvec[2], dataRepository);
if (colorBand != null) {
noiseGenerator.doColorband(colorBand, texres, dataRepository);
if (texres.nor != null) {// calculate bumpnormal
texres.nor[0] = noiseGenerator.woodInt(tex, texvec[0] + nabla, texvec[1], texvec[2], dataRepository);
texres.nor[1] = noiseGenerator.woodInt(tex, texvec[0], texvec[1] + nabla, texvec[2], dataRepository);
texres.nor[2] = noiseGenerator.woodInt(tex, texvec[0], texvec[1], texvec[2] + nabla, dataRepository);
noiseGenerator.texNormalDerivate(colorBand, texres, dataRepository);
for(int k = -halfD; k < halfD; ++k) {
texvec[2] = dDelta * k;
texres.tin = noiseGenerator.woodInt(tex, texvec[0], texvec[1], texvec[2], dataRepository);
if (colorBand != null) {
noiseGenerator.doColorband(colorBand, texres, dataRepository);
if (texres.nor != null) {// calculate bumpnormal
texres.nor[0] = noiseGenerator.woodInt(tex, texvec[0] + nabla, texvec[1], texvec[2], dataRepository);
texres.nor[1] = noiseGenerator.woodInt(tex, texvec[0], texvec[1] + nabla, texvec[2], dataRepository);
texres.nor[2] = noiseGenerator.woodInt(tex, texvec[0], texvec[1], texvec[2] + nabla, dataRepository);
noiseGenerator.texNormalDerivate(colorBand, texres, dataRepository);
}
noiseGenerator.brightnesAndContrastRGB(tex, texres);
data.put((byte) (texres.tr * 255.0f));
data.put((byte) (texres.tg * 255.0f));
data.put((byte) (texres.tb * 255.0f));
} else {
noiseGenerator.brightnesAndContrast(texres, contrast, bright);
data.put((byte) (texres.tin * 255));
}
noiseGenerator.brightnesAndContrastRGB(tex, texres);
data.put((byte) (texres.tr * 255.0f));
data.put((byte) (texres.tg * 255.0f));
data.put((byte) (texres.tb * 255.0f));
} else {
noiseGenerator.brightnesAndContrast(texres, contrast, bright);
data.put((byte) (texres.tin * 255));
}
}
}
return new Texture2D(new Image(format, width, height, data));
ArrayList<ByteBuffer> dataArray = new ArrayList<ByteBuffer>(1);
dataArray.add(data);
return new Texture3D(new Image(format, width, height, depth, dataArray));
}
}

@ -41,6 +41,7 @@ import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
@ -68,6 +69,7 @@ import com.jme3.texture.Image.Format;
import com.jme3.texture.Texture;
import com.jme3.texture.Texture.WrapMode;
import com.jme3.texture.Texture2D;
import com.jme3.texture.Texture3D;
import com.jme3.util.BufferUtils;
/**
@ -194,7 +196,8 @@ public class TextureHelper extends AbstractBlenderHelper {
int type = ((Number) tex.getFieldValue("type")).intValue();
int width = dataRepository.getBlenderKey().getGeneratedTextureWidth();
int height = dataRepository.getBlenderKey().getGeneratedTextureHeight();
int depth = dataRepository.getBlenderKey().getGeneratedTextureDepth();
switch (type) {
case TEX_IMAGE:// (it is first because probably this will be most commonly used)
Pointer pImage = (Pointer) tex.getFieldValue("ima");
@ -214,7 +217,7 @@ public class TextureHelper extends AbstractBlenderHelper {
case TEX_VORONOI:
case TEX_DISTNOISE:
TextureGenerator textureGenerator = textureGenerators.get(Integer.valueOf(type));
result = textureGenerator.generate(tex, width, height, dataRepository);
result = textureGenerator.generate(tex, width, height, depth, dataRepository);
break;
case TEX_NONE:// No texture, do nothing
break;
@ -266,7 +269,11 @@ public class TextureHelper extends AbstractBlenderHelper {
data.rewind();
int width = texture.getImage().getWidth();
int height = texture.getImage().getHeight();
ByteBuffer newData = BufferUtils.createByteBuffer(width * height * 4);
int depth = texture.getImage().getDepth();
if(depth==0) {
depth = 1;
}
ByteBuffer newData = BufferUtils.createByteBuffer(width * height * depth * 4);
float[] resultPixel = new float[4];
int dataIndex = 0;
@ -276,9 +283,15 @@ 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) (1.0 * 255.0f));
newData.put(dataIndex++, (byte) 255.0f);//1.0f * 255.0f
}
if(texture.getType()==Texture.Type.TwoDimensional) {
return new Texture2D(new Image(Format.RGBA8, width, height, newData));
} else {
ArrayList<ByteBuffer> dataArray = new ArrayList<ByteBuffer>(1);
dataArray.add(newData);
return new Texture3D(new Image(Format.RGBA8, width, height, depth, dataArray));
}
return new Texture2D(new Image(Format.RGBA8, width, height, newData));
}
/**

@ -0,0 +1,324 @@
/*
* Copyright (c) 2009-2010 jMonkeyEngine
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.jme3.scene.plugins.blender.textures;
import java.nio.FloatBuffer;
import java.util.List;
import java.util.logging.Logger;
import com.jme3.bounding.BoundingBox;
import com.jme3.bounding.BoundingSphere;
import com.jme3.bounding.BoundingVolume;
import com.jme3.math.Vector2f;
import com.jme3.math.Vector3f;
import com.jme3.scene.Geometry;
import com.jme3.scene.Mesh;
import com.jme3.scene.VertexBuffer;
import com.jme3.scene.VertexBuffer.Format;
import com.jme3.scene.VertexBuffer.Usage;
import com.jme3.texture.Texture.Type;
import com.jme3.util.BufferUtils;
/**
* This class is used for UV coordinates generation.
* @author Marcin Roguski (Kaelthas)
*/
public class UVCoordinatesGenerator {
private static final Logger LOGGER = Logger.getLogger(UVCoordinatesGenerator.class.getName());
public static final int TEXCO_ORCO = 1;
public static final int TEXCO_REFL = 2;
public static final int TEXCO_NORM = 4;
public static final int TEXCO_GLOB = 8;
public static final int TEXCO_UV = 16;
public static final int TEXCO_OBJECT = 32;
public static final int TEXCO_LAVECTOR = 64;
public static final int TEXCO_VIEW = 128;
public static final int TEXCO_STICKY = 256;
public static final int TEXCO_OSA = 512;
public static final int TEXCO_WINDOW = 1024;
public static final int NEED_UV = 2048;
public static final int TEXCO_TANGENT = 4096;
// still stored in vertex->accum, 1 D
public static final int TEXCO_PARTICLE_OR_STRAND = 8192; // strand is used
// for normal
// materials,
// particle for halo
// materials
public static final int TEXCO_STRESS = 16384;
public static final int TEXCO_SPEED = 32768;
/**
* This method generates UV coordinates for the given geometries.
* @param texco
* texture coordinates type
* @param textureType
* the type of the texture (only 2D and 3D)
* @param geometries
* a list of geometries that will have coordinates applied
*/
public static void generateUVCoordinates(int texco, Type textureType, List<Geometry> geometries) {
for (Geometry geometry : geometries) {
UVCoordinatesGenerator.generateUVCoordinates(texco, textureType, geometry.getMesh());
}
}
/**
* This method generates UV coordinates for the given mesh.
* @param texco
* texture coordinates type
* @param textureType
* the type of the texture (only 2D and 3D)
* @param mesh
* a mesh that will have coordinates applied
*/
public static void generateUVCoordinates(int texco, Type textureType, Mesh mesh) {
VertexBuffer result = null;
switch (texco) {
case TEXCO_ORCO:
if (textureType == Type.TwoDimensional) {
} else if (textureType == Type.ThreeDimensional) {
BoundingBox bb = UVCoordinatesGenerator.getBoundingBox(mesh);
result = new VertexBuffer(com.jme3.scene.VertexBuffer.Type.TexCoord);
FloatBuffer positions = mesh.getFloatBuffer(com.jme3.scene.VertexBuffer.Type.Position);
float[] uvCoordinates = BufferUtils.getFloatArray(positions);
Vector3f min = bb.getMin(null);
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>
for (int i = 0; i < uvCoordinates.length; i += 3) {
uvCoordinates[i] = (uvCoordinates[i] - min.x) / ext[0];
uvCoordinates[i + 1] = (uvCoordinates[i + 1] - min.y) / ext[1];
uvCoordinates[i + 2] = (uvCoordinates[i + 2] - min.z) / ext[2];
}
result.setupData(Usage.Static, 3, Format.Float, BufferUtils.createFloatBuffer(uvCoordinates));
} else {
throw new IllegalStateException("Unsupported texture type: " + textureType);
}
break;
case TEXCO_GLOB:
break;
case TEXCO_TANGENT:
break;
case TEXCO_UV:
break;
case TEXCO_STRESS:
break;
case TEXCO_NORM:
break;
case TEXCO_LAVECTOR:
case TEXCO_OBJECT:
case TEXCO_OSA:
case TEXCO_PARTICLE_OR_STRAND:
case TEXCO_REFL:
case TEXCO_SPEED:
case TEXCO_STICKY:
case TEXCO_VIEW:
case TEXCO_WINDOW:
LOGGER.warning("Texture coordinates type not currently supported: " + texco);
break;
default:
throw new IllegalStateException("Unknown texture coordinates value: " + texco);
}
mesh.clearBuffer(VertexBuffer.Type.TexCoord);// in case there are coordinates already set
mesh.setBuffer(result);
}
/**
* Flat projection for 2D textures.
* @param mesh
* mesh that is to be projected
* @return UV coordinates after the projection
*/
public Vector2f[] flatProjection(Mesh mesh) {
return null;// TODO: implement
}
/**
* Cube projection for 2D textures.
* @param mesh
* mesh that is to be projected
* @return UV coordinates after the projection
*/
public Vector2f[] cubeProjection(Mesh mesh) {
return null;// TODO: implement
}
/**
* Tube projection for 2D textures.
* @param mesh
* mesh that is to be projected
* @return UV coordinates after the projection
*/
public Vector2f[] tubeProjection(Mesh mesh) {
return null;// TODO: implement
}
/**
* Sphere projection for 2D textures.
* @param mesh
* mesh that is to be projected
* @return UV coordinates after the projection
*/
public Vector2f[] sphereProjection(Mesh mesh) {
return null;// TODO: implement
// Vector2f[] uvTable = new Vector2f[vertexList.size()];
// Ray ray = new Ray();
// CollisionResults cr = new CollisionResults();
// Vector3f yVec = new Vector3f();
// Vector3f zVec = new Vector3f();
// for(Geometry geom : geometries) {
// if(materialHelper.hasTexture(geom.getMaterial())) {//generate only when material has a texture
// geom.getMesh().updateBound();
// BoundingSphere bs = this.getBoundingSphere(geom.getMesh());
// float r2 = bs.getRadius() * bs.getRadius();
// yVec.set(0, -bs.getRadius(), 0);
// zVec.set(0, 0, -bs.getRadius());
// Vector3f center = bs.getCenter();
// ray.setOrigin(center);
// //we cast each vertex of the current mesh on the bounding box to determine the UV-coordinates
// for(int i=0;i<geom.getMesh().getIndexBuffer().size();++i) {
// int index = geom.getMesh().getIndexBuffer().get(i);
//
// ray.setOrigin(vertexList.get(index));
// ray.setDirection(normalList.get(index));
//
// //finding collision point
// cr.clear();
// bs.collideWith(ray, cr);//there is ALWAYS one collision
// Vector3f p = cr.getCollision(0).getContactPoint();
// p.subtractLocal(center);
// //arcLength = FastMath.acos(p.dot(yVec)/(p.length * yVec.length)) * r <- an arc length on the sphere (from top to the point on
// the sphere)
// //but yVec.length == r and p.length == r so: arcLength = FastMath.acos(p.dot(yVec)/r^2)/r
// //U coordinate is as follows: u = arcLength / PI*r
// //so to compute it faster we just write: u = FastMath.acos(p.dot(yVec)/r^2) / PI;
// float u = FastMath.acos(p.dot(yVec)/r2) / FastMath.PI;
// //we use similiar method to compute v
// //the only difference is that we need to cast the p vector on ZX plane
// //and use its length instead of r
// p.y = 0;
// float v = FastMath.acos(p.dot(zVec)/(bs.getRadius()*p.length())) / FastMath.PI;
// uvTable[index] = new Vector2f(u, v);
// }
// }
// }
}
/**
* This method returns the bounding box of the given geometries.
* @param geometries
* the list of geometries
* @return bounding box of the given geometries
*/
private static BoundingBox getBoundingBox(List<Geometry> geometries) {
BoundingBox result = null;
for (Geometry geometry : geometries) {
BoundingBox bb = UVCoordinatesGenerator.getBoundingBox(geometry.getMesh());
if (result == null) {
result = bb;
} else {
result.merge(bb);
}
}
return result;
}
/**
* This method returns the bounding box of the given mesh.
* @param mesh
* the mesh
* @return bounding box of the given mesh
*/
private static BoundingBox getBoundingBox(Mesh mesh) {
mesh.updateBound();
BoundingVolume bv = mesh.getBound();
if (bv instanceof BoundingBox) {
return (BoundingBox) bv;
} else if (bv instanceof BoundingSphere) {
BoundingSphere bs = (BoundingSphere) bv;
float r = bs.getRadius();
return new BoundingBox(bs.getCenter(), r, r, r);
} else {
throw new IllegalStateException("Unknown bounding volume type: " + bv.getClass().getName());
}
}
/**
* This method returns the bounding sphere of the given geometries.
* @param geometries
* the list of geometries
* @return bounding spheres of the given geometries
*/
private static BoundingSphere getBoundingSphere(List<Geometry> geometries) {
BoundingSphere result = null;
for (Geometry geometry : geometries) {
BoundingSphere bs = UVCoordinatesGenerator.getBoundingSphere(geometry.getMesh());
if (result == null) {
result = bs;
} else {
result.merge(bs);
}
}
return result;
}
/**
* This method returns the bounding sphere of the given mesh.
* @param mesh
* the mesh
* @return bounding sphere of the given mesh
*/
private static BoundingSphere getBoundingSphere(Mesh mesh) {
mesh.updateBound();
BoundingVolume bv = mesh.getBound();
if (bv instanceof BoundingBox) {
BoundingBox bb = (BoundingBox) bv;
float r = Math.max(bb.getXExtent(), bb.getYExtent());
r = Math.max(r, bb.getZExtent());
return new BoundingSphere(r, bb.getCenter());
} else if (bv instanceof BoundingSphere) {
return (BoundingSphere) bv;
} else {
throw new IllegalStateException("Unknown bounding volume type: " + bv.getClass().getName());
}
}
}
Loading…
Cancel
Save