Loading a 3DS file (min3D framework for Android)

NOTE: This OpenGL ES 1.1 framework isn’t maintained anymore. Check out the OpenGL ES 2.0 Rajawali framework which also supports live wallpapers.

Another update to the min3D framework for Android. A new parser that allows you to load in 3DS files (used by the Autodesk 3ds Max 3D modeling, animation and rendering software).

In the previous tutorials (Loading 3D models with the min3D framework for Android and Loading multiple 3D objects from an Obj file (min3D for Android)) there are some basic instructions regarding resource names that apply to this bit of code as well.

Here’s the code (can be found in the Google Code repository as well):


package min3d.sampleProject1;

import min3d.core.Object3dContainer;
import min3d.core.RendererActivity;
import min3d.parser.IParser;
import min3d.parser.Parser;

public class ExampleLoad3DSFile extends RendererActivity {
	private final float CAM_RADIUS_X = 20;
	private final float CAM_RADIUS_Y = 15;
	private final float CAM_RADIUS_Z = 30;
	private final float ROTATION_SPEED = 1;
	private Object3dContainer monster;
	private float degrees;

	@Override
	public void initScene() {
		IParser parser = Parser.createParser(Parser.Type.MAX_3DS,
				getResources(), "min3d.sampleProject1:raw/monster_high");
		parser.parse();

		monster = parser.getParsedObject();
		monster.scale().x = monster.scale().y = monster.scale().z  = .5f;
		monster.position().y = -10;
		scene.addChild(monster);

		scene.camera().target = monster.position();
	}

	@Override
	public void updateScene() {
		float radians = degrees * ((float)Math.PI / 180);

		scene.camera().position.x = (float)Math.cos(radians) * CAM_RADIUS_X;
		scene.camera().position.y = (float)Math.sin(radians) * CAM_RADIUS_Y;
		scene.camera().position.z = (float)Math.sin(radians) * CAM_RADIUS_Z;

		degrees += ROTATION_SPEED;
	}
}

Here’s the result (click the image to see the youtube video):

Loading multiple 3D objects from an Obj file (min3D for Android)

NOTE: This OpenGL ES 1.1 framework isn’t maintained anymore. Check out the OpenGL ES 2.0 Rajawali framework which also supports live wallpapers.

I just committed an update to min3D‘s .obj file parser.  Yesterday’s tutorial showed how you can import an .obj file into min3D.

The latest commit adds support for multiple files in one .obj file. In this example, the car’s body and 4 wheels are separate objects.

This is the RendererActivity code that shows you how to get the separate objects from the parsed file:


package min3d.sampleProject1;

import min3d.core.Object3d;
import min3d.core.Object3dContainer;
import min3d.core.RendererActivity;
import min3d.parser.IParser;
import min3d.parser.Parser;

public class ExampleLoadObjFileMultiple extends RendererActivity {
	private final float MAX_ROTATION = 40;
	private final float MAX_CAM_X = 6f;
	private Object3dContainer car;
	private Object3d tireRR;
	private Object3d tireRF;
	private Object3d tireLR;
	private Object3d tireLF;
	private int rotationDirection;
	private float camDirection;

	@Override
	public void initScene() {
		IParser parser = Parser.createParser(Parser.Type.OBJ,
				getResources(), "min3d.sampleProject1:raw/camaro2_obj");
		parser.parse();

		car = parser.getParsedObject();
		scene.addChild(car);

		tireRR = car.getChildByName("tire_rr");
		tireRF = car.getChildByName("tire_rf");
		tireLR = car.getChildByName("tire_lr");
		tireLF = car.getChildByName("tire_lf");

		tireLF.position().x = -.6f;
		tireLF.position().y = 1.11f;
		tireLF.position().z = .3f;

		tireRF.position().x = .6f;
		tireRF.position().y = 1.11f;
		tireRF.position().z = .3f;

		tireRR.position().x = .6f;
		tireRR.position().y = -1.05f;
		tireRR.position().z = .3f;

		tireLR.position().x = -.6f;
		tireLR.position().y = -1.05f;
		tireLR.position().z = .3f;

		car.rotation().x = -90;
		car.rotation().z = 180;

		scene.camera().position.x = MAX_CAM_X;
		scene.camera().position.z = 3.5f;
		scene.camera().position.y = 3.5f;

		rotationDirection = 1;
		camDirection = -.01f;
	}

	@Override
	public void updateScene() {
		tireRF.rotation().z += rotationDirection;
		tireLF.rotation().z += rotationDirection;

		if(Math.abs(tireRF.rotation().z) >= MAX_ROTATION)
			rotationDirection = -rotationDirection;

		scene.camera().position.x += camDirection;

		if(Math.abs(scene.camera().position.x) >= MAX_CAM_X)
			camDirection = -camDirection;
	}
}

View the result here (click on the image to see the video):

Obj parser for min3D: multiple=

Loading 3D models with the min3D framework for Android

NOTE: This OpenGL ES 1.1 framework isn’t maintained anymore. Check out the OpenGL ES 2.0 Rajawali framework which also supports live wallpapers.

Min3D is a new 3D framework based on OpenGL ES for Android. It’s still in its early stages, but new stuff is getting added rapidly. If you have an Android phone you can download the demo .apk file and install it on your phone.

I started contributing to the framework by writing a parser for .obj files. Almost all 3D programs export to this format, so it was an obvious choice. The first version of this parser has just been committed to Google Code and I still need to add support for a couple of things:

  • multiple objects in one file
  • groups of objects
  • bump map, specular texture map, etc

Here’s an example of how to use the new Obj parser. These are the export option from Blender:

Blender to Obj  exporter options

Blender to Obj exporter options

When you export materials, you can also select “copy images” .

The Obj file should be exported to [your android project]/res/raw. Both the .obj and .mtl files have the same filename and should be renamed so there are no conflicts in the resource manager. It is best to remove the dot between the file name and the extension and replace it with an underscore. Like so:

  • camaro.obj renamed to camaro_obj
  • camaro.mtl renamed to camaro_mtl

Don’t worry about changing the file names in the file itself. The parser will take care of this. Just be sure that there are no paths prefixed to the file name.

The images should be placed in [your android project]/res/drawable. You don’t need to worry about file extensions here. Here’s what the structure looks like for the demo project:

Example project structure

Example project structure

Now all that’s left is adding a few lines of code. It’s as simple as creation a new Activity that is based on min3D’s RenderActivity. The parser code should be added to the initScene() method:


package min3d.sampleProject1;

import min3d.core.Object3dContainer;
import min3d.core.RendererActivity;
import min3d.parser.IParser;
import min3d.parser.Parser;

/**
 * How to load a model from a .obj file
 *
 * @author dennis.ippel
 *
 */
public class ExampleLoadObjFile extends RendererActivity {
	private Object3dContainer objModel;

	@Override
	public void initScene() {
		IParser parser = Parser.createParser(Parser.Type.OBJ,
				getResources(), "min3d.sampleProject1:raw/camaro_obj");
		parser.parse();

		objModel = parser.getParsedObject();
		objModel.scale().x = objModel.scale().y = objModel.scale().z = .7f;
		scene.addChild(objModel);
	}

	@Override
	public void updateScene() {
		objModel.rotation().x++;
		objModel.rotation().z++;
	}
}

The Parser.createParser() method takes two arguments:

  • the parser type (only obj for now)
  • the location of the obj file resource (in “package:type/entry” format)

The rest should be self-explanatory.

This is what the result looks like for the example project:

Example min3D Obj parser output

Example min3D Obj parser output