波士頓動力之Handle

波士頓動力之Handle
波士頓動力之Handle

『Handle』是美國波士頓動力種製作的機器人,它將兩個車輪裝在雙腿,結合波士頓動力之前製作的『四足動物』和『兩足機器人』的動力學、平衡和移動操縱原理.它的結構非常簡單只有10個驅動關節.車輪在崎嶇地表都能高速走動『落斜』『落樓梯』『自轉』『單邊橋』『跳欄』.雙腿幾乎可以在任何地方行走.比起通過雙腿或四足走動的機器人更高效.通過雙腿與車輪結合『Handle』具有兩全其美的優點.充滿電後大約可行使24km.
『Handle』通過液壓制動可以拿起超過45KG(100磅)的負重,但雙腿卻很細可以在狹小的空間內移動.所有關節都自動進行了協調,實現高難度動作.如果量產搬運工要失業.

參數 數值
高度 2m
體重 105kg
速度 14.5km/h
跳高 1.2米
負重 45kg
動力 電池
驅動 液壓與電動
感知 深度相機
關節 10個

 

 

波士頓動力之SpotMini

波士頓動力之SpotMini
波士頓動力之SpotMini

SpotMini是波士頓動力公司設計的小型四足機器人,可在家居和辦公環境靈活走動.它有兩個版本,無頭版只重25kg,裝上『雞頭』也只是30kg.完全使用電池作為動力,是波士頓動力目前最安靜的計器人.完全充電後可以活動90分鐘.

SpotMini繼承了它的大佬SPOT的所有機動性, 而且增加五軸自由活動的手臂.和增強型傳感器拾取物體和處理物體的能力.傳感器裝置包括『立體相機』、『深度相機』、『姿態測量器』以及裝在四肢的『位置傳感器』與『力量傳感器』.這些傳感器都有助於加強SpotMini導航和移動的操控能力.

更示範『無頭SpotMini』因開唔到門而Call『雞頭SpotMini』開門的過程.然後一起通過.

參數 數值
高度 0.84m
體重 30kg
負重 14kg
動力 電池
驅動 電動
感知 三維視覺系統
關節 17個

 

OpenGL之紋理映射字體

OpenGL之紋理映射字體

因為『3D輪廓字體』只是填充純色,但可以對『3D輪廓字體』應用紋理映射,以增強其外觀效果.紋理座標可以讓OpenGL自動生成.演示程式下載:

1.讓OpenGL為文本生成紋理座標,並固定於3D模型

glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);

glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);

glEnable(GL_TEXTURE_GEN_S);

glEnable(GL_TEXTURE_GEN_T);

2.載入紋理

Load_File_Texture(&font3D->texture, hInstance, filename);

3.綁定紋理

glBindTexture(GL_TEXTURE_2D, texture->texID);

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_LINEAR);

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);

OpenGL之3D輪廓字體

OpenGL之3D輪廓字體

之前一直使用Windows自帶字體輸出文本,但只限2D的『位圖字體』.在Windows下有獨有輪廓字體函式.讓文本具有一定的厚度.讓所有的Windows字體轉換成3D字體.演示程式可輸入英文字符,下載程式:

1.存儲輪廓字體位置和方向,生成256個GLYPHMETRICSFLOAT變量

GLYPHMETRICSFLOAT gmf[256];

2.創建大小為256個字符的顯示列表,對所有256個ASCII碼支持.

UINT base;// 顯示列表的BASE ID

base = glGenLists(256);

3.創建字體句柄

HFONT font;

font=CreateFont(1,0,0,0,FW_BOLD,FALSE,FALSE,FALSE,ANSI_CHARSET,OUT_TT_PRECIS,CLIP_DEFAULT_PRECIS,NTIALIASED_QUALITY,FF_DONTCARE|DEFAULT_PITCH,”Arial”);

4.為字體選擇設備環境

SelectObject(hDC,font);

5.創建3D輪廓字體,每個ASCII對應一個輪廓字體

wglUseFontOutlines(hDC,0,256,base,0.0f,FONT3D_DEPTH,WGL_FONT_POLYGONS,gmf);

6.複製當前矩陣並壓棧

glPushMatrix();

7.將文本定位於場景空間的中央.計算文本的長度

length = (int)strlen(text);

for(int i=0;i<length; ++i)

{

char  c = text[i];

width = width + gmf[c].gmfCellIncX;

if(gmf[c].gmfCellIncX > height )

height = gmf[c].gmfCellIncX;

}

8.設定文本座標

glTranslatef(posX – (width0.1f)/2.0f,posY – (height0.1f)/2.0f ,posZ + (FONT3D_DEPTH*0.1f)/2.0f);

9.顯示列表屬性壓棧

glPushAttrib(GL_LIST_BIT);

10.載入顯示列表ID

glListBase(base);

11.渲染文本

glCallLists((int)strlen(text),GL_UNSIGNED_BYTE,text);

12.顯示列表屬性出棧

glPopAttrib();

OpenGL之位圖字體

OpenGL之位圖字體

要在屏幕上顯示文本可以使用Windows自帶字體進行渲染.比起之前使用『點陣字體』方便簡潔很多,但此方法只式用於Windows.演示程式可輸入英文字符,下載程式:

1.創建96個顯示列表IDs,存儲生成的字符位圖

UINT base;// 顯示列表的BASE ID

base = glGenLists(96);//創建大小為96BYTE的顯示列表

2.創建顯示列表後,使用CreateFont()創建字體

HFONT font;// 字體句柄

font=CreateFont(12,0,0,0,FW_BOLD,FALSE,FALSE,FALSE,ANSI_CHARSET,OUT_TT_PRECIS,CLIP_DEFAULT_PRECIS,ANTIALIASED_QUALITY,FF_DONTCARE | DEFAULT_PITCH,”Courier”);

3.為字體選擇一個設備環境

SelectObject(hDC,font);

4.從系統載入字體文檔並生成位圖.

wglUseFontBitmaps(hDC,32,96,base);

5.設定屏幕位置

glRasterPos2i(xPos,yPos);

7.顯示列表屬性壓棧

glPushAttrib(GL_LIST_BIT);

6.載入顯示列表ID

glListBase(base-32);

7.渲染文本

glCallLists((int)strlen(text),GL_UNSIGNED_BYTE,text);

8.顯示列表屬性出棧

glPopAttrib();

USB3.0前置分線器

USB3.0前置分線器

以前買過幾款USB分線器質量都不太好.在網上購得這款USB3.0分線器.支持一拖四.需要主板內置USB3.0/3.1(SuperSpeed USB)端口(19針)與SATA-5V電源.佔用3.5寸FDD(軟驅位).芯片是臺灣的創惟Genesys Logic的GL3520.經測試我的Seagete移動硬碟插主板的後置USB是拖唔起的(除非換成雙USB供電).但這個USB3.0分線器帶有5V電源所以供電充足.喂一的缺點是不支持USB3.1

OpenGL之視錐體裁剪

OpenGL之視錐體裁剪

圖形引擎繪製任何睇不見(視錐截體之外)的任何物體,都會浪費保貴GPU資源.相機的視錐體定義你所能夠梯到的3D世界空間.視錐體由相機的位置和視野組成.視錐體由六個平面組成.只要進入視錐體內的3D模型都應被渲染.(被其它3D模型遮檔除外).位於視錐體之外則不必渲染.

OpenGL會自動丟棄在視錐體之外的三角形.但OpenGL是逐個三角形進行視錐體裁剪.當你有大量(幾萬個)的三角形進入OpenGL裁剪隊列時.會大大地降低程式性能.

最簡單的優化方式是定義3D球形容器,用於包裹你的3D模型.然後使用視錐體與3D球形進行測試.如果3D球形完全在視錐體之外.即可放棄渲染3D模型.如果3D模型部分或全部進入視錐體內,則交由OpenGL繼序進行三角形裁剪

演示程式中有幾百個隨機移動球體,按空格鍵啟用或禁用『視錐體裁剪』.未啟用之前不到200幀.一但啟動『視錐體裁剪』則超過1000幀.性能大幅提高五倍(視渲染球體的個數而定).程式下載:

 

定義3D球體

typedef struct SPHERE3D{

float    x, y, z;// 中心點

float    radius;// 球體半徑

}SPHERE3D,* SPHERE3D_PTR;

 

定義3D平面

typedef struct PLANE3D_TYP{

float A, B, C;// 平面法線向量

float D;//平面到原點最近距離

}PLANE3D,*PLANE3D_PTR;

 

定義視錐體

typedef struct FRUSTUM_TYP {

PLANE3D planes[6];//6個平面

}FRUSTUM, *FRUSTUM_PTR;

 

1.平面方程式定義:

Ax + By + Cz + D = 0

A,B,C:平面的法線向量

D:從平面到原點的距離

x,y,z:平面上的任意點

結果為零:該點落在平面上

結果為正:該點為于平面的前方

結果為負:該點為於平面的後方

 

2.確定視錐體尺寸,獲取投影矩陣和模型視口矩陣

glGetFloatv(GL_PROJECTION_MATRIX, (GLfloat*)&projection);

glGetFloatv(GL_MODELVIEW_MATRIX, (GLfloat*)&modelview);

 

3.投影矩陣乘以模型視口矩陣

glPushMatrix();

glLoadMatrixf((GLfloat*)&projection);

glMultMatrixf((GLfloat*)&modelview);

glGetFloatv(GL_MODELVIEW_MATRIX, (GLfloat*)&modelview);

glPopMatrix();

 

4.提取視錐體的六個平面

int scale = (row < 0) ? -1 : 1;

row = abs(row) – 1;

plane->A = mat->M[0][3] + scale * mat->M[0][row];

plane->B = mat->M[1][3] + scale * mat->M[1][row];

plane->C = mat->M[2][3] + scale * mat->M[2][row];

plane->D = mat->M[3][3] + scale * mat->M[3][row];

平面(plane) 行(row)
左則 1
右則 -1
底部 2
頂部 -2
近端 3
遠端 -3

 

5.平面歸一化

float length = sqrtf(plane->A * plane->A + plane->B * plane->B + plane->C * plane->C);

plane->A /= length;

plane->B /= length;

plane->C /= length;

plane->D /= length;

 

6.檢查3D球體是否為於視錐體內

frustum:視錐體

sphere:球體

返回值:若在視錐體內返回TRUE,否則反回FALSE

bool Compute_Sphere_In_Frustum(FRUSTUM_PTR frustum, SPHERE3D_PTR sphere)

{

float dist;

for (int i=0;i<6;++i)

{// 判斷球體是否為與六個平面之前

PLANE3D_PTR plane = &frustum->planes[i];

// 計算點與平面的距離,若為正在視錐體內,若為負在視錐體外

dist = plane->A * sphere->x + plane->B * sphere->y + plane->C * sphere->z + plane->D;

if (dist <= -sphere->radius)

return false;// 在視錐體外

}

return true; // 在視錐體內

}

 

OpenGL之數組鎖定

OpenGL之數組鎖定

OpenGL允許鎖定(lock)與解鎖(unlock)數組.當鎖定(lock)數組後,數據便不能更改.當存在大量共用的頂點,並且進行多次操作.能大大地提高運行速度

 

數據初此化後鎖定數組

void glLockArraysEXT(GLint first, GLsizei count);

first:頂點索引

count:頂點個數

 

程序退出時對數組解鎖

void glUnlockArraysEXT(void);

 

演示程式中,因為地形數據不會改變,對其進行鎖定.按空格鍵可切換鎖定(lock)與解鎖(unlock).幀數大約提升10%.只是兩行代碼就有不小的性能改進.下載:

OpenGL之頂點數組與多紋理映射

OpenGL之頂點數組與多紋理映射
將頂點數組『VertexArray』應用於多紋理『Multitexture』映射,由於每個紋理單元都有其自已的狀態.要將每個紋理單元都單度地啟用頂點數組,並且為其每個紋理單元設定紋理座標的頂點數組.通過常試可以將多個2D紋理(GL_TEXTURE_2D)進行映射,但2D紋理與1D紋理(GL_TEXTURE_1D)多次償試都無法將『頂點數組』應用『紋理數組』映射暈.演示程式按空格鍵切換『多紋理映射』草地紋理與高度紋理.兩者幀數相約.下載:

 

要讓紋理單元使用頂點數組,必須先激活它.

void glClientActiveTexture(GLenum texture);

texture:紋理單元索引GL_TEXTURE0_ARB~GL_TEXTURE31_ARB

 

啟用紋理單元頂點座標數組

void glEnableClientState(GLenum array);

禁用紋理單元頂點座標數組

void glDisableClientState(GLenum array);

array:GL_TEXTURE_COORD_ARRAY 紋理座標數組

 

為紋理單元設定指定數組

void WINAPI glTexCoordPointer(Glint size,GLenum type,GLsizei stride,const GLvoid  *pointer);

 

設置兩個紋理單元設置頂點數組

glClientActiveTexture(GL_TEXTURE0_ARB);// 激活紋理0 

glEnableClientState(GL_VERTEX_ARRAY); // 啟用頂點數組

glEnableClientState(GL_TEXTURE_COORD_ARRAY); // 啟用紋理座標數組

glVertexPointer(3, GL_FLOAT, 0, terrain->vertex_array);// 頂點數組

glTexCoordPointer(3, GL_FLOAT, 0, terrain->grass_texcoord);// 紋理數組

glClientActiveTexture(GL_TEXTURE1_ARB);// 激活紋理1

glEnableClientState(GL_TEXTURE_COORD_ARRAY);

glTexCoordPointer(3, GL_FLOAT,0, terrain->height_texcoord);// 紋理數組

glDrawArrays(GL_TRIANGLES, 0, polygon_num);// 繪畫所有當前以啟用的頂點數組

glDisable(GL_TEXTURE_1D);// 禁用紋理單元1

glClientActiveTexture(GL_TEXTURE0_ARB);// 重新激活紋理0,這個很重要否則會影響其它紋理貼圖

glDisableClientState(GL_VERTEX_ARRAY); // 禁用頂點數組

glDisableClientState(GL_TEXTURE_COORD_ARRAY); // 禁用紋理座標數組

glDisableClientState(GL_NORMAL_ARRAY);// 禁用法線數組