Browse Source

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

Kae..pl 14 years ago
parent
commit
8deba71f8d

+ 30 - 32
engine/src/blender/com/jme3/scene/plugins/blender/JmeConverter.java → engine/src/blender/com/jme3/scene/plugins/blender/AbstractBlenderLoader.java

@@ -32,7 +32,10 @@
 package com.jme3.scene.plugins.blender;
 package com.jme3.scene.plugins.blender;
 
 
 import java.util.List;
 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.FeaturesToLoad;
 import com.jme3.asset.BlenderKey.WorldData;
 import com.jme3.asset.BlenderKey.WorldData;
 import com.jme3.light.AmbientLight;
 import com.jme3.light.AmbientLight;
@@ -42,8 +45,10 @@ import com.jme3.math.ColorRGBA;
 import com.jme3.renderer.Camera;
 import com.jme3.renderer.Camera;
 import com.jme3.scene.Geometry;
 import com.jme3.scene.Geometry;
 import com.jme3.scene.Node;
 import com.jme3.scene.Node;
+import com.jme3.scene.Spatial;
 import com.jme3.scene.plugins.blender.cameras.CameraHelper;
 import com.jme3.scene.plugins.blender.cameras.CameraHelper;
 import com.jme3.scene.plugins.blender.exceptions.BlenderFileException;
 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.file.Structure;
 import com.jme3.scene.plugins.blender.lights.LightHelper;
 import com.jme3.scene.plugins.blender.lights.LightHelper;
 import com.jme3.scene.plugins.blender.materials.MaterialHelper;
 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.
  * This class converts blender file blocks into jMonkeyEngine data structures.
- * @author Marcin Roguski
+ * @author Marcin Roguski (Kaelthas)
  */
  */
-/* package */class JmeConverter {
-
-	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;
-	}
+/* package */ abstract class AbstractBlenderLoader implements AssetLoader {
+	private static final Logger LOGGER = Logger.getLogger(AbstractBlenderLoader.class.getName());
+	
+	protected BlenderContext	blenderContext;
 
 
 	/**
 	/**
 	 * This method converts the given structure to a scene node.
 	 * 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
 	 *        structure of a scene
 	 * @return scene's node
 	 * @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) {
 		if ((blenderContext.getBlenderKey().getFeaturesToLoad() & FeaturesToLoad.SCENES) == 0) {
 			return null;
 			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;
 	}
 	}
 
 
 	/**
 	/**

+ 15 - 1
engine/src/blender/com/jme3/scene/plugins/blender/BlenderContext.java

@@ -31,12 +31,15 @@
  */
  */
 package com.jme3.scene.plugins.blender;
 package com.jme3.scene.plugins.blender;
 
 
+import java.io.IOException;
 import java.util.ArrayList;
 import java.util.ArrayList;
 import java.util.EmptyStackException;
 import java.util.EmptyStackException;
 import java.util.HashMap;
 import java.util.HashMap;
 import java.util.List;
 import java.util.List;
 import java.util.Map;
 import java.util.Map;
 import java.util.Stack;
 import java.util.Stack;
+import java.util.logging.Level;
+import java.util.logging.Logger;
 
 
 import com.jme3.asset.AssetManager;
 import com.jme3.asset.AssetManager;
 import com.jme3.asset.BlenderKey;
 import com.jme3.asset.BlenderKey;
@@ -58,7 +61,8 @@ import com.jme3.scene.plugins.blender.modifiers.Modifier;
  * @author Marcin Roguski (Kaelthas)
  * @author Marcin Roguski (Kaelthas)
  */
  */
 public class BlenderContext {
 public class BlenderContext {
-
+	private static final Logger LOGGER = Logger.getLogger(BlenderContext.class.getName());
+	
     /** The blender key. */
     /** The blender key. */
     private BlenderKey blenderKey;
     private BlenderKey blenderKey;
     /** The header of the file block. */
     /** The header of the file block. */
@@ -459,6 +463,16 @@ public class BlenderContext {
         }
         }
         return blenderKey.getDefaultMaterial();
         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
      * This enum defines what loaded data type user wants to retreive. It can be either filled structure or already

+ 35 - 24
engine/src/blender/com/jme3/scene/plugins/blender/BlenderLoader.java

@@ -38,7 +38,6 @@ import java.util.logging.Level;
 import java.util.logging.Logger;
 import java.util.logging.Logger;
 
 
 import com.jme3.asset.AssetInfo;
 import com.jme3.asset.AssetInfo;
-import com.jme3.asset.AssetLoader;
 import com.jme3.asset.BlenderKey;
 import com.jme3.asset.BlenderKey;
 import com.jme3.asset.BlenderKey.FeaturesToLoad;
 import com.jme3.asset.BlenderKey.FeaturesToLoad;
 import com.jme3.asset.BlenderKey.LoadingResults;
 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.
  * 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());
 	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. */
 	/** The blocks read from the file. */
 	protected List<FileBlockHeader>	blocks;
 	protected List<FileBlockHeader>	blocks;
-	/** Blender input stream. */
-	protected BlenderInputStream	inputStream;
 
 
 	@Override
 	@Override
 	public Spatial load(AssetInfo assetInfo) throws IOException {
 	public Spatial load(AssetInfo assetInfo) throws IOException {
 		try {
 		try {
 			this.setup(assetInfo);
 			this.setup(assetInfo);
 
 
+			BlenderKey blenderKey = blenderContext.getBlenderKey();
 			LoadingResults loadingResults = blenderKey.prepareLoadingResults();
 			LoadingResults loadingResults = blenderKey.prepareLoadingResults();
 			WorldData worldData = null;// a set of data used in different scene aspects
 			WorldData worldData = null;// a set of data used in different scene aspects
 			for (FileBlockHeader block : blocks) {
 			for (FileBlockHeader block : blocks) {
 				switch (block.getCode()) {
 				switch (block.getCode()) {
 					case FileBlockHeader.BLOCK_OB00:// Object
 					case FileBlockHeader.BLOCK_OB00:// Object
-						Object object = converter.toObject(block.getStructure(blenderContext));
+						Object object = this.toObject(block.getStructure(blenderContext));
 						if (object instanceof Node) {
 						if (object instanceof Node) {
 							if ((blenderKey.getFeaturesToLoad() & FeaturesToLoad.OBJECTS) != 0) {
 							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() });
 								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);
 									loadingResults.addObject((Node) object);
 								}
 								}
 							}
 							}
@@ -114,12 +106,12 @@ public class BlenderLoader implements AssetLoader {
 						break;
 						break;
 					case FileBlockHeader.BLOCK_MA00:// Material
 					case FileBlockHeader.BLOCK_MA00:// Material
 						if (blenderKey.isLoadUnlinkedAssets() && (blenderKey.getFeaturesToLoad() & FeaturesToLoad.MATERIALS) != 0) {
 						if (blenderKey.isLoadUnlinkedAssets() && (blenderKey.getFeaturesToLoad() & FeaturesToLoad.MATERIALS) != 0) {
-							loadingResults.addMaterial(converter.toMaterial(block.getStructure(blenderContext)));
+							loadingResults.addMaterial(this.toMaterial(block.getStructure(blenderContext)));
 						}
 						}
 						break;
 						break;
 					case FileBlockHeader.BLOCK_SC00:// Scene
 					case FileBlockHeader.BLOCK_SC00:// Scene
 						if ((blenderKey.getFeaturesToLoad() & FeaturesToLoad.SCENES) != 0) {
 						if ((blenderKey.getFeaturesToLoad() & FeaturesToLoad.SCENES) != 0) {
-							loadingResults.addScene(converter.toScene(block.getStructure(blenderContext)));
+							loadingResults.addScene(this.toScene(block.getStructure(blenderContext)));
 						}
 						}
 						break;
 						break;
 					case FileBlockHeader.BLOCK_WO00:// World
 					case FileBlockHeader.BLOCK_WO00:// World
@@ -127,7 +119,7 @@ public class BlenderLoader implements AssetLoader {
 							Structure worldStructure = block.getStructure(blenderContext);
 							Structure worldStructure = block.getStructure(blenderContext);
 							String worldName = worldStructure.getName();
 							String worldName = worldStructure.getName();
 							if (blenderKey.getUsedWorld() == null || blenderKey.getUsedWorld().equals(worldName)) {
 							if (blenderKey.getUsedWorld() == null || blenderKey.getUsedWorld().equals(worldName)) {
-								worldData = converter.toWorldData(worldStructure);
+								worldData = this.toWorldData(worldStructure);
 								if ((blenderKey.getFeaturesToLoad() & FeaturesToLoad.LIGHTS) != 0) {
 								if ((blenderKey.getFeaturesToLoad() & FeaturesToLoad.LIGHTS) != 0) {
 									loadingResults.addLight(worldData.getAmbientLight());
 									loadingResults.addLight(worldData.getAmbientLight());
 								}
 								}
@@ -136,11 +128,7 @@ public class BlenderLoader implements AssetLoader {
 						break;
 						break;
 				}
 				}
 			}
 			}
-			try {
-				inputStream.close();
-			} catch (IOException e) {
-				LOGGER.log(Level.SEVERE, e.getMessage(), e);
-			}
+			blenderContext.dispose();
 			return loadingResults;
 			return loadingResults;
 		} catch (BlenderFileException e) {
 		} catch (BlenderFileException e) {
 			LOGGER.log(Level.SEVERE, e.getMessage(), e);
 			LOGGER.log(Level.SEVERE, e.getMessage(), e);
@@ -148,6 +136,30 @@ public class BlenderLoader implements AssetLoader {
 		return null;
 		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.
 	 * This method sets up the loader.
 	 * @param assetInfo
 	 * @param assetInfo
@@ -158,6 +170,7 @@ public class BlenderLoader implements AssetLoader {
 	protected void setup(AssetInfo assetInfo) throws BlenderFileException {
 	protected void setup(AssetInfo assetInfo) throws BlenderFileException {
 		// registering loaders
 		// registering loaders
 		ModelKey modelKey = (ModelKey) assetInfo.getKey();
 		ModelKey modelKey = (ModelKey) assetInfo.getKey();
+		BlenderKey blenderKey;
 		if (modelKey instanceof BlenderKey) {
 		if (modelKey instanceof BlenderKey) {
 			blenderKey = (BlenderKey) modelKey;
 			blenderKey = (BlenderKey) modelKey;
 		} else {
 		} else {
@@ -166,7 +179,7 @@ public class BlenderLoader implements AssetLoader {
 		}
 		}
 
 
 		// opening stream
 		// opening stream
-		inputStream = new BlenderInputStream(assetInfo.openStream(), assetInfo.getManager());
+		BlenderInputStream inputStream = new BlenderInputStream(assetInfo.openStream(), assetInfo.getManager());
 
 
 		// reading blocks
 		// reading blocks
 		blocks = new ArrayList<FileBlockHeader>();
 		blocks = new ArrayList<FileBlockHeader>();
@@ -217,7 +230,5 @@ public class BlenderLoader implements AssetLoader {
 			int lay = ((Number) sceneFileBlock.getStructure(blenderContext).getFieldValue("lay")).intValue();
 			int lay = ((Number) sceneFileBlock.getStructure(blenderContext).getFieldValue("lay")).intValue();
 			blenderContext.getBlenderKey().setLayersToLoad(lay);// load only current layer
 			blenderContext.getBlenderKey().setLayersToLoad(lay);// load only current layer
 		}
 		}
-
-		converter = new JmeConverter(blenderContext);
 	}
 	}
 }
 }

+ 5 - 11
engine/src/blender/com/jme3/scene/plugins/blender/BlenderModelLoader.java

@@ -32,12 +32,11 @@
 package com.jme3.scene.plugins.blender;
 package com.jme3.scene.plugins.blender;
 
 
 import java.io.IOException;
 import java.io.IOException;
-import java.util.List;
 import java.util.logging.Level;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 import java.util.logging.Logger;
 
 
 import com.jme3.asset.AssetInfo;
 import com.jme3.asset.AssetInfo;
-import com.jme3.asset.BlenderKey.LoadingResults;
+import com.jme3.asset.BlenderKey;
 import com.jme3.light.Light;
 import com.jme3.light.Light;
 import com.jme3.scene.Node;
 import com.jme3.scene.Node;
 import com.jme3.scene.Spatial;
 import com.jme3.scene.Spatial;
@@ -55,13 +54,14 @@ public class BlenderModelLoader extends BlenderLoader {
     @Override
     @Override
     public Spatial load(AssetInfo assetInfo) throws IOException {
     public Spatial load(AssetInfo assetInfo) throws IOException {
         try {
         try {
-            setup(assetInfo);
+            this.setup(assetInfo);
             
             
+            BlenderKey blenderKey = blenderContext.getBlenderKey();
             Node modelRoot = new Node(blenderKey.getName());
             Node modelRoot = new Node(blenderKey.getName());
             
             
             for (FileBlockHeader block : blocks) {
             for (FileBlockHeader block : blocks) {
                 if (block.getCode() == FileBlockHeader.BLOCK_OB00) {
                 if (block.getCode() == FileBlockHeader.BLOCK_OB00) {
-                    Object object = converter.toObject(block.getStructure(blenderContext));
+                    Object object = this.toObject(block.getStructure(blenderContext));
                     if (object instanceof Node) {
                     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()});
                         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 (((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;
             return modelRoot;
         } catch (BlenderFileException e) {
         } catch (BlenderFileException e) {
             LOGGER.log(Level.SEVERE, e.getMessage(), e);
             LOGGER.log(Level.SEVERE, e.getMessage(), e);