package org.ourunix.android.jpct.ball; import java.io.IOException; import java.io.InputStream; import javax.microedition.khronos.egl.EGLConfig; import javax.microedition.khronos.opengles.GL10; import org.ourunix.android.GLSurfaceViewActivity; import org.ourunix.android.R; import org.ourunix.android.RenderBase; import com.threed.jpct.*; import com.threed.jpct.Matrix; import com.threed.jpct.util.BitmapHelper; import com.threed.jpct.util.MemoryHelper; import android.content.Context; import android.content.res.AssetManager; import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.opengl.*; //http://blog.csdn.net/itde1/article/details/754341 //http://www.jpct.net/jpct-ae/doc/index.html //http://blog.csdn.net/wangziling100/article/details/7287803 public class BallCollisionRenderer extends RenderBase{ // FrameBuffer对象 private FrameBuffer fb; // World对象 private World world; // RGBColor //private RGBColor back = null; // Object3D对象 private Object3D plane=null; private Object3D ball1=null; private Object3D ball2=null; private Mesh mesh1 = null; final float TABLE_Y = -39; // SimpleVector // 通过设置组件的x,y,z向量来创建一个SimpleVector对象 ,表示小球的运动方向和速度 private SimpleVector move = new SimpleVector(-4.0, 0.0, 4.0); private boolean fire = true; //是否击球 private boolean collsion=false;//是否发生碰撞 private SimpleVector tem; // FPS private int fps = 0; private long time = System.currentTimeMillis(); // 默认构造 // 对该项目的一些优化 public BallCollisionRenderer(Context context) { super(context); // 传入Resources方法 LoadFile.loadb(context.getResources()); new LoadFile(context.getResources()); // 绘制的最多的Polygon数量,默认为4096,此处如果超过500,则不绘制 Config.maxPolysVisible = 500; // 最远的合适的平面,默认为1000 Config.farPlane = 1500; Config.glTransparencyMul = 0.1f; Config.glTransparencyOffset = 0.1f; // 使JPCT-AE这个引擎使用顶点而不是顶点数组缓冲对象,因为它可能会使某些硬件更快 // 但在Samsung Galaxy,它并不能工作的很好,可能使之崩溃,这就是它默认为false的原因 Config.useVBO = true; //back = new RGBColor(50, 50, 100); Texture.defaultToMipmapping(true); Texture.defaultTo4bpp(true); } public void setFire(boolean fire){ this.fire = fire; } @Override public void onDrawFrame(GL10 gl) { // TODO Auto-generated method stub try { if (true) { move();//实现上下左右键 if(fire){ SimpleVector trsn = ball2.checkForCollisionSpherical(move, 10f); //求出两个球之间距离 SimpleVector length=new SimpleVector(ball1.getTransformedCenter().x-ball2.getTransformedCenter().x, ball1.getTransformedCenter().y-ball2.getTransformedCenter().y,ball1.getTransformedCenter().z-ball2.getTransformedCenter().z); //判断两球之间距离是否小于两球半径之和,若小于,则发生碰撞 if(length.length()<=20+5){ collsion=true;//碰撞发生 } //如果发生碰撞 if(collsion){ //getTranslation :Returns(SimpleVector) the translation of the object (from its origin to its current position) //判断小球是否已经跨越平面了 if(ball2.getTranslation(tem).z<-100||ball1.getTranslation(tem).z>100){ ball1.clearTranslation(); ball2.clearTranslation(); ball1.translate(0, TABLE_Y, 0); ball2.translate(50, TABLE_Y, -50); //ball1.setVisibility(false);//球消失 //ball2.setVisibility(false); fire = false; } else{//小球设置新的运动方向 ball1.translate(new SimpleVector(1,0,3)); ball2.translate(new SimpleVector(-2,0,-2)); } } else{ //或者if(!collsion) //如果没有碰撞 ball2.translate(trsn); } SimpleVector axis=new SimpleVector(1,0,1);//球旋转时轴的方向 ball2.rotateAxis(axis, (float)Math.toRadians(10));//实现球旋转 } // 以定义好的RGBColor清屏 //fb.clear(back); fb.clear(); // 变换和灯光所有的多 边形 world.renderScene(fb); // 绘制由renderScene产生的场景 world.draw(fb); // 渲染显示图像 fb.display(); // fps加1 fps+=1; // 打印输出fps if (System.currentTimeMillis() - time > 1000) { System.out.println(fps + "fps"); fps = 0; time = System.currentTimeMillis(); } } else { if (fb != null) { fb.dispose(); fb = null; } } } catch (Exception e) { e.printStackTrace(); // 打印异常信息 Logger.log("Drawing thread terminated!", Logger.MESSAGE); } } @Override public void onSurfaceChanged(GL10 gl, int width, int height) { // TODO Auto-generated method stub if (fb != null) { fb = null; } // 新产生一个FrameBuffer对象 fb = new FrameBuffer(gl, width, height); } @Override public void onSurfaceCreated(GL10 gl, EGLConfig config) { // TODO Auto-generated method stub Logger.log("onCreate"); // 混合渲染 gl.glEnable(GL10.GL_BLEND); gl.glBlendFunc(GL10.GL_ONE, GL10.GL_ONE_MINUS_SRC_ALPHA); // 新建world对象 world = new World(); // 纹理 TextureManager tm = TextureManager.getInstance(); Texture texture2 = new Texture(LoadFile.bitmap1); Texture texture3 = new Texture(LoadFile.bitmap2); Texture texture4 = new Texture(BitmapHelper.rescale(BitmapHelper.convert(LoadFile.resource.getDrawable(R.drawable.ball01)), 256, 256)); tm.addTexture("texture2", texture2); tm.addTexture("texture3", texture3); tm.addTexture("texture4",texture4); // 初始化各3D元素 plane = Primitives.getPlane(20, 10); // 得到平面 //也可以采用上面得到平面的方法,这里采用的是加载3ds模型 plane=loadModel("table.3ds", 4f); plane.translate(0, -30, 20); plane.rotateX(-(float) Math.PI / 2); // 从jpct-ae的坐标旋转到正常坐标系 plane.rotateY((float)Math.PI/2); ball1 = Primitives.getSphere(10); // 得到球体 ball1.translate(0, -39, 0); ball2=Primitives.getSphere(10); ball2.translate(50, -39, -50); //设置纹理贴图方式 plane.calcTextureWrap(); plane.setTexture("texture2"); ball1.calcTextureWrapSpherical(); ball1.setTexture("texture3"); ball2.calcTextureWrapSpherical(); ball2.setTexture("texture4"); world.addObject(plane); world.addObject(ball1); world.addObject(ball2); //设置碰撞模式 ball1.setCollisionMode(Object3D.COLLISION_CHECK_OTHERS); ball2.setCollisionMode(Object3D.COLLISION_CHECK_SELF); plane.setCollisionMode(Object3D.COLLISION_CHECK_OTHERS); // 设置环境光 world.setAmbientLight(255, 255, 255); //这里设置光照的地方不成功,不能显示光照,不知道为什么???????????? //设置光照 Light light=new Light(world); light.setPosition(new SimpleVector(ball1.getTransformedCenter().x, ball1.getTransformedCenter().y-100,ball1.getTransformedCenter().z-50)); light.setIntensity(255, 0, 0); //以上3段代码没有效果 // 编译所有对象 world.buildAllObjects(); // Camera相关 Camera cam = world.getCamera(); cam.setPositionToCenter(ball1); cam.align(ball1);//将相机方向对着物体的Z轴正方向 //相机绕着X轴旋转20度 cam.rotateCameraX((float) Math.toRadians(20)); cam.moveCamera(Camera.CAMERA_MOVEOUT, 250); // 向外以移动 cam.moveCamera(Camera.CAMERA_MOVEUP, 60); //cam.lookAt(plane.getTransformedCenter()); // 回收内存 MemoryHelper.compact(); } // 载入模型 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; } public void move() { Camera cam=world.getCamera(); if (GLSurfaceViewActivity.up) { // 按向上方向键 cam.moveCamera(cam.getDirection(), -2);//摄像机向里面移动 } if (GLSurfaceViewActivity.down) { cam.moveCamera(cam.getDirection(), 2);//向外移动 } if (GLSurfaceViewActivity.left) { plane.rotateY((float) Math.toRadians(-10));// 向左旋转 } if (GLSurfaceViewActivity.right) { plane.rotateY((float) Math.toRadians(10)); // 向右旋转 } } } //载入文件 class LoadFile { public static Resources resource; public static Bitmap bitmap1; public static Bitmap bitmap2; public static Bitmap bitmap3; public LoadFile(Resources res) { resource = res; } // 载入模型 public static InputStream loadf(String fileName) { AssetManager am = LoadFile.resource.getAssets(); try { return am.open(fileName); } catch (IOException e) { return null; } } // 载入纹理图片 public static void loadb(Resources res) { bitmap1 = BitmapFactory.decodeResource(res, R.raw.table); bitmap2 = BitmapFactory.decodeResource(res, R.raw.bool1); bitmap3=BitmapFactory.decodeResource(res, R.raw.bool2); } }