Bugfix: fix to importing blend files with linked content.
This commit is contained in:
parent
edaf49c00c
commit
b34649d399
@ -230,18 +230,22 @@ public class BlenderKey extends ModelKey {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Not used any more.
|
||||||
* This method sets the asset root path.
|
* This method sets the asset root path.
|
||||||
* @param assetRootPath
|
* @param assetRootPath
|
||||||
* the assets root path
|
* the assets root path
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public void setAssetRootPath(String assetRootPath) {
|
public void setAssetRootPath(String assetRootPath) {
|
||||||
this.assetRootPath = assetRootPath;
|
this.assetRootPath = assetRootPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Not used any more.
|
||||||
* This method returns the asset root path.
|
* This method returns the asset root path.
|
||||||
* @return the asset root path
|
* @return the asset root path
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public String getAssetRootPath() {
|
public String getAssetRootPath() {
|
||||||
return assetRootPath;
|
return assetRootPath;
|
||||||
}
|
}
|
||||||
|
@ -31,8 +31,6 @@
|
|||||||
*/
|
*/
|
||||||
package com.jme3.scene.plugins.blender;
|
package com.jme3.scene.plugins.blender;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@ -40,25 +38,17 @@ import java.util.Map.Entry;
|
|||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
import com.jme3.animation.Animation;
|
|
||||||
import com.jme3.asset.AssetNotFoundException;
|
import com.jme3.asset.AssetNotFoundException;
|
||||||
import com.jme3.asset.BlenderKey;
|
import com.jme3.asset.BlenderKey;
|
||||||
import com.jme3.export.Savable;
|
import com.jme3.export.Savable;
|
||||||
import com.jme3.light.Light;
|
|
||||||
import com.jme3.math.FastMath;
|
import com.jme3.math.FastMath;
|
||||||
import com.jme3.math.Quaternion;
|
import com.jme3.math.Quaternion;
|
||||||
import com.jme3.post.Filter;
|
|
||||||
import com.jme3.renderer.Camera;
|
|
||||||
import com.jme3.scene.Node;
|
|
||||||
import com.jme3.scene.Spatial;
|
import com.jme3.scene.Spatial;
|
||||||
import com.jme3.scene.plugins.blender.BlenderContext.LoadedDataType;
|
import com.jme3.scene.plugins.blender.BlenderContext.LoadedDataType;
|
||||||
import com.jme3.scene.plugins.blender.file.BlenderFileException;
|
import com.jme3.scene.plugins.blender.file.BlenderFileException;
|
||||||
import com.jme3.scene.plugins.blender.file.Pointer;
|
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.materials.MaterialContext;
|
|
||||||
import com.jme3.scene.plugins.blender.meshes.TemporalMesh;
|
|
||||||
import com.jme3.scene.plugins.blender.objects.Properties;
|
import com.jme3.scene.plugins.blender.objects.Properties;
|
||||||
import com.jme3.texture.Texture;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A purpose of the helper class is to split calculation code into several classes. Each helper after use should be cleared because it can
|
* A purpose of the helper class is to split calculation code into several classes. Each helper after use should be cleared because it can
|
||||||
@ -157,7 +147,6 @@ public abstract class AbstractBlenderHelper {
|
|||||||
* @throws BlenderFileException
|
* @throws BlenderFileException
|
||||||
* and exception is throw when problems with reading a blend file occur
|
* and exception is throw when problems with reading a blend file occur
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
protected Object loadLibrary(Structure id) throws BlenderFileException {
|
protected Object loadLibrary(Structure id) throws BlenderFileException {
|
||||||
Pointer pLib = (Pointer) id.getFieldValue("lib");
|
Pointer pLib = (Pointer) id.getFieldValue("lib");
|
||||||
if (pLib.isNotNull()) {
|
if (pLib.isNotNull()) {
|
||||||
@ -167,79 +156,21 @@ public abstract class AbstractBlenderHelper {
|
|||||||
String path = library.getFieldValue("filepath").toString();
|
String path = library.getFieldValue("filepath").toString();
|
||||||
|
|
||||||
if (!blenderContext.getLinkedFeatures().keySet().contains(path)) {
|
if (!blenderContext.getLinkedFeatures().keySet().contains(path)) {
|
||||||
File file = new File(path);
|
|
||||||
List<String> pathsToCheck = new ArrayList<String>();
|
|
||||||
String currentPath = file.getName();
|
|
||||||
do {
|
|
||||||
pathsToCheck.add(currentPath);
|
|
||||||
file = file.getParentFile();
|
|
||||||
if (file != null) {
|
|
||||||
currentPath = file.getName() + '/' + currentPath;
|
|
||||||
}
|
|
||||||
} while (file != null);
|
|
||||||
|
|
||||||
Spatial loadedAsset = null;
|
Spatial loadedAsset = null;
|
||||||
BlenderKey blenderKey = null;
|
BlenderKey blenderKey = new BlenderKey(path);
|
||||||
for (String p : pathsToCheck) {
|
|
||||||
blenderKey = new BlenderKey(p);
|
|
||||||
blenderKey.setLoadUnlinkedAssets(true);
|
blenderKey.setLoadUnlinkedAssets(true);
|
||||||
try {
|
try {
|
||||||
loadedAsset = blenderContext.getAssetManager().loadAsset(blenderKey);
|
loadedAsset = blenderContext.getAssetManager().loadAsset(blenderKey);
|
||||||
break;// break if no exception was thrown
|
|
||||||
} catch (AssetNotFoundException e) {
|
} catch (AssetNotFoundException e) {
|
||||||
LOGGER.log(Level.FINEST, "Cannot locate linked resource at path: {0}.", p);
|
LOGGER.log(Level.FINEST, "Cannot locate linked resource at path: {0}.", path);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (loadedAsset != null) {
|
if (loadedAsset != null) {
|
||||||
Map<String, Map<String, Object>> linkedData = loadedAsset.getUserData("linkedData");
|
Map<String, Map<String, Object>> linkedData = loadedAsset.getUserData("linkedData");
|
||||||
|
|
||||||
for (Entry<String, Map<String, Object>> entry : linkedData.entrySet()) {
|
for (Entry<String, Map<String, Object>> entry : linkedData.entrySet()) {
|
||||||
String linkedDataFilePath = "this".equals(entry.getKey()) ? path : entry.getKey();
|
String linkedDataFilePath = "this".equals(entry.getKey()) ? path : entry.getKey();
|
||||||
|
blenderContext.getLinkedFeatures().put(linkedDataFilePath, entry.getValue());
|
||||||
List<Node> scenes = (List<Node>) entry.getValue().get("scenes");
|
|
||||||
for (Node scene : scenes) {
|
|
||||||
blenderContext.addLinkedFeature(linkedDataFilePath, "SC" + scene.getName(), scene);
|
|
||||||
}
|
|
||||||
List<Node> objects = (List<Node>) entry.getValue().get("objects");
|
|
||||||
for (Node object : objects) {
|
|
||||||
blenderContext.addLinkedFeature(linkedDataFilePath, "OB" + object.getName(), object);
|
|
||||||
}
|
|
||||||
List<TemporalMesh> meshes = (List<TemporalMesh>) entry.getValue().get("meshes");
|
|
||||||
for (TemporalMesh mesh : meshes) {
|
|
||||||
blenderContext.addLinkedFeature(linkedDataFilePath, "ME" + mesh.getName(), mesh);
|
|
||||||
}
|
|
||||||
List<MaterialContext> materials = (List<MaterialContext>) entry.getValue().get("materials");
|
|
||||||
for (MaterialContext materialContext : materials) {
|
|
||||||
blenderContext.addLinkedFeature(linkedDataFilePath, "MA" + materialContext.getName(), materialContext);
|
|
||||||
}
|
|
||||||
List<Texture> textures = (List<Texture>) entry.getValue().get("textures");
|
|
||||||
for (Texture texture : textures) {
|
|
||||||
blenderContext.addLinkedFeature(linkedDataFilePath, "TE" + texture.getName(), texture);
|
|
||||||
}
|
|
||||||
List<Texture> images = (List<Texture>) entry.getValue().get("images");
|
|
||||||
for (Texture image : images) {
|
|
||||||
blenderContext.addLinkedFeature(linkedDataFilePath, "IM" + image.getName(), image);
|
|
||||||
}
|
|
||||||
List<Animation> animations = (List<Animation>) entry.getValue().get("animations");
|
|
||||||
for (Animation animation : animations) {
|
|
||||||
blenderContext.addLinkedFeature(linkedDataFilePath, "AC" + animation.getName(), animation);
|
|
||||||
}
|
|
||||||
List<Camera> cameras = (List<Camera>) entry.getValue().get("cameras");
|
|
||||||
for (Camera camera : cameras) {
|
|
||||||
blenderContext.addLinkedFeature(linkedDataFilePath, "CA" + camera.getName(), camera);
|
|
||||||
}
|
|
||||||
List<Light> lights = (List<Light>) entry.getValue().get("lights");
|
|
||||||
for (Light light : lights) {
|
|
||||||
blenderContext.addLinkedFeature(linkedDataFilePath, "LA" + light.getName(), light);
|
|
||||||
}
|
|
||||||
Spatial sky = (Spatial) entry.getValue().get("sky");
|
|
||||||
if (sky != null) {
|
|
||||||
blenderContext.addLinkedFeature(linkedDataFilePath, sky.getName(), sky);
|
|
||||||
}
|
|
||||||
List<Filter> filters = (List<Filter>) entry.getValue().get("filters");
|
|
||||||
for (Filter filter : filters) {
|
|
||||||
blenderContext.addLinkedFeature(linkedDataFilePath, filter.getName(), filter);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
LOGGER.log(Level.WARNING, "No features loaded from path: {0}.", path);
|
LOGGER.log(Level.WARNING, "No features loaded from path: {0}.", path);
|
||||||
|
@ -44,8 +44,11 @@ import com.jme3.animation.Bone;
|
|||||||
import com.jme3.animation.Skeleton;
|
import com.jme3.animation.Skeleton;
|
||||||
import com.jme3.asset.AssetManager;
|
import com.jme3.asset.AssetManager;
|
||||||
import com.jme3.asset.BlenderKey;
|
import com.jme3.asset.BlenderKey;
|
||||||
|
import com.jme3.light.Light;
|
||||||
import com.jme3.material.Material;
|
import com.jme3.material.Material;
|
||||||
import com.jme3.math.ColorRGBA;
|
import com.jme3.math.ColorRGBA;
|
||||||
|
import com.jme3.post.Filter;
|
||||||
|
import com.jme3.renderer.Camera;
|
||||||
import com.jme3.scene.Node;
|
import com.jme3.scene.Node;
|
||||||
import com.jme3.scene.plugins.blender.animations.BlenderAction;
|
import com.jme3.scene.plugins.blender.animations.BlenderAction;
|
||||||
import com.jme3.scene.plugins.blender.animations.BoneContext;
|
import com.jme3.scene.plugins.blender.animations.BoneContext;
|
||||||
@ -55,6 +58,8 @@ import com.jme3.scene.plugins.blender.file.DnaBlockData;
|
|||||||
import com.jme3.scene.plugins.blender.file.FileBlockHeader;
|
import com.jme3.scene.plugins.blender.file.FileBlockHeader;
|
||||||
import com.jme3.scene.plugins.blender.file.FileBlockHeader.BlockCode;
|
import com.jme3.scene.plugins.blender.file.FileBlockHeader.BlockCode;
|
||||||
import com.jme3.scene.plugins.blender.file.Structure;
|
import com.jme3.scene.plugins.blender.file.Structure;
|
||||||
|
import com.jme3.scene.plugins.blender.materials.MaterialContext;
|
||||||
|
import com.jme3.texture.Texture;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The class that stores temporary data and manages it during loading the belnd
|
* The class that stores temporary data and manages it during loading the belnd
|
||||||
@ -77,7 +82,7 @@ public class BlenderContext {
|
|||||||
/** The asset manager. */
|
/** The asset manager. */
|
||||||
private AssetManager assetManager;
|
private AssetManager assetManager;
|
||||||
/** The blocks read from the file. */
|
/** The blocks read from the file. */
|
||||||
protected List<FileBlockHeader> blocks;
|
protected List<FileBlockHeader> blocks = new ArrayList<FileBlockHeader>();
|
||||||
/**
|
/**
|
||||||
* A map containing the file block headers. The key is the old memory address.
|
* A map containing the file block headers. The key is the old memory address.
|
||||||
*/
|
*/
|
||||||
@ -233,6 +238,7 @@ public class BlenderContext {
|
|||||||
* the block header to store
|
* the block header to store
|
||||||
*/
|
*/
|
||||||
public void addFileBlockHeader(Long oldMemoryAddress, FileBlockHeader fileBlockHeader) {
|
public void addFileBlockHeader(Long oldMemoryAddress, FileBlockHeader fileBlockHeader) {
|
||||||
|
blocks.add(fileBlockHeader);
|
||||||
fileBlockHeadersByOma.put(oldMemoryAddress, fileBlockHeader);
|
fileBlockHeadersByOma.put(oldMemoryAddress, fileBlockHeader);
|
||||||
List<FileBlockHeader> headers = fileBlockHeadersByCode.get(fileBlockHeader.getCode());
|
List<FileBlockHeader> headers = fileBlockHeadersByCode.get(fileBlockHeader.getCode());
|
||||||
if (headers == null) {
|
if (headers == null) {
|
||||||
@ -242,6 +248,13 @@ public class BlenderContext {
|
|||||||
headers.add(fileBlockHeader);
|
headers.add(fileBlockHeader);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the block headers
|
||||||
|
*/
|
||||||
|
public List<FileBlockHeader> getBlocks() {
|
||||||
|
return blocks;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method returns the block header of a given memory address. If the
|
* This method returns the block header of a given memory address. If the
|
||||||
* header is not present then null is returned.
|
* header is not present then null is returned.
|
||||||
@ -332,22 +345,14 @@ public class BlenderContext {
|
|||||||
* The method adds linked content to the blender context.
|
* The method adds linked content to the blender context.
|
||||||
* @param blenderFilePath
|
* @param blenderFilePath
|
||||||
* the path of linked blender file
|
* the path of linked blender file
|
||||||
* @param featureName
|
* @param featureGroup
|
||||||
* the linked feature name
|
* the linked feature group (ie. scenes, materials, meshes, etc.)
|
||||||
* @param feature
|
* @param feature
|
||||||
* the linked feature
|
* the linked feature
|
||||||
*/
|
*/
|
||||||
public void addLinkedFeature(String blenderFilePath, String featureName, Object feature) {
|
@Deprecated
|
||||||
if (feature != null) {
|
public void addLinkedFeature(String blenderFilePath, String featureGroup, Object feature) {
|
||||||
Map<String, Object> linkedFeatures = this.linkedFeatures.get(blenderFilePath);
|
// the method is deprecated and empty at the moment
|
||||||
if (linkedFeatures == null) {
|
|
||||||
linkedFeatures = new HashMap<String, Object>();
|
|
||||||
this.linkedFeatures.put(blenderFilePath, linkedFeatures);
|
|
||||||
}
|
|
||||||
if (!linkedFeatures.containsKey(featureName)) {
|
|
||||||
linkedFeatures.put(featureName, feature);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -358,9 +363,106 @@ public class BlenderContext {
|
|||||||
* the feature name we want to get
|
* the feature name we want to get
|
||||||
* @return linked feature or null if none was found
|
* @return linked feature or null if none was found
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
public Object getLinkedFeature(String blenderFilePath, String featureName) {
|
public Object getLinkedFeature(String blenderFilePath, String featureName) {
|
||||||
Map<String, Object> linkedFeatures = this.linkedFeatures.get(blenderFilePath);
|
Map<String, Object> linkedFeatures = this.linkedFeatures.get(blenderFilePath);
|
||||||
return linkedFeatures != null ? linkedFeatures.get(featureName) : null;
|
if(linkedFeatures != null) {
|
||||||
|
String namePrefix = (featureName.charAt(0) + "" + featureName.charAt(1)).toUpperCase();
|
||||||
|
featureName = featureName.substring(2);
|
||||||
|
|
||||||
|
if("SC".equals(namePrefix)) {
|
||||||
|
List<Node> scenes = (List<Node>) linkedFeatures.get("scenes");
|
||||||
|
if(scenes != null) {
|
||||||
|
for(Node scene : scenes) {
|
||||||
|
if(featureName.equals(scene.getName())) {
|
||||||
|
return scene;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if("OB".equals(namePrefix)) {
|
||||||
|
List<Node> features = (List<Node>) linkedFeatures.get("objects");
|
||||||
|
if(features != null) {
|
||||||
|
for(Node feature : features) {
|
||||||
|
if(featureName.equals(feature.getName())) {
|
||||||
|
return feature;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if("ME".equals(namePrefix)) {
|
||||||
|
List<Node> features = (List<Node>) linkedFeatures.get("meshes");
|
||||||
|
if(features != null) {
|
||||||
|
for(Node feature : features) {
|
||||||
|
if(featureName.equals(feature.getName())) {
|
||||||
|
return feature;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if("MA".equals(namePrefix)) {
|
||||||
|
List<MaterialContext> features = (List<MaterialContext>) linkedFeatures.get("materials");
|
||||||
|
if(features != null) {
|
||||||
|
for(MaterialContext feature : features) {
|
||||||
|
if(featureName.equals(feature.getName())) {
|
||||||
|
return feature;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if("TX".equals(namePrefix)) {
|
||||||
|
List<Texture> features = (List<Texture>) linkedFeatures.get("textures");
|
||||||
|
if(features != null) {
|
||||||
|
for(Texture feature : features) {
|
||||||
|
if(featureName.equals(feature.getName())) {
|
||||||
|
return feature;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if("IM".equals(namePrefix)) {
|
||||||
|
List<Texture> features = (List<Texture>) linkedFeatures.get("images");
|
||||||
|
if(features != null) {
|
||||||
|
for(Texture feature : features) {
|
||||||
|
if(featureName.equals(feature.getName())) {
|
||||||
|
return feature;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if("AC".equals(namePrefix)) {
|
||||||
|
List<Animation> features = (List<Animation>) linkedFeatures.get("animations");
|
||||||
|
if(features != null) {
|
||||||
|
for(Animation feature : features) {
|
||||||
|
if(featureName.equals(feature.getName())) {
|
||||||
|
return feature;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if("CA".equals(namePrefix)) {
|
||||||
|
List<Camera> features = (List<Camera>) linkedFeatures.get("cameras");
|
||||||
|
if(features != null) {
|
||||||
|
for(Camera feature : features) {
|
||||||
|
if(featureName.equals(feature.getName())) {
|
||||||
|
return feature;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if("LA".equals(namePrefix)) {
|
||||||
|
List<Light> features = (List<Light>) linkedFeatures.get("lights");
|
||||||
|
if(features != null) {
|
||||||
|
for(Light feature : features) {
|
||||||
|
if(featureName.equals(feature.getName())) {
|
||||||
|
return feature;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if("FI".equals(featureName)) {
|
||||||
|
List<Filter> features = (List<Filter>) linkedFeatures.get("lights");
|
||||||
|
if(features != null) {
|
||||||
|
for(Filter feature : features) {
|
||||||
|
if(featureName.equals(feature.getName())) {
|
||||||
|
return feature;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -659,4 +761,9 @@ public class BlenderContext {
|
|||||||
public static enum LoadedDataType {
|
public static enum LoadedDataType {
|
||||||
STRUCTURE, FEATURE, TEMPORAL_MESH;
|
STRUCTURE, FEATURE, TEMPORAL_MESH;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return blenderKey == null ? "BlenderContext [key = null]" : "BlenderContext [ key = " + blenderKey.toString() + " ]";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -31,6 +31,9 @@
|
|||||||
*/
|
*/
|
||||||
package com.jme3.scene.plugins.blender;
|
package com.jme3.scene.plugins.blender;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
@ -41,9 +44,13 @@ import java.util.logging.Logger;
|
|||||||
|
|
||||||
import com.jme3.animation.Animation;
|
import com.jme3.animation.Animation;
|
||||||
import com.jme3.asset.AssetInfo;
|
import com.jme3.asset.AssetInfo;
|
||||||
|
import com.jme3.asset.AssetKey;
|
||||||
import com.jme3.asset.AssetLoader;
|
import com.jme3.asset.AssetLoader;
|
||||||
|
import com.jme3.asset.AssetLocator;
|
||||||
|
import com.jme3.asset.AssetManager;
|
||||||
import com.jme3.asset.BlenderKey;
|
import com.jme3.asset.BlenderKey;
|
||||||
import com.jme3.asset.ModelKey;
|
import com.jme3.asset.ModelKey;
|
||||||
|
import com.jme3.asset.StreamAssetInfo;
|
||||||
import com.jme3.light.Light;
|
import com.jme3.light.Light;
|
||||||
import com.jme3.math.ColorRGBA;
|
import com.jme3.math.ColorRGBA;
|
||||||
import com.jme3.post.Filter;
|
import com.jme3.post.Filter;
|
||||||
@ -81,22 +88,17 @@ import com.jme3.texture.Texture;
|
|||||||
public class BlenderLoader implements AssetLoader {
|
public class BlenderLoader implements AssetLoader {
|
||||||
private static final Logger LOGGER = Logger.getLogger(BlenderLoader.class.getName());
|
private static final Logger LOGGER = Logger.getLogger(BlenderLoader.class.getName());
|
||||||
|
|
||||||
/** The blocks read from the file. */
|
|
||||||
protected List<FileBlockHeader> blocks;
|
|
||||||
/** The blender context. */
|
|
||||||
protected BlenderContext blenderContext;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Spatial load(AssetInfo assetInfo) throws IOException {
|
public Spatial load(AssetInfo assetInfo) throws IOException {
|
||||||
try {
|
try {
|
||||||
this.setup(assetInfo);
|
BlenderContext blenderContext = this.setup(assetInfo);
|
||||||
|
|
||||||
AnimationHelper animationHelper = blenderContext.getHelper(AnimationHelper.class);
|
AnimationHelper animationHelper = blenderContext.getHelper(AnimationHelper.class);
|
||||||
animationHelper.loadAnimations();
|
animationHelper.loadAnimations();
|
||||||
|
|
||||||
BlenderKey blenderKey = blenderContext.getBlenderKey();
|
BlenderKey blenderKey = blenderContext.getBlenderKey();
|
||||||
LoadedFeatures loadedFeatures = new LoadedFeatures();
|
LoadedFeatures loadedFeatures = new LoadedFeatures();
|
||||||
for (FileBlockHeader block : blocks) {
|
for (FileBlockHeader block : blenderContext.getBlocks()) {
|
||||||
switch (block.getCode()) {
|
switch (block.getCode()) {
|
||||||
case BLOCK_OB00:
|
case BLOCK_OB00:
|
||||||
ObjectHelper objectHelper = blenderContext.getHelper(ObjectHelper.class);
|
ObjectHelper objectHelper = blenderContext.getHelper(ObjectHelper.class);
|
||||||
@ -181,7 +183,7 @@ public class BlenderLoader implements AssetLoader {
|
|||||||
|
|
||||||
LOGGER.fine("Loading scenes and attaching them to the root object.");
|
LOGGER.fine("Loading scenes and attaching them to the root object.");
|
||||||
for (FileBlockHeader sceneBlock : loadedFeatures.sceneBlocks) {
|
for (FileBlockHeader sceneBlock : loadedFeatures.sceneBlocks) {
|
||||||
loadedFeatures.scenes.add(this.toScene(sceneBlock.getStructure(blenderContext)));
|
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.");
|
LOGGER.fine("Creating the root node of the model and applying loaded nodes of the scene and loaded features to it.");
|
||||||
@ -220,7 +222,7 @@ public class BlenderLoader implements AssetLoader {
|
|||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new IOException("Unexpected importer exception occured: " + e.getLocalizedMessage(), e);
|
throw new IOException("Unexpected importer exception occured: " + e.getLocalizedMessage(), e);
|
||||||
} finally {
|
} finally {
|
||||||
this.clear();
|
this.clear(assetInfo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -228,11 +230,12 @@ public class BlenderLoader implements AssetLoader {
|
|||||||
* This method converts the given structure to a scene node.
|
* This method converts the given structure to a scene node.
|
||||||
* @param structure
|
* @param structure
|
||||||
* structure of a scene
|
* structure of a scene
|
||||||
|
* @param blenderContext the blender context
|
||||||
* @return scene's node
|
* @return scene's node
|
||||||
* @throws BlenderFileException
|
* @throws BlenderFileException
|
||||||
* an exception throw when problems with blender file occur
|
* an exception throw when problems with blender file occur
|
||||||
*/
|
*/
|
||||||
private Node toScene(Structure structure) throws BlenderFileException {
|
private Node toScene(Structure structure, BlenderContext blenderContext) throws BlenderFileException {
|
||||||
ObjectHelper objectHelper = blenderContext.getHelper(ObjectHelper.class);
|
ObjectHelper objectHelper = blenderContext.getHelper(ObjectHelper.class);
|
||||||
Node result = new Node(structure.getName());
|
Node result = new Node(structure.getName());
|
||||||
List<Structure> base = ((Structure) structure.getFieldValue("base")).evaluateListBase();
|
List<Structure> base = ((Structure) structure.getFieldValue("base")).evaluateListBase();
|
||||||
@ -265,7 +268,7 @@ public class BlenderLoader implements AssetLoader {
|
|||||||
* @throws BlenderFileException
|
* @throws BlenderFileException
|
||||||
* an exception is throw when something wrong happens with blender file
|
* an exception is throw when something wrong happens with blender file
|
||||||
*/
|
*/
|
||||||
protected void setup(AssetInfo assetInfo) throws BlenderFileException {
|
protected BlenderContext setup(AssetInfo assetInfo) throws BlenderFileException {
|
||||||
// registering loaders
|
// registering loaders
|
||||||
ModelKey modelKey = (ModelKey) assetInfo.getKey();
|
ModelKey modelKey = (ModelKey) assetInfo.getKey();
|
||||||
BlenderKey blenderKey;
|
BlenderKey blenderKey;
|
||||||
@ -273,16 +276,15 @@ public class BlenderLoader implements AssetLoader {
|
|||||||
blenderKey = (BlenderKey) modelKey;
|
blenderKey = (BlenderKey) modelKey;
|
||||||
} else {
|
} else {
|
||||||
blenderKey = new BlenderKey(modelKey.getName());
|
blenderKey = new BlenderKey(modelKey.getName());
|
||||||
blenderKey.setAssetRootPath(modelKey.getFolder());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// opening stream
|
// opening stream
|
||||||
BlenderInputStream inputStream = new BlenderInputStream(assetInfo.openStream());
|
BlenderInputStream inputStream = new BlenderInputStream(assetInfo.openStream());
|
||||||
|
|
||||||
// reading blocks
|
// reading blocks
|
||||||
blocks = new ArrayList<FileBlockHeader>();
|
List<FileBlockHeader> blocks = new ArrayList<FileBlockHeader>();
|
||||||
FileBlockHeader fileBlock;
|
FileBlockHeader fileBlock;
|
||||||
blenderContext = new BlenderContext();
|
BlenderContext blenderContext = new BlenderContext();
|
||||||
blenderContext.setBlenderVersion(inputStream.getVersionNumber());
|
blenderContext.setBlenderVersion(inputStream.getVersionNumber());
|
||||||
blenderContext.setAssetManager(assetInfo.getManager());
|
blenderContext.setAssetManager(assetInfo.getManager());
|
||||||
blenderContext.setInputStream(inputStream);
|
blenderContext.setInputStream(inputStream);
|
||||||
@ -317,15 +319,19 @@ public class BlenderLoader implements AssetLoader {
|
|||||||
if (sceneFileBlock != null) {
|
if (sceneFileBlock != null) {
|
||||||
blenderContext.setSceneStructure(sceneFileBlock.getStructure(blenderContext));
|
blenderContext.setSceneStructure(sceneFileBlock.getStructure(blenderContext));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// adding locator for linked content
|
||||||
|
assetInfo.getManager().registerLocator(assetInfo.getKey().getName(), LinkedContentLocator.class);
|
||||||
|
|
||||||
|
return blenderContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The internal data is only needed during loading so make it unreachable so that the GC can release
|
* The internal data is only needed during loading so make it unreachable so that the GC can release
|
||||||
* that memory (which can be quite large amount).
|
* that memory (which can be quite large amount).
|
||||||
*/
|
*/
|
||||||
protected void clear() {
|
protected void clear(AssetInfo assetInfo) {
|
||||||
blenderContext = null;
|
assetInfo.getManager().unregisterLocator(assetInfo.getKey().getName(), LinkedContentLocator.class);
|
||||||
blocks = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -362,4 +368,50 @@ public class BlenderLoader implements AssetLoader {
|
|||||||
*/
|
*/
|
||||||
private ColorRGBA backgroundColor = ColorRGBA.Gray;
|
private ColorRGBA backgroundColor = ColorRGBA.Gray;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static class LinkedContentLocator implements AssetLocator {
|
||||||
|
private File rootFolder;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setRootPath(String rootPath) {
|
||||||
|
rootFolder = new File(rootPath);
|
||||||
|
if(rootFolder.isFile()) {
|
||||||
|
rootFolder = rootFolder.getParentFile();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("rawtypes")
|
||||||
|
@Override
|
||||||
|
public AssetInfo locate(AssetManager manager, AssetKey key) {
|
||||||
|
if(key instanceof BlenderKey) {
|
||||||
|
File linkedAbsoluteFile = new File(key.getName());
|
||||||
|
if(linkedAbsoluteFile.exists() && linkedAbsoluteFile.isFile()) {
|
||||||
|
try {
|
||||||
|
return new StreamAssetInfo(manager, key, new FileInputStream(linkedAbsoluteFile));
|
||||||
|
} catch (FileNotFoundException e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
File linkedFileInCurrentAssetFolder = new File(rootFolder, linkedAbsoluteFile.getName());
|
||||||
|
if(linkedFileInCurrentAssetFolder.exists() && linkedFileInCurrentAssetFolder.isFile()) {
|
||||||
|
try {
|
||||||
|
return new StreamAssetInfo(manager, key, new FileInputStream(linkedFileInCurrentAssetFolder));
|
||||||
|
} catch (FileNotFoundException e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
File linkedFileInCurrentFolder = new File(".", linkedAbsoluteFile.getName());
|
||||||
|
if(linkedFileInCurrentFolder.exists() && linkedFileInCurrentFolder.isFile()) {
|
||||||
|
try {
|
||||||
|
return new StreamAssetInfo(manager, key, new FileInputStream(linkedFileInCurrentFolder));
|
||||||
|
} catch (FileNotFoundException e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -81,6 +81,7 @@ public class LandscapeHelper extends AbstractBlenderHelper {
|
|||||||
if ((mode & MODE_MIST) != 0) {
|
if ((mode & MODE_MIST) != 0) {
|
||||||
LOGGER.fine("Loading fog.");
|
LOGGER.fine("Loading fog.");
|
||||||
result = new FogFilter();
|
result = new FogFilter();
|
||||||
|
result.setName("FIfog");
|
||||||
result.setFogColor(this.toBackgroundColor(worldStructure));
|
result.setFogColor(this.toBackgroundColor(worldStructure));
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user