Load 3d models with jPCT-AE

Romain picture Romain · Mar 8, 2013 · Viewed 8.4k times · Source

I am trying to load 3d models in my application with jPCT-AE. I read through several tutorials and I think I understand the basics, but I have yet to succeed in integrating the 3d files I have.

I am making use of pieces of codes I found on tutorials package com.example.jpct;

import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Field;

import javax.microedition.khronos.egl.EGL10;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.egl.EGLDisplay;
import javax.microedition.khronos.opengles.GL10;

import android.app.Activity;
import android.content.res.AssetManager;
import android.opengl.GLSurfaceView;
import android.os.Bundle;
import android.view.MotionEvent;

import com.threed.jpct.Camera;
import com.threed.jpct.FrameBuffer;
import com.threed.jpct.Light;
import com.threed.jpct.Loader;
import com.threed.jpct.Logger;
import com.threed.jpct.Object3D;
import com.threed.jpct.Primitives;
import com.threed.jpct.RGBColor;
import com.threed.jpct.SimpleVector;
import com.threed.jpct.Texture;
import com.threed.jpct.TextureManager;
import com.threed.jpct.World;
import com.threed.jpct.util.BitmapHelper;
import com.threed.jpct.util.MemoryHelper;
import java.io.*;


import com.threed.jpct.*;

import android.content.res.Resources;
import android.opengl.GLSurfaceView.EGLConfigChooser;
import android.opengl.GLSurfaceView.Renderer;
import android.util.Log;

 /**
 * A simple demo. This shows more how to use jPCT-AE than it shows how to write
 * a proper application for Android. It includes basic activity management to
 * handle pause and resume...
 * 
 * @author EgonOlsen
 * 
 */
public class MainActivity extends Activity {

// Used to handle pause and resume...
private static MainActivity master = null;

private GLSurfaceView mGLView;
private MyRenderer renderer = null;
private FrameBuffer fb = null;
private World world = null;
private RGBColor back = new RGBColor(50, 50, 100);

private float touchTurn = 0;
private float touchTurnUp = 0;

private float xpos = -1;
private float ypos = -1;

private Object3D cube = null;
private int fps = 0;

private Light sun = null;

AssetManager assMan;
InputStream is;

private String thingName = "palm-realviz";
private int thingScale = 1;//end 


protected void onCreate(Bundle savedInstanceState) {

    Logger.log("onCreate");

    if (master != null) {
        copy(master);
    }

    super.onCreate(savedInstanceState);
    mGLView = new GLSurfaceView(getApplication());

    mGLView.setEGLConfigChooser(new GLSurfaceView.EGLConfigChooser() {
        public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display) {
            // Ensure that we get a 16bit framebuffer. Otherwise, we'll fall
            // back to Pixelflinger on some device (read: Samsung I7500)
            int[] attributes = new int[] { EGL10.EGL_DEPTH_SIZE, 16, EGL10.EGL_NONE };
            EGLConfig[] configs = new EGLConfig[1];
            int[] result = new int[1];
            egl.eglChooseConfig(display, attributes, configs, 1, result);
            return configs[0];
        }
    });

    renderer = new MyRenderer();
    mGLView.setRenderer(renderer);
    setContentView(mGLView);
}

@Override
protected void onPause() {
    super.onPause();
    mGLView.onPause();
}

@Override
protected void onResume() {
    super.onResume();
    mGLView.onResume();
}

@Override
protected void onStop() {
    super.onStop();
}

private void copy(Object src) {
    try {
        Logger.log("Copying data from master Activity!");
        Field[] fs = src.getClass().getDeclaredFields();
        for (Field f : fs) {
            f.setAccessible(true);
            f.set(this, f.get(src));
        }
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
}

public boolean onTouchEvent(MotionEvent me) {

    if (me.getAction() == MotionEvent.ACTION_DOWN) {
        xpos = me.getX();
        ypos = me.getY();
        return true;
    }

    if (me.getAction() == MotionEvent.ACTION_UP) {
        xpos = -1;
        ypos = -1;
        touchTurn = 0;
        touchTurnUp = 0;
        return true;
    }

    if (me.getAction() == MotionEvent.ACTION_MOVE) {
        float xd = me.getX() - xpos;
        float yd = me.getY() - ypos;

        xpos = me.getX();
        ypos = me.getY();

        touchTurn = xd / -100f;
        touchTurnUp = yd / -100f;
        return true;
    }

    try {
        Thread.sleep(15);
    } catch (Exception e) {
        // No need for this...
    }

    return super.onTouchEvent(me);
}

protected boolean isFullscreenOpaque() {
    return true;
}

class MyRenderer implements GLSurfaceView.Renderer {

    private long time = System.currentTimeMillis();

    public MyRenderer() {
    }

    public void onSurfaceChanged(GL10 gl, int w, int h) {
        if (fb != null) {
            fb.dispose();
        }
        fb = new FrameBuffer(gl, w, h);

        if (master == null) {

            world = new World();
            world.setAmbientLight(20, 20, 20);

            sun = new Light(world);
            sun.setIntensity(250, 250, 250);

            // Create a texture out of the icon...:-)
            Texture texture = new Texture(BitmapHelper.rescale(BitmapHelper.convert(getResources().getDrawable(R.drawable.ic_launcher)), 64, 64));
            TextureManager.getInstance().addTexture("texture", texture);


            try {
                cube = loadModel("assets/" + thingName + ".3ds", thingScale);
            } catch (UnsupportedEncodingException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

                    //Primitives.getCube(10);
            //cube.calcTextureWrapSpherical();
            //cube.setTexture("texture");
            //cube.strip();
            cube.build();

            world.addObject(cube);

            Camera cam = world.getCamera();
            cam.moveCamera(Camera.CAMERA_MOVEOUT, 50);
            cam.lookAt(cube.getTransformedCenter());

            SimpleVector sv = new SimpleVector();
            sv.set(cube.getTransformedCenter());
            sv.y -= 100;
            sv.z -= 100;
            sun.setPosition(sv);
            MemoryHelper.compact();

            if (master == null) {
                Logger.log("Saving master Activity!");
                master = MainActivity.this;
            }
        }
    }

    public void onSurfaceCreated(GL10 gl, EGLConfig config) {
    }

    public void onDrawFrame(GL10 gl) {
        if (touchTurn != 0) {
            cube.rotateY(touchTurn);
            touchTurn = 0;
        }

        if (touchTurnUp != 0) {
            cube.rotateX(touchTurnUp);
            touchTurnUp = 0;
        }

        fb.clear(back);
        world.renderScene(fb);
        world.draw(fb);
        fb.display();

        if (System.currentTimeMillis() - time >= 1000) {
            Logger.log(fps + "fps");
            fps = 0;
            time = System.currentTimeMillis();
        }
        fps++;
    }

       private Object3D loadModel(String filename, float scale) throws UnsupportedEncodingException {

           InputStream stream = new ByteArrayInputStream(filename.getBytes("UTF-8"));
            Object3D[] model = Loader.load3DS(stream, scale);
            Object3D o3d = new Object3D(0);
            Object3D temp = null;
            for (int i = 0; i < model.length; i++) {
                temp = model[i];
                temp.setCenter(SimpleVector.ORIGIN);
                temp.rotateX((float)( -.5*Math.PI));
                temp.rotateMesh();
                temp.setRotationMatrix(new Matrix());
                o3d = Object3D.mergeObjects(o3d, temp);
                o3d.build();
            }
            return o3d;
        }

}
}

So the applications fails, here is my logCat

FATAL EXCEPTION: GLThread 93
java.lang.RuntimeException: [ 1363008600568 ] - ERROR: Not a valid 3DS file!
at com.threed.jpct.Logger.log(Logger.java:189)
at com.threed.jpct.Loader.load3DS(Loader.java:1554)
at com.threed.jpct.Loader.load3DS(Loader.java:154)
at com.example.jpct.MainActivity$MyRenderer.loadModel(MainActivity.java:269)
at com.example.jpct.MainActivity$MyRenderer.onSurfaceChanged(MainActivity.java:207)
at android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1505)
at android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1240)

the 3d file is in the "assets" folder, and is a 3ds valid file (I tested it on other 3d engine)

Can you help me please?

Answer

Sam R. picture Sam R. · Mar 13, 2013

Try to construct your InputStream in loadModel method with this instead:

InputStream stream = mContext.getAssets().open("FILENAME.3DS")

And see if it changes anything or not. Here the Context is the Application Context which you can get from the Activity that creates the renderer:

// the "this" refers to your "MainActivity"
Context mContext = this.getApplicationContext();