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
This commit is contained in:
parent
ec4486d5eb
commit
8deba71f8d
@ -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…
x
Reference in New Issue
Block a user