Blender loading logic refactoring:

- JmeConverter replaced by AbstractBlenderLoader
- scene loading implemented (now all objects are attached to the scene node)

git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@8252 75d07b2b-3a1a-0410-a2c5-0572b91ccdca
3.0
Kae..pl 13 years ago
parent ec4486d5eb
commit 8deba71f8d
  1. 60
      engine/src/blender/com/jme3/scene/plugins/blender/AbstractBlenderLoader.java
  2. 14
      engine/src/blender/com/jme3/scene/plugins/blender/BlenderContext.java
  3. 59
      engine/src/blender/com/jme3/scene/plugins/blender/BlenderLoader.java
  4. 16
      engine/src/blender/com/jme3/scene/plugins/blender/BlenderModelLoader.java

@ -32,7 +32,10 @@
package com.jme3.scene.plugins.blender;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.jme3.asset.AssetLoader;
import com.jme3.asset.BlenderKey.FeaturesToLoad;
import com.jme3.asset.BlenderKey.WorldData;
import com.jme3.light.AmbientLight;
@ -42,8 +45,10 @@ import com.jme3.math.ColorRGBA;
import com.jme3.renderer.Camera;
import com.jme3.scene.Geometry;
import com.jme3.scene.Node;
import com.jme3.scene.Spatial;
import com.jme3.scene.plugins.blender.cameras.CameraHelper;
import com.jme3.scene.plugins.blender.exceptions.BlenderFileException;
import com.jme3.scene.plugins.blender.file.Pointer;
import com.jme3.scene.plugins.blender.file.Structure;
import com.jme3.scene.plugins.blender.lights.LightHelper;
import com.jme3.scene.plugins.blender.materials.MaterialHelper;
@ -52,37 +57,12 @@ import com.jme3.scene.plugins.blender.objects.ObjectHelper;
/**
* This class converts blender file blocks into jMonkeyEngine data structures.
* @author Marcin Roguski
* @author Marcin Roguski (Kaelthas)
*/
/* package */class JmeConverter {
/* package */ abstract class AbstractBlenderLoader implements AssetLoader {
private static final Logger LOGGER = Logger.getLogger(AbstractBlenderLoader.class.getName());
private final BlenderContext blenderContext;
/**
* Constructor. Creates the loader and checks if the given data is correct.
* @param blenderContext
* the blender context; it should have the following field set: - asset manager - blender key - dna block
* data - blender input stream Otherwise IllegalArgumentException will be thrown.
* @param featuresToLoad
* bitwise flag describing what features are to be loaded
* @see FeaturesToLoad FeaturesToLoad
*/
public JmeConverter(BlenderContext blenderContext) {
// validating the given data first
if (blenderContext.getAssetManager() == null) {
throw new IllegalArgumentException("Cannot find asset manager!");
}
if (blenderContext.getBlenderKey() == null) {
throw new IllegalArgumentException("Cannot find blender key!");
}
if (blenderContext.getDnaBlockData() == null) {
throw new IllegalArgumentException("Cannot find dna block!");
}
if (blenderContext.getInputStream() == null) {
throw new IllegalArgumentException("Cannot find blender file stream!");
}
this.blenderContext = blenderContext;
}
protected BlenderContext blenderContext;
/**
* This method converts the given structure to a scene node.
@ -90,11 +70,29 @@ import com.jme3.scene.plugins.blender.objects.ObjectHelper;
* structure of a scene
* @return scene's node
*/
public Node toScene(Structure structure) {// TODO: import the scene
public Node toScene(Structure structure) {
if ((blenderContext.getBlenderKey().getFeaturesToLoad() & FeaturesToLoad.SCENES) == 0) {
return null;
}
return new Node(structure.getName());
Node result = new Node(structure.getName());
try {
List<Structure> base = ((Structure)structure.getFieldValue("base")).evaluateListBase(blenderContext);
for(Structure b : base) {
Pointer pObject = (Pointer) b.getFieldValue("object");
if(pObject.isNotNull()) {
Structure objectStructure = pObject.fetchData(blenderContext.getInputStream()).get(0);
Object object = this.toObject(objectStructure);
if(object instanceof Spatial) {
result.attachChild((Spatial) object);
} else if(object instanceof Light) {
result.addLight((Light)object);
}
}
}
} catch (BlenderFileException e) {
LOGGER.log(Level.SEVERE, e.getLocalizedMessage(), e);
}
return result;
}
/**

@ -31,12 +31,15 @@
*/
package com.jme3.scene.plugins.blender;
import java.io.IOException;
import java.util.ArrayList;
import java.util.EmptyStackException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Stack;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.jme3.asset.AssetManager;
import com.jme3.asset.BlenderKey;
@ -58,6 +61,7 @@ import com.jme3.scene.plugins.blender.modifiers.Modifier;
* @author Marcin Roguski (Kaelthas)
*/
public class BlenderContext {
private static final Logger LOGGER = Logger.getLogger(BlenderContext.class.getName());
/** The blender key. */
private BlenderKey blenderKey;
@ -460,6 +464,16 @@ public class BlenderContext {
return blenderKey.getDefaultMaterial();
}
public void dispose() {
try {
inputStream.close();
} catch (IOException e) {
LOGGER.log(Level.SEVERE, e.getLocalizedMessage(), e);
}
loadedFeatures.clear();
loadedFeaturesByName.clear();
}
/**
* This enum defines what loaded data type user wants to retreive. It can be either filled structure or already
* converted data.

@ -38,7 +38,6 @@ import java.util.logging.Level;
import java.util.logging.Logger;
import com.jme3.asset.AssetInfo;
import com.jme3.asset.AssetLoader;
import com.jme3.asset.BlenderKey;
import com.jme3.asset.BlenderKey.FeaturesToLoad;
import com.jme3.asset.BlenderKey.LoadingResults;
@ -67,38 +66,31 @@ import com.jme3.scene.plugins.blender.textures.TextureHelper;
/**
* This is the main loading class. Have in notice that asset manager needs to have loaders for resources like textures.
* @author Marcin Roguski
* @author Marcin Roguski (Kaelthas)
*/
public class BlenderLoader implements AssetLoader {
public class BlenderLoader extends AbstractBlenderLoader {
private static final Logger LOGGER = Logger.getLogger(BlenderLoader.class.getName());
/** Converter for blender structures. */
protected JmeConverter converter;
/** The blender context. */
protected BlenderContext blenderContext;
/** The blender key to use. */
protected BlenderKey blenderKey;
/** The blocks read from the file. */
protected List<FileBlockHeader> blocks;
/** Blender input stream. */
protected BlenderInputStream inputStream;
@Override
public Spatial load(AssetInfo assetInfo) throws IOException {
try {
this.setup(assetInfo);
BlenderKey blenderKey = blenderContext.getBlenderKey();
LoadingResults loadingResults = blenderKey.prepareLoadingResults();
WorldData worldData = null;// a set of data used in different scene aspects
for (FileBlockHeader block : blocks) {
switch (block.getCode()) {
case FileBlockHeader.BLOCK_OB00:// Object
Object object = converter.toObject(block.getStructure(blenderContext));
Object object = this.toObject(block.getStructure(blenderContext));
if (object instanceof Node) {
if ((blenderKey.getFeaturesToLoad() & FeaturesToLoad.OBJECTS) != 0) {
LOGGER.log(Level.INFO, "{0}: {1}--> {2}", new Object[] { ((Node) object).getName(), ((Node) object).getLocalTranslation().toString(), ((Node) object).getParent() == null ? "null" : ((Node) object).getParent().getName() });
if (((Node) object).getParent() == null) {
if (this.isRootObject(loadingResults, (Node)object)) {
loadingResults.addObject((Node) object);
}
}
@ -114,12 +106,12 @@ public class BlenderLoader implements AssetLoader {
break;
case FileBlockHeader.BLOCK_MA00:// Material
if (blenderKey.isLoadUnlinkedAssets() && (blenderKey.getFeaturesToLoad() & FeaturesToLoad.MATERIALS) != 0) {
loadingResults.addMaterial(converter.toMaterial(block.getStructure(blenderContext)));
loadingResults.addMaterial(this.toMaterial(block.getStructure(blenderContext)));
}
break;
case FileBlockHeader.BLOCK_SC00:// Scene
if ((blenderKey.getFeaturesToLoad() & FeaturesToLoad.SCENES) != 0) {
loadingResults.addScene(converter.toScene(block.getStructure(blenderContext)));
loadingResults.addScene(this.toScene(block.getStructure(blenderContext)));
}
break;
case FileBlockHeader.BLOCK_WO00:// World
@ -127,7 +119,7 @@ public class BlenderLoader implements AssetLoader {
Structure worldStructure = block.getStructure(blenderContext);
String worldName = worldStructure.getName();
if (blenderKey.getUsedWorld() == null || blenderKey.getUsedWorld().equals(worldName)) {
worldData = converter.toWorldData(worldStructure);
worldData = this.toWorldData(worldStructure);
if ((blenderKey.getFeaturesToLoad() & FeaturesToLoad.LIGHTS) != 0) {
loadingResults.addLight(worldData.getAmbientLight());
}
@ -136,11 +128,7 @@ public class BlenderLoader implements AssetLoader {
break;
}
}
try {
inputStream.close();
} catch (IOException e) {
LOGGER.log(Level.SEVERE, e.getMessage(), e);
}
blenderContext.dispose();
return loadingResults;
} catch (BlenderFileException e) {
LOGGER.log(Level.SEVERE, e.getMessage(), e);
@ -148,6 +136,30 @@ public class BlenderLoader implements AssetLoader {
return null;
}
/**
* This method indicates if the given spatial is a root object. It means it
* has no parent or is directly attached to one of the already loaded scene
* nodes.
*
* @param loadingResults
* loading results containing the scene nodes
* @param spatial
* spatial object
* @return <b>true</b> if the given spatial is a root object and
* <b>false</b> otherwise
*/
protected boolean isRootObject(LoadingResults loadingResults, Spatial spatial) {
if(spatial.getParent() == null) {
return true;
}
for(Node scene : loadingResults.getScenes()) {
if(spatial.getParent().equals(scene)) {
return true;
}
}
return false;
}
/**
* This method sets up the loader.
* @param assetInfo
@ -158,6 +170,7 @@ public class BlenderLoader implements AssetLoader {
protected void setup(AssetInfo assetInfo) throws BlenderFileException {
// registering loaders
ModelKey modelKey = (ModelKey) assetInfo.getKey();
BlenderKey blenderKey;
if (modelKey instanceof BlenderKey) {
blenderKey = (BlenderKey) modelKey;
} else {
@ -166,7 +179,7 @@ public class BlenderLoader implements AssetLoader {
}
// opening stream
inputStream = new BlenderInputStream(assetInfo.openStream(), assetInfo.getManager());
BlenderInputStream inputStream = new BlenderInputStream(assetInfo.openStream(), assetInfo.getManager());
// reading blocks
blocks = new ArrayList<FileBlockHeader>();
@ -217,7 +230,5 @@ public class BlenderLoader implements AssetLoader {
int lay = ((Number) sceneFileBlock.getStructure(blenderContext).getFieldValue("lay")).intValue();
blenderContext.getBlenderKey().setLayersToLoad(lay);// load only current layer
}
converter = new JmeConverter(blenderContext);
}
}

@ -32,12 +32,11 @@
package com.jme3.scene.plugins.blender;
import java.io.IOException;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.jme3.asset.AssetInfo;
import com.jme3.asset.BlenderKey.LoadingResults;
import com.jme3.asset.BlenderKey;
import com.jme3.light.Light;
import com.jme3.scene.Node;
import com.jme3.scene.Spatial;
@ -55,13 +54,14 @@ public class BlenderModelLoader extends BlenderLoader {
@Override
public Spatial load(AssetInfo assetInfo) throws IOException {
try {
setup(assetInfo);
this.setup(assetInfo);
BlenderKey blenderKey = blenderContext.getBlenderKey();
Node modelRoot = new Node(blenderKey.getName());
for (FileBlockHeader block : blocks) {
if (block.getCode() == FileBlockHeader.BLOCK_OB00) {
Object object = converter.toObject(block.getStructure(blenderContext));
Object object = this.toObject(block.getStructure(blenderContext));
if (object instanceof Node) {
LOGGER.log(Level.INFO, "{0}: {1}--> {2}", new Object[]{((Node) object).getName(), ((Node) object).getLocalTranslation().toString(), ((Node) object).getParent() == null ? "null" : ((Node) object).getParent().getName()});
if (((Node) object).getParent() == null) {
@ -72,13 +72,7 @@ public class BlenderModelLoader extends BlenderLoader {
}
}
}
try {
inputStream.close();
} catch(IOException e) {
LOGGER.warning(e.getLocalizedMessage());
}
blenderContext.dispose();
return modelRoot;
} catch (BlenderFileException e) {
LOGGER.log(Level.SEVERE, e.getMessage(), e);

Loading…
Cancel
Save