声明:
本系列文章使用的Libgdx版本均为0.99版本
Libgdx游戏开发交流群 323876830
在Opengl中,有许多矩阵变换,可以分为视角(Viewing),模型(Modeling)和投影(Projection)操作,这些操作可以有选择,平移,缩放,正侧投影,透视投影等。
如果我们使用照相机拍照的过程做类比,可以更好的理解3D 坐标变换的过程。
下图为Android OpenGL ES坐标变换的过程:
好了,上面只是对opengl三维变换知识的一个普及。 下面我们将要针对Libgdx中怎么处理这些东西的做一下分析。
Viewing和Modeling(MODELVIEW) 变换
为什么把这两个放在一起呢?我们可以这样想想, 当我们拉近镜头(物体不动)的时候,和物体靠近镜头(镜头不动),
或者镜头视角向上偏移(物体不动)和物体视角相对镜头向下偏移, 效果是一样的。 如下图:
view变换在Camera中给我们提供了所需字段 镜头位置,镜头指向目标位置的方向,镜头观测点方向为“上”的向量
/** the position of the camera **/ public final Vector3 position = new Vector3(); /** the unit length direction vector of the camera **/ public final Vector3 direction = new Vector3(0, 0, -1); /** the unit length up vector of the camera **/ public final Vector3 up = new Vector3(0, 1, 0);
变换的结果存储在view矩阵中
/** the view matrix **/ public final Matrix4 view = new Matrix4();
model的变换的操作其实都已经移交到view变换中了, 所以就没有单独计算了。
投影变换Projection
在Opengl中的两种投影变换对应于Camera中的两个子类OrthographicCamera和PerspectiveCamera,分别是正投影和
透视投影。
先看看透视投影,如下图
粉色区域就是我们要得到的区域,又叫视锥。需要的数据也就有 视锥的view angle,视锥的宽高比,裁剪面的近距离,创建面的远距离
在PerspectiveCamera透视投射镜头中,我们也可以找到这些我们所需要的数据。
/** the field of view in degrees **/ public float fieldOfView = 67;
/** the near clipping plane distance, has to be positive **/ public float near = 1; /** the far clipping plane distance, has to be positive **/ public float far = 100;
组装投射矩阵数据
float aspect = viewportWidth / viewportHeight; projection.setToProjection(Math.abs(near), Math.abs(far), fieldOfView, aspect);
下图为正投影镜头
它的视锥为一长方体,特点是物体的大小不随到观测点的距离而变化,投影后可以保持物体之间的距离和夹角。
在OrthographicCamera中表示
this.near = 0;
projection.setToOrtho(zoom * -viewportWidth / 2, zoom * (viewportWidth / 2), zoom * -(viewportHeight / 2), zoom * viewportHeight / 2, near, far);
在绘制的时候,我们可以使用Camera的apply方法,应用矩阵
public void apply (GL10 gl) { gl.glMatrixMode(GL10.GL_PROJECTION); gl.glLoadMatrixf(projection.val, 0); gl.glMatrixMode(GL10.GL_MODELVIEW); gl.glLoadMatrixf(view.val, 0); }
这里要多提一下SpriteBatch中使用镜头的方式
GL10 gl = Gdx.gl10; gl.glMatrixMode(GL10.GL_PROJECTION); gl.glLoadMatrixf(projectionMatrix.val, 0); gl.glMatrixMode(GL10.GL_MODELVIEW); gl.glLoadMatrixf(transformMatrix.val, 0);
大家有没有发现有点诡异?
在投射模式下使用的是projectionMatrix投影矩阵,乍一看是没什么问题, 但是这个projectionMatrix是由
投影矩阵和view变换矩阵的组合矩阵
combined.set(projection); Matrix4.mul(combined.val, view.val);
projectionMatrix其实就是combined
而transformMatrix这个也不是我们上面的view变换矩阵,而是一个空矩阵,可以让我们来set进去的。
好了,矩阵变换就到这里了, 有什么问题大家可以多多指教。