trueSpace建模之座標軸與視點控制器

trueSpace建模之座標軸與視點控制器

學習trueSpace建模需要理解其座標系統.而trueSpace座標軸與OpenGL座標軸有所不同.

座標軸 簡介
X軸 網格橫向為X軸,左則為負右則為正
Y軸 網格縱向為Y軸,指向屏幕為負反向則為正
Z軸 Z軸則垂直於網格下負上正.

要在3D場景中移動『位置』與『視點』可通過『view control』巡覽指示器.它通常在屏幕右下角.但有個更好用工具,按V鍵將視點對齊對象模型『Look at Current Object』

工具 簡介
半圓 繞『對象/視點』旋轉
圓套 拖動則移動控制器,而點擊則修改屬性
橫軸 左鍵繞Y軸旋轉,右鍵繞XZ軸旋轉
橫軸箭頭 視點沿X軸移動
縱軸 左鍵繞X軸旋轉,右鍵繞ZY軸旋轉
縱軸箭頭 視點沿Z軸移動
垂直軸 左鍵繞Z軸旋轉,右鍵繞XY軸旋轉
垂直箭頭 視點沿Y軸移動
步行 按滑鼠移動方向移動
XY平面 左鍵XY平面移動,沿Z軸移動
YZ平面 左鍵YZ平面移動,沿X軸移動
XZ平面 左鍵XZ平面移動,沿Y軸移動
雙下箭頭 飛行模式
單下箭頭 步行模式
十字箭頭 拖放實現控制器縮放
關閉『view control』巡覽指示器
關閉 關閉屬性

 

trueSpace建模之設置參考圖

trueSpace建模之設置參考圖

3D建模你需要『素描圖』或『照片』作為參考圖,最常用方法是創建『plane』平面.然後貼上參考圖

  1. 新建『Scene』場景『File->New->Scene』
  2. 在常境中添加『Plane』平面.
  3. 3D模型尺寸.這裡設長2米高1米
  4. 按『space』空格『Object Tool』選擇平面
  5. 滑鼠右擊『Object Tool』打開『object info』
  6. 『Size』X輸入2(長2米).Y輸入1(高1米).Z輸入0
  7. 『Rotation』x輸入90(垂直圖層).z輸入-180(倒轉圖層)
  8. 『Loaction』x輸入0(中心).y輸入0(中心).z輸入5
  9. 滑鼠點擊『Image Browser』圖片瀏覽器輸入路徑打開圖像
  10. 滑鼠點擊『Material Library』材質庫.把『Image Browser』圖片拖過來『Material Library』.作為『材質』以備使用
  11. 然後將『材質』拖放到『Plane』平面.貼上參考圖
  12. 『Local Light』添加全域燈光.並調至最光.

trueSpace之設置場景單位與對象單位

trueSpace之設置場景單位與對象單位

在3D建模過程中你可能會忽略模型尺寸.雖然你可以通過『縮放』與遊戲相適配.良好建模習慣是預先計算模型尺寸.『3D建模環境』中1米等於『3D遊戲世界』中1米.准好使用公制標準,因為大部分遊戲引擎都以此為標準.

  1. 滑鼠右擊『Object tool』對象工具(白色箭頭)按鈕.打開『object info』面板
  2. 滑鼠點擊『object info』面板右上角『紅三角』展開面板
  3. 將『Convert』對象轉換設置為Meters(米)
  4. 將『Units』對象單位設置為Meters(米)
  5. 將『Units』場景單位設置為Meters(米)

經設定後trueSpace網格單位為1m2.其網格長寬均24格.亦即長寬均24米『Meters』.而『object info』面板也應將其保留.可以隨時睇到『#vertices』頂點量與『#faces』三角量.

設定對象尺寸與角度,位置.

Location 『位置』
Rotation 『旋轉』角(0~360)
Size 『尺寸』以『Obj.Units』為單位

 

貓咪生貓仔

貓咪生貓仔
貓咪生貓仔

今晨暴雨後晨跑,在樓梯發現貓咪生左三隻黑色貓仔.晨跑後影左幾張相.接近貓咪時它好緊張啊.

Android遊戲之跟隨相機

Android遊戲之跟隨相機

『跟隨相機』與『歐拉相機』喂一區別在於屬性設置不同.跟隨相機常將它固定在移動物體上.它需要以下屬性:

3D空間位置position

向上向量.相當於在相機上貼上一個向上箭頭up

視點向量即相機視口朝向目標lookAt

遠裁剪面far

近裁剪面near

『視場』即視口角度fieldOfView

視口縱橫比aspectRatio

再移動相機時你需要分被相機『位置』與『視點』.『跟隨相機』生成代碼:

設定相機視口,寬與高為屏幕分辨率

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

設置相機矩陣,將當前堆棧設為投影矩陣

gl.glMatrixMode(GL10.GL_PROJECTION);

棧頂載入單位矩陣

gl.glLoadIdentity();

設置透視投影矩陣.定義視錐體參數.『視口角度』『視口縱橫比』『遠近裁剪面』

GLU.gluPerspective(gl, fieldOfView, aspectRation, near, far);

將當前堆棧設為模型視圖矩陣

gl.glMatrixMode(GL10.GL_MODELVIEW);

棧頂載入單位矩陣

gl.glLoadIdentity();

生成方位矩陣,好處在於能防止出現弄反位置或角度

GLU.gluLookAt(gl, position.x,position.y,position.z,

lookAt.x, lookAt.y, lookAt.z,

up.x, up.y, up.z);

Android遊戲之第一人稱相機(歐拉相機)

Android遊戲之第一人稱相機(歐拉相機)

歐拉相機即第一稱射擊遊戲中時用相機.你需要定義以下屬性

『視場』即視口角度fieldOfView

視口縱橫比aspectRatio

遠裁剪面far

近裁剪面near

3D空間位置position

繞y軸旋轉角yaw

繞x軸旋轉角pitch.角度值-90~+90度之間.這類似於頭部傾斜角.若超過這角度則造成骨折.

 

設定歐拉相機視口,寬與高為屏幕分辨率

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

設置歐拉相機矩陣.首先將當前堆棧設為投影矩陣

gl.glMatrixMode(GL10.GL_PROJECTION);

棧頂載入單位矩陣

gl.glLoadIdentity();

設置投影矩陣.你需定義要視錐體

GLU.gluPerspective(gl, fieldOfView, aspectRatio, near, far);

設為模型視圖矩陣

gl.glMatrixMode(GL10.GL_MODELVIEW);

棧頂載入單位矩陣

gl.glLoadIdentity();

繞x軸旋轉角度

gl.glRotatef(-pitch,1,0,0);

繞Y軸旋轉角度

gl.glRotatef(-yaw,0,1,0);

移動相機,相機位於原點且鏡頭指向z軸負方向

gl.glTranslatef(-position.x,-position.y,-position.z);

 

獲取相機方向

相機未旋轉時指向z軸負向

float[] inVec = {0,0,-1,1};

float[] outVec = {0,0,0,0};

設置單位矩陣

float[] matrix = {0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0};

Matrix.setIdentityM(matrix,0);

繞x軸俯仰

Matrix.rotateM(matrix, 0, yaw,0,1,0);

繞Y軸旋轉

Matrix.rotateM(matrix, 0, pitch,1,0,0);

將矩陣和向量相乘的單位方向向量

Matrix.multiplyMV(outVec, 0, matrix, 0, inVec, 0);

direcion.set(outVec[0],outVec[1],outVec[2]);

 

 

Android遊戲之紋理鏈Mipmap

Android遊戲之紋理鏈Mipmap

當相機遠離模型時,模型也會變小.其紋理渲染採樣時會顆粒狀失真.解決失真問題關鍵在於讓屏幕中體積較小物體或遠離視點時.使用低分辯率『紋理Texture』圖像.稱值為紋理鏈.首先獲取紋理尺寸.然後創建比小分辨率紋理圖,把分辨率縮小一半.重複這一過程直到分辨率為1.為了在OpenGL ES使用紋理鏈,需要執行以下兩步

  1. 將縮小係數過濾器設置為GL_XXX_MIPMAP_XXX這裡設置為如果不使用MIPMAP.只會使用首個紋理
  2. 通過縮小紋理創建圖鏈.並將圖片上傳提交給OpenGL ES.作為當前圖層.圖層從0開此,0圖層為原始圖層,然後上傳圖層.然後將其寬度與高除以2不斷創建縮小圖層並上傳.回收位圖.直到寬與高等於零.最後一張紋理1*1像素.則退出循環.並且紋理鏈只能綁定單一紋理
  3. 對於3D模形使用紋理鏈mipmap,而在2D材質無需應用
  4. 若啟用mipmap所繪製物較小.性能提升較明顯.因為GPU只需從小圖片中提取紋理元素
  5. 若啟用mipmap紋理鏈會比沒有使用多佔用33%記憶體.但可換來視角效果提升.特別對遠景物體可修正粒狀失真.
  6. mipmap紋理鏈僅對正方形紋理有效.並且僅在OpenGL ES 1.x獲得支持.

 

紋理位圖載入與綁定.在其基礎加入紋理鏈代碼

GL10 gl = GRAPHICS.gl;

生成空的紋理對象,並獲取id

gl.glGenTextures(1, ids,0);

int id = ids[0];

讀取紋理圖

Bitmap  bitmap = BITMAP.Read(file_name);

綁定紋理ID

gl.glBindTexture(GL10.GL_TEXTURE_2D, id);

設置紋理屬性,紋理過濾器,指定縮小倍數過濾器

gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR_MIPMAP_NEAREST);

指定放大倍數過濾器

gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);

獲取紋理寬度與高度

int    width = bitmap.getWidth();

int    height = bitmap.getHeight();

原始圖層索引為0

int level = 0;

while(true) {

上傳紋理

GLUtils.texImage2D(GL10.GL_TEXTURE_2D, level, bitmap, 0);

圖層索引號加一

++level;

計算縮小一半紋理位圖寬與高

int newWidth = bitmap.getWidth()/2;

int newHeight = bitmap.getHeight()/2;

寬與高等於零時跳出循環

if(newWidth == 0)

break;

創建縮小一半紋理位圖

Bitmap  newBitmap = Bitmap.createBitmap(newWidth,newHeight,bitmap.getConfig());

Canvas canvas = new Canvas(newBitmap);

canvas.drawBitmap(bitmap,

new Rect(0,0,bitmap.getWidth(),bitmap.getHeight()),

new Rect(0,0,newWidth,newHeight),

null);

回收位圖資源

bitmap.recycle();

bitmap = newBitmap;

}

取消邦定紋理ID

gl.glBindTexture(GL10.GL_TEXTURE_2D, 0);

回收位圖資源

bitmap.recycle();

 

Android遊戲之射燈

Android遊戲之射燈

射燈是OpenGL ES中燈光中最耗GPU資源燈光.但其3D效果十分逼真.睇上圖.射燈有多個參數需指定.『位置』『照射方向』『照射角度』小於180度、『衰減指數』小於零,若設為0則亮度不衰減,實制『衰減值』與遊戲3D空間尺寸有關.這裡設為0.01.以及三個光照顏色『環境色』『漫反射色』『鏡面反射色』

public class LightSpot {

private float[] ambient  = {1.0f, 1.0f, 1.0f, 1.0f};// 射燈-環境色

private float[] diffuse  = {1.0f, 1.0f, 1.0f, 1.0f};// 射燈-漫反射色

private float[] specular = {0.0f, 0.0f, 0.0f, 1.0f};// 射燈-高光顏色

private float[] position = {0.0f, 3.0f, 0.0f, 1.0f};// 射燈-位置

private float[] direction = {0.0f, -1.0f, 0.0f, 0.0f};// 射燈-方向

private float  cutoff    = 45;// 射燈-角度範圍,缺省為180.0

private float  exponent  = 0.01f;// 衰減指數,缺省為0.0f

int     id = 0;// 光照ID

// 射燈ID 輸入:GL10.GL_LIGHT0至GL10.GL_LIGHT7

LightSpot(int ID){

this.id = ID;

}

//設置射燈方向,轉換為方向向量.最後w分量設0,代表方向

public void setDirection(float x,float y,float z){

direction[0] = x – position[0];

direction[1] = y – position[1];

direction[2] = z – position[2];

direction[3] = 0;

}

// 設定射燈位置.w分量設為1代表位置向量

public void setPosition(float x,float y,float z){

position[0] = x;

position[1] = y;

position[2] = z;

position[3] = 1;

}

// 設定射燈顏色

public void setColor(float r,float g,float b){

ambient[0] = r;

ambient[1] = g;

ambient[2] = b;

ambient[3] = 1;

}

//使能射燈

public void enable(){

GL10 gl = GRAPHICS.gl;

gl.glEnable(id);//使能

gl.glLightfv(id,GL10.GL_AMBIENT, ambient, 0);// 射燈-環境色

gl.glLightfv(id,GL10.GL_DIFFUSE, diffuse, 0);// 射燈-漫反射色

gl.glLightfv(id,GL10.GL_SPECULAR, specular, 0);// 射燈-高光顏色

gl.glLightfv(id,GL10.GL_POSITION, position, 0);// 位置

gl.glLightfv(id,GL10.GL_SPOT_DIRECTION, direction, 0);// 方向

gl.glLightf(id,GL10.GL_SPOT_CUTOFF,cutoff); //  角度範圍

gl.glLightf(id,GL10.GL_SPOT_EXPONENT,exponent);// 衰減指數

}

// 屏蔽射燈

public void disable(){

GL10 gl = GRAPHICS.gl;

gl.glDisable(id);

}

}

Android遊戲之材質

Android遊戲之材質

物體都由特定材質構成.材質決定照射在物體上光返射方式並會改變反射光顏色.材質為多邊形設置材質屬性用於光照計算,它是全域性影響所有繪製多邊形,直到它在次調用.OpenGL ES中需要為每種材質指定『環境色』『漫反射色』『鏡面反射色』RGBA顏色值.此材質吸收光.只有『光源顏色』與『材質顏色』最小值運算(RGB值)得到『反射光顏色』

材質顏色 光源顏色 反射光顏色『最小值運算』
(0,1,0) (1,1,1) (0,1,0)
(0,1,0) (1,0,0) (0,0,0)
(0,0,1) (1,1,1) (0,0,1)

材質類代碼

public class Material {

private float[] ambient  = {1.0f, 1.0f, 1.0f, 1.0f};// 材質-環境色

private float[] diffuse  = {1.0f, 1.0f, 1.0f,  1.0f};// 材質-漫反射色

private float[] specular = {1.0f, 1.0f, 1.0f, 1.0f};// 材質-鏡面顏色

//設置材質環境色

public void setAmbient(float r,float g,float b){

ambient[0]=r;

ambient[1]=g;

ambient[2]=b;

ambient[3]=1;

}

// 設置材質漫反射色

public void setDiffuse(float r,float g,float b){

diffuse[0]=r;

diffuse[1]=g;

diffuse[2]=b;

diffuse[3]=1;

}

// 設置材質鏡面反射色

public void setSpecular(float r,float g,float b){

specular[0]=r;

specular[1]=g;

specular[2]=b;

specular[3]=1;

}

//使能材質

public void enable(){

GL10 gl = GRAPHICS.gl;

gl.glMaterialfv(GL10.GL_FRONT_AND_BACK,GL10.GL_AMBIENT,  ambient, 0);// 環境色

gl.glMaterialfv(GL10.GL_FRONT_AND_BACK,GL10.GL_DIFFUSE,  diffuse, 0);//  漫反射色

gl.glMaterialfv(GL10.GL_FRONT_AND_BACK,GL10.GL_SPECULAR, specular,0);//  鏡面反射色

}

}

Android遊戲之定向光

Android遊戲之定向光

定向光具有方向但沒有位置.首先在3D空間定義一個點,而『方向』表示為該點指向『原點』向量之方向.若在3D空間右則射過來定向光

public class LightDirectional {

private float[] ambient  = {1.0f, 1.0f, 1.0f, 1.0f};// 點光-環境色

private float[] diffuse  = {1.0f, 1.0f, 1.0f, 1.0f};// 點光-漫反射色

private float[] specular = {0.0f, 0.0f, 0.0f, 1.0f};// 點光-高光顏色
private float[] direction = {0, 0, -1, 0};// 定向光-方向

int id = 0;//  燈光ID

構造定向光.燈光id:GL10.GL_LIGHT0至GL10.GL_LIGHT7

public LightDirectional(int ID){

this.id = ID;//  燈光ID

}

設置方向,將位置轉換為方向.將w分量設0,代表方向

public void setDirection(float x,float y,float z){

direction[0] = -x;

direction[1] = -y;

direction[2] = -z;

direction[3] = 0;

}

設置定向光顏色

public void setColor(float r,float g,float b){

ambient[0] = r;

ambient[1] = g;

ambient[2] = b;

ambient[3] = 1;

}

使能設置頂向光顏色環境色、漫反射色、高光顏色、位置.最後一個參數是數組索引

public void enable(){

GL10 gl = GRAPHICS.gl;

gl.glEnable(id);//使能

gl.glLightfv(id,GL10.GL_AMBIENT, ambient, 0);

gl.glLightfv(id,GL10.GL_DIFFUSE, diffuse, 0);

gl.glLightfv(id,GL10.GL_SPECULAR, specular, 0);

gl.glLightfv(id,GL10.GL_POSITION, direction, 0);

}

定向光屏蔽

public void disable(GL10 gl){

gl.glDisable(id);

}

}