今天这篇文章将会说明如何利用JPCT-AE框架来实现3DS的载入及为它铺纹理
首先还是说明,它是如此的简单(当然是了解之后),与载入MD2不同的是,如果载入一个3DS文件它是没有动画效果的,所以"android 3D 游戏实现之人物行走(MD2)"中的doAnim()方法在这里就没有了。其它都差不多一样了。
好,下面以实例来说明
(1)LoadModels类就不多说了,如果不明白,可以参看前面所有的Opengl es程序的源代码,在那里你会找到一个满意的答案。
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 LoadModels 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.rock);
}
}
// 载入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.Matrix;
import com.threed.jpct.Object3D;
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;
public class MyRenderer implements Renderer {
// 纹理数组
private String[] textures = { "rock" };
// scale
private int thingScale = 1;
// world对象
private World world;
// FrameBuffer对象
private FrameBuffer fb;
// Object3D
private Object3D thing;
public void onDrawFrame(GL10 gl) {
// 以黑色清除整个屏幕
fb.clear(RGBColor.BLACK);
// 对所有多边形进行变换及灯光操作
world.renderScene(fb);
// 绘制已经由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);
// 循环将已存在Texture以新的名字存入TextureManager中
for (int i = 0; i < textures.length; i++) {
TextureManager.getInstance().addTexture(textures[i],
new Texture(LoadImage.bitmap));
}
thing = loadModel("rock.3ds", thingScale);
// 为Object3D对象设置纹理
thing.setTexture(textures[0]);
// 渲染绘制前进行的操作
thing.build();
// 将thing添加Object3D对象中
world.addObject(thing);
// 调整坐标系
world.getCamera().setPosition(5, 0, -5);
// 在world中应用刚设置好了的坐标系
world.getCamera().lookAt(thing.getTransformedCenter());
}
// 载入模型
private Object3D loadModel(String filename, float scale) {
// 将载入的3ds文件保存到model数组中
Object3D[] model = Loader.load3DS(LoadAssets.loadf(filename), scale);
// 取第一个3ds文件
Object3D o3d = new Object3D(0);
// 临时变量temp
Object3D temp = null;
// 遍历model数组
for (int i = 0; i < model.length; i++) {
// 给temp赋予model数组中的某一个
temp = model[i];
// 设置temp的中心为 origin (0,0,0)
temp.setCenter(SimpleVector.ORIGIN);
// 沿x轴旋转坐标系到正常的坐标系(jpct-ae的坐标中的y,z是反的)
temp.rotateX((float) (-.5 * Math.PI));
// 使用旋转矩阵指定此对象旋转网格的原始数据
temp.rotateMesh();
// new 一个矩阵来作为旋转矩阵
temp.setRotationMatrix(new Matrix());
// 合并o3d与temp
o3d = Object3D.mergeObjects(o3d, temp);
// 主要是为了从桌面版JPCT到android版的移徝(桌面版此处为o3d.build())
o3d.compile();
}
// 返回o3d对象
return o3d;
}
}
运行效果: