额,有nehe的教程,就不用买杨丰盛的视频喽,接着看吧,虽然看英文烦点,不过总比没有好。
(1)RealWorld
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.KeyEvent;
public class RealWorld extends Activity {
private MyRenderer renderer = new MyRenderer();
GLSurfaceView glSurfaceView;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
glSurfaceView = new GLSurfaceView(this);
LoadImage.load(getResources());
new LoadTxt(getResources());
glSurfaceView.setRenderer(renderer);
setContentView(glSurfaceView);
}
@Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
renderer.onKeyUp(keyCode, event);
return super.onKeyUp(keyCode, event);
}
}
// 载入图片
class LoadImage {
public static Bitmap bitmap;
public static void load(Resources res) {
bitmap = BitmapFactory.decodeResource(res, R.drawable.img);
}
}
//New
// 读取world.txt文件
class LoadTxt {
public static Resources res;
public LoadTxt(Resources res) {
LoadTxt.res = res;
}
public static InputStream getFile(String file) {
AssetManager am = LoadTxt.res.getAssets();
try {
return am.open(file);
} catch (IOException e) {
return null;
}
}
}
(2)Data类
package sim.feel;
import java.util.ArrayList;
import java.util.List;
//区段结构
class SECTOR {
int numtriangles; // triangle结构数目
List<TRIANGLE> triangle = new ArrayList<TRIANGLE>(); // triangle的list
}
// 三角形
class TRIANGLE {
VERTEX vertex[] = new VERTEX[3];
}
// 构建顶点结构
class VERTEX {
float x, y, z; // 3d坐标
float u, v; // 纹理坐标
public VERTEX(float x, float y, float z, float u, float v) {
super();
this.x = x;
this.y = y;
this.z = z;
this.u = u;
this.v = v;
}
}
(3)MyRenderer
package sim.feel;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
import android.opengl.GLSurfaceView.Renderer;
import android.opengl.GLUtils;
import android.view.KeyEvent;
public class MyRenderer implements Renderer {
SECTOR sector = new SECTOR();
int[] texture = new int[3];
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;
//NEW
// 读取资源数据
public void setUp() {
BufferedReader br = new BufferedReader(new InputStreamReader(
LoadTxt.getFile("data/world.txt")));
TRIANGLE triangle = new TRIANGLE();
int vertexIndex = 0;
try {
String line = null;
// 读完所有数据后循环终止
while ((line = br.readLine()) != null) {
// 以"/"字符开始或以空格开始的行跳过
if (line.startsWith("/") || line.trim().length() <= 0) {
continue;
}
// //s表示 空格,回车,换行等空白符 ,+号表示一个或多个的意思
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;
sector.triangle.add(triangle);
triangle = new TRIANGLE();
}
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
// Texture用这种方法也不错,呵呵
public void LoadTextures(GL10 gl) {
// Create Nearest Filtered Texture
IntBuffer textureBuffer = IntBuffer.allocate(3);
gl.glGenTextures(1, texture, 0);
gl.glBindTexture(GL10.GL_TEXTURE_2D, texture[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);
GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, LoadImage.bitmap, 0);
texture[1] = textureBuffer.get(2);
gl.glBindTexture(GL10.GL_TEXTURE_2D, texture[1]);
gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER,
GL10.GL_LINEAR);
gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER,
GL10.GL_LINEAR);
GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, LoadImage.bitmap, 0);
}
@Override
public void onDrawFrame(GL10 gl) {
// 清除屏幕和深度缓存
gl.glClear(GL10.GL_DEPTH_BUFFER_BIT | GL10.GL_COLOR_BUFFER_BIT);
gl.glLoadIdentity(); // reset the view
float xtrans = -xpos;
float ztrans = -zpos;
float ytrans = -walkbias - 0.25f;
float sceneroty = 360.0f - yrot;
FloatBuffer vertexPointer;
FloatBuffer texCoordPointer;
float[] vertex = new float[9];
float[] coord = new float[6];
ByteBuffer vertexByteBuffer = ByteBuffer
.allocateDirect(vertex.length * 4);
vertexByteBuffer.order(ByteOrder.nativeOrder());
vertexPointer = vertexByteBuffer.asFloatBuffer();
vertexPointer.put(vertex);
vertexPointer.position(0);
ByteBuffer texCoordByteBuffer = ByteBuffer
.allocateDirect(coord.length * 4);
texCoordByteBuffer.order(ByteOrder.nativeOrder());
texCoordPointer = texCoordByteBuffer.asFloatBuffer();
texCoordPointer.put(coord);
texCoordPointer.position(0);
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, texture[1]);
for (TRIANGLE triangle : sector.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) {
gl.glViewport(0, 0, width, height);
float ratio = (float) 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 arg1) {
LoadTextures(gl);
gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_FASTEST);
gl.glClearColorx(0, 0, 0, 0);
// 开启深度测试
gl.glEnable(GL10.GL_DEPTH_TEST);
gl.glDepthFunc(GL10.GL_LESS);
gl.glShadeModel(GL10.GL_SMOOTH);
// 开启纹理
gl.glEnable(GL10.GL_TEXTURE_2D);
// 开启混合
gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE);
setUp();
}
//NEW
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;
}
}
效果图 :