如果充分理解了HelloWorld(见android 3D 游戏实现之First step),了解了一些JPCT-AE游戏框架的机制,
那么,这个示例可以是进阶篇了,其实用JPCT-AE加载3DS,MD2文件都很简单了,主要是掌握一些基本的操作,
今天我先把怎么实现加载MD2文件的代码附上,明天我再传上如果实现载入3DS及3DS KeyFrame动画的代码附上。
此程序所需的纹理贴图及MD2文件请从http://download.csdn.net/user/Simdanfeg处下载
下面附上源程序(呵呵,很Cool^_^)
(1)Activity源码
package sim.feel; import java.io.IOException; import java.io.InputStream; import android.app.Activity; import android.content.res.AssetManager; import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.opengl.GLSurfaceView; import android.os.Bundle; public class LoadM extends Activity { private GLSurfaceView glView; private MyRenderer mr; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // 加载图片 LoadImage.loadi(getResources()); // 加载文件 new LoadAssets(getResources()); glView = new GLSurfaceView(this); mr = new MyRenderer(); glView.setRenderer(mr); setContentView(glView); } } // 载入纹理图片 class LoadImage { public static Bitmap bitmap; public static void loadi(Resources res) { bitmap = BitmapFactory.decodeResource(res, R.drawable.disco); } } // 载入Assets文件夹下的文件 class LoadAssets { public static Resources res; public LoadAssets(Resources resources) { res = resources; } public static InputStream loadf(String fileName) { AssetManager am = LoadAssets.res.getAssets(); try { return am.open(fileName, AssetManager.ACCESS_UNKNOWN); } catch (IOException e) { return null; } } }
(2)MyRenderer类代码
package sim.feel; import javax.microedition.khronos.egl.EGLConfig; import javax.microedition.khronos.opengles.GL10; import android.opengl.GLSurfaceView.Renderer; import com.threed.jpct.FrameBuffer; import com.threed.jpct.Loader; import com.threed.jpct.Object3D; import com.threed.jpct.RGBColor; import com.threed.jpct.Texture; import com.threed.jpct.TextureManager; import com.threed.jpct.World; public class MyRenderer implements Renderer { // 纹理数组 private String[] textures = { "disco" }; // scale private float thingScale = 0.8f; // world对象 private World world; // FrameBuffer对象 private FrameBuffer fb; // Object3D private Object3D snork; // 行走动画 private int an = 2; private float ind = 0; /** * 绘制到屏幕上 */ public void onDrawFrame(GL10 gl) { doAnim(); // 以蓝色清除整个屏幕 fb.clear(RGBColor.BLACK); world.renderScene(fb); world.draw(fb); fb.display(); } public void onSurfaceChanged(GL10 gl, int width, int height) { if (fb != null) { fb = null; } fb = new FrameBuffer(gl, width, height); } public void onSurfaceCreated(GL10 gl, EGLConfig arg1) { world = new World(); world.setAmbientLight(150, 150, 150); // 将所有纹理添加到所定义的纹理数组中,此程序只有一个,所以为txtures[0] for (int i = 0; i < textures.length; i++) { TextureManager.getInstance().addTexture(textures[i], new Texture(LoadImage.bitmap)); } // 从assets文件夹中读取snork.md2文件 snork = loadModel("snork.md2", thingScale); // 旋转snork对象到"适当位置" snork.translate(0, -25, -50); // 给snork对象添加名为disco的纹理贴图 snork.setTexture(textures[0]); // 释放部分资源 snork.strip(); // 编译 snork.build(); // 将snork添加到World对象中 world.addObject(snork); world.getCamera().setPosition(0, 0, -100); world.getCamera().lookAt(snork.getTransformedCenter()); } // 载入模型 private Object3D loadModel(String filename, float scale) { Object3D model = Loader.loadMD2(LoadAssets.loadf(filename), scale); return model; } /** * 实现MD2人物行走的关键代码 */ public void doAnim() { //每一帧加0.018f ind += 0.018f; if (ind > 1f) { ind -= 1f; } // 关于此处的两个变量,ind的值为0-1(jpct-ae规定),0表示第一帧,1为最后一帧; //至于an这个变量,它的意思是sub-sequence如果在keyframe(3ds中),因为在一个 //完整的动画包含了seq和sub-sequence,所以设置为2表示执行sub-sequence的动画, //但这里设置为2我就不太明白了,不过如果不填,效果会不自然,所以我就先暂时把它 //设置为2 snork.animate(ind, an); } }