use of com.jme3.scene.plugins.blender.file.Pointer in project jmonkeyengine by jMonkeyEngine.
the class ObjectHelper method getTransformation.
/**
* This method calculates local transformation for the object. Parentage is
* taken under consideration.
*
* @param objectStructure
* the object's structure
* @return objects transformation relative to its parent
*/
public Transform getTransformation(Structure objectStructure, BlenderContext blenderContext) {
TempVars tempVars = TempVars.get();
Matrix4f parentInv = tempVars.tempMat4;
Pointer pParent = (Pointer) objectStructure.getFieldValue("parent");
if (pParent.isNotNull()) {
Structure parentObjectStructure = (Structure) blenderContext.getLoadedFeature(pParent.getOldMemoryAddress(), LoadedDataType.STRUCTURE);
this.getMatrix(parentObjectStructure, "obmat", fixUpAxis, parentInv).invertLocal();
} else {
parentInv.loadIdentity();
}
Matrix4f globalMatrix = this.getMatrix(objectStructure, "obmat", fixUpAxis, tempVars.tempMat42);
Matrix4f localMatrix = parentInv.multLocal(globalMatrix);
this.getSizeSignums(objectStructure, tempVars.vect1);
localMatrix.toTranslationVector(tempVars.vect2);
localMatrix.toRotationQuat(tempVars.quat1);
localMatrix.toScaleVector(tempVars.vect3);
Transform t = new Transform(tempVars.vect2, tempVars.quat1.normalizeLocal(), tempVars.vect3.multLocal(tempVars.vect1));
tempVars.release();
return t;
}
use of com.jme3.scene.plugins.blender.file.Pointer in project jmonkeyengine by jMonkeyEngine.
the class ParticlesHelper method toParticleEmitter.
@SuppressWarnings("unchecked")
public ParticleEmitter toParticleEmitter(Structure particleSystem) throws BlenderFileException {
ParticleEmitter result = null;
Pointer pParticleSettings = (Pointer) particleSystem.getFieldValue("part");
if (pParticleSettings.isNotNull()) {
Structure particleSettings = pParticleSettings.fetchData().get(0);
int totPart = ((Number) particleSettings.getFieldValue("totpart")).intValue();
// draw type will be stored temporarily in the name (it is used during modifier applying operation)
int drawAs = ((Number) particleSettings.getFieldValue("draw_as")).intValue();
// P - point, L - line, N - None, B - Bilboard
char nameSuffix;
switch(drawAs) {
case PART_DRAW_NOT:
nameSuffix = 'N';
// no need to generate particles in this case
totPart = 0;
break;
case PART_DRAW_BB:
nameSuffix = 'B';
break;
case PART_DRAW_OB:
case PART_DRAW_GR:
nameSuffix = 'P';
// TODO: support groups and aobjects
LOGGER.warning("Neither object nor group particles supported yet! Using point representation instead!");
break;
case PART_DRAW_LINE:
nameSuffix = 'L';
// TODO: support lines
LOGGER.warning("Lines not yet supported! Using point representation instead!");
default:
// all others are rendered as points in blender
nameSuffix = 'P';
}
result = new ParticleEmitter(particleSettings.getName() + nameSuffix, Type.Triangle, totPart);
if (nameSuffix == 'N') {
// no need to set anything else
return result;
}
// setting the emitters shape (the shapes meshes will be set later during modifier applying operation)
int from = ((Number) particleSettings.getFieldValue("from")).intValue();
switch(from) {
case PART_FROM_VERT:
result.setShape(new EmitterMeshVertexShape());
break;
case PART_FROM_FACE:
result.setShape(new EmitterMeshFaceShape());
break;
case PART_FROM_VOLUME:
result.setShape(new EmitterMeshConvexHullShape());
break;
default:
LOGGER.warning("Default shape used! Unknown emitter shape value ('from' parameter: " + from + ')');
}
// reading acceleration
DynamicArray<Number> acc = (DynamicArray<Number>) particleSettings.getFieldValue("acc");
result.setGravity(-acc.get(0).floatValue(), -acc.get(1).floatValue(), -acc.get(2).floatValue());
// setting the colors
result.setEndColor(new ColorRGBA(1f, 1f, 1f, 1f));
result.setStartColor(new ColorRGBA(1f, 1f, 1f, 1f));
// reading size
float sizeFactor = nameSuffix == 'B' ? 1.0f : 0.3f;
float size = ((Number) particleSettings.getFieldValue("size")).floatValue() * sizeFactor;
result.setStartSize(size);
result.setEndSize(size);
// reading lifetime
int fps = blenderContext.getBlenderKey().getFps();
float lifetime = ((Number) particleSettings.getFieldValue("lifetime")).floatValue() / fps;
float randlife = ((Number) particleSettings.getFieldValue("randlife")).floatValue() / fps;
result.setLowLife(lifetime * (1.0f - randlife));
result.setHighLife(lifetime);
// preparing influencer
ParticleInfluencer influencer;
int phystype = ((Number) particleSettings.getFieldValue("phystype")).intValue();
switch(phystype) {
case PART_PHYS_NEWTON:
influencer = new NewtonianParticleInfluencer();
((NewtonianParticleInfluencer) influencer).setNormalVelocity(((Number) particleSettings.getFieldValue("normfac")).floatValue());
((NewtonianParticleInfluencer) influencer).setVelocityVariation(((Number) particleSettings.getFieldValue("randfac")).floatValue());
((NewtonianParticleInfluencer) influencer).setSurfaceTangentFactor(((Number) particleSettings.getFieldValue("tanfac")).floatValue());
((NewtonianParticleInfluencer) influencer).setSurfaceTangentRotation(((Number) particleSettings.getFieldValue("tanphase")).floatValue());
break;
case PART_PHYS_BOIDS:
case // TODO: support other influencers
PART_PHYS_KEYED:
LOGGER.warning("Boids and Keyed particles physic not yet supported! Empty influencer used!");
case PART_PHYS_NO:
default:
influencer = new EmptyParticleInfluencer();
}
result.setParticleInfluencer(influencer);
}
return result;
}
use of com.jme3.scene.plugins.blender.file.Pointer in project jmonkeyengine by jMonkeyEngine.
the class TextureHelper method getTexture.
/**
* This class returns a texture read from the file or from packed blender
* data. The returned texture has the name set to the value of its blender
* type.
*
* @param textureStructure
* texture structure filled with data
* @param blenderContext
* the blender context
* @return the texture that can be used by JME engine
* @throws BlenderFileException
* this exception is thrown when the blend file structure is
* somehow invalid or corrupted
*/
public Texture getTexture(Structure textureStructure, Structure mTex, BlenderContext blenderContext) throws BlenderFileException {
Texture result = (Texture) blenderContext.getLoadedFeature(textureStructure.getOldMemoryAddress(), LoadedDataType.FEATURE);
if (result != null) {
return result;
}
if ("ID".equals(textureStructure.getType())) {
LOGGER.fine("Loading texture from external blend file.");
return (Texture) this.loadLibrary(textureStructure);
}
int type = ((Number) textureStructure.getFieldValue("type")).intValue();
int imaflag = ((Number) textureStructure.getFieldValue("imaflag")).intValue();
switch(type) {
case // (it is first because probably this will be most commonly used)
TEX_IMAGE:
Pointer pImage = (Pointer) textureStructure.getFieldValue("ima");
if (pImage.isNotNull()) {
Structure image = pImage.fetchData().get(0);
Texture loadedTexture = this.loadImageAsTexture(image, imaflag, blenderContext);
if (loadedTexture != null) {
result = loadedTexture;
this.applyColorbandAndColorFactors(textureStructure, result.getImage(), blenderContext);
}
}
break;
case TEX_CLOUDS:
case TEX_WOOD:
case TEX_MARBLE:
case TEX_MAGIC:
case TEX_BLEND:
case TEX_STUCCI:
case TEX_NOISE:
case TEX_MUSGRAVE:
case TEX_VORONOI:
case TEX_DISTNOISE:
result = new GeneratedTexture(textureStructure, mTex, textureGeneratorFactory.createTextureGenerator(type), blenderContext);
break;
case // No texture, do nothing
TEX_NONE:
break;
case TEX_POINTDENSITY:
case TEX_VOXELDATA:
case TEX_PLUGIN:
case TEX_ENVMAP:
case TEX_OCEAN:
LOGGER.log(Level.WARNING, "Unsupported texture type: {0} for texture: {1}", new Object[] { type, textureStructure.getName() });
break;
default:
throw new BlenderFileException("Unknown texture type: " + type + " for texture: " + textureStructure.getName());
}
if (result != null) {
result.setName(textureStructure.getName());
result.setWrap(WrapMode.Repeat);
// decide if the mipmaps will be generated
switch(blenderContext.getBlenderKey().getMipmapGenerationMethod()) {
case ALWAYS_GENERATE:
result.setMinFilter(MinFilter.Trilinear);
break;
case NEVER_GENERATE:
break;
case GENERATE_WHEN_NEEDED:
if ((imaflag & 0x04) != 0) {
result.setMinFilter(MinFilter.Trilinear);
}
break;
default:
throw new IllegalStateException("Unknown mipmap generation method: " + blenderContext.getBlenderKey().getMipmapGenerationMethod());
}
if (type != TEX_IMAGE) {
// only generated textures should have this key
result.setKey(new GeneratedTextureKey(textureStructure.getName()));
}
if (LOGGER.isLoggable(Level.FINE)) {
LOGGER.log(Level.FINE, "Adding texture {0} to the loaded features with OMA = {1}", new Object[] { result.getName(), textureStructure.getOldMemoryAddress() });
}
blenderContext.addLoadedFeatures(textureStructure.getOldMemoryAddress(), LoadedDataType.STRUCTURE, textureStructure);
blenderContext.addLoadedFeatures(textureStructure.getOldMemoryAddress(), LoadedDataType.FEATURE, result);
}
return result;
}
use of com.jme3.scene.plugins.blender.file.Pointer in project jmonkeyengine by jMonkeyEngine.
the class Face method loadAll.
/**
* Loads all faces of a given mesh.
* @param meshStructure
* the mesh structure we read the faces from
* @param userUVGroups
* UV groups defined by the user
* @param verticesColors
* the vertices colors of the mesh
* @param temporalMesh
* the temporal mesh the faces will belong to
* @param blenderContext
* the blender context
* @return list of faces read from the given mesh structure
* @throws BlenderFileException
* an exception is thrown when problems with file reading occur
*/
public static List<Face> loadAll(Structure meshStructure, Map<String, List<Vector2f>> userUVGroups, List<byte[]> verticesColors, TemporalMesh temporalMesh, BlenderContext blenderContext) throws BlenderFileException {
LOGGER.log(Level.FINE, "Loading all faces from mesh: {0}", meshStructure.getName());
List<Face> result = new ArrayList<Face>();
MeshHelper meshHelper = blenderContext.getHelper(MeshHelper.class);
if (meshHelper.isBMeshCompatible(meshStructure)) {
LOGGER.fine("Reading BMesh.");
Pointer pMLoop = (Pointer) meshStructure.getFieldValue("mloop");
Pointer pMPoly = (Pointer) meshStructure.getFieldValue("mpoly");
if (pMPoly.isNotNull() && pMLoop.isNotNull()) {
List<Structure> polys = pMPoly.fetchData();
List<Structure> loops = pMLoop.fetchData();
for (Structure poly : polys) {
int materialNumber = ((Number) poly.getFieldValue("mat_nr")).intValue();
int loopStart = ((Number) poly.getFieldValue("loopstart")).intValue();
int totLoop = ((Number) poly.getFieldValue("totloop")).intValue();
boolean smooth = (((Number) poly.getFieldValue("flag")).byteValue() & 0x01) != 0x00;
Integer[] vertexIndexes = new Integer[totLoop];
for (int i = loopStart; i < loopStart + totLoop; ++i) {
vertexIndexes[i - loopStart] = ((Number) loops.get(i).getFieldValue("v")).intValue();
}
// uvs always must be added wheater we have texture or not
Map<String, List<Vector2f>> uvCoords = new HashMap<String, List<Vector2f>>();
for (Entry<String, List<Vector2f>> entry : userUVGroups.entrySet()) {
List<Vector2f> uvs = entry.getValue().subList(loopStart, loopStart + totLoop);
uvCoords.put(entry.getKey(), new ArrayList<Vector2f>(uvs));
}
List<byte[]> vertexColors = null;
if (verticesColors != null && verticesColors.size() > 0) {
vertexColors = new ArrayList<byte[]>(totLoop);
for (int i = loopStart; i < loopStart + totLoop; ++i) {
vertexColors.add(verticesColors.get(i));
}
}
result.add(new Face(vertexIndexes, smooth, materialNumber, uvCoords, vertexColors, temporalMesh));
}
}
} else {
LOGGER.fine("Reading traditional faces.");
Pointer pMFace = (Pointer) meshStructure.getFieldValue("mface");
List<Structure> mFaces = pMFace.isNotNull() ? pMFace.fetchData() : null;
if (mFaces != null && mFaces.size() > 0) {
// indicates if the material with the specified number should have a texture attached
for (int i = 0; i < mFaces.size(); ++i) {
Structure mFace = mFaces.get(i);
int materialNumber = ((Number) mFace.getFieldValue("mat_nr")).intValue();
boolean smooth = (((Number) mFace.getFieldValue("flag")).byteValue() & 0x01) != 0x00;
int v1 = ((Number) mFace.getFieldValue("v1")).intValue();
int v2 = ((Number) mFace.getFieldValue("v2")).intValue();
int v3 = ((Number) mFace.getFieldValue("v3")).intValue();
int v4 = ((Number) mFace.getFieldValue("v4")).intValue();
int vertCount = v4 == 0 ? 3 : 4;
// uvs always must be added wheater we have texture or not
Map<String, List<Vector2f>> faceUVCoords = new HashMap<String, List<Vector2f>>();
for (Entry<String, List<Vector2f>> entry : userUVGroups.entrySet()) {
List<Vector2f> uvCoordsForASingleFace = new ArrayList<Vector2f>(vertCount);
for (int j = 0; j < vertCount; ++j) {
uvCoordsForASingleFace.add(entry.getValue().get(i * 4 + j));
}
faceUVCoords.put(entry.getKey(), uvCoordsForASingleFace);
}
List<byte[]> vertexColors = null;
if (verticesColors != null && verticesColors.size() > 0) {
vertexColors = new ArrayList<byte[]>(vertCount);
vertexColors.add(verticesColors.get(v1));
vertexColors.add(verticesColors.get(v2));
vertexColors.add(verticesColors.get(v3));
if (vertCount == 4) {
vertexColors.add(verticesColors.get(v4));
}
}
result.add(new Face(vertCount == 4 ? new Integer[] { v1, v2, v3, v4 } : new Integer[] { v1, v2, v3 }, smooth, materialNumber, faceUVCoords, vertexColors, temporalMesh));
}
}
}
LOGGER.log(Level.FINE, "Loaded {0} faces.", result.size());
return result;
}
use of com.jme3.scene.plugins.blender.file.Pointer in project jmonkeyengine by jMonkeyEngine.
the class MeshHelper method loadUVCoordinates.
/**
* The method loads the UV coordinates. The result is a map where the key is the user's UV set name and the values are UV coordinates.
* But depending on the mesh type (triangle/quads or bmesh) the lists in the map have different meaning.
* For bmesh they are enlisted just like they are stored in the blend file (in loops).
* For traditional faces every 4 UV's should be assigned for a single face.
* @param meshStructure
* the mesh structure
* @return a map that sorts UV coordinates between different UV sets
* @throws BlenderFileException
* an exception is thrown when problems with blend file occur
*/
@SuppressWarnings("unchecked")
public LinkedHashMap<String, List<Vector2f>> loadUVCoordinates(Structure meshStructure) throws BlenderFileException {
LOGGER.log(Level.FINE, "Loading UV coordinates from mesh: {0}.", meshStructure.getName());
LinkedHashMap<String, List<Vector2f>> result = new LinkedHashMap<String, List<Vector2f>>();
if (this.isBMeshCompatible(meshStructure)) {
// in this case the UV's are assigned to vertices (an array is the same length as the vertex array)
Structure loopData = (Structure) meshStructure.getFieldValue("ldata");
Pointer pLoopDataLayers = (Pointer) loopData.getFieldValue("layers");
List<Structure> loopDataLayers = pLoopDataLayers.fetchData();
for (Structure structure : loopDataLayers) {
Pointer p = (Pointer) structure.getFieldValue("data");
if (p.isNotNull() && ((Number) structure.getFieldValue("type")).intValue() == MeshHelper.UV_DATA_LAYER_TYPE_BMESH) {
String uvSetName = structure.getFieldValue("name").toString();
List<Structure> uvsStructures = p.fetchData();
List<Vector2f> uvs = new ArrayList<Vector2f>(uvsStructures.size());
for (Structure uvStructure : uvsStructures) {
DynamicArray<Number> loopUVS = (DynamicArray<Number>) uvStructure.getFieldValue("uv");
uvs.add(new Vector2f(loopUVS.get(0).floatValue(), loopUVS.get(1).floatValue()));
}
result.put(uvSetName, uvs);
}
}
} else {
// in this case UV's are assigned to faces (the array has the same legnth as the faces count)
Structure facesData = (Structure) meshStructure.getFieldValue("fdata");
Pointer pFacesDataLayers = (Pointer) facesData.getFieldValue("layers");
if (pFacesDataLayers.isNotNull()) {
List<Structure> facesDataLayers = pFacesDataLayers.fetchData();
for (Structure structure : facesDataLayers) {
Pointer p = (Pointer) structure.getFieldValue("data");
if (p.isNotNull() && ((Number) structure.getFieldValue("type")).intValue() == MeshHelper.UV_DATA_LAYER_TYPE_FMESH) {
String uvSetName = structure.getFieldValue("name").toString();
List<Structure> uvsStructures = p.fetchData();
List<Vector2f> uvs = new ArrayList<Vector2f>(uvsStructures.size());
for (Structure uvStructure : uvsStructures) {
DynamicArray<Number> mFaceUVs = (DynamicArray<Number>) uvStructure.getFieldValue("uv");
uvs.add(new Vector2f(mFaceUVs.get(0).floatValue(), mFaceUVs.get(1).floatValue()));
uvs.add(new Vector2f(mFaceUVs.get(2).floatValue(), mFaceUVs.get(3).floatValue()));
uvs.add(new Vector2f(mFaceUVs.get(4).floatValue(), mFaceUVs.get(5).floatValue()));
uvs.add(new Vector2f(mFaceUVs.get(6).floatValue(), mFaceUVs.get(7).floatValue()));
}
result.put(uvSetName, uvs);
}
}
}
}
return result;
}
Aggregations