Android之3D物理引擎


Android下有很多优秀的3D物理引擎,如alien3d,gamine,jpct等,今天,我们介绍如何使用jpct(选这个引擎是因为它的官网上的Demo和ScreenShots很不错)



1.

在http://www.jpct.net/下载jpct,jpct全部都是用Java写的,有两个版本,一个是在桌面OS上运行的(如Windows,Linux等),另一个是在Android上运行的,我们把这两个都下载下来,我们都会用到。

以下是官网的一些截图,很不错:

Android之3D物理引擎_第1张图片


Android之3D物理引擎_第2张图片


Android之3D物理引擎_第3张图片


Android之3D物理引擎_第4张图片



2.

我下载的桌面版是jpctapi.zip,Android版是jpct-ae.zip

分别解压。



下面我们要正式开始了,我们今天要做三个实验,第一个是掌握如何编译jpct的Demo,第二个是如何使用jpct写一个HelloWorld,第三个是jpct写一个在Android上跑的3D程序并下载到真机上运行。前两个实验都用桌面版的jpct,最后一个实验用Android版的jpct下面我们正式开始:



实验一:

打开jpct的example,有四个example,以car为例:

分别运行如下命令:

unzip jpctapi.zip
cd jpct/examples/car

chmod 777 run_java.sh

./run_java.sh

就会弹出一个窗口,如下:

Android之3D物理引擎_第5张图片



同时控制台输入如下内容:

Adding Lightsource: 0Adding Lightsource: 1Adding Lightsource: 2Loading Texture...textures/other/numbers.jpgLoading Texture...textures/rocks.jpgLoading file models/terascene.3dsFile models/terascene.3ds loaded...146731 bytesProcessing new material Material!Processing object from 3DS-file: t3_wholeObject 't3_whole_jPCT0' created using 7200 polygons and 3721 vertices.Loading Texture...textures/spot.jpgCreated 1485 triangle-strips for t3_whole_jPCT0 in 1 pass(es)Loading Texture...textures/spot.jpgLoading Texture...textures/decal.jpgLoading Texture...textures/radar.jpgLoading Texture...textures/plant.jpgLoading Texture...textures/plant2.jpgLoading file models/plant.3dsFile models/plant.3ds loaded...1307 bytesProcessing new material Material!Processing object from 3DS-file: skinObject 'skin_jPCT129' created using 34 polygons and 29 vertices.Loading Texture...textures/skidmark.jpgBuilding octree for 7200 triangles!Octree constructed with 517 nodes / 423 leafs.Java version is: 1.6.0_26-> support for BufferedImageVersion helper for 1.5+ initialized!-> using BufferedImageSoftware renderer (OpenGL mode) initializedSoftware renderer disposedSoftware renderer (OpenGL mode) initialized339-361 -> using splitted buffer access!New WorldProcessor created using 1 thread(s) and granularity of 1!Creating new world processor buffer for thread mainSoftware renderer disposed


这是一个小车3D游戏,按方向键,小车会在高低不平的山坡上移动,如下:

Android之3D物理引擎_第6张图片



下面的截图是另一个example:fps的截图:

Android之3D物理引擎_第7张图片



至此,我们学会了如何编译Demo,下面是一个小小的补充:如何在Eclipse中编译:


1.

在Eclipse中新建一个Java project,取名为Demo



2.

将car/src/下的java源文件全部copy到Demo/src里去,同时将car/models和car/textures也一同copy到Demo下,完成后的结果如下图:

Android之3D物理引擎_第8张图片


3.

右击Demo,选择Properties,在Java Build Path的Libaries下,点击"Add External JARs...",把jpct.jar加入到Project中去,如下图:

Android之3D物理引擎_第9张图片



4.

点击Run As Java Application就可以了,效果和之前的一样。


至此,第一个实验完成!




实验二:

我们要用Eclipse来写一个3D程序,主要的程序就是官网的HelloWorld,官网的Wiki有对它的详细说明:

http://www.jpct.net/wiki/index.php/Hello_World



1.

新建一个HelloWorld的Java Project,和第一步一样,把jpct.jar加入到Libraries中



2.

新建一个HelloWorld类,输入如下内容:

import javax.swing.JFrame;import com.threed.jpct.FrameBuffer;import com.threed.jpct.IRenderer;import com.threed.jpct.Object3D;import com.threed.jpct.Primitives;import com.threed.jpct.Texture;import com.threed.jpct.TextureManager;import com.threed.jpct.World;public class HelloWorld {private World world;private FrameBuffer buffer;private Object3D box;private JFrame frame;public static void main(String[] args) throws Exception {new HelloWorld().loop();}public HelloWorld() throws Exception {frame=new JFrame("Hello world");frame.setSize(800, 600);frame.setVisible(true);frame.setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);world = new World();world.setAmbientLight(0, 255, 0);TextureManager.getInstance().addTexture("box", new Texture("box.jpg"));box = Primitives.getBox(13f, 2f);box.setTexture("box");box.setEnvmapped(Object3D.ENVMAP_ENABLED);box.build();world.addObject(box);world.getCamera().setPosition(50, -50, -5);world.getCamera().lookAt(box.getTransformedCenter());}private void loop() throws Exception {buffer = new FrameBuffer(800, 600, FrameBuffer.SAMPLINGMODE_NORMAL);while (frame.isShowing()) {box.rotateY(0.01f);buffer.clear(java.awt.Color.BLUE);world.renderScene(buffer);world.draw(buffer);buffer.update();buffer.display(frame.getGraphics());Thread.sleep(10);}buffer.disableRenderer(IRenderer.RENDERER_OPENGL);buffer.dispose();frame.dispose();System.exit(0);}}



3.

将examples/helloworld/下的box.jpg拷贝到HelloWorld下,因为我们的程序里用到了它



4.

点击Run As Java Application就可以了,如下图:

Android之3D物理引擎_第10张图片



这是一个在不停旋转的长方体。



其实,我们也可以直接运行Demo的Helloworld:

cd jpct/examples/helloworld

chmod 777 run_software.sh

./run_software.sh



注意,在helloworld下一共有三个不同平台的版本:OpenGL,awtgl和软件模拟的OpenGL,我们的例子用的就是软件模拟的OpenGL(我的机器无法运行OpenGL的版本,很奇怪!),你也可以试试其他版本的,效果是一样的



至此,第二个实验完成,我们用jpct写了一个HelloWorld



第三个实验

我们写一个Android下跑的3D程序:屏幕中央有一个正方体,用手拖动到不同的地方会朝那个地方旋转,这里这样参考了官网的Demo:http://www.jpct.net/wiki/index.php/Hello_World_for_Android



1.

新建一个Demo的Android Project,如下:

Android之3D物理引擎_第11张图片



2.

将jpct-ae.jar加入到Project中(注意,不是jpct.jar)



3.

修改DemoActivity.java如下:

package com.test.demo;import java.lang.reflect.Field;import javax.microedition.khronos.egl.EGL10;import javax.microedition.khronos.egl.EGLConfig;import javax.microedition.khronos.egl.EGLDisplay;import javax.microedition.khronos.opengles.GL10;import android.app.Activity;import android.opengl.GLSurfaceView;import android.os.Bundle;import android.view.MotionEvent;import com.threed.jpct.Camera;import com.threed.jpct.FrameBuffer;import com.threed.jpct.Light;import com.threed.jpct.Logger;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.TextureManager;import com.threed.jpct.World;import com.threed.jpct.util.BitmapHelper;import com.threed.jpct.util.MemoryHelper;public class DemoActivity extends Activity {// Used to handle pause and resume...private static DemoActivity master = null;private GLSurfaceView mGLView;private MyRenderer renderer = null;private FrameBuffer fb = null;private World world = null;private RGBColor back = new RGBColor(50, 50, 100);private float touchTurn = 0;private float touchTurnUp = 0;private float xpos = -1;private float ypos = -1;private Object3D cube = null;private int fps = 0;private Light sun = null;protected void onCreate(Bundle savedInstanceState) {Logger.log("onCreate");if (master != null) {copy(master);}super.onCreate(savedInstanceState);mGLView = new GLSurfaceView(getApplication());mGLView.setEGLConfigChooser(new GLSurfaceView.EGLConfigChooser() {public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display) {// Ensure that we get a 16bit framebuffer. Otherwise, we'll fall// back to Pixelflinger on some device (read: Samsung I7500)int[] attributes = new int[] { EGL10.EGL_DEPTH_SIZE, 16, EGL10.EGL_NONE };EGLConfig[] configs = new EGLConfig[1];int[] result = new int[1];egl.eglChooseConfig(display, attributes, configs, 1, result);return configs[0];}});renderer = new MyRenderer();mGLView.setRenderer(renderer);setContentView(mGLView);}@Overrideprotected void onPause() {super.onPause();mGLView.onPause();}@Overrideprotected void onResume() {super.onResume();mGLView.onResume();}@Overrideprotected void onStop() {super.onStop();}private void copy(Object src) {try {Logger.log("Copying data from master Activity!");Field[] fs = src.getClass().getDeclaredFields();for (Field f : fs) {f.setAccessible(true);f.set(this, f.get(src));}} catch (Exception e) {throw new RuntimeException(e);}}public boolean onTouchEvent(MotionEvent me) {if (me.getAction() == MotionEvent.ACTION_DOWN) {xpos = me.getX();ypos = me.getY();return true;}if (me.getAction() == MotionEvent.ACTION_UP) {xpos = -1;ypos = -1;touchTurn = 0;touchTurnUp = 0;return true;}if (me.getAction() == MotionEvent.ACTION_MOVE) {float xd = me.getX() - xpos;float yd = me.getY() - ypos;xpos = me.getX();ypos = me.getY();touchTurn = xd / -100f;touchTurnUp = yd / -100f;return true;}try {Thread.sleep(15);} catch (Exception e) {// No need for this...}return super.onTouchEvent(me);}protected boolean isFullscreenOpaque() {return true;}class MyRenderer implements GLSurfaceView.Renderer {private long time = System.currentTimeMillis();public MyRenderer() {}public void onSurfaceChanged(GL10 gl, int w, int h) {if (fb != null) {fb.dispose();}fb = new FrameBuffer(gl, w, h);if (master == null) {world = new World();world.setAmbientLight(20, 20, 20);sun = new Light(world);sun.setIntensity(250, 250, 250);// Create a texture out of the icon...:-)Texture texture = new Texture(BitmapHelper.rescale(BitmapHelper.convert(getResources().getDrawable(R.drawable.ic_launcher)), 64, 64));TextureManager.getInstance().addTexture("texture", texture);cube = Primitives.getCube(10);cube.calcTextureWrapSpherical();cube.setTexture("texture");cube.strip();cube.build();world.addObject(cube);Camera cam = world.getCamera();cam.moveCamera(Camera.CAMERA_MOVEOUT, 50);cam.lookAt(cube.getTransformedCenter());SimpleVector sv = new SimpleVector();sv.set(cube.getTransformedCenter());sv.y -= 100;sv.z -= 100;sun.setPosition(sv);MemoryHelper.compact();if (master == null) {Logger.log("Saving master Activity!");master = DemoActivity.this;}}}public void onSurfaceCreated(GL10 gl, EGLConfig config) {}public void onDrawFrame(GL10 gl) {if (touchTurn != 0) {cube.rotateY(touchTurn);touchTurn = 0;}if (touchTurnUp != 0) {cube.rotateX(touchTurnUp);touchTurnUp = 0;}fb.clear(back);world.renderScene(fb);world.draw(fb);fb.display();if (System.currentTimeMillis() - time >= 1000) {Logger.log(fps + "fps");fps = 0;time = System.currentTimeMillis();}fps++;}}}



4.

点击Run As Android Application,打开模拟器,效果如下:

Android之3D物理引擎_第12张图片



拖动中央的正方体,会朝不同的方向旋转



至此,第三个实验完成,快下载到手机里玩玩吧~~



这三个实验只是jpct的使用而已,更复杂的东西需要看官网的Wiki和相关文档




完成!

更多相关文章

  1. Android:设置圆形头像,Android截取圆形图片
  2. (4.1.21.4)Android Handler 异步消息处理机制的妙用 创建强大的图
  3. [转]Android 应用初始化及窗体事件(按键)的分发 [此博文包含图片]
  4. Android复制assets目录下的图片到内存
  5. android处理键盘事件之物理按键 (一)
  6. Android单张图片查看、单指移动、双指缩放、双击最大化或最小化
  7. android 2d物理引擎-Box2d
  8. [Android] 旋转照片/图片
  9. Android 效率开发之图片保存到图库

随机推荐

  1. Centos 安装 android sdk
  2. android shape记录
  3. Android input keyevent
  4. android studio gradle编译时的jar冲突错
  5. android Rokon游戏引擎源码分享
  6. android textview 部分文字加颜色并可点
  7. Android图片圆角 用简单的方法实现
  8. android终端模拟器运行命令可以进行adb c
  9. Android(安卓)高手进阶教程(十三)之----A
  10. Android当导入项目时出现:ERROR: Your pro