Android3D编程之导入3dsMd2模型

发表于2017-09-12
评论0 3.1k浏览

提要

3d模型的导入是游戏开发中比较基础的部分了,这里通过jpct这个游戏引擎来加载的,实现起来比较简单。


jpct简介

jPCT是一款基于OpenGL技术开发的3D图形引擎(PC环境为标准OpenGL,Android为OpenGL ES), 以Java语言为基础的,拥有功能强大的Java 3D解决方案。该引擎与LGame(此为2D游戏引擎)相类似,目前拥有PC(J2SE)以及Android两个开发版本。

jPCT的最大优势之一,就在于它惊人的向下兼容性。在PC环境中,jPCT甚至可以运行在JVM1.1环境之中,因为jPCT内部提供的图形渲染接口完 全符合所有的Java 1.1规范(就连已经消失的Microsoft VM乃至更古老的Netscape 4 VM也不例外)。

最低运行环境要求为Android 1.5。

去官网 - http://www.jpct.net/可以下载到打包好的jar文件,还有自带的两个demo。

使用jPCT之前最好把两个demo都跑一下,还有常去查看jpct的doc http://www.jpct.net/jpct-ae/doc/

模型的加载都是基于HelloWorld来修改的。


主要用到的对象及方法

Object3D

 表示的是3维物体对象,在渲染的时候,需要添加进World对象。一个Object3D只能被一个world加载依次,调用的方法是 World.addObject() 或者继承式的绑定。

其中有一个 animate(float index)  方法用于md2的关键帧动画。index取值在(0,1),0为第一帧。

Loader

Loader类提供了很多用于加载文件的静态方法,用于加载模型,动作,纹理或者文本。主要用的的方法有:

loadMD2 - 加载md2模型;

load3DS - 加载3DS模型;

loadOBJ - 加载obj模型;


代码实现

首先看MainActivity.java

  1. package com.threed.jpct.example;  
  2.   
  3. import java.lang.reflect.Field;  
  4.   
  5. import javax.microedition.khronos.egl.EGL10;  
  6. import javax.microedition.khronos.egl.EGLConfig;  
  7. import javax.microedition.khronos.egl.EGLDisplay;  
  8. import javax.microedition.khronos.opengles.GL10;  
  9.   
  10. import android.annotation.SuppressLint;  
  11. import android.app.Activity;  
  12. import android.opengl.GLSurfaceView;  
  13. import android.os.Bundle;  
  14. import android.view.MotionEvent;  
  15.   
  16. import com.threed.jpct.Camera;  
  17. import com.threed.jpct.FrameBuffer;  
  18. import com.threed.jpct.Light;  
  19. import com.threed.jpct.Logger;  
  20. import com.threed.jpct.Object3D;  
  21. import com.threed.jpct.Primitives;  
  22. import com.threed.jpct.RGBColor;  
  23. import com.threed.jpct.SimpleVector;  
  24. import com.threed.jpct.Texture;  
  25. import com.threed.jpct.TextureManager;  
  26. import com.threed.jpct.World;  
  27. import com.threed.jpct.util.BitmapHelper;  
  28. import com.threed.jpct.util.MemoryHelper;  
  29.   
  30. /** 
  31.  * A simple demo. This shows more how to use jPCT-AE than it shows how to write 
  32.  * a proper application for Android. It includes basic activity management to 
  33.  * handle pause and resume... 
  34.  *  
  35.  * @author EgonOlsen 
  36.  *  
  37.  */  
  38. public class MainActivity extends Activity {  
  39.   
  40.     // Used to handle pause and resume...  
  41.     private static MainActivity master = null;  
  42.   
  43.     private GLSurfaceView mGLView;  
  44.     private MyRender render = null;  
  45.     private FrameBuffer fb = null;  
  46.     private World world = null;  
  47.     private RGBColor back = new RGBColor(5050100);  
  48.   
  49.     private float touchTurn = 0;  
  50.     private float touchTurnUp = 0;  
  51.   
  52.     private float xpos = -1;  
  53.     private float ypos = -1;  
  54.   
  55.     private Object3D cube = null;  
  56.     private int fps = 0;  
  57.   
  58.     private Light sun = null;  
  59.   
  60.     @SuppressLint("NewApi"protected void onCreate(Bundle savedInstanceState) {  
  61.   
  62.         Logger.log("onCreate");  
  63.   
  64.         if (master != null) {  
  65.             copy(master);  
  66.         }  
  67.   
  68.         super.onCreate(savedInstanceState);  
  69.         mGLView = new GLSurfaceView(getApplication());  
  70.   
  71.         mGLView.setEGLConfigChooser(new GLSurfaceView.EGLConfigChooser() {  
  72.             public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display) {  
  73.                 // Ensure that we get a 16bit framebuffer. Otherwise, we'll fall  
  74.                 // back to Pixelflinger on some device (read: Samsung I7500)  
  75.                 int[] attributes = new int[] { EGL10.EGL_DEPTH_SIZE, 16, EGL10.EGL_NONE };  
  76.                 EGLConfig[] configs = new EGLConfig[1];  
  77.                 int[] result = new int[1];  
  78.                 egl.eglChooseConfig(display, attributes, configs, 1, result);  
  79.                 return configs[0];  
  80.             }  
  81.         });  
  82.   
  83.         render = new MyRender(this);  
  84.         mGLView.setRenderer(render);  
  85.         setContentView(mGLView);  
  86.     }  
  87.   
  88.     @Override  
  89.     protected void onPause() {  
  90.         super.onPause();  
  91.         mGLView.onPause();  
  92.     }  
  93.   
  94.     @Override  
  95.     protected void onResume() {  
  96.         super.onResume();  
  97.         mGLView.onResume();  
  98.     }  
  99.   
  100.     @Override  
  101.     protected void onStop() {  
  102.         super.onStop();  
  103.     }  
  104.   
  105.     private void copy(Object src) {  
  106.         try {  
  107.             Logger.log("Copying data from master Activity!");  
  108.             Field[] fs = src.getClass().getDeclaredFields();  
  109.             for (Field f : fs) {  
  110.                 f.setAccessible(true);  
  111.                 f.set(this, f.get(src));  
  112.             }  
  113.         } catch (Exception e) {  
  114.             throw new RuntimeException(e);  
  115.         }  
  116.     }  
  117.   
  118.     public boolean onTouchEvent(MotionEvent me) {  
  119.   
  120.         if (me.getAction() == MotionEvent.ACTION_DOWN) {  
  121.             xpos = me.getX();  
  122.             ypos = me.getY();  
  123.             return true;  
  124.         }  
  125.   
  126.         if (me.getAction() == MotionEvent.ACTION_UP) {  
  127.             xpos = -1;  
  128.             ypos = -1;  
  129.             touchTurn = 0;  
  130.             touchTurnUp = 0;  
  131.             render.setTouchTurn(0);  
  132.             render.setTouchTurnUp(0);  
  133.             return true;  
  134.         }  
  135.   
  136.         if (me.getAction() == MotionEvent.ACTION_MOVE) {  
  137.             float xd = me.getX() - xpos;  
  138.             float yd = me.getY() - ypos;  
  139.   
  140.             xpos = me.getX();  
  141.             ypos = me.getY();  
  142.   
  143.             touchTurn = xd / -100f;  
  144.             touchTurnUp = yd / -100f;  
  145.             render.setTouchTurn(touchTurn);  
  146.             render.setTouchTurnUp(touchTurnUp);  
  147.             //System.out.println("Move");  
  148.             return true;  
  149.         }  
  150.   
  151.         try {  
  152.             Thread.sleep(15);  
  153.         } catch (Exception e) {  
  154.             // No need for this...  
  155.         }  
  156.   
  157.         return super.onTouchEvent(me);  
  158.     }  
  159.   
  160.       
  161.       
  162. }  

MyRender .java

[java] view plain copy
  1. package com.threed.jpct.example;  
  2. import java.io.IOException;  
  3. import java.io.InputStream;  
  4. import java.nio.ByteBuffer;  
  5. import java.nio.ByteOrder;  
  6. import java.nio.FloatBuffer;  
  7.   
  8. import javax.microedition.khronos.egl.EGLConfig;  
  9. import javax.microedition.khronos.opengles.GL10;  
  10.   
  11. import android.opengl.GLES20;  
  12. import android.opengl.GLSurfaceView;  
  13. import android.util.Log;  
  14.   
  15. import com.threed.jpct.Camera;  
  16. import com.threed.jpct.FrameBuffer;  
  17. import com.threed.jpct.Light;  
  18. import com.threed.jpct.Loader;  
  19. import com.threed.jpct.Logger;  
  20. import com.threed.jpct.Matrix;  
  21. import com.threed.jpct.Object3D;  
  22. import com.threed.jpct.Primitives;  
  23. import com.threed.jpct.RGBColor;  
  24. import com.threed.jpct.SimpleVector;  
  25. import com.threed.jpct.Texture;  
  26. import com.threed.jpct.TextureManager;  
  27. import com.threed.jpct.World;  
  28. import android.annotation.SuppressLint;  
  29. import android.content.Context;  
  30.   
  31. import com.threed.jpct.util.BitmapHelper;  
  32. import com.threed.jpct.util.MemoryHelper;  
  33.   
  34. @SuppressLint("NewApi"public class MyRender  implements GLSurfaceView.Renderer {  
  35.   
  36.     private long time = System.nanoTime();    
  37.     private FrameBuffer fb = null;  
  38.     private Light sun = null;  
  39.     private Object3D cube = null;  
  40.     private World world = null;  
  41.     private int fps = 0;  
  42.     private Object3D rockModel;  
  43.     private Object3D chongLou;  
  44.     private Object3D mdModel;  
  45.     private Context mContext;  
  46.   
  47.     private float touchTurn = 0;  
  48.     private float touchTurnUp = 0;  
  49.       
  50.     // 行走动画    
  51.     private int an = 2;    
  52.     private float ind = 0;    
  53.   
  54.     public MyRender(Context c) {  
  55.         mContext = c;  
  56.     }  
  57.   
  58.     public void onSurfaceChanged(GL10 gl, int w, int h) {  
  59.         if (fb != null) {  
  60.             fb.dispose();  
  61.         }  
  62.         fb = new FrameBuffer(gl, w, h);  
  63.         GLES20.glViewport(00, w, h);  
  64.   
  65.     }  
  66.   
  67.     public void onSurfaceCreated(GL10 gl, EGLConfig config) {   
  68.         gl.glClearColor(0.0f, 0.0f, 0.0f, 0.5f);  
  69.   
  70.         world = new World();  
  71.         world.setAmbientLight(150150150);  
  72.   
  73.   
  74.         Texture texture = new Texture(BitmapHelper.rescale(BitmapHelper.convert(mContext.getResources().getDrawable(R.drawable.rock)), 6464));  
  75.         Texture texture2 = new Texture(BitmapHelper.rescale(BitmapHelper.convert(mContext.getResources().getDrawable(R.drawable.texture2)), 6464));  
  76.         Texture texture3 = new Texture(BitmapHelper.rescale(BitmapHelper.convert(mContext.getResources().getDrawable(R.drawable.snork)), 6464));  
  77.         TextureManager.getInstance().addTexture("texture", texture);  
  78.         TextureManager.getInstance().addTexture("texture2", texture2);  
  79.         TextureManager.getInstance().addTexture("texture3", texture3);  
  80.   
  81.         cube =Primitives.getCube(10);  
  82.         cube.calcTextureWrapSpherical();  
  83.         cube.setTexture("texture");  
  84.         cube.strip();  
  85.         cube.build();   
  86.         rockModel = loadModel("rock.3ds"1);  
  87.         //rockModel.setTexture("texture");  
  88.         rockModel.setTexture("texture");  
  89.         rockModel.strip();  
  90.         rockModel.build();   
  91.         rockModel.translate(050);  
  92.           
  93.         chongLou = loadModel("hu.3ds"1);  
  94.         chongLou.setTexture("texture2");  
  95.         chongLou.strip();  
  96.         chongLou.build();   
  97.   
  98.         mdModel = loadMdModel("snork.md2"0.3f);  
  99.         mdModel.setTexture("texture3");  
  100.         mdModel.strip();  
  101.         mdModel.build();   
  102.         mdModel.translate(-200);   
  103.           
  104.         //System.out.println(mdModel.getAnimationSequence().getName(1));  
  105.   
  106.         world.addObject(rockModel);  
  107.         world.addObject(chongLou);  
  108.         world.addObject(mdModel);  
  109.   
  110.         sun = new Light(world);  
  111.         sun.setIntensity(250250250);  
  112.   
  113.         Camera cam = world.getCamera();  
  114.         cam.moveCamera(Camera.CAMERA_MOVEOUT, 10);  
  115.         cam.lookAt(cube.getTransformedCenter());  
  116.   
  117.         SimpleVector sv = new SimpleVector();  
  118.         sv.set(cube.getTransformedCenter());  
  119.         sv.y -= 100;  
  120.         sv.z -= 100;  
  121.         sun.setPosition(sv);  
  122.         MemoryHelper.compact();  
  123.     }  
  124.   
  125.     public void onDrawFrame(GL10 gl) {  
  126.         // Clears the screen and depth buffer.    
  127.         gl.glClear(GL10.GL_COLOR_BUFFER_BIT | // OpenGL docs.    
  128.                 GL10.GL_DEPTH_BUFFER_BIT);   
  129.         doAnim();    
  130.         fb.clear(RGBColor.BLACK);  
  131.         world.renderScene(fb);  
  132.         world.draw(fb);  
  133.         fb.display();  
  134.   
  135.         if (touchTurn != 0) {  
  136.             rockModel.rotateY(touchTurn);  
  137.             chongLou.rotateY(touchTurn);  
  138.             mdModel.rotateY(touchTurn);  
  139.             touchTurn = 0;  
  140.         }  
  141.   
  142.   
  143.         if (touchTurnUp != 0) {  
  144.             rockModel.rotateX(touchTurnUp);  
  145.             chongLou.rotateX(touchTurnUp);  
  146.             mdModel.rotateX(touchTurnUp);  
  147.             touchTurnUp = 0;  
  148.         }  
  149.   
  150.   
  151.   
  152.         if (System.nanoTime() - time >= 1000000000) {  
  153.             Logger.log(fps   "fps");  
  154.             Log.d("FPSCounter""fps: "   fps);    
  155.   
  156.             //System.out.println(fps "fps");  
  157.             fps = 0;  
  158.             time = System.nanoTime() ;  
  159.         }  
  160.         //  
  161.         fps ;  
  162.     }  
  163.   
  164.   
  165.   
  166.     public static int loadShader(int type, String shaderCode){    
  167.   
  168.         // create a vertex shader type (GLES20.GL_VERTEX_SHADER)    
  169.         // or a fragment shader type (GLES20.GL_FRAGMENT_SHADER)    
  170.         int shader = GLES20.glCreateShader(type);    
  171.   
  172.         // add the source code to the shader and compile it    
  173.         GLES20.glShaderSource(shader, shaderCode);    
  174.         GLES20.glCompileShader(shader);    
  175.   
  176.         return shader;    
  177.     }    
  178.   
  179.     public Object3D loadModel(String filename, float scale){  
  180.         InputStream is = null;  
  181.         try {  
  182.             is =mContext.getAssets().open(filename);  
  183.         } catch (IOException e) {  
  184.             // TODO Auto-generated catch block  
  185.             e.printStackTrace();  
  186.         }  
  187.         Object3D[] model = Loader.load3DS(is, scale);  
  188.         Object3D o3d = new Object3D(0);  
  189.         Object3D temp = null;  
  190.         for (int i = 0; i < model.length; i ) {  
  191.             temp = model[i];  
  192.             temp.setCenter(SimpleVector.ORIGIN);  
  193.             temp.rotateX((float)( -.5*Math.PI));  
  194.             temp.rotateMesh();  
  195.             temp.setRotationMatrix(new Matrix());  
  196.             o3d = Object3D.mergeObjects(o3d, temp);  
  197.             o3d.build();  
  198.         }  
  199.         return o3d;   
  200.     }  
  201.   
  202.     public Object3D loadMdModel(String filename, float scale)  
  203.     {  
  204.         InputStream is = null;  
  205.         try {  
  206.             is =mContext.getAssets().open(filename);  
  207.         } catch (IOException e) {  
  208.             // TODO Auto-generated catch block  
  209.             e.printStackTrace();  
  210.         }  
  211.         Object3D model = Loader.loadMD2(is, scale);    
  212.         return model;    
  213.   
  214.     }  
  215.   
  216.     public void doAnim() {    
  217.         //每一帧加0.018f    
  218.         ind  = 0.018f;    
  219.         if (ind > 1f) {    
  220.         ind -= 1f;  
  221.         }    
  222.         mdModel.animate(ind, an);   
  223.     }  
  224.       
  225.     public void setTouchTurn(float count)  
  226.     {  
  227.         touchTurn = count;  
  228.     }  
  229.   
  230.     public void setTouchTurnUp(float count)  
  231.     {  
  232.         touchTurnUp = count;  
  233.     }  
  234.   
  235. }  


代码还是比较简单 。。。


运行结果:





源码下载(包含模型)

如社区发表内容存在侵权行为,您可以点击这里查看侵权投诉指引