您的位置:首页 > 移动开发 > Android开发

Android高级进阶十一 Android OpenGL建立3D空间

2012-02-01 13:01 225 查看
最新版本:Android高级进阶十一
Android OpenGL建立3D空间

这一篇文章继续写在Android上使用OpenGL,前阶段的文章一直是旨在建立一个3D的形状,这一篇文章我们就来建立一个3D的空间模型。

老规矩先上效果图:



这次我们使用一个文件来存储我们所有顶点及纹理定点数据,具体使用方式待会儿见分晓。

代码如下:

WordActivity.java

Java代码

package org.ourunix.android.world;

import android.app.Activity;

import android.opengl.GLSurfaceView;

import android.os.Bundle;

import android.view.KeyEvent;

public class WordActivity extends Activity {

/** Called when the activity is first created. */

GLRenderer render;

@Override

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

GLSurfaceView glView = new GLSurfaceView(this);

render = new GLRenderer(this);

glView.setRenderer(render);

setContentView(glView);

}

@Override

public boolean onKeyUp(int keyCode, KeyEvent event) {

// TODO Auto-generated method stub

return render.onKeyUp(keyCode, event);

}

}

ScData.java

Java代码

package org.ourunix.android.world;

import java.util.ArrayList;

import java.util.List;

public class ScData {

public static class VERTEX{

float x, y, z; //三角形的顶点坐标

float u, v;//纹理坐标

public VERTEX(float x, float y , float z, float u, float v){

this.x = x;

this.y = y;

this.z = z;

this.u = u;

this.v = v;

}

}

//三角形结构

public static class TRIANGLE{

VERTEX[] vertex = new VERTEX[3];

}

//区段结构

public static class SECTOR{

int numTriangles;

List<TRIANGLE> triangle = new ArrayList<TRIANGLE>();

}

}

GLRenderer.java

Java代码

package org.ourunix.android.world;

import java.io.BufferedReader;

import java.io.IOException;

import java.io.InputStream;

import java.io.InputStreamReader;

import java.nio.FloatBuffer;

import java.nio.IntBuffer;

import javax.microedition.khronos.egl.EGLConfig;

import javax.microedition.khronos.opengles.GL10;

import org.ourunix.android.world.ScData.SECTOR;

import org.ourunix.android.world.ScData.TRIANGLE;

import org.ourunix.android.world.ScData.VERTEX;

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.GLUtils;

import android.opengl.GLSurfaceView.Renderer;

import android.view.KeyEvent;

public class GLRenderer implements Renderer {

private Context mContext;

SECTOR sector1 = new SECTOR();

public final static float piover180 = 0.0174532925f;

float heading;

float xpos;

float zpos;

float yrot; // Y Rotation

float walkbias = 0;

float walkbiasangle = 0;

float lookupdown = 0.0f;

float z=0.0f;

private int[] texturesID = new int[3];

public GLRenderer(Context ctx){

mContext = ctx;

}

@Override

public void onDrawFrame(GL10 gl) {

// TODO Auto-generated method stub

gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT); // Clear The Screen And The Depth Buffer

gl.glLoadIdentity(); // Reset The View

float xtrans = -xpos;

float ztrans = -zpos;

float ytrans = -walkbias-0.25f;

float sceneroty = 360.0f - yrot;

FloatBuffer vertexPointer = Utils.BufferUtil.fBuffer(new float[9]);

FloatBuffer texCoordPointer = Utils.BufferUtil.fBuffer(new float[6]);

gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexPointer);

gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, texCoordPointer);

gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);

gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);

gl.glLoadIdentity();

gl.glRotatef(lookupdown, 1.0f, 0.0f, 0.0f);

gl.glRotatef(sceneroty, 0.0f, 1.0f, 0.0f);

gl.glTranslatef(xtrans, ytrans, ztrans);

gl.glBindTexture(GL10.GL_TEXTURE_2D, texturesID[0]);

for(TRIANGLE triangle : sector1.triangle)

{

vertexPointer.clear();

texCoordPointer.clear();

gl.glNormal3f(0.0f, 0.0f, 1.0f);

for(int i=0; i<3; i++)

{

VERTEX vt = triangle.vertex[i];

vertexPointer.put(vt.x);

vertexPointer.put(vt.y);

vertexPointer.put(vt.z);

texCoordPointer.put(vt.u);

texCoordPointer.put(vt.v);

}

gl.glDrawArrays(GL10.GL_TRIANGLES, 0, 4);

}

gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);

gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);

}

@Override

public void onSurfaceChanged(GL10 gl, int width, int height) {

// TODO Auto-generated method stub

float ratio = (float)width/height;

gl.glViewport(0, 0, width, height);

gl.glMatrixMode(GL10.GL_PROJECTION);

gl.glLoadIdentity();

gl.glFrustumf(-ratio, ratio, -1, 1, 1, 10);

gl.glMatrixMode(GL10.GL_MODELVIEW);

gl.glLoadIdentity();

}

@Override

public void onSurfaceCreated(GL10 gl, EGLConfig config) {

// TODO Auto-generated method stub

//加载纹理

gl.glEnable(GL10.GL_TEXTURE_2D);

LoadGLTextures(gl);

//开启混色透明

gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE);

gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_FASTEST);

gl.glClearColor(0, 0, 0, 0);

gl.glShadeModel(GL10.GL_SMOOTH);

//开启深度测试

gl.glClearDepthf(1.0f);

gl.glDepthFunc(GL10.GL_LESS);

gl.glEnable(GL10.GL_DEPTH_TEST);

SetupWorld();

}

private void LoadGLTextures(GL10 gl) {

int[] imgArray = {R.drawable.img};

// TODO Auto-generated method stub

for (int i = 0; i < 3; i++){

IntBuffer textureBuffer = IntBuffer.allocate(1);

gl.glGenTextures(1, textureBuffer);

texturesID[i] = textureBuffer.get();

gl.glBindTexture(GL10.GL_TEXTURE_2D, texturesID[i]);

Bitmap bmp = BitmapFactory.decodeResource(mContext.getResources(), imgArray[0]);

//生成纹理

GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bmp, 0);

// 线形滤波

gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_NEAREST);

gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_NEAREST);

}

}

private void SetupWorld() {

// TODO Auto-generated method stub

GLFile glFile = new GLFile(mContext.getResources());

BufferedReader br = new BufferedReader(new InputStreamReader(glFile.getFile("data/world.txt")));

TRIANGLE triangle = new TRIANGLE();

int vertexIndex = 0;

try {

String line = null;

while((line = br.readLine()) != null){

if(line.trim().length() <= 0 || line.startsWith("/")){

continue;

}

String part[] = line.trim().split("\\s+");

float x = Float.valueOf(part[0]);

float y = Float.valueOf(part[1]);

float z = Float.valueOf(part[2]);

float u = Float.valueOf(part[3]);

float v = Float.valueOf(part[4]);

VERTEX vertex = new VERTEX(x, y, z, u, v);

triangle.vertex[vertexIndex] = vertex;

vertexIndex ++;

if(vertexIndex == 3){

vertexIndex = 0;

sector1.triangle.add(triangle);

triangle = new TRIANGLE();

}

}

} catch (IOException e) {

e.printStackTrace();

}

}

public boolean onKeyUp(int keyCode, KeyEvent event)

{

switch ( keyCode )

{

case KeyEvent.KEYCODE_DPAD_LEFT:

yrot -= 1.5f;

break;

case KeyEvent.KEYCODE_DPAD_RIGHT:

yrot += 1.5f;

break;

case KeyEvent.KEYCODE_DPAD_UP:

// 沿游戏者所在的X平面移动

xpos -= (float)Math.sin(heading*piover180) * 0.05f;

// 沿游戏者所在的Z平面移动

zpos -= (float)Math.cos(heading*piover180) * 0.05f;

if (walkbiasangle >= 359.0f)// 如果walkbiasangle大于359度

{

walkbiasangle = 0.0f;// 将 walkbiasangle 设为0

}

else

{

walkbiasangle+= 10;// 如果 walkbiasangle < 359 ,则增加 10

}

// 使游戏者产生跳跃感

walkbias = (float)Math.sin(walkbiasangle * piover180)/20.0f;

break;

case KeyEvent.KEYCODE_DPAD_DOWN:

// 沿游戏者所在的X平面移动

xpos += (float)Math.sin(heading*piover180) * 0.05f;

// 沿游戏者所在的Z平面移动

zpos += (float)Math.cos(heading*piover180) * 0.05f;

// 如果walkbiasangle小于1度

if (walkbiasangle <= 1.0f)

{

walkbiasangle = 359.0f;// 使 walkbiasangle 等于 359

}

else

{

walkbiasangle-= 10;// 如果 walkbiasangle > 1 减去 10

}

// 使游戏者产生跳跃感

walkbias = (float)Math.sin(walkbiasangle * piover180)/20.0f;

break;

}

return false;

}

public class GLFile

{

public Resources resources;

public GLFile(Resources r)

{

resources = r;

}

public InputStream getFile(String name){

AssetManager am = resources.getAssets();

try {

return am.open(name);

} catch (IOException e) {

e.printStackTrace();

return null;

}

}

}

}

Utils.java

Java代码

package org.ourunix.android.world;

import java.nio.ByteBuffer;

import java.nio.ByteOrder;

import java.nio.FloatBuffer;

import java.nio.IntBuffer;

import java.nio.ShortBuffer;

public class Utils {

public static class BufferUtil {

public static IntBuffer intBuffer;

public static FloatBuffer floatBuffer;

public static ShortBuffer shortBuffer;

public static IntBuffer iBuffer(int[] a) {

// 先初始化buffer,数组的长度*4,因为一个float占4个字节

ByteBuffer mbb = ByteBuffer.allocateDirect(a.length * 4);

// 数组排列用nativeOrder

mbb.order(ByteOrder.nativeOrder());

intBuffer = mbb.asIntBuffer();

intBuffer.put(a);

intBuffer.position(0);

return intBuffer;

}

public static FloatBuffer fBuffer(float[] a) {

// 先初始化buffer,数组的长度*4,因为一个float占4个字节

ByteBuffer mbb = ByteBuffer.allocateDirect(a.length * 4);

// 数组排列用nativeOrder

mbb.order(ByteOrder.nativeOrder());

floatBuffer = mbb.asFloatBuffer();

floatBuffer.put(a);

floatBuffer.position(0);

return floatBuffer;

}

public static ShortBuffer sBuffer(short[] a) {

// 先初始化buffer,数组的长度*4,因为一个float占4个字节

ByteBuffer mbb = ByteBuffer.allocateDirect(a.length * 2);

// 数组排列用nativeOrder

mbb.order(ByteOrder.nativeOrder());

shortBuffer = mbb.asShortBuffer();

shortBuffer.put(a);

shortBuffer.position(0);

return shortBuffer;

}

}

}

源码下载:Android高级进阶十一
Android OpenGL建立3D空间源码
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: