`
solonot
  • 浏览: 3694 次
  • 性别: Icon_minigender_1
  • 来自: 广州
最近访客 更多访客>>
文章分类
社区版块
存档分类
最新评论

LIBGDX版NEHE OPENGL- 2. Your First Polygon

 
阅读更多

说是原创,其实都是参考了libgdx wiki里的教程。不过我自己都做过,一点点的打字,一张张图的截下来。

看到太多LIBGDX 2D方面的教程,于是冲动着自己想学点3D方面的东西。毕竟,如果只做2D,用libgdx还不如cocos2d-x来得方便。

假设已经通过 gdx-setup-ui.jar建好了libgdx的项目,并且import到eclipse中。以下内容实在是太初级,菜鸟可能都有踩两脚的冲动。

我这里看起来是这样的。


通过gdx-setup-ui.jar建立的项目,大体上分为主项目,和android/ios/desktop/html项目。

这个是一个可运行的项目,运行desktop下的Main.java,然后就能得到:


接下来,对这个项目稍做修改:

新建Class: com.kyugao.nehe.NeHeLibgdx extends Game. 删掉原来的com.kyugao.nehe.MyGdxGame. 然后,添上几行代码如下:

package com.kyugao.nehe;

import com.badlogic.gdx.Game;
import com.badlogic.gdx.graphics.FPSLogger;
import com.kyugao.screen.FirstPolygon;

public class NeHeLibgdx extends Game {

	private FPSLogger fpsLogger;

	@Override
	public void create() {
		// TODO Auto-generated method stub
		setScreen(new FirstPolygon());
		fpsLogger = new FPSLogger();
	}

	@Override
	public void render() {
		// TODO Auto-generated method stub
		super.render();
		fpsLogger.log();
	}

}

Game类是ApplicationListener的一个抽象实现,对一个游戏的生命周期做了一个默认的处理,这里,在create方法中,设置好要显示的screen,并且在render方法中开始render就好了。另外加的一个FPSLogger是为了输出FPS信息,这些信息会输出在console里面。

接下来就要定义我们的FirstPolygon screen. 新建一个包,com.kyugao.screen。如果我有坚持下去,每一课都会在这里新添加一个screen.

那第一课的screen就是com.kyugao.screen.FirstPolygon implements Screen.

代码如下:

package com.kyugao.screen;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Screen;
import com.badlogic.gdx.graphics.GL10;
import com.badlogic.gdx.graphics.Mesh;
import com.badlogic.gdx.graphics.VertexAttribute;
import com.badlogic.gdx.graphics.VertexAttributes.Usage;

public class FirstPolygon implements Screen {

	private Mesh triangleMesh;

	@Override
	public void render(float delta) {
		Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
		drawGLScene();
	}

	private boolean drawGLScene() {
		triangleMesh.render(GL10.GL_TRIANGLES, 0, 3);
		return true;
	}
	
	@Override
	public void show() {
		triangleMesh = new Mesh(true, 3, 3, new VertexAttribute(Usage.Position,
				3, "a_position"));
		triangleMesh.setVertices(new float[] { -0.5f, -0.5f, 0, // point 1
				0.5f, -0.5f, 0, // point 2
				0, 0.5f, 0 }); // point 3
		triangleMesh.setIndices(new short[] { 0, 1, 2 });
	}

	@Override
	public void hide() {
	}

	@Override
	public void pause() {
	}

	@Override
	public void resume() {
	}

	@Override
	public void dispose() {
	}

	@Override
	public void resize(int width, int height) {
	}
}

screen的方法,这里重写了show()和render().

Screen下面的show方法,会在被Game设置后调用一次, 之后就反复的通过render去绘制画面了。

render方法中:

Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT); // opengl中的清屏函数,在这里,默认的清屏颜色是黑色,所以看到的背景色都是黑的。通过glClearColor可以自定义这个清屏颜色,比如,我们想要红色的背景Gdx.gl.glClearColor(1, 0, 0, 1),那每次render时填充的颜色就是红色。可以提到一下,如果不需要背景颜色变幻,那glClearColor只要一次指定就好,所以可以写在show()里。

在通过glClear清屏之后,调用drawGLScene来画图形。

show方法:

初始化mesh, 关于mesh,iciba翻译是网格,所以很简单的理解,我定义了三个点的,分别如坐标上写的。然后指定了他们的indices(index), 0, 1, 2

再次运行desktop project下面的Main. 可以得到下面这个图形:



一个三角形,一个正方形:

// glTranslatef(-1.5f,0.0f,-6.0f);

// glVertex3f( 0.0f, 1.0f, 0.0f); // Top

// glVertex3f(-1.0f,-1.0f, 0.0f); // Bottom Left

// glVertex3f( 1.0f,-1.0f, 0.0f); // Bottom Right

// glTranslatef(3.0f,0.0f,0.0f);

// glVertex3f(-1.0f, 1.0f, 0.0f); // Top Left

// glVertex3f( 1.0f, 1.0f, 0.0f); // Top Right

// glVertex3f( 1.0f,-1.0f, 0.0f); // Bottom Right

// glVertex3f(-1.0f,-1.0f, 0.0f); // Bottom Left

先计算一下三角形的三个点,glTranslatef 与 三个顶点相加:

TOP: -1.5f, 1.0f, -6.0f

BL: -2.5f, -1.0f, -6.0f

BR: -0.5f, -1.0f, -6.0f

然后正方形的:// glTranslatef(-1.5f,0.0f,-6.0f); +// glTranslatef(3.0f,0.0f,0.0f); = glTranslatef(1.5f, 0.0f, -6.0f),于是:

TL: 0.5f, 1.0f, -6.0f

TR: 2.5f, 1.0f, -6.0f

BR: 2.5f, -1.0f, -6.0f

BL: 0.5f, -1.0f, -6.0f

根据计算值,我重新构建了两个mesh,并且修改drawGLScene方法, 如下:

	private Mesh triangleMesh, squareMesh;

	private boolean drawGLScene() {
		triangleMesh.render(GL10.GL_TRIANGLES, 0, 3);
		squareMesh.render(GL10.GL_TRIANGLE_STRIP, 0, 4);
		return true;
	}

	@Override
	public void show() {
		triangleMesh = new Mesh(true, 3, 3, new VertexAttribute(Usage.Position,
				3, "a_position"));
		squareMesh = new Mesh(true, 4, 4, new VertexAttribute(Usage.Position,
				3, "b_position"));
		triangleMesh.setVertices(new float[] { //
				-1.5f, 1.0f, -6.0f, // point 1
						-2.5f, -1.0f, -6.0f, // point 2
						-0.5f, -1.0f, -6.0f }); // point 3
		triangleMesh.setIndices(new short[] { 0, 1, 2 });

		squareMesh.setVertices(new float[] { 0.5f, -1.0f, -6.0f,// point BL
				2.5f, -1.0f, -6.0f,// point BR
				0.5f, 1.0f, -6.0f, // point TL
				2.5f, 1.0f, -6.0f // point TR
				});
		squareMesh.setIndices(new short[] { 0, 1, 2, 3 });
	}
可是,当我一运行,屏幕上只有一片黑色,这个就不截图了。

扩展3D空间,将纸,换成取景器Camera:

平面上画图,一张纸就够了,可是在3D空间里,为了更好的观察,我们要用一个照像机:

package com.kyugao.screen;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Screen;
import com.badlogic.gdx.graphics.GL10;
import com.badlogic.gdx.graphics.Mesh;
import com.badlogic.gdx.graphics.PerspectiveCamera;
import com.badlogic.gdx.graphics.VertexAttribute;
import com.badlogic.gdx.graphics.VertexAttributes.Usage;

public class FirstPolygon implements Screen {

	private Mesh triangleMesh, squareMesh;
	private PerspectiveCamera camera;

	@Override
	public void render(float delta) {

		camera.update();
		camera.apply(Gdx.graphics.getGL10());
		Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
		drawGLScene();
	}

	private boolean drawGLScene() {
		triangleMesh.render(GL10.GL_TRIANGLES, 0, 3);
		squareMesh.render(GL10.GL_TRIANGLE_STRIP, 0, 4);
		return true;
	}

	@Override
	public void show() {
		triangleMesh = new Mesh(true, 3, 3, new VertexAttribute(Usage.Position,
				3, "a_position"));
		squareMesh = new Mesh(true, 4, 4, new VertexAttribute(Usage.Position,
				3, "b_position"));
		triangleMesh.setVertices(new float[] { //
				-1.5f, 1.0f, -6.0f, // point 1
						-2.5f, -1.0f, -6.0f, // point 2
						-0.5f, -1.0f, -6.0f }); // point 3
		triangleMesh.setIndices(new short[] { 0, 1, 2 });

		squareMesh.setVertices(new float[] { 0.5f, -1.0f, -6.0f,// point BL
				2.5f, -1.0f, -6.0f,// point BR
				0.5f, 1.0f, -6.0f, // point TL
				2.5f, 1.0f, -6.0f // point TR
				});
		squareMesh.setIndices(new short[] { 0, 1, 2, 3 });
	}

	@Override
	public void hide() {
	}

	@Override
	public void pause() {
	}

	@Override
	public void resume() {
	}

	@Override
	public void dispose() {
	}

	@Override
	public void resize(int width, int height) {
		float aspectRatio = (float) width / (float) height;
		camera = new PerspectiveCamera(45, 2f * aspectRatio, 2f);
	}

}
上面是Screen的全部代码,主要是添加了一个照相机 camera,形象一点说,是一个取景器。

在窗口大小改变时,就是取景器的大小改变了,新建一个camera, 然后在每一次render时,更新camera属性,重新render画面。

new PerspectiveCamera(45, 2f * aspectRatio, 2f);
相机参数:45是角度,如果你的眼睛可以看面前的180度,那就把45改掉。

2f * aspectRatio, 2f,分别是宽与高,在默认情况下,opengl es把窗口定义为, 以中心点为原点,x, y轴的正负方向各单位1的长度。


(from http://code.google.com/p/libgdx)

但是,如果窗口的长与宽比不是1:1,比如,我横向拉伸了窗后,上面的正方形就变成了:

(from http://code.google.com/p/libgdx)

所以,要计算camera的长宽比。最终,运行一下程序,得到了:


第一课结束。

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics