Blend2Java Howto

Dusty Phillips dgp@buchuki.com

This document outlines what needs to be done to create objects in blender that can be exported using Blend2Java, and loaded using Java3D programming. I had a heck of a time figuring everything out, partially from a lack of understanding of blender, partially from knowing less about Java3D than I thought, and partially from not knowing how the script worked. This document is supposed to make things a little easier for you, but it may contain many errors; feel free to experiment.

Set up Blend2Java

The first step is to set up Blend2Java to work with blender. You can load it as a python script using the file menu, or you can add these lines at the top of the file export.py: #!BPY """ Name: 'Blend2Java' Blender: 232 Group: 'Export' """ and put the file in your blender python directory. This can be set in the User Preferences window of blender under the File Paths tab. Set the Python directory, and remember to save your default settings so it always loads from that directory. If you chose to do it this way, Blend2Java should always show up in your export menu.

Create Object

Creating Blend2Java objects is not difficult, provided you know a little Blender. These instructions assume you know a little bit about what you're doing.

The objects must be meshes (spacebar - add - mesh - <your choice>) You can manipulate the meshes and add, remove, extrude, spin, etc the vertices as you wish. You must also ensure that the objects have the proper faces. To create a face, select three or four vertices and press the 'f' key. Any faces created thus will be polygons in the exported geometry. Most of the default meshes have at least one face already, so if you wish to experiment you might want to stick with a default mesh to begin with.

If you wish to move the object, you must move all the vertices in edit mode; it doesn't work to move the object in object mode. You can select all vertices with the 'a' key, and then move them.

Rotation works the same way; you have to rotate all vertices in edit mode. In addition, it seems to be difficult to tell which way the object will be rotated when it is added to the scene. I understand that the positions are not related to the x, y, and z axis in blender, but are related to the position of the object itself. Apparently, the way the object is facing when you add it to blender will be facing the positive Z axis (out) when you add it to the Java 3D scene. For example, whether you are in front, top, or side view, if you add a mesh plane to the blender scene (it faces you when you add it), it will be facing you when you export it. To make things confusing, you can rotate the plane in any direction you like in Object mode (in Blender), and it will still be facing you when you load it in Java 3D. However, if you rotate it in edit mode, it will now be facing the direction you rotate it to. I assume this is related to the fact that vertex positions are calculated locally, and object position calculated externally (if you know Java3D, I would suggest that you imagine the vertex positions as part of the Blender object geometry, and the object position as being a TransformGroup above the object).

The objects must have a material. To do this, switch to the buttons window, and click the "red sphere" button to set up materials. If no material is set, click "add new" to add one.

If you do not wish to use textures, set up the material properties as you wish (adjust colours, shininess, ambient factor, etc). If you create objects with multiple materials, then multiple Shape3Ds will be output. You have to ensure that each material is assigned to full faces, not just to vertices, or the output won't be as expected. I personally find it easier to use a different blender object for each material, just as they would be loaded (as Shape3Ds) in Java3D.

if you wish to use textures, make sure the "TexFace" button is enabled in the Material properties, but don't bother adding a texture linked to the material; it won't work. Textures are added using UV face; this is a multi step process.

In the 3D view, select UV Face Select from the Edit Mode/Object Mode menu. Select all faces using the 'a' key (if faces are selected, then dotted lines show up). You could select only some of the faces, but only one texture will be used for all faces anyway.

Now switch to UV/Image editor mode. Click the Image menu item and open a texture from somewhere in your filesystem. This texture will be applied to the entire object (use separate objects if you want separate textures).

Switch back to the 3D View and select Unwrap UVs from the face menu (or just press the 'U' key). Select a mapping that is suitable to your object. You can change the mapping, so experimenting doesn't hurt.

Now switch back to the UV/Image Editor. You should see the vertices of the 3D mode there; you can move them about on the texture to set the 2 Dimensional texture coordinates of each vertex. It might help to have a split 3D window view open so you know which vertex you are working with.

Export Object

If blend2java is loaded, you should be able to find it in the File-Export menu or Scripts Window. Select this option. The exporter simply writes an XML file (or xml.gz if you want it compressed via gzip) that can be loaded by Java 3D. Click Start Export; if everything is right you won't get any errors. Otherwise, you may have to do some debugging (run blender from a linux console or DOS prompt to see the errors the script is throwing). Common problems include: no material set, some vertices without faces.

If you want to edit the Default directory, you can edit the export.pyscript in a text editor and change the line (around line 395) that sets the DEFAULT_OUT_DIR variable.

If all goes well, you should have a file named after the material(s) and the object in your output directory. The filename will have '.textured' in it if texturing was enabled. If you wanted textures and the name doesn't indicate this, some problems could be: TexFace not enabled in Material, Texture Image not set in UV/Image editor, Texture coordinates not properly mapped.

You can rename the file to anything, as long as it has the .xml extension.

Edit Export

If you are using textures, you may want to edit the file output by blend2java. Find the line that sets the userdata for the object (A search feature in your text editor is a must). You will notice this is where the texture is set. You may want to add a relative or absolute path to some directory where the texture is stored; the script only saves the name of the texture, not the file location.

Another option is to store all textures in the same directory and load them from this directory when you load the textures in Java3D. In this case, you wouldn't need to change anything in the export file, as the filename is already saved.

You could also tweak coordinate and some appearance values while you have the exported object open, but I wouldn't recommend it. It's easier to do this from within blender. ;)

Use Object In Java

Now you are ready to load the object in your Java3D program. This is trivial if you don't use textures, almost trivial if you do.

Your java source code must import the java.beans and java.io packages as well as relevant J3D packages. If you gzipped your files, you will also have to import from java.util.zip.

Create a XMLDecoder referencing a FileInputStream that is connected to the xml file output by Blender. You will have to wrap this in a BufferedInputStream, and if you GZipped it you will have to wrap the FileInputStream in a GZIPInputStream. One of these should do the trick: XMLDecoder de = new XMLDecoder(new BufferedInputStream(new GZIPInputStream( new FileInputStream(filename)))); or: XMLDecoder de = new XMLDecoder(new BufferedInputStream( new FileInputStream(filename))); where filename is a variable containing the path to your .xml file.

Now all you have to do is read a Shape3D from it: Shape3D shape = (Shape3D) de.readObject();

If texturing is not enabled (you can test for this using shape.getUserData()!=null), you are done. If you want to load a texture, you have a bit more work to do.

First get the texture name as a string from the shape's user data: String texname = (String) shape.getUserData();

Add any directory information to the texture name if your program is designed thus, and create a TextureLoader. Create a texture and set the appearance: TextureLoader loader = new TextureLoader(texname, null); ImageComponent2D image = loader.getImage(); Texture2D texture = new Texture2D(Texture.BASE_LEVEL, Texture.RGBA, image.getWidth(), image.getHeight()); texture.setImage(0, image); texture.setEnable(true); Appearance app = retval.getAppearance(); app.setTexture(texture);

You may also want to set TextureAttributes (for example, to use MODULATE mode), and Polygon attributes (disable culling) at this time.

You can now use the shape3D in a scene graph and it will serve you as well as any Shape3D you created in code!