效果比5月份那份代码和谐了一点,但仍有待改进,现在我将代码发上来。
完整项目可以去http://simdanfeg.download.csdn.net/处下载
(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; import android.view.Window; import android.view.WindowManager; public class AdvancedExample extends Activity { // GLSurfaceView private GLSurfaceView glView; // 实例化MyRenderer对象 private MyRenderer mr = new MyRenderer(); @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // 设置无标题 requestWindowFeature(Window.FEATURE_NO_TITLE); // 设置全屏 getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); // init loadFile new LoadFile(getResources()); glView = new GLSurfaceView(this); glView.setRenderer(mr); setContentView(glView); } } // 载入文件 class LoadFile { public static Resources resource; public LoadFile(Resources res) { resource = res; } // file public static InputStream loadf(String fileName) { AssetManager am = LoadFile.resource.getAssets(); try { return am.open(fileName); } catch (IOException e) { return null; } } // image public static Bitmap loadi(int id) { Bitmap bitmap = BitmapFactory.decodeResource(resource, id); return bitmap; } }
(2)Renderer类
package sim.feel; import javax.microedition.khronos.egl.EGLConfig; import javax.microedition.khronos.opengles.GL10; import android.graphics.Bitmap; import android.opengl.GLSurfaceView.Renderer; import com.threed.jpct.Camera; import com.threed.jpct.Config; import com.threed.jpct.FrameBuffer; import com.threed.jpct.GenericVertexController; import com.threed.jpct.Light; import com.threed.jpct.Loader; import com.threed.jpct.Matrix; import com.threed.jpct.Mesh; 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.TextureInfo; import com.threed.jpct.TextureManager; import com.threed.jpct.World; import com.threed.jpct.util.MemoryHelper; /** * 一个包含3ds,md2导入及纹理等的综合例子 * * @author Simdanfeg * */ public class MyRenderer implements Renderer { // 圆周率 private static float PI = (float) Math.PI; // FrameBuffer private FrameBuffer fb = null; // World对象 private World world = null; // Object3D对象,分别为平面,人物,岩石,天空 private Object3D plane = null; private Object3D snork = null; private Object3D rock = null; private Object3D dome = null; // Light对象 private Light sun = null; // ind private float ind = 0; // FPS private int fps = 0; // 返回当前毫秒数 private long time = System.currentTimeMillis(); // Bitmap对象 private Bitmap igrass = null; private Bitmap idisco = null; private Bitmap irock = null; private Bitmap inormals = null; private Bitmap isky = null; // TextureManager对象 private TextureManager tm = null; // 默认构造 public MyRenderer() { // 优化操作 Config.maxPolysVisible = 1000; Config.farPlane = 1500; Config.glTransparencyMul = 0.1f; Config.glTransparencyOffset = 0.1f; Config.useVBO = true; Texture.defaultToMipmapping(true); Texture.defaultTo4bpp(true); } // 将载入的图片添加到TextureManager中 public void loadTexture() { igrass = LoadFile.loadi(R.drawable.grasssample2); idisco = LoadFile.loadi(R.drawable.disco); irock = LoadFile.loadi(R.drawable.rock); inormals = LoadFile.loadi(R.drawable.normals); isky = LoadFile.loadi(R.drawable.sky); // TextureManager tm = TextureManager.getInstance(); tm.addTexture("grass", new Texture(igrass)); tm.addTexture("disco", new Texture(idisco)); tm.addTexture("rock", new Texture(irock)); tm.addTexture("normals", new Texture(inormals)); tm.addTexture("sky", new Texture(isky)); } public void onDrawFrame(GL10 gl) { SimpleVector offset = new SimpleVector(1, 0, -1).normalize(); // animate the snork and the dome animate(); offset.rotateY(0.007f); // render the scene fb.clear(); world.renderScene(fb); world.draw(fb); fb.display(); // print out the fps to the console if (System.currentTimeMillis() - time >= 1000) { System.out.println(fps); fps = 0; time = System.currentTimeMillis(); } fps++; } 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 height) { // 启用混合 gl.glEnable(GL10.GL_BLEND); gl.glBlendFunc(GL10.GL_ONE, GL10.GL_ONE_MINUS_SRC_ALPHA); // Load textures loadTexture(); // World world = new World(); // 设置world环境光 world.setAmbientLight(120, 120, 120); // Load/create and setup objects // 平面(草地) plane = Primitives.getPlane(20, 15); plane.rotateX(PI / 2); plane.setSpecularLighting(true); // 设置纹理 plane.setTexture("grass"); plane.setCollisionMode(Object3D.COLLISION_CHECK_OTHERS); // plane.forceGeometryIndices(true); // 岩石 rock = loadModel("rock.3ds", 15f); rock.translate(0, 0, -90); rock.rotateX(-PI / 2); // 设置双重纹理 TextureInfo stoneTex = new TextureInfo(tm.getTextureID("rock")); stoneTex.add(tm.getTextureID("normals"), TextureInfo.MODE_MODULATE); rock.setTexture(stoneTex); rock.setSpecularLighting(true); // 人物 snork = Loader.loadMD2(LoadFile.loadf("snork.md2"), 0.8f); snork.translate(0, -25, -50); snork.rotateY(45); snork.setTexture("disco"); // 设置碰撞模式 snork.setCollisionMode(Object3D.COLLISION_CHECK_SELF); // 天空 dome = loadModel("dome.3ds", 0.5f); dome.build(); dome.setTexture("sky"); dome.calcTextureWrap(); // 优化,但有用此方法显示有问题 // tileTexture(dome, 3); // 计算plane与dome的差矢量 dome.translate(plane.getTransformedCenter().calcSub( dome.getTransformedCenter())); dome.setLighting(Object3D.LIGHTING_NO_LIGHTS); // dome.forceGeometryIndices(true); dome.setAdditionalColor(RGBColor.WHITE); // 将Object3d传入到World对象中 world.addObject(plane); world.addObject(rock); world.addObject(snork); world.addObject(dome); // 编译world中所有对象 world.buildAllObjects(); // Compile all objects for better performance plane.compile(); rock.compile(); dome.compile(); plane.strip(); rock.strip(); dome.strip(); // 变形plane,这太有意思了,我喜欢 // Deform the plane Mesh planeMesh = plane.getMesh(); planeMesh.setVertexController(new Mod(), false); planeMesh.applyVertexController(); planeMesh.removeVertexController(); // Move camera Camera cam = world.getCamera(); cam.moveCamera(Camera.CAMERA_MOVEOUT, 150); cam.moveCamera(Camera.CAMERA_MOVEUP, 100); cam.lookAt(plane.getTransformedCenter()); cam.setFOV(1.5f); // Setup dynamic light source sun = new Light(world); sun.setIntensity(250, 250, 250); // 回收内存 MemoryHelper.compact(); } /* * 动画 */ private void animate() { ind += 0.1f; if (ind > 1) { ind -= 1; } snork.animate(ind, 2); snork.rotateY(-0.02f); snork.translate(0, -50, 0); SimpleVector dir = snork.getXAxis(); dir = snork.checkForCollisionEllipsoid(dir, new SimpleVector(5, 20, 5), 5); snork.translate(dir); dir = snork.checkForCollisionEllipsoid(new SimpleVector(0, 100, 0), new SimpleVector(5, 20, 5), 1); snork.translate(dir); } // 载入模型 private Object3D loadModel(String filename, float scale) { // 将载入的3ds文件保存到model数组中 Object3D[] model = Loader.load3DS(LoadFile.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,x是反的) 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; } // static class Mod public static class Mod extends GenericVertexController { private static final long serialVersionUID = 1L; public void apply() { // 返回未修改前plane的Mesh信息 SimpleVector[] s = getSourceMesh(); // 定义SimpleVector得到DestinationMesh SimpleVector[] d = getDestinationMesh(); // 变形主要操作 for (int i = 0; i < s.length; i++) { d[i].z = s[i].z - (10f * ((float) Math.sin(s[i].x / 50f) + (float) Math .cos(s[i].y / 50f))); d[i].x = s[i].x; d[i].y = s[i].y; } } } }
效果图