使用jPCT-AE加载3D模型

9

我正在尝试在我的应用程序中使用jPCT-AE加载3D模型。我阅读了几篇教程,我认为我理解了基础知识,但是我还没有成功地集成我拥有的3D文件。

我正在利用我在教程中找到的代码片段 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;
        }

}
}

应用程序出现故障,这是我的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)

3D文件在名为“资产”的文件夹中,是一个有效的3DS文件(我已在其他三维引擎上测试过)。

请问您需要帮助吗?

4个回答

9

尝试使用以下内容在 loadModel 方法中构建你的 InputStream:

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

看看是否有任何变化。 这里的Context应用程序上下文,您可以从创建渲染器的Activity中获取:

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

2
我可以确认这个方法是有效的。最初,我看到了一个黑屏,因为我的3ds文件格式太大了(2.9MB)。然后我改用了几千字节范围内的3ds文件,它运行得非常好。感谢您的回答。 - JDS

1

Amrish Kumar的答案几乎正确,但他漏掉了一个重要的括号。

cube=Object3D.mergeAll(Loader.load3DS(getResources().getAssets().open("cubeship.3ds"), 1));

而且你最好能捕捉到任何错误!

所以:

try {
     cube = Object3D.mergeAll(Loader.load3DS(getResources().getAssets().open("cubeship.3ds"), 1));
} catch (IOException e) {
     e.printStackTrace();
}

希望这能帮助到未来的搜索者!

1
cube=Object3D.mergeAll(Loader.load3DS(getResources().getAssets().open("chair.3ds", 5));

使用此行加载3ds文件。以同样的方式,您可以加载jPCT-AE支持的其他文件格式。

0
InputStream stream = new ByteArrayInputStream(filename.getBytes("UTF-8"));

我猜测...你代码中的上述行并没有将文件读入InputStream中,而是仅仅复制了文件名字符串对象的字节数组。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接