Android之3D物理引擎

來源:互聯網
上載者:User

Android之3D物理引擎


Android下有很多優秀的3D物理引擎,如alien3d,gamine,jpct等,今天,我們介紹如何使用jpct(選這個引擎是因為它的官網上的Demo和ScreenShots很不錯)



1.

在http://www.jpct.net/下載jpct,jpct全部都是用Java寫的,有兩個版本,一個是在案頭OS上啟動並執行(如Windows,Linux等),另一個是在Android上啟動並執行,我們把這兩個都下載下來,我們都會用到。

以下是官網的一些,很不錯:










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

就會彈出一個視窗,如下:




同時控制台輸入如下內容:

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遊戲,按方向鍵,小車會在高低不平的山坡上移動,如下:




下面的是另一個example:fps的:




至此,我們學會了如何編譯Demo,下面是一個小小的補充:如何在Eclipse中編譯:


1.

在Eclipse中建立一個Java project,取名為Demo



2.

將car/src/下的java源檔案全部copy到Demo/src裡去,同時將car/models和car/textures也一同copy到Demo下,完成後的結果如:



3.

右擊Demo,選擇Properties,在Java Build Path的Libaries下,點擊"Add External JARs...",把jpct.jar加入到Project中去,如:




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就可以了,如:




這是一個在不停旋轉的長方體。



其實,我們也可以直接運行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,如下:




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,開啟模擬器,效果如下:




拖動中央的正方體,會朝不同的方向旋轉



至此,第三個實驗完成,快下載到手機裡玩玩吧~~



這三個實驗只是jpct的使用而已,更複雜的東西需要看官網的Wiki和相關文檔




完成!

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.