最近學習了 opengl es, 要顯示3D 的效果,主要對座標系和位置向量有一個概念.
Matrix.frustumM 透視投影 target
Matrix.setLookAtM 相機位置 camera
Matrix.multiplyMM 矩陣合併 result view
在OpenGLES環境中,投影和相機視角使你繪製的對象以更接近物理對象的樣子顯示。這是通過對座標精確的數學變換實現的。
投影:這種變換跟據所在GLSurfaceView的寬和高調整對象的座標。如果沒有變換,對象會被不規則的視口扭曲。
投射需要在OpenGLview創建或發生變化時調用,在renderer的onSurfaceChanged()方法中
在Android設備中顯示圖形的一個基本問題是它們的屏幕的尺寸和形狀可能不同.OpenGL假設一個正方形的,一致的座標系統,並且,默認情況下,也樂於把這些座標畫到你的非正方形屏幕上,就像在正方形上一樣.
相機視角:變換基於一個"虛擬相機"的位置調整"對象"的座標。提供了一些工具方法變換繪製對象的顯示來模擬一個相機。
一個相機視口的變換隻在創建GLSurfaceView時調用,或跟據用戶動作動態調用。
一、 Matrix.setLookAtM 設置相機位置 / 設置的是 View矩陣.決定攝影機的空間位置.
//project 矩陣
//rmOffset
public static void setLookAtM(float[] rm, int rmOffset,
float eyeX, float eyeY, float eyeZ,
float centerX, float centerY, float centerZ, float upX, float upY,
float upZ) {
1.1 相機的座標 -5, 0, 15
eyeX 相機在X軸偏移量(-5左邊) , eyey 相機在Y軸偏移量(0), eyez 相機在Z軸偏移量(15)
1.2 目標的位置 座標 0,0,0
centerX ,centerY,centerZ 物體中心點,居中一般都是 0,0,0
1.3 相機的視覺向量 (向量有3個屬性,一個就是起始點,二個方向,三個就是量)
upx 攝像機UP向量X分量
upy 攝像機UP向量Y分量
upz 攝像機UP向量Z分量
----- up x,y,z----------
(1) 0,1,0
代表相機的起始點和 Y軸 組成的向量, 對應效果圖1
(2) 1,0,0
代表相機的起始點和 X軸 組成的向量,對應效果圖2
(2) 1,1,0
代表相機的起始點和 X Y 組成的向量,對應效果圖3
CX,CY,CZ: -5,0,15 | TX,TY,TZ: 0,0,0
二、Matrix.frustumM 設置透視投影 / 設置的自是Project 投影矩陣, 決定取景時的鏡頭配置 ,如可視角度, Z距離範圍
public static void frustumM (float[] m, int offset, float left, float right, float bottom, float top, float near, float far)
Parameters:
m the float array that holds the perspective matrix
offset the offset into float array m where the perspective matrix data is written
float left, //near面的left
float right, //near面的right
float bottom, //near面的bottom
float top, //near面的top
float near, //near面距離
float far //far面距離
設置這些參數能起到的作用:left,right, bottom,top,這4個參數會影響圖像左右和上下縮放比
(float) width / height
top和bottom和top會影響上下縮放比,如果left和right已經設置好縮放,
則bottom只需要設置爲-1,top設置爲1,這樣就能保持圖像不變形。
也可以將left,right 與bottom,top交換比例,即bottom和top設置爲 -height/width 和 height/width, left和right設置爲-1和1。
near 和 far 就是一個物體的前面和後面,near和far需要結合拍攝相機即觀察者眼睛的位置來設置
(1) 假如 setLookAtM中設置cx = 0, cy = 0, cz = 20
float near :
範圍設置 < 20 才能看到繪製圖像
範圍設置 > 20,圖像就會處於了觀察這眼睛的後面,這樣繪製的圖像就會消失在鏡頭前,
float far :
far參數影響的是立體圖形的背面,far一定比near大,一般會設置得比較大,如果設置的比較小,一旦3D圖形尺寸很大,這時候由於far太小,
這個投影矩陣沒法容納圖形全部的背面,這樣3D圖形的背面會有部分隱藏掉的
三、 Matrix.multiplyMM
Multiplies two 4x4 matrices together and stores the result in a third 4x4 matrix. In matrix notation: result = lhs x rhs.
將投影矩陣和相機視圖變換矩陣結合的一個方法,生成一個新的矩陣mMVPMatrix。
public static native void multiplyMM(float[] result, int resultOffset,
float[] lhs, int lhsOffset, float[] rhs, int rhsOffset);
float[] lhs project
float[] rhs
result 生成的Result 的矩陣, 就是最終顯示在 GLSurfaceView 上的
demo:
private float[] mProjectMatrix = new float[16];
private float[] mViewMatrix = new float[16];
private float[] mResultMatrix = new float[16];
@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
GLES20.glEnable(GLES20.GL_DEPTH_TEST);
}
@Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
//計算寬高比
float ratio=(float)width/height;
//設置透視投影
Matrix.frustumM(mProjectMatrix, 0, -ratio, ratio, -1, 1, 3, 20);
//設置相機位置
Matrix.setLookAtM(mViewMatrix, 0, 0f, 0f, 15f, 0f, 0f, 0f, 0f, 1f, 0.0f);
//計算變換矩陣
Matrix.multiplyMM(mResultMatrix,0,mProjectMatrix,0,mViewMatrix,0);
}