Update: See this wiki page for up to date info.
Blender importer for jMonkeyEngine 3.
Introduction.
Importing models to any game engine is as much important as using them. The quality of the models depends on the abilities of people who create it and on the tools they use.
Blender is one of the best free tools for creating 3D enviroments. Its high amount of features attract many model designers.
So far jMonkeyEngine used Ogre mesh files to import 3D data. These files were created by the python script that exported data from blender.
It was important to have always the lates version of the script that is compatible with the version of blender and to use it before importing data to jme.
Now we have an opportunity to simplify the import process by loading data directly from blender binary files: .blend.
Usage
To use it in your game you should follow the standard asset loading path.
First register all the locators you need to find the blend file.
[java]
assetManager.registerLocator(āblender/file/pathā, ChosenLocatorClass.class);
[/java]
Then register the blender loader.
You have two loaders available.
1. BlenderLoader that loads the whole scene. It returns an instance of LoadingResults that contains all the data loaded from the scene.
[java]
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<AnimData> animations;
/* All cameras from the file. /
private List<Camera> cameras;
/* All lights from the file. /
private List<Light> lights;
/* Access Methods goes here. */
}
[/java]
2. BlenderModelLoader loads only the model node and should be used if you have a single model in a file.
To register the model do the following:
[java]
assetManager.registerLoader(BlenderLoader.class, āblendā);
[/java]
or
[java]
assetManager.registerLoader(BlenderModelLoader.class, āblendā);
[/java]
The last thing to do is to create a proper key.
You can use com.jme3.asset.BlenderKey for that.
The simplest use is to create the key with the assetās name.
It has many differens settings descibing the blender file more precisely, but all of them have default values so you do not need to worry about it at the beggining.
You can use ModelKey as well. This will give the same result as using default BlenderKey.
How it works?
BlenderLoader (as well as BlenderModelLoader) is looking for all kinds of known assets to load.
Itās primary use is of course to load the models withon the files.
Each blender object is imported as scene Node. The node should have applied textures and materials as well.
If you define animations in your BlenderKey the animations will as well be imported and attached to the model.
Here is the list of how blender features are mapped into jme.
Blender jMonkeyEngine
Scene ā Node
Object ā Node
Mesh ā List (one mesh can have several materials so that is why a list is needed here)
Lamp ā Light
Camera ā Camera
Material ā Material
Texture ā Texture
Curve ā Node (with Curve as its mesh)
Surface ā Node (surface is transformed to the proper mesh)
Using BlenderLoader can allow you to use blend file as your local assets repository.
You can store your textures, materials or meshes there and simply import it when needed.
Currently blender 2.49 and 2.5+ are supported (only the stable versions).
Probably versions before 2.49 will work pretty well too, but I never checked that
Currently supported features.
1. Loading scene (only the current scene is loaded and imported as a node)
2. Loading mesh objects.
Meshes are split into several geometries when they have several materials applied.
All faces are stored as triangles (even if blender uses quads).
The mesh is āSmoothā aware.
User defined UV coordinates are read.
3. Loading textures.
Both image and generated textures are imported.
Textures influence is supported (āInfluenceā tab in blender 2.5+ and āMap toā in 2.49).
Map input is not yet fully supported (currently working on it ) so please use UV-mapping for all kinds of textures.
3.1. Image textures.
Textures can be loaded from: png, jpg, bmp, dds and tga.
Both textures stored in the blender file and the outside are loaded (the outside textures need a valid path).
Image textures are stored as Texture2D.
3.2. Generated textures.
All generated textures can be loaded except: VoxelData, EnviromentMap and PointDensity.
Feel free to use colorbands.
Generated textures are 3D textures.
4. Loading materials.
Materials are loaded and attached to geometries.
Because jMonkeyEngine supports only one material for each Mesh, if you apply several materials to one object ā it will be split into several meshes (but still in one node).
5. Loading animations.
Bone animations are supported for now.
Armatures are imported as Skeleton. Constraint loading is not fully supported so use it carefully.
Only assigning vertices to bones is at the moment supported so do not use bonesā envelopes.
6. Loading modifiers.
Currently the following modifiers are supported:
6.1. Array modifier
6.2. Mirror modifier
6.3. Armature modifier (see loading animations)
6.4. Particles modifier (see loading particles)
More will come with time.
7. Constraints loading
Constraints are basicly supported but they do not work the way Iād like it. So feel free to experiment with it. I will create another post when I get it to work properly.
8. Particles loading.
Some features of particles loading is supported. You can use only particle emitters at the moment.
You can choose to emit particles from vertices, faces or the geometryās convex hull (instead of volume).
Currently Newtonian Physics is only supported.
It was mostly tested for blender 2.49 (so Iām not 100% sure about its use in blender 2.5+).
9. Using sculpting.
This should work quite well for now :).
10. Importing curves.
Both bezier and NURBS curves are supproted.
Feel free to use bevel and taper objects as well
11. Importing surfaces
NURBS surface and sphere can be imported.
Planned features.
1. Full support for texture input mapping (automatic generation of UV-coordinates) (working on that).
2. Support for object animation.
3. Full support for bone and object constraints.
4. More modifiers loaded.
5. Loading texts.
6. Loading meta objects (if jme will support it ).
Known bugs (Iāll fix them when I fix more important stuff ):
1. Blend texture is located in a wrong direction.
2. Blend texture has different colors on borders than expected.
I know that the current version of loader is not yet fully functional, but belive me ā Blender is a very large issue
Hope I will meet your expectations.
Cheers,
Marcin Roguski (Kaelthas)
P.S.
This text might be edited in a meantime if I forgot about something
Great process! ^^
Do you test any animations with blender 2.5 models? Iām not able to load any.
Great work man :). I knew the BlenderImporter supported many features, but not so many so.
The blender loader is registered by default, you donāt need to register it.
Is it possible to get only a list of objects(only names) with their transformations (locations. rotations, scale) or transform matrices.
I want to try using blender as a JME scene composer.
Ok, I try to do it. Guys, how can I get a list of objects in a blend file? LoadingResults in my case equals 0.
I tried to get a list, but I failed:
[java] BlenderKey bk = new BlenderKey(āModels/blender_test_scene/blender_test_scene.blendā);
LoadingResults lr = bk.prepareLoadingResults();
System.out.println(lr.getObjects().size());
Node nd = (Node) assetManager.loadModel(bk);
System.out.println(nd.getChildren().size());[/java]
lr.getObjects().size() equals 0. But āndā loads all blend objects (8 objects in my case).
And nd.getChildren().size() equals 8.
Hi,
sorry I didnāt respond earlier. Iāve been very busy recently.
āprepareLoadingResults()ā only creates an empty instance of the results.
The LoadingResults instance is being filled during loading but you have to register āBlenderLoaderā and not āBlenderModelLoaderā.
Then the returned Spatial from the asset manager will be an instance of LoadingResults class.
And now I think that āprepareLoadingResults()ā should be made private.
It is of no use I belive to developers and can confuse some people as I see
Yahoooo!!! I did a scene composer with blender. Just a small test. We can move, rotate, scale any objects in blender and then load j3o object instances instead of blend objects with blender objects Names and Transforms. Blender can be as a World Builder or a Scene Constructor! Just take any blend file and change the name in a BlenderKey.
@Kaelthas I LOVE YOU!!! I have been waiting that loader about 8 months. You became my dream to reality! That was my vital feature.
The only one thing I donāt know how to make is how to unload BlenderKey and BlenderKeyās Node (nd) from cache?
[java]package basic_examples;
import com.jme3.app.SimpleApplication;
import com.jme3.asset.BlenderKey;
import com.jme3.material.Material;
import com.jme3.math.;
import com.jme3.scene.;
import com.jme3.scene.Node;
import com.jme3.scene.shape.*;
public class blender_scene_composer extends SimpleApplication {
Geometry geom_a;
public static void main(String[] args) {
blender_scene_composer app = new blender_scene_composer();
app.start();
}
@Override
public void simpleInitApp() {
// Create a box Geometry
Box box_a = new Box(Vector3f.ZERO, 1, 1, 1);
geom_a = new Geometry(āBox_Aā, box_a);
geom_a.updateModelBound();
Material mat_a = new Material(assetManager, āCommon/MatDefs/Misc/Unshaded.j3mdā);
mat_a.setColor(ām_Colorā, ColorRGBA.Blue);
geom_a.setMaterial(mat_a);
// Load a blender file
BlenderKey bk = new BlenderKey(āModels/blender_test_scene/blender_test_scene.blendā);
Node nd = (Node) assetManager.loadModel(bk);
//Create empty Nodes
Node [] nds = new Node [nd.getChildren().size()];
Node nd2 = new Node(āndā);
// Get Names and Transforms of Objects from the blend file
for (int i=0; i<nd.getChildren().size(); i++) {
nds = new Node(nd.getChild(i).getName());
nds.setLocalTransform(nd.getChild(i).getLocalTransform());
nd2.attachChild(nds);
System.out.print(nd2.getChild(i).getName());
System.out.println(nd2.getChild(i).getLocalTransform());
}
// Attach boxes with names and transformations of the blend file to a Scene
for (int i=0; i<nd2.getChildren().size(); i++) {
Node ndGet = (Node) nd2.getChild(i);
ndGet.attachChild(geom_a.clone());
}
rootNode.attachChild(nd2);
flyCam.setMoveSpeed(30);
}
}
[/java]
Dude, you could do all that before already and it works wth the model loader too xD ClearCache command on assetmanager also didnāt change.
MAAAANNNN I LOVE YOU TOOO!!!
JME IS THE BEST!!!
You probably gonna explode when I tell you that me and @Kaelthas will extend the blender-jmp bridge to an point where the changes in the blend file are transferred automatically to any created j3o file and that you will be able to use blend files like asset packs in jmp, copying textures, materials and models out of the blend file to the project directly?
:o It is AMAZING!
Will this BRIDGE be in JME 3.0?
With exception for terrain creation, that have to be created in jmp.
@Kaelthas: If I could I would pay you for that work. I think, this is one of the most important jme-projects.
thumbs up^^
glaucomardano said:
With exception for terrain creation, that have to be created in jmp.
As I said, you will be able to create a j3o scene file, add a terrain, add a model from a blend file and when the blend file changes the j3o will be updated.
normen said:
As I said, you will be able to create a j3o scene file, add a terrain, add a model from a blend file and when the blend file changes the j3o will be updated.
Hmmm. So we will be able to edit/sculpt jme terrains in blender too?!....
It's going to be a feature of the beta jmp version?
No, jme terrain is a jme feature ^^
@normen, assetManager does not have ClearCache() method. Only DesktorAssetManager has one. But is it possible to use CleanCache() with asset manager?
Yeah, cast to DesktopAssetManager? ^^
sorry, what is ācastā? o you mean to use DesktopAssetManager?