/*
* Copyright (c) 2009-2012 jMonkeyEngine
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.jme3.asset;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Queue;
import com.jme3.animation.Animation;
import com.jme3.bounding.BoundingVolume;
import com.jme3.collision.Collidable;
import com.jme3.collision.CollisionResults;
import com.jme3.collision.UnsupportedCollisionException;
import com.jme3.export.InputCapsule;
import com.jme3.export.JmeExporter;
import com.jme3.export.JmeImporter;
import com.jme3.export.OutputCapsule;
import com.jme3.material.Material;
import com.jme3.material.RenderState.FaceCullMode;
import com.jme3.math.ColorRGBA;
import com.jme3.post.Filter;
import com.jme3.scene.CameraNode;
import com.jme3.scene.LightNode;
import com.jme3.scene.Node;
import com.jme3.scene.SceneGraphVisitor;
import com.jme3.scene.Spatial;
import com.jme3.texture.Texture;
/**
* Blender key. Contains path of the blender file and its loading properties.
* @author Marcin Roguski (Kaelthas)
*/
public class BlenderKey extends ModelKey {
protected static final int DEFAULT_FPS = 25;
/**
* FramesPerSecond parameter describe how many frames there are in each second. It allows to calculate the time
* between the frames.
*/
protected int fps = DEFAULT_FPS;
/**
* This variable is a bitwise flag of FeatureToLoad interface values; By default everything is being loaded.
*/
protected int featuresToLoad = FeaturesToLoad.ALL;
/** This variable determines if assets that are not linked to the objects should be loaded. */
protected boolean loadUnlinkedAssets;
/** The root path for all the assets. */
protected String assetRootPath;
/** This variable indicate if Y axis is UP axis. If not then Z is up. By default set to true. */
protected boolean fixUpAxis = true;
/** Generated textures resolution (PPU - Pixels Per Unit). */
protected int generatedTexturePPU = 128;
/**
* The name of world settings that the importer will use. If not set or specified name does not occur in the file
* then the first world settings in the file will be used.
*/
protected String usedWorld;
/**
* User's default material that is set fo objects that have no material definition in blender. The default value is
* null. If the value is null the importer will use its own default material (gray color - like in blender).
*/
protected Material defaultMaterial;
/** Face cull mode. By default it is disabled. */
protected FaceCullMode faceCullMode = FaceCullMode.Back;
/**
* Variable describes which layers will be loaded. N-th bit set means N-th layer will be loaded.
* If set to -1 then the current layer will be loaded.
*/
protected int layersToLoad = -1;
/** A variable that toggles the object custom properties loading. */
protected boolean loadObjectProperties = true;
/**
* Maximum texture size. Might be dependant on the graphic card.
* This value is taken from <b>org.lwjgl.opengl.GL11.GL_MAX_TEXTURE_SIZE</b>.
*/
protected int maxTextureSize = 8192;
/** Allows to toggle generated textures loading. Disabled by default because it very often takes too much memory and needs to be used wisely. */
protected boolean loadGeneratedTextures;
/** Tells if the mipmaps will be generated by jme or not. By default generation is dependant on the blender settings. */
protected MipmapGenerationMethod mipmapGenerationMethod = MipmapGenerationMethod.GENERATE_WHEN_NEEDED;
/**
* If the sky has only generated textures applied then they will have the following size (both width and height). If 2d textures are used then the generated
* textures will get their proper size.
*/
protected int skyGeneratedTextureSize = 1000;
/** The radius of a shape that will be used while creating the generated texture for the sky. The higher it is the larger part of the texture will be seen. */
protected float skyGeneratedTextureRadius = 1;
/** The shape against which the generated texture for the sky will be created. */
protected SkyGeneratedTextureShape skyGeneratedTextureShape = SkyGeneratedTextureShape.SPHERE;
/**
* This field tells if the importer should optimise the use of textures or not. If set to true, then textures of the same mapping type will be merged together
* and textures that in the final result will never be visible - will be discarded.
*/
protected boolean optimiseTextures;
/** A map between node name and its animation names. */
protected Map<String, List<String>> nodeAnimationMap = new HashMap<String, List<String>>();
/** A map between node name and its skeleton animation names. */
protected Map<String, List<String>> skeletonAnimationMap = new HashMap<String, List<String>>();
/**
* Constructor used by serialization mechanisms.
*/
public BlenderKey() {
}
/**
* Constructor. Creates a key for the given file name.
* @param name
* the name (path) of a file
*/
public BlenderKey(String name) {
super(name);
}
/**
* This method returns frames per second amount. The default value is BlenderKey.DEFAULT_FPS = 25.
* @return the frames per second amount
*/
public int getFps() {
return fps;
}
/**
* This method sets frames per second amount.
* @param fps
* the frames per second amount
*/
public void setFps(int fps) {
this.fps = fps;
}
/**
* This method returns the face cull mode.
* @return the face cull mode
*/
public FaceCullMode getFaceCullMode() {
return faceCullMode;
}
/**
* This method sets the face cull mode.
* @param faceCullMode
* the face cull mode
*/
public void setFaceCullMode(FaceCullMode faceCullMode) {
this.faceCullMode = faceCullMode;
}
/**
* This method sets layers to be loaded.
* @param layersToLoad
* layers to be loaded
*/
public void setLayersToLoad(int layersToLoad) {
this.layersToLoad = layersToLoad;
}
/**
* This method returns layers to be loaded.
* @return layers to be loaded
*/
public int getLayersToLoad() {
return layersToLoad;
}
/**
* This method sets the properies loading policy.
* By default the value is true.
* @param loadObjectProperties
* true to load properties and false to suspend their loading
*/
public void setLoadObjectProperties(boolean loadObjectProperties) {
this.loadObjectProperties = loadObjectProperties;
}
/**
* @return the current properties loading properties
*/
public boolean isLoadObjectProperties() {
return loadObjectProperties;
}
/**
* The default value for this parameter is the same as defined by: org.lwjgl.opengl.GL11.GL_MAX_TEXTURE_SIZE.
* If by any means this is too large for user's hardware configuration use the 'setMaxTextureSize' method to change that.
* @return maximum texture size (width/height)
*/
public int getMaxTextureSize() {
return maxTextureSize;
}
/**
* This method sets the maximum texture size.
* @param maxTextureSize
* the maximum texture size
*/
public void setMaxTextureSize(int maxTextureSize) {
this.maxTextureSize = maxTextureSize;
}
/**
* This method sets the flag that toggles the generated textures loading.
* @param loadGeneratedTextures
* <b>true</b> if generated textures should be loaded and <b>false</b> otherwise
*/
public void setLoadGeneratedTextures(boolean loadGeneratedTextures) {
this.loadGeneratedTextures = loadGeneratedTextures;
}
/**
* @return tells if the generated textures should be loaded (<b>false</b> is the default value)
*/
public boolean isLoadGeneratedTextures() {
return loadGeneratedTextures;
}
/**
* This method sets the asset root path.
* @param assetRootPath
* the assets root path
*/
public void setAssetRootPath(String assetRootPath) {
this.assetRootPath = assetRootPath;
}
/**
* This method returns the asset root path.
* @return the asset root path
*/
public String getAssetRootPath() {
return assetRootPath;
}
/**
* This method adds features to be loaded.
* @param featuresToLoad
* bitwise flag of FeaturesToLoad interface values
*/
public void includeInLoading(int featuresToLoad) {
this.featuresToLoad |= featuresToLoad;
}
/**
* This method removes features from being loaded.
* @param featuresNotToLoad
* bitwise flag of FeaturesToLoad interface values
*/
public void excludeFromLoading(int featuresNotToLoad) {
featuresToLoad &= ~featuresNotToLoad;
}
public boolean shouldLoad(int featureToLoad) {
return (featuresToLoad & featureToLoad) != 0;
}
/**
* This method returns bitwise value of FeaturesToLoad interface value. It describes features that will be loaded by
* the blender file loader.
* @return features that will be loaded by the blender file loader
*/
public int getFeaturesToLoad() {
return featuresToLoad;
}
/**
* This method determines if unlinked assets should be loaded.
* If not then only objects on selected layers will be loaded and their assets if required.
* If yes then all assets will be loaded even if they are on inactive layers or are not linked
* to anything.
* @return <b>true</b> if unlinked assets should be loaded and <b>false</b> otherwise
*/
public boolean isLoadUnlinkedAssets() {
return loadUnlinkedAssets;
}
/**
* This method sets if unlinked assets should be loaded.
* If not then only objects on selected layers will be loaded and their assets if required.
* If yes then all assets will be loaded even if they are on inactive layers or are not linked
* to anything.
* @param loadUnlinkedAssets
* <b>true</b> if unlinked assets should be loaded and <b>false</b> otherwise
*/
public void setLoadUnlinkedAssets(boolean loadUnlinkedAssets) {
this.loadUnlinkedAssets = loadUnlinkedAssets;
}
/**
* This method creates an object where loading results will be stores. Only those features will be allowed to store
* that were specified by features-to-load flag.
* @return an object to store loading results
*/
public LoadingResults prepareLoadingResults() {
return new LoadingResults(featuresToLoad);
}
/**
* This method sets the fix up axis state. If set to true then Y is up axis. Otherwise the up i Z axis. By default Y
* is up axis.
* @param fixUpAxis
* the up axis state variable
*/
public void setFixUpAxis(boolean fixUpAxis) {
this.fixUpAxis = fixUpAxis;
}
/**
* This method returns the fix up axis state. If set to true then Y is up axis. Otherwise the up i Z axis. By
* default Y is up axis.
* @return the up axis state variable
*/
public boolean isFixUpAxis() {
return fixUpAxis;
}
/**
* This method sets the generated textures resolution.
* @param generatedTexturePPU
* the generated textures resolution
*/
public void setGeneratedTexturePPU(int generatedTexturePPU) {
this.generatedTexturePPU = generatedTexturePPU;
}
/**
* @return the generated textures resolution
*/
public int getGeneratedTexturePPU() {
return generatedTexturePPU;
}
/**
* @return mipmaps generation method
*/
public MipmapGenerationMethod getMipmapGenerationMethod() {
return mipmapGenerationMethod;
}
/**
* @param mipmapGenerationMethod
* mipmaps generation method
*/
public void setMipmapGenerationMethod(MipmapGenerationMethod mipmapGenerationMethod) {
this.mipmapGenerationMethod = mipmapGenerationMethod;
}
/**
* @return the size of the generated textures for the sky (used if no flat textures are applied)
*/
public int getSkyGeneratedTextureSize() {
return skyGeneratedTextureSize;
}
/**
* @param skyGeneratedTextureSize
* the size of the generated textures for the sky (used if no flat textures are applied)
*/
public void setSkyGeneratedTextureSize(int skyGeneratedTextureSize) {
if (skyGeneratedTextureSize <= 0) {
throw new IllegalArgumentException("The texture size must be a positive value (the value given as a parameter: " + skyGeneratedTextureSize + ")!");
}
this.skyGeneratedTextureSize = skyGeneratedTextureSize;
}
/**
* @return the radius of a shape that will be used while creating the generated texture for the sky, the higher it is the larger part of the texture will be seen
*/
public float getSkyGeneratedTextureRadius() {
return skyGeneratedTextureRadius;
}
/**
* @param skyGeneratedTextureRadius
* the radius of a shape that will be used while creating the generated texture for the sky, the higher it is the larger part of the texture will be seen
*/
public void setSkyGeneratedTextureRadius(float skyGeneratedTextureRadius) {
this.skyGeneratedTextureRadius = skyGeneratedTextureRadius;
}
/**
* @return the shape against which the generated texture for the sky will be created (by default it is a sphere).
*/
public SkyGeneratedTextureShape getSkyGeneratedTextureShape() {
return skyGeneratedTextureShape;
}
/**
* @param skyGeneratedTextureShape
* the shape against which the generated texture for the sky will be created
*/
public void setSkyGeneratedTextureShape(SkyGeneratedTextureShape skyGeneratedTextureShape) {
if (skyGeneratedTextureShape == null) {
throw new IllegalArgumentException("The sky generated shape type cannot be null!");
}
this.skyGeneratedTextureShape = skyGeneratedTextureShape;
}
/**
* If set to true, then textures of the same mapping type will be merged together
* and textures that in the final result will never be visible - will be discarded.
* @param optimiseTextures
* the variable that tells if the textures should be optimised or not
*/
public void setOptimiseTextures(boolean optimiseTextures) {
this.optimiseTextures = optimiseTextures;
}
/**
* @return the variable that tells if the textures should be optimised or not (by default the optimisation is disabled)
*/
public boolean isOptimiseTextures() {
return optimiseTextures;
}
/**
* This mehtod sets the name of the WORLD data block taht should be used during file loading. By default the name is
* not set. If no name is set or the given name does not occur in the file - the first WORLD data block will be used
* during loading (assumin any exists in the file).
* @param usedWorld
* the name of the WORLD block used during loading
*/
public void setUsedWorld(String usedWorld) {
this.usedWorld = usedWorld;
}
/**
* This mehtod returns the name of the WORLD data block taht should be used during file loading.
* @return the name of the WORLD block used during loading
*/
public String getUsedWorld() {
return usedWorld;
}
/**
* This method sets the default material for objects.
* @param defaultMaterial
* the default material
*/
public void setDefaultMaterial(Material defaultMaterial) {
this.defaultMaterial = defaultMaterial;
}
/**
* This method returns the default material.
* @return the default material
*/
public Material getDefaultMaterial() {
return defaultMaterial;
}
/**
* Adds spatial animation name for specified node.
* @param nodeName
* the name of the node
* @param animationName
* the spatial animation name
*/
public void addNodeAnimation(String nodeName, String animationName) {
List<String> animations = nodeAnimationMap.get(nodeName);
if (animations == null) {
animations = new ArrayList<String>();
nodeAnimationMap.put(nodeName, animations);
}
animations.add(animationName);
}
/**
* Returns all spatial animation names for the given node.
* @param nodeName
* the name of the node
* @return all spatial animations names or null if none are defined
*/
public List<String> getNodeAnimationNames(String nodeName) {
return nodeAnimationMap.get(nodeName);
}
/**
* Adds bone animation name for specified node.
* @param nodeName
* the name of the node
* @param animationName
* the bone animation name
*/
public void addSkeletonAnimation(String nodeName, String animationName) {
List<String> animations = skeletonAnimationMap.get(nodeName);
if (animations == null) {
animations = new ArrayList<String>();
skeletonAnimationMap.put(nodeName, animations);
}
animations.add(animationName);
}
/**
* Returns all bone animation names for the given node.
* @param nodeName
* the name of the node
* @return all bone animations names or null if none are defined
*/
public List<String> getSkeletonAnimationNames(String nodeName) {
return skeletonAnimationMap.get(nodeName);
}
@Override
public void write(JmeExporter e) throws IOException {
super.write(e);
OutputCapsule oc = e.getCapsule(this);
oc.write(fps, "fps", DEFAULT_FPS);
oc.write(featuresToLoad, "features-to-load", FeaturesToLoad.ALL);
oc.write(loadUnlinkedAssets, "load-unlinked-assets", false);
oc.write(assetRootPath, "asset-root-path", null);
oc.write(fixUpAxis, "fix-up-axis", true);
oc.write(generatedTexturePPU, "generated-texture-ppu", 128);
oc.write(usedWorld, "used-world", null);
oc.write(defaultMaterial, "default-material", null);
oc.write(faceCullMode, "face-cull-mode", FaceCullMode.Off);
oc.write(layersToLoad, "layers-to-load", -1);
oc.write(mipmapGenerationMethod, "mipmap-generation-method", MipmapGenerationMethod.GENERATE_WHEN_NEEDED);
oc.write(skyGeneratedTextureSize, "sky-generated-texture-size", 1000);
oc.write(skyGeneratedTextureRadius, "sky-generated-texture-radius", 1f);
oc.write(skyGeneratedTextureShape, "sky-generated-texture-shape", SkyGeneratedTextureShape.SPHERE);
oc.write(optimiseTextures, "optimise-textures", false);
if (nodeAnimationMap == null) {
oc.write(0, "node-anims-map-size", 0);
} else {
oc.write(nodeAnimationMap.size(), "node-anims-map-size", 0);
int counter = 0;
for (Entry<String, List<String>> entry : nodeAnimationMap.entrySet()) {
oc.write(entry.getKey(), "node-anim-" + counter, null);
oc.write(entry.getValue().toArray(new String[entry.getValue().size()]), "node-anims-" + counter, null);
++counter;
}
}
if (skeletonAnimationMap == null) {
oc.write(0, "skeleton-anims-map-size", 0);
} else {
oc.write(skeletonAnimationMap.size(), "skeleton-anims-map-size", 0);
int counter = 0;
for (Entry<String, List<String>> entry : skeletonAnimationMap.entrySet()) {
oc.write(entry.getKey(), "skeleton-anim-" + counter, null);
oc.write(entry.getValue().toArray(new String[entry.getValue().size()]), "skeleton-anims-" + counter, null);
++counter;
}
}
}
@Override
public void read(JmeImporter e) throws IOException {
super.read(e);
InputCapsule ic = e.getCapsule(this);
fps = ic.readInt("fps", DEFAULT_FPS);
featuresToLoad = ic.readInt("features-to-load", FeaturesToLoad.ALL);
loadUnlinkedAssets = ic.readBoolean("load-unlinked-assets", false);
assetRootPath = ic.readString("asset-root-path", null);
fixUpAxis = ic.readBoolean("fix-up-axis", true);
generatedTexturePPU = ic.readInt("generated-texture-ppu", 128);
usedWorld = ic.readString("used-world", null);
defaultMaterial = (Material) ic.readSavable("default-material", null);
faceCullMode = ic.readEnum("face-cull-mode", FaceCullMode.class, FaceCullMode.Off);
layersToLoad = ic.readInt("layers-to=load", -1);
mipmapGenerationMethod = ic.readEnum("mipmap-generation-method", MipmapGenerationMethod.class, MipmapGenerationMethod.GENERATE_WHEN_NEEDED);
skyGeneratedTextureSize = ic.readInt("sky-generated-texture-size", 1000);
skyGeneratedTextureRadius = ic.readFloat("sky-generated-texture-radius", 1f);
skyGeneratedTextureShape = ic.readEnum("sky-generated-texture-shape", SkyGeneratedTextureShape.class, SkyGeneratedTextureShape.SPHERE);
optimiseTextures = ic.readBoolean("optimise-textures", false);
int animsSize = ic.readInt("node-anims-map-size", 0);
nodeAnimationMap = new HashMap<String, List<String>>(animsSize);
if (animsSize > 0) {
for (int i = 0; i < animsSize; ++i) {
String nodeName = ic.readString("node-anim-" + i, null);
String[] anims = ic.readStringArray("node-anims-" + i, null);
nodeAnimationMap.put(nodeName, new ArrayList<String>(Arrays.asList(anims)));// must create ArrayList because 'asList' method returns unmodifiable list
}
}
animsSize = ic.readInt("skeleton-anims-map-size", 0);
skeletonAnimationMap = new HashMap<String, List<String>>(animsSize);
if (animsSize > 0) {
for (int i = 0; i < animsSize; ++i) {
String nodeName = ic.readString("skeleton-anim-" + i, null);
String[] anims = ic.readStringArray("skeleton-anims-" + i, null);
skeletonAnimationMap.put(nodeName, new ArrayList<String>(Arrays.asList(anims)));// must create ArrayList because 'asList' method returns unmodifiable list
}
}
}
@Override
public int hashCode() {
final int prime = 31;
int result = super.hashCode();
result = prime * result + (assetRootPath == null ? 0 : assetRootPath.hashCode());
result = prime * result + (defaultMaterial == null ? 0 : defaultMaterial.hashCode());
result = prime * result + (faceCullMode == null ? 0 : faceCullMode.hashCode());
result = prime * result + featuresToLoad;
result = prime * result + (fixUpAxis ? 1231 : 1237);
result = prime * result + fps;
result = prime * result + generatedTexturePPU;
result = prime * result + layersToLoad;
result = prime * result + (loadGeneratedTextures ? 1231 : 1237);
result = prime * result + (loadObjectProperties ? 1231 : 1237);
result = prime * result + (loadUnlinkedAssets ? 1231 : 1237);
result = prime * result + maxTextureSize;
result = prime * result + (mipmapGenerationMethod == null ? 0 : mipmapGenerationMethod.hashCode());
result = prime * result + (nodeAnimationMap == null ? 0 : nodeAnimationMap.hashCode());
result = prime * result + (optimiseTextures ? 1231 : 1237);
result = prime * result + (skeletonAnimationMap == null ? 0 : skeletonAnimationMap.hashCode());
result = prime * result + Float.floatToIntBits(skyGeneratedTextureRadius);
result = prime * result + (skyGeneratedTextureShape == null ? 0 : skyGeneratedTextureShape.hashCode());
result = prime * result + skyGeneratedTextureSize;
result = prime * result + (usedWorld == null ? 0 : usedWorld.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (!(obj instanceof BlenderKey)) {
return false;
}
BlenderKey other = (BlenderKey) obj;
if (assetRootPath == null) {
if (other.assetRootPath != null) {
return false;
}
} else if (!assetRootPath.equals(other.assetRootPath)) {
return false;
}
if (defaultMaterial == null) {
if (other.defaultMaterial != null) {
return false;
}
} else if (!defaultMaterial.equals(other.defaultMaterial)) {
return false;
}
if (faceCullMode != other.faceCullMode) {
return false;
}
if (featuresToLoad != other.featuresToLoad) {
return false;
}
if (fixUpAxis != other.fixUpAxis) {
return false;
}
if (fps != other.fps) {
return false;
}
if (generatedTexturePPU != other.generatedTexturePPU) {
return false;
}
if (layersToLoad != other.layersToLoad) {
return false;
}
if (loadGeneratedTextures != other.loadGeneratedTextures) {
return false;
}
if (loadObjectProperties != other.loadObjectProperties) {
return false;
}
if (loadUnlinkedAssets != other.loadUnlinkedAssets) {
return false;
}
if (maxTextureSize != other.maxTextureSize) {
return false;
}
if (mipmapGenerationMethod != other.mipmapGenerationMethod) {
return false;
}
if (nodeAnimationMap == null) {
if (other.nodeAnimationMap != null) {
return false;
}
} else if (!nodeAnimationMap.equals(other.nodeAnimationMap)) {
return false;
}
if (optimiseTextures != other.optimiseTextures) {
return false;
}
if (skeletonAnimationMap == null) {
if (other.skeletonAnimationMap != null) {
return false;
}
} else if (!skeletonAnimationMap.equals(other.skeletonAnimationMap)) {
return false;
}
if (Float.floatToIntBits(skyGeneratedTextureRadius) != Float.floatToIntBits(other.skyGeneratedTextureRadius)) {
return false;
}
if (skyGeneratedTextureShape != other.skyGeneratedTextureShape) {
return false;
}
if (skyGeneratedTextureSize != other.skyGeneratedTextureSize) {
return false;
}
if (usedWorld == null) {
if (other.usedWorld != null) {
return false;
}
} else if (!usedWorld.equals(other.usedWorld)) {
return false;
}
return true;
}
/**
* This enum tells the importer if the mipmaps for textures will be generated by jme. <li>NEVER_GENERATE and ALWAYS_GENERATE are quite understandable <li>GENERATE_WHEN_NEEDED is an option that checks if the texture had 'Generate mipmaps' option set in blender, mipmaps are generated only when the option is set
* @author Marcin Roguski (Kaelthas)
*/
public static enum MipmapGenerationMethod {
NEVER_GENERATE, ALWAYS_GENERATE, GENERATE_WHEN_NEEDED;
}
/**
* This interface describes the features of the scene that are to be loaded.
* @author Marcin Roguski (Kaelthas)
*/
public static interface FeaturesToLoad {
int SCENES = 0x0000FFFF;
int OBJECTS = 0x0000000B;
int ANIMATIONS = 0x00000004;
int MATERIALS = 0x00000003;
int TEXTURES = 0x00000001;
int CAMERAS = 0x00000020;
int LIGHTS = 0x00000010;
int WORLD = 0x00000040;
int ALL = 0xFFFFFFFF;
}
/**
* The shape againts which the sky generated texture will be created.
*
* @author Marcin Roguski (Kaelthas)
*/
public static enum SkyGeneratedTextureShape {
CUBE, SPHERE;
}
/**
* This class holds the loading results according to the given loading flag.
* @author Marcin Roguski (Kaelthas)
*/
public static class LoadingResults extends Spatial {
/** Bitwise mask of features that are to be loaded. */
private final int featuresToLoad;
/** The scenes from the file. */
private List<Node> scenes;
/** Objects from all scenes. */
private List<Node> objects;
/** Materials from all objects. */
private List<Material> materials;
/** Textures from all objects. */
private List<Texture> textures;
/** Animations of all objects. */
private List<Animation> animations;
/** All cameras from the file. */
private List<CameraNode> cameras;
/** All lights from the file. */
private List<LightNode> lights;
/** Loaded sky. */
private Spatial sky;
/** Scene filters (ie. FOG). */
private List<Filter> filters;
/**
* The background color of the render loaded from the horizon color of the world. If no world is used than the gray color
* is set to default (as in blender editor.
*/
private ColorRGBA backgroundColor = ColorRGBA.Gray;
/**
* Private constructor prevents users to create an instance of this class from outside the
* @param featuresToLoad
* bitwise mask of features that are to be loaded
* @see FeaturesToLoad FeaturesToLoad
*/
private LoadingResults(int featuresToLoad) {
this.featuresToLoad = featuresToLoad;
if ((featuresToLoad & FeaturesToLoad.SCENES) != 0) {
scenes = new ArrayList<Node>();
}
if ((featuresToLoad & FeaturesToLoad.OBJECTS) != 0) {
objects = new ArrayList<Node>();
if ((featuresToLoad & FeaturesToLoad.MATERIALS) != 0) {
materials = new ArrayList<Material>();
if ((featuresToLoad & FeaturesToLoad.TEXTURES) != 0) {
textures = new ArrayList<Texture>();
}
}
if ((featuresToLoad & FeaturesToLoad.ANIMATIONS) != 0) {
animations = new ArrayList<Animation>();
}
}
if ((featuresToLoad & FeaturesToLoad.CAMERAS) != 0) {
cameras = new ArrayList<CameraNode>();
}
if ((featuresToLoad & FeaturesToLoad.LIGHTS) != 0) {
lights = new ArrayList<LightNode>();
}
}
/**
* This method returns a bitwise flag describing what features of the blend file will be included in the result.
* @return bitwise mask of features that are to be loaded
* @see FeaturesToLoad FeaturesToLoad
*/
public int getLoadedFeatures() {
return featuresToLoad;
}
/**
* This method adds a scene to the result set.
* @param scene
* scene to be added to the result set
*/
public void addScene(Node scene) {
if (scenes != null) {
scenes.add(scene);
}
}
/**
* This method adds an object to the result set.
* @param object
* object to be added to the result set
*/
public void addObject(Node object) {
if (objects != null) {
objects.add(object);
}
}
/**
* This method adds a material to the result set.
* @param material
* material to be added to the result set
*/
public void addMaterial(Material material) {
if (materials != null) {
materials.add(material);
}
}
/**
* This method adds a texture to the result set.
* @param texture
* texture to be added to the result set
*/
public void addTexture(Texture texture) {
if (textures != null) {
textures.add(texture);
}
}
/**
* This method adds a camera to the result set.
* @param camera
* camera to be added to the result set
*/
public void addCamera(CameraNode camera) {
if (cameras != null) {
cameras.add(camera);
}
}
/**
* This method adds a light to the result set.
* @param light
* light to be added to the result set
*/
public void addLight(LightNode light) {
if (lights != null) {
lights.add(light);
}
}
/**
* This method sets the sky of the scene. Only one sky can be set.
* @param sky
* the sky to be set
*/
public void setSky(Spatial sky) {
this.sky = sky;
}
/**
* This method adds a scene filter. Filters are used to load FOG or other
* scene effects that blender can define.
* @param filter
* the filter to be added
*/
public void addFilter(Filter filter) {
if (filter != null) {
if (filters == null) {
filters = new ArrayList<Filter>(5);
}
filters.add(filter);
}
}
/**
* @param backgroundColor
* the background color
*/
public void setBackgroundColor(ColorRGBA backgroundColor) {
this.backgroundColor = backgroundColor;
}
/**
* @return all loaded scenes
*/
public List<Node> getScenes() {
return scenes;
}
/**
* @return all loaded objects
*/
public List<Node> getObjects() {
return objects;
}
/**
* @return all loaded materials
*/
public List<Material> getMaterials() {
return materials;
}
/**
* @return all loaded textures
*/
public List<Texture> getTextures() {
return textures;
}
/**
* @return all loaded animations
*/
public List<Animation> getAnimations() {
return animations;
}
/**
* @return all loaded cameras
*/
public List<CameraNode> getCameras() {
return cameras;
}
/**
* @return all loaded lights
*/
public List<LightNode> getLights() {
return lights;
}
/**
* @return the scene's sky
*/
public Spatial getSky() {
return sky;
}
/**
* @return scene filters
*/
public List<Filter> getFilters() {
return filters;
}
/**
* @return the background color
*/
public ColorRGBA getBackgroundColor() {
return backgroundColor;
}
@Override
public int collideWith(Collidable other, CollisionResults results) throws UnsupportedCollisionException {
return 0;
}
@Override
public void updateModelBound() {
}
@Override
public void setModelBound(BoundingVolume modelBound) {
}
@Override
public int getVertexCount() {
return 0;
}
@Override
public int getTriangleCount() {
return 0;
}
@Override
public Spatial deepClone() {
return null;
}
@Override
public void depthFirstTraversal(SceneGraphVisitor visitor) {
}
@Override
protected void breadthFirstTraversal(SceneGraphVisitor visitor, Queue<Spatial> queue) {
}
}
}