use of com.jme3.scene.plugins.blender.file.FileBlockHeader in project jmonkeyengine by jMonkeyEngine.
the class ArrayModifier method apply.
@Override
public void apply(Node node, BlenderContext blenderContext) {
if (invalid) {
LOGGER.log(Level.WARNING, "Array modifier is invalid! Cannot be applied to: {0}", node.getName());
} else {
TemporalMesh temporalMesh = this.getTemporalMesh(node);
if (temporalMesh != null) {
LOGGER.log(Level.FINE, "Applying array modifier to: {0}", temporalMesh);
if (offset == null) {
// the node will be repeated several times in the same place
offset = new float[] { 0.0f, 0.0f, 0.0f };
}
if (scale == null) {
// the node will be repeated several times in the same place
scale = new float[] { 0.0f, 0.0f, 0.0f };
} else {
// getting bounding box
temporalMesh.updateModelBound();
BoundingVolume boundingVolume = temporalMesh.getWorldBound();
if (boundingVolume instanceof BoundingBox) {
scale[0] *= ((BoundingBox) boundingVolume).getXExtent() * 2.0f;
scale[1] *= ((BoundingBox) boundingVolume).getYExtent() * 2.0f;
scale[2] *= ((BoundingBox) boundingVolume).getZExtent() * 2.0f;
} else if (boundingVolume instanceof BoundingSphere) {
float radius = ((BoundingSphere) boundingVolume).getRadius();
scale[0] *= radius * 2.0f;
scale[1] *= radius * 2.0f;
scale[2] *= radius * 2.0f;
} else {
throw new IllegalStateException("Unknown bounding volume type: " + boundingVolume.getClass().getName());
}
}
// adding object's offset
float[] objectOffset = new float[] { 0.0f, 0.0f, 0.0f };
if (pOffsetObject != null && pOffsetObject.isNotNull()) {
FileBlockHeader offsetObjectBlock = blenderContext.getFileBlock(pOffsetObject.getOldMemoryAddress());
ObjectHelper objectHelper = blenderContext.getHelper(ObjectHelper.class);
try {
// we take the structure in case the object was not yet loaded
Structure offsetStructure = offsetObjectBlock.getStructure(blenderContext);
Vector3f translation = objectHelper.getTransformation(offsetStructure, blenderContext).getTranslation();
objectOffset[0] = translation.x;
objectOffset[1] = translation.y;
objectOffset[2] = translation.z;
} catch (BlenderFileException e) {
LOGGER.log(Level.WARNING, "Problems in blender file structure! Object offset cannot be applied! The problem: {0}", e.getMessage());
}
}
// getting start and end caps
MeshHelper meshHelper = blenderContext.getHelper(MeshHelper.class);
TemporalMesh[] caps = new TemporalMesh[] { null, null };
Pointer[] pCaps = new Pointer[] { pStartCap, pEndCap };
for (int i = 0; i < pCaps.length; ++i) {
if (pCaps[i].isNotNull()) {
FileBlockHeader capBlock = blenderContext.getFileBlock(pCaps[i].getOldMemoryAddress());
try {
// we take the structure in case the object was not yet loaded
Structure capStructure = capBlock.getStructure(blenderContext);
Pointer pMesh = (Pointer) capStructure.getFieldValue("data");
List<Structure> meshesArray = pMesh.fetchData();
caps[i] = meshHelper.toTemporalMesh(meshesArray.get(0), blenderContext);
} catch (BlenderFileException e) {
LOGGER.log(Level.WARNING, "Problems in blender file structure! Cap object cannot be applied! The problem: {0}", e.getMessage());
}
}
}
Vector3f translationVector = new Vector3f(offset[0] + scale[0] + objectOffset[0], offset[1] + scale[1] + objectOffset[1], offset[2] + scale[2] + objectOffset[2]);
if (blenderContext.getBlenderKey().isFixUpAxis()) {
float y = translationVector.y;
translationVector.y = translationVector.z;
translationVector.z = y == 0 ? 0 : -y;
}
// getting/calculating repeats amount
int count = 0;
if (fittype == 0) {
// Fixed count
count = this.count - 1;
} else if (fittype == 1) {
// Fixed length
float length = this.length;
if (translationVector.length() > 0.0f) {
count = (int) (length / translationVector.length()) - 1;
}
} else if (fittype == 2) {
// Fit curve
throw new IllegalStateException("Fit curve should be transformed to Fixed Length array type!");
} else {
throw new IllegalStateException("Unknown fit type: " + fittype);
}
// adding translated nodes and caps
Vector3f totalTranslation = new Vector3f(translationVector);
if (count > 0) {
TemporalMesh originalMesh = temporalMesh.clone();
for (int i = 0; i < count; ++i) {
TemporalMesh clone = originalMesh.clone();
for (Vector3f v : clone.getVertices()) {
v.addLocal(totalTranslation);
}
temporalMesh.append(clone);
totalTranslation.addLocal(translationVector);
}
}
if (caps[0] != null) {
translationVector.multLocal(-1);
TemporalMesh capsClone = caps[0].clone();
for (Vector3f v : capsClone.getVertices()) {
v.addLocal(translationVector);
}
temporalMesh.append(capsClone);
}
if (caps[1] != null) {
TemporalMesh capsClone = caps[1].clone();
for (Vector3f v : capsClone.getVertices()) {
v.addLocal(totalTranslation);
}
temporalMesh.append(capsClone);
}
} else {
LOGGER.log(Level.WARNING, "Cannot find temporal mesh for node: {0}. The modifier will NOT be applied!", node);
}
}
}
use of com.jme3.scene.plugins.blender.file.FileBlockHeader in project jmonkeyengine by jMonkeyEngine.
the class BlenderLoader method load.
@Override
public Spatial load(AssetInfo assetInfo) throws IOException {
try {
BlenderContext blenderContext = this.setup(assetInfo);
AnimationHelper animationHelper = blenderContext.getHelper(AnimationHelper.class);
animationHelper.loadAnimations();
BlenderKey blenderKey = blenderContext.getBlenderKey();
LoadedFeatures loadedFeatures = new LoadedFeatures();
for (FileBlockHeader block : blenderContext.getBlocks()) {
switch(block.getCode()) {
case BLOCK_OB00:
ObjectHelper objectHelper = blenderContext.getHelper(ObjectHelper.class);
Node object = (Node) objectHelper.toObject(block.getStructure(blenderContext), blenderContext);
if (LOGGER.isLoggable(Level.FINE)) {
LOGGER.log(Level.FINE, "{0}: {1}--> {2}", new Object[] { object.getName(), object.getLocalTranslation().toString(), object.getParent() == null ? "null" : object.getParent().getName() });
}
if (object.getParent() == null) {
loadedFeatures.objects.add(object);
}
if (object instanceof LightNode && ((LightNode) object).getLight() != null) {
loadedFeatures.lights.add(((LightNode) object).getLight());
} else if (object instanceof CameraNode && ((CameraNode) object).getCamera() != null) {
loadedFeatures.cameras.add(((CameraNode) object).getCamera());
}
break;
case // Scene
BLOCK_SC00:
loadedFeatures.sceneBlocks.add(block);
break;
case // Material
BLOCK_MA00:
MaterialHelper materialHelper = blenderContext.getHelper(MaterialHelper.class);
MaterialContext materialContext = materialHelper.toMaterialContext(block.getStructure(blenderContext), blenderContext);
loadedFeatures.materials.add(materialContext);
break;
case // Mesh
BLOCK_ME00:
MeshHelper meshHelper = blenderContext.getHelper(MeshHelper.class);
TemporalMesh temporalMesh = meshHelper.toTemporalMesh(block.getStructure(blenderContext), blenderContext);
loadedFeatures.meshes.add(temporalMesh);
break;
case // Image
BLOCK_IM00:
TextureHelper textureHelper = blenderContext.getHelper(TextureHelper.class);
Texture image = textureHelper.loadImageAsTexture(block.getStructure(blenderContext), 0, blenderContext);
if (image != null && image.getImage() != null) {
// render results are stored as images but are not being loaded
loadedFeatures.images.add(image);
}
break;
case BLOCK_TE00:
Structure textureStructure = block.getStructure(blenderContext);
int type = ((Number) textureStructure.getFieldValue("type")).intValue();
if (type == TextureHelper.TEX_IMAGE) {
TextureHelper texHelper = blenderContext.getHelper(TextureHelper.class);
Texture texture = texHelper.getTexture(textureStructure, null, blenderContext);
if (texture != null) {
// null is returned when texture has no image
loadedFeatures.textures.add(texture);
}
} else {
LOGGER.fine("Only image textures can be loaded as unlinked assets. Generated textures will be applied to an existing object.");
}
break;
case // World
BLOCK_WO00:
LandscapeHelper landscapeHelper = blenderContext.getHelper(LandscapeHelper.class);
Structure worldStructure = block.getStructure(blenderContext);
String worldName = worldStructure.getName();
if (blenderKey.getUsedWorld() == null || blenderKey.getUsedWorld().equals(worldName)) {
Light ambientLight = landscapeHelper.toAmbientLight(worldStructure);
if (ambientLight != null) {
loadedFeatures.objects.add(new LightNode(null, ambientLight));
loadedFeatures.lights.add(ambientLight);
}
loadedFeatures.sky = landscapeHelper.toSky(worldStructure);
loadedFeatures.backgroundColor = landscapeHelper.toBackgroundColor(worldStructure);
Filter fogFilter = landscapeHelper.toFog(worldStructure);
if (fogFilter != null) {
loadedFeatures.filters.add(landscapeHelper.toFog(worldStructure));
}
}
break;
case BLOCK_AC00:
LOGGER.fine("Loading unlinked animations is not yet supported!");
break;
default:
LOGGER.log(Level.FINEST, "Ommiting the block: {0}.", block.getCode());
}
}
LOGGER.fine("Baking constraints after every feature is loaded.");
ConstraintHelper constraintHelper = blenderContext.getHelper(ConstraintHelper.class);
constraintHelper.bakeConstraints(blenderContext);
LOGGER.fine("Loading scenes and attaching them to the root object.");
for (FileBlockHeader sceneBlock : loadedFeatures.sceneBlocks) {
loadedFeatures.scenes.add(this.toScene(sceneBlock.getStructure(blenderContext), blenderContext));
}
LOGGER.fine("Creating the root node of the model and applying loaded nodes of the scene and loaded features to it.");
Node modelRoot = new Node(blenderKey.getName());
for (Node scene : loadedFeatures.scenes) {
modelRoot.attachChild(scene);
}
if (blenderKey.isLoadUnlinkedAssets()) {
LOGGER.fine("Setting loaded content as user data in resulting sptaial.");
Map<String, Map<String, Object>> linkedData = new HashMap<String, Map<String, Object>>();
Map<String, Object> thisFileData = new HashMap<String, Object>();
thisFileData.put("scenes", loadedFeatures.scenes == null ? new ArrayList<Object>() : loadedFeatures.scenes);
thisFileData.put("objects", loadedFeatures.objects == null ? new ArrayList<Object>() : loadedFeatures.objects);
thisFileData.put("meshes", loadedFeatures.meshes == null ? new ArrayList<Object>() : loadedFeatures.meshes);
thisFileData.put("materials", loadedFeatures.materials == null ? new ArrayList<Object>() : loadedFeatures.materials);
thisFileData.put("textures", loadedFeatures.textures == null ? new ArrayList<Object>() : loadedFeatures.textures);
thisFileData.put("images", loadedFeatures.images == null ? new ArrayList<Object>() : loadedFeatures.images);
thisFileData.put("animations", loadedFeatures.animations == null ? new ArrayList<Object>() : loadedFeatures.animations);
thisFileData.put("cameras", loadedFeatures.cameras == null ? new ArrayList<Object>() : loadedFeatures.cameras);
thisFileData.put("lights", loadedFeatures.lights == null ? new ArrayList<Object>() : loadedFeatures.lights);
thisFileData.put("filters", loadedFeatures.filters == null ? new ArrayList<Object>() : loadedFeatures.filters);
thisFileData.put("backgroundColor", loadedFeatures.backgroundColor);
thisFileData.put("sky", loadedFeatures.sky);
linkedData.put("this", thisFileData);
linkedData.putAll(blenderContext.getLinkedFeatures());
modelRoot.setUserData("linkedData", linkedData);
}
return modelRoot;
} catch (BlenderFileException e) {
throw new IOException(e.getLocalizedMessage(), e);
} catch (Exception e) {
throw new IOException("Unexpected importer exception occured: " + e.getLocalizedMessage(), e);
} finally {
this.clear(assetInfo);
}
}
use of com.jme3.scene.plugins.blender.file.FileBlockHeader in project jmonkeyengine by jMonkeyEngine.
the class AnimationHelper method getCurveType.
/**
* This method returns the type of the ipo curve.
*
* @param structure
* the structure must contain the 'rna_path' field and
* 'array_index' field (the type is not important here)
* @param blenderContext
* the blender context
* @return the type of the curve
*/
public int getCurveType(Structure structure, BlenderContext blenderContext) {
// reading rna path first
BlenderInputStream bis = blenderContext.getInputStream();
int currentPosition = bis.getPosition();
Pointer pRnaPath = (Pointer) structure.getFieldValue("rna_path");
FileBlockHeader dataFileBlock = blenderContext.getFileBlock(pRnaPath.getOldMemoryAddress());
bis.setPosition(dataFileBlock.getBlockPosition());
String rnaPath = bis.readString();
bis.setPosition(currentPosition);
int arrayIndex = ((Number) structure.getFieldValue("array_index")).intValue();
// determining the curve type
if (rnaPath.endsWith("location")) {
return Ipo.AC_LOC_X + arrayIndex;
}
if (rnaPath.endsWith("rotation_quaternion")) {
return Ipo.AC_QUAT_W + arrayIndex;
}
if (rnaPath.endsWith("scale")) {
return Ipo.AC_SIZE_X + arrayIndex;
}
if (rnaPath.endsWith("rotation") || rnaPath.endsWith("rotation_euler")) {
return Ipo.OB_ROT_X + arrayIndex;
}
LOGGER.log(Level.WARNING, "Unknown curve rna path: {0}", rnaPath);
return -1;
}
use of com.jme3.scene.plugins.blender.file.FileBlockHeader in project jmonkeyengine by jMonkeyEngine.
the class CurvesTemporalMesh method loadNurbSurface.
/**
* This method loads the NURBS curve or surface.
* @param nurb
* the NURBS data structure
* @throws BlenderFileException
* an exception is thrown when problems with reading occur
*/
@SuppressWarnings("unchecked")
private void loadNurbSurface(Structure nurb, int materialIndex) throws BlenderFileException {
// loading the knots
List<Float>[] knots = new List[2];
Pointer[] pKnots = new Pointer[] { (Pointer) nurb.getFieldValue("knotsu"), (Pointer) nurb.getFieldValue("knotsv") };
for (int i = 0; i < knots.length; ++i) {
if (pKnots[i].isNotNull()) {
FileBlockHeader fileBlockHeader = blenderContext.getFileBlock(pKnots[i].getOldMemoryAddress());
BlenderInputStream blenderInputStream = blenderContext.getInputStream();
blenderInputStream.setPosition(fileBlockHeader.getBlockPosition());
int knotsAmount = fileBlockHeader.getCount() * fileBlockHeader.getSize() / 4;
knots[i] = new ArrayList<Float>(knotsAmount);
for (int j = 0; j < knotsAmount; ++j) {
knots[i].add(Float.valueOf(blenderInputStream.readFloat()));
}
}
}
// loading the flags and orders (basis functions degrees)
int flag = ((Number) nurb.getFieldValue("flag")).intValue();
boolean smooth = (flag & FLAG_SMOOTH) != 0;
int flagU = ((Number) nurb.getFieldValue("flagu")).intValue();
int flagV = ((Number) nurb.getFieldValue("flagv")).intValue();
int orderU = ((Number) nurb.getFieldValue("orderu")).intValue();
int orderV = ((Number) nurb.getFieldValue("orderv")).intValue();
// loading control points and their weights
int pntsU = ((Number) nurb.getFieldValue("pntsu")).intValue();
int pntsV = ((Number) nurb.getFieldValue("pntsv")).intValue();
List<Structure> bPoints = ((Pointer) nurb.getFieldValue("bp")).fetchData();
List<List<Vector4f>> controlPoints = new ArrayList<List<Vector4f>>(pntsV);
for (int i = 0; i < pntsV; ++i) {
List<Vector4f> uControlPoints = new ArrayList<Vector4f>(pntsU);
for (int j = 0; j < pntsU; ++j) {
DynamicArray<Float> vec = (DynamicArray<Float>) bPoints.get(j + i * pntsU).getFieldValue("vec");
if (blenderContext.getBlenderKey().isFixUpAxis()) {
uControlPoints.add(new Vector4f(vec.get(0).floatValue(), vec.get(2).floatValue(), -vec.get(1).floatValue(), vec.get(3).floatValue()));
} else {
uControlPoints.add(new Vector4f(vec.get(0).floatValue(), vec.get(1).floatValue(), vec.get(2).floatValue(), vec.get(3).floatValue()));
}
}
if ((flagU & 0x01) != 0) {
for (int k = 0; k < orderU - 1; ++k) {
uControlPoints.add(uControlPoints.get(k));
}
}
controlPoints.add(uControlPoints);
}
if ((flagV & 0x01) != 0) {
for (int k = 0; k < orderV - 1; ++k) {
controlPoints.add(controlPoints.get(k));
}
}
int originalVerticesAmount = vertices.size();
int resolu = ((Number) nurb.getFieldValue("resolu")).intValue();
if (knots[1] == null) {
// creating the NURB curve
Curve curve = new Curve(new Spline(controlPoints.get(0), knots[0]), resolu);
FloatBuffer vertsBuffer = (FloatBuffer) curve.getBuffer(Type.Position).getData();
beziers.add(new BezierLine(BufferUtils.getVector3Array(vertsBuffer), materialIndex, smooth, false));
} else {
// creating the NURB surface
int resolv = ((Number) nurb.getFieldValue("resolv")).intValue();
int uSegments = resolu * controlPoints.get(0).size() - 1;
int vSegments = resolv * controlPoints.size() - 1;
Surface nurbSurface = Surface.createNurbsSurface(controlPoints, knots, uSegments, vSegments, orderU, orderV, smooth);
FloatBuffer vertsBuffer = (FloatBuffer) nurbSurface.getBuffer(Type.Position).getData();
vertices.addAll(Arrays.asList(BufferUtils.getVector3Array(vertsBuffer)));
FloatBuffer normalsBuffer = (FloatBuffer) nurbSurface.getBuffer(Type.Normal).getData();
normals.addAll(Arrays.asList(BufferUtils.getVector3Array(normalsBuffer)));
IndexBuffer indexBuffer = nurbSurface.getIndexBuffer();
for (int i = 0; i < indexBuffer.size(); i += 3) {
int index1 = indexBuffer.get(i) + originalVerticesAmount;
int index2 = indexBuffer.get(i + 1) + originalVerticesAmount;
int index3 = indexBuffer.get(i + 2) + originalVerticesAmount;
faces.add(new Face(new Integer[] { index1, index2, index3 }, smooth, materialIndex, null, null, this));
}
}
}
use of com.jme3.scene.plugins.blender.file.FileBlockHeader in project jmonkeyengine by jMonkeyEngine.
the class BlenderLoader method setup.
/**
* This method sets up the loader.
* @param assetInfo
* the asset info
* @throws BlenderFileException
* an exception is throw when something wrong happens with blender file
*/
protected BlenderContext setup(AssetInfo assetInfo) throws BlenderFileException {
// registering loaders
ModelKey modelKey = (ModelKey) assetInfo.getKey();
BlenderKey blenderKey;
if (modelKey instanceof BlenderKey) {
blenderKey = (BlenderKey) modelKey;
} else {
blenderKey = new BlenderKey(modelKey.getName());
}
// opening stream
BlenderInputStream inputStream = new BlenderInputStream(assetInfo.openStream());
// reading blocks
List<FileBlockHeader> blocks = new ArrayList<FileBlockHeader>();
FileBlockHeader fileBlock;
BlenderContext blenderContext = new BlenderContext();
blenderContext.setBlenderVersion(inputStream.getVersionNumber());
blenderContext.setAssetManager(assetInfo.getManager());
blenderContext.setInputStream(inputStream);
blenderContext.setBlenderKey(blenderKey);
// creating helpers
blenderContext.putHelper(AnimationHelper.class, new AnimationHelper(inputStream.getVersionNumber(), blenderContext));
blenderContext.putHelper(TextureHelper.class, new TextureHelper(inputStream.getVersionNumber(), blenderContext));
blenderContext.putHelper(MeshHelper.class, new MeshHelper(inputStream.getVersionNumber(), blenderContext));
blenderContext.putHelper(ObjectHelper.class, new ObjectHelper(inputStream.getVersionNumber(), blenderContext));
blenderContext.putHelper(CurvesHelper.class, new CurvesHelper(inputStream.getVersionNumber(), blenderContext));
blenderContext.putHelper(LightHelper.class, new LightHelper(inputStream.getVersionNumber(), blenderContext));
blenderContext.putHelper(CameraHelper.class, new CameraHelper(inputStream.getVersionNumber(), blenderContext));
blenderContext.putHelper(ModifierHelper.class, new ModifierHelper(inputStream.getVersionNumber(), blenderContext));
blenderContext.putHelper(MaterialHelper.class, new MaterialHelper(inputStream.getVersionNumber(), blenderContext));
blenderContext.putHelper(ConstraintHelper.class, new ConstraintHelper(inputStream.getVersionNumber(), blenderContext));
blenderContext.putHelper(ParticlesHelper.class, new ParticlesHelper(inputStream.getVersionNumber(), blenderContext));
blenderContext.putHelper(LandscapeHelper.class, new LandscapeHelper(inputStream.getVersionNumber(), blenderContext));
// reading the blocks (dna block is automatically saved in the blender context when found)
FileBlockHeader sceneFileBlock = null;
do {
fileBlock = new FileBlockHeader(inputStream, blenderContext);
if (!fileBlock.isDnaBlock()) {
blocks.add(fileBlock);
// save the scene's file block
if (fileBlock.getCode() == BlockCode.BLOCK_SC00) {
sceneFileBlock = fileBlock;
}
}
} while (!fileBlock.isLastBlock());
if (sceneFileBlock != null) {
blenderContext.setSceneStructure(sceneFileBlock.getStructure(blenderContext));
}
// adding locator for linked content
assetInfo.getManager().registerLocator(assetInfo.getKey().getName(), LinkedContentLocator.class);
return blenderContext;
}
Aggregations