在J2ME里可以使用M3G(即JSR184)可选包来开发3D应用,大家都知道。而我想把J2ME上开发的3D游戏移植到ANDROID上,如果直接用OpenGL ES,由于它没有M3G中封装好的一些责成的框架和算法,需要自己重新开发的东西比较多,所以想要是能直接在ANDROID中用M3G就好了。
在网上找了一些资料,有一个帖子给出了如下示例代码,由两个文件组成:
M3GTestView.java (作为被显示的View):
package org.vgvp.m3g;
import javax.microedition.khronos.egl.EGL10;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.egl.EGLContext;
import javax.microedition.khronos.egl.EGLDisplay;
import javax.microedition.khronos.egl.EGLSurface;
import javax.microedition.khronos.opengles.GL10;
import javax.microedition.m3g.Appearance;
import javax.microedition.m3g.Camera;
import javax.microedition.m3g.Graphics3D;
import javax.microedition.m3g.Group;
import javax.microedition.m3g.Image2D;
import javax.microedition.m3g.IndexBuffer;
import javax.microedition.m3g.Light;
import javax.microedition.m3g.Mesh;
import javax.microedition.m3g.Texture2D;
import javax.microedition.m3g.TriangleStripArray;
import javax.microedition.m3g.VertexArray;
import javax.microedition.m3g.VertexBuffer;
import javax.microedition.m3g.World;import android.content.Context;
import android.util.Log;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;public class M3GTestView extends SurfaceView  implements SurfaceHolder.Callback{    private final float TOUCH_SCALE_FACTOR=180.0f/320;    protected  SurfaceHolder    mHolder;    protected  RenderThreadX    mRenderThread;    private float mPreviousX=0.0f;    private float mPreviousY=0.0f;    public M3GTestView(Context context){       super(context);       setFocusable(true);         requestFocus();       mHolder = getHolder();    //南京航空航天大学 臧春杰        mHolder.addCallback(this);       mHolder.setType(SurfaceHolder.SURFACE_TYPE_GPU);    }    public void surfaceChanged(SurfaceHolder holder, int format, int width,   int height)    {       Log.d("HelloWorld", "surfaceChanged");    }    public void surfaceCreated(SurfaceHolder holder)    {             mRenderThread = new RenderThreadX(this);       mRenderThread.start();    }    public void surfaceDestroyed(SurfaceHolder holder)    {           boolean retry = true;       while (retry)       {           try {              mRenderThread.join();              retry = false;           } catch (InterruptedException e) {           }       }       mRenderThread.endEGL();    }    public boolean onTouchEvent(MotionEvent e) {        float x = e.getX();        float y = e.getY();        switch (e.getAction()) {            case MotionEvent.ACTION_MOVE:            {                float dx = x - mPreviousX;                 float dy = y - mPreviousY;                 float xAngle=dx*TOUCH_SCALE_FACTOR;                 float yAngle=dy*TOUCH_SCALE_FACTOR;                 mRenderThread.reDrawScene(xAngle,yAngle);            }        }        mPreviousX = x;        mPreviousY = y;            return true;    }}class RenderThreadX extends Thread
{    /** Handle to the surface manager object we interact with */     private SurfaceHolder mSurfaceHolder;     private M3GTestView mView;     private boolean mRun = false;     private EGL10 egl;     private EGLDisplay display;     private EGLSurface surface;     private GL10 gl;         private EGLContext glc;    // JSR184    private World mWorld = null;    private    Camera mCamera;    private Graphics3D mG3d;    private Light mLight;    private Light mLight_Ab;    private Group mAllMesh;    private Image2D[] image2D;    private Texture2D[] texture;  
    public RenderThreadX(M3GTestView view)    {       super();       mView = view;       mSurfaceHolder = mView.mHolder;       mG3d = Graphics3D.getInstance();       mWorld=new World();       mCamera=new Camera();       mLight = new Light();       mLight_Ab = new Light();    }     public void run()     {       initMesh();       initEGL();        DrawScene();        SwapBuffer();     }     private void initMesh(){         int width = mView.getWidth();       int height = mView.getHeight();       float aspect = (float)width/(float)height;       mCamera.setPerspective(60, aspect, 1, 100);       mCamera.setTranslation(0, 0, 10);       mWorld.addChild(mCamera);       mWorld.setActiveCamera(mCamera);       mAllMesh = new Group();       mWorld.addChild(mAllMesh);       Mesh blueMesh = MeshFactory3D.createCube();       Mesh cubeMesh = null;       cubeMesh = (Mesh)blueMesh.duplicate();       mAllMesh.addChild(cubeMesh);        cubeMesh.postRotate(45, 1, 1, 1);      }       private void initEGL(){       egl = (EGL10) EGLContext.getEGL();       display = egl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);       int[] version = new int[2];       egl.eglInitialize(display, version);         int[] configSpec = {              EGL10.EGL_RED_SIZE, 5,              EGL10.EGL_GREEN_SIZE, 6,              EGL10.EGL_BLUE_SIZE, 5,              EGL10.EGL_ALPHA_SIZE, 0,              EGL10.EGL_DEPTH_SIZE, 16,              EGL10.EGL_STENCIL_SIZE, 0,              EGL10.EGL_NONE};             EGLConfig[] configs = new EGLConfig[1];       int[] numConfig = new int[1];       egl.eglChooseConfig(display, configSpec, configs, 1, numConfig);       EGLConfig config = configs[0];           glc = egl.eglCreateContext(display, config,EGL10.EGL_NO_CONTEXT, null);           surface = egl.eglCreateWindowSurface(display, config, mView.getHolder(), null);       egl.eglMakeCurrent(display, surface, surface, glc);       Log.d("EGL", "EGL CONFIG SET END" );       gl = (GL10) (glc.getGL());                           gl.glViewport(0, 0, mView.getWidth(), mView.getHeight());         Log.d("EGL","mView.getWidth() = "+mView.getWidth()+", mView.getHeight() = "+mView.getHeight());       gl.glHint(GL10.GL_POLYGON_SMOOTH_HINT , GL10.GL_NICEST); // anti-alias        }      public void endEGL()    {       Log.d("EGL","endEGL");       // Free OpenGL resources       egl.eglMakeCurrent(display, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_SURFACE,              EGL10.EGL_NO_CONTEXT);       egl.eglDestroySurface(display, surface);       egl.eglDestroyContext(display, glc);       egl.eglTerminate(display);    }    protected void SwapBuffer(){       egl.eglSwapBuffers(display, surface);    }    // RenderScene     public void DrawScene()     {        mG3d.render(mWorld);     }     public void reDrawScene(float xAngel,float yAngel){        mAllMesh.postRotate(xAngel,0.0f,1.0f,0.0f);        mAllMesh.postRotate(yAngel,1.0f,0.0f,0.0f);     }}class MeshFactory3D {      /**       * Constructor has private access because class contains static       * methods exclusively.       */      private MeshFactory3D() {}          public static Mesh createCube() {         VertexBuffer vertexBuffer = new VertexBuffer();         byte[] positions = {         -1, -1,  1,   1, -1,  1,  -1,  1,  1,   1,  1,  1, // front          1, -1, -1,  -1, -1, -1,   1,  1, -1,  -1,  1, -1, // back          1, -1,  1,   1, -1, -1,   1,  1,  1,   1,  1, -1, // right         -1, -1, -1,  -1, -1,  1,  -1,  1, -1,  -1,  1,  1, // left         -1,  1,  1,   1,  1,  1,  -1,  1, -1,   1,  1, -1, // top         -1, -1, -1,   1, -1, -1,  -1, -1,  1,   1, -1,  1  // bottom       };
        VertexArray vertexPositions = new VertexArray(positions.length/3, 3, 1);       vertexPositions.set(0, positions.length/3, positions);
       
       vertexBuffer.setPositions(vertexPositions, 1, null);       int[] triangleLengths = {4, 4, 4, 4, 4, 4};             IndexBuffer triangleInfo=new TriangleStripArray(0,triangleLengths);       return new Mesh(vertexBuffer, triangleInfo,new Appearance());    }}
TestM3G.java (作为主Activity) :
package org.vgvp.m3g;import android.app.Activity;
import android.os.Bundle;public class TestM3G extends Activity { M3GTestView view = null;

@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);

view = new M3GTestView(this);
setContentView(view);
}}
(AndroidManifest.xml略)并且在JAVA Build Path中添加了jsr-184.jar包,可以成功编译生成。但是跟踪执行发现,当程序运行到mG3d = Graphics3D.getInstance();这句时出现运行时错误。用adb logcat输出的相关错误栈信息如下:E/AndroidRuntime( 1716): Uncaught handler: thread main exiting due to uncaught exceptionE/AndroidRuntime( 1716): java.lang.ExceptionInInitializerErrorE/AndroidRuntime( 1716):  at org.vgvp.m3g.RenderThreadX.<init>(M3GTestView.java:192)… …E/AndroidRuntime( 1716): Caused by: java.lang.UnsatisfiedLinkError: cacheFIDE/AndroidRuntime( 1716):  at javax.microedition.m3g.Engine.cacheFID(Native Method)E/AndroidRuntime( 1716):  at javax.microedition.m3g.Graphics3D.<clinit>(Graphics3D.java:791)E/AndroidRuntime( 1716):  ... 26 more有哪位大虾能告诉我这是什么原因?在ANDROID里到底怎么能用上M3G呢?

解决方案 »

  1.   

    ,不是啊,原始范例就是那么写的。它与在J2ME里使用M3G相比,就是多了很少的几句跟OpenGL有关的东西,但是绝大部分都是M3G的
      

  2.   

    我也看不懂这个程序究竟是怎么让M3G和OPENGL关联起来的,但是原帖就是这么写的http://www.wscxy.com/nuaa/article.asp?id=126
      

  3.   

    看了一下,人家说得很清楚“本文假设你已经有JSR184库了。有了接口类了”。JSR184的jar包只是对底层OPENGL进行了JNI接口封装。具体还需要实现库,也就是Android的上的.so文件。要实现M3G到Android上跑,你就得用NDK写一套JSR184的OPENGL实现库。这可是个恐怖而艰巨的任务。
      

  4.   


    原帖作者已经给出的程序源码就是我帖出的这些,只字未提如何实现底层的内容,说明肯定是有现成的库。  你这句话提醒我了,我直接把WTK里的JSR184包放到ANDROID工程的BUILD PATH中肯定不行啊,看来一定有针对ANDROID平台的JSR184包
      

  5.   

    也就是把这个m3g文件导入到Android应用程序中很不容易是吗?
      

  6.   

    其实应该是用OpenGL ES,不可能用M3G的方式