CRC32校驗

CRC32校驗
CRC32校驗

『CRC32』同『MD5』『SHA1』壹樣,計『貳进制』數值『指紋』,佢速度快,HASH校验值肆字節.两DWORD值相等比較. 适宜網络數據傳輸, 校驗數據係咪完璧.

DWORD CRC32_Table[256] = {
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba,
0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,
0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940,
0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116,
0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a,
0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818,
0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c,
0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086,
0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4,
0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe,
0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252,
0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60,
0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04,
0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a,
0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e,
0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0,
0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6,
0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d,
};

DWORD CRC32(PBYTE buf, int len){
int i;
DWORD crc;

crc = 0xffffffffL;
for (i = 0; i < len; ++i )
crc = CRC32_Table[(crc ^ buf[i]) & 0xff] ^ (crc >> 8);

crc = crc ^ 0xffffffffL;
return crc;
}

 

色鑑-丹色

色鑑-丹色
色鑑-丹色

『丹』主成份係水銀同硫磺天然礦物.愛蒞整顏料同入藥. 所以『丹色』含有劇毒性.色近紅土色, 比『朱色』偏紅.

紅亦即火屬,驅魔消厄.神社神宫神殿木制建築皆塗『丹色』, 呌『丹塗』.

木表層『丹塗』可防蟲蛀.

『丹色』取自天然礦石『鉛丹』, 又呌『光明丹』.

丹色 光明丹
源料 鉛丹
英文 Cinnabar
RGB  
RGB  
CMYK C=0 M=59 Y=78 K=11

C=0 M=68 Y=80 K=20

用途 天然紅色顏料

 

色鑑-綠青

色鑑-綠青
色鑑-綠青

『綠青』源自『孔雀石』,天然綠色顏料.作為傳統綠色顏料,愛蒞畫草草木木.

將天然『孔雀石』敲碎磨粉.又呌『岩綠青』/『松葉綠青』.

神殿屋頂採用綠青色銅瓦.

青銅佛像長期好天曬落雨淋. 青銅氧化生鏽. 此視像亦呌『綠青』.

綠青 岩綠青/松葉綠青
  孔雀石/ Malachite
英文  
RGB R=108 g=160 b=129

R=76 g=142 b=112

RGB 0x6ca081

0x4c8e70

CMYK C=62 M=23 Y=55 K=0

C=70 M=25 Y=60 K=10

用途 天然綠色顏料

 

年號

年號
年號

年號愛蒞紀年,『天皇更替』『天災人禍』之時更改年號.

飛鳥時代-年號/元號 儒略曆 天皇
大化 645年6月 孝德天皇
白雉 650年2月
朱鳥 686年7月 天武天皇
大寶 701年3月 文武天皇
慶雲 704年5月
和銅 708年正月 元明天皇

 

奈良時代-年號 儒略曆  
靈龜 715年九月 元正天皇
養老 717年十一月
神龜 724年二月 聖武天皇
天平 729年八月
天平感寶 749年四月
天平勝寶 749年七月 孝謙天皇
天平寶字 757年八月
天平神護 765年正月 稱德天皇
神護景雲 767年八月
寶龜 770年十月 光仁天皇
天應 781年四月
延曆 782年八月 桓武天皇

 

平安時代-年號 儒略曆 天皇
大同 806年五月 平城天皇
弘仁 810年九月 嵯峨天皇
天長 824年正月 淳和天皇
承和 834年正月 仁明天皇
嘉祥 848年六月
仁壽 851年四月 文德天皇
齊衡 854年十一月
天安 857年二月
貞觀 859年四月 清和天皇
元慶 877年四月 陽成天皇
仁和 885年二月 光孝天皇
寬平 889年四月 宇多天皇
昌泰 898年四月 醍醐天皇
延喜 901年七月
延長 923年閏四月
承平 931年四月 朱雀天皇
天慶 938年五月
天曆 947年四月 村上天皇
天德 957年十月
應和 961年二月
康保 964年七月
安和 968年八月 冷泉天皇
天祿 970年三月 圓融天皇
天延 973年十二月
貞元 976年七月
天元 978年十一月
永觀 983年四月
寬和 985年四月 花山天皇
永延 987年四月 一條天皇
永祚 989年八月
正曆 990年十一月
長德 995年二月
長保 999年正月
寬弘 1004年七月
長和 1012年十二月 三條天皇
寬仁 1017年四月 後一條天皇
治安 1021年二月
萬壽 1024年七月
長元 1028年七月
長曆 1037年四月 後朱雀天皇
長久 1040年十一月
寬德 1044年十一月
永承 1046年四月 後冷泉天皇
天喜 1053年正月
康平 1058年八月
治曆 1065年八月
延久 1069年四月 後三條天皇
承保 1074年八月 白河天皇
承曆 1077年十一月
永保 1081年二月
應德 1084年二月
寬治 1087年四月 堀河天皇
嘉保 1094年十二月
永長 1096年十二月
承德 1097年十一月
康和 1099年八月
長治 1104年二月
嘉承 1106年四月
天仁 1108年八月 鳥羽天皇
天永 1110年七月
永久 1113年七月
元永 1118年四月
保安 1120年四月
天治 1124年四月 崇德天皇
大治 1126年正月
天承 1131年正月
長承 1132年八月
保延 1135年四月
永治 1141年七月
康治 1142年四月 近衛天皇
天養 1144年二月
久安 1145年七月
仁平 1151年正月
久壽 1154年十月
保元 1156年四月 後白河天皇
平治 1159年四月 二條天皇
永曆 1160年正月
應保 1161年九月
長寬 1163年三月
永萬 1165年六月
仁安 1166年八月 六條天皇
嘉應 1169年四月 高倉天皇
承安 1171年四月
安元 1175年七月
治承 1177年八月
養和 1181年七月 安德天皇
壽永 1182年五月
元曆 1184年四月 後鳥羽天皇

 

鎌倉時代-年號 儒略曆 天皇
文治 1185年八月 後鳥羽天皇
建久 1190年四月
正治 1199年四月 土御門天皇
建仁 1201年二月
元久 1204年二月
建永 1206年四月
承元 1207年十月
建曆 1211年三月 順德天皇
建保 1213年十二月
承久 1219年四月
貞應 1222年四月 後堀河天皇
元仁 1224年十一月
嘉祿 1225年四月
安貞 1227年十二月
寬喜 1229年三月
貞永 1232年四月
天福 1233年四月 四條天皇
文曆 1234年十一月
嘉禎 1235年九月
曆仁 1238年十一月
延應 1239年二月
仁治 1240年七月
寬元 1243年二月 後嵯峨天皇
寶治 1247年二月 後深草天皇
建長 1249年三月
康元 1256年十月
正嘉 1257年三月
正元 1259年三月
文應 1260年四月 龜山天皇
弘長 1261年二月
文永 1264年二月
建治 1275年四月 後宇多天皇
弘安 1278年二月
正應 1288年四月 伏見天皇
永仁 1293年八月
正安 1299年四月 後伏見天皇
乾元 1302年十一月 後二條天皇
嘉元 1303年八月
德治 1306年十二月
延慶 1308年十月 花園天皇
應長 1311年四月
正和 1312年三月
文保 1317年二月
元應 1319年四月 後醍醐天皇
元亨 1321年二月
正中 1324年十二月
嘉曆 1326年四月
元德 1329年八月
元弘 1331年八月

 

室町時代-建武新政年號 儒略曆 天皇
建武 1334年正月 後醍醐天皇

 

室町時代-南朝年號 儒略曆 天皇
延元 1336年二月 後醍醐天皇
興國 1340年四月 後村上天皇
正平 1346年四月
建德 1370年十二月 長慶天皇
文中 1372年三月
天授 1375年五月
弘和 1381年二月
元中 1384年四月 後龜山天皇

 

室町時代-北朝年號 儒略曆 天皇
建武 1336年二月 光明天皇
曆應 1338年八月
康永 1342年四月
貞和 1345年十月
觀應 1350年二月 崇光天皇
文和 1352年九月 後光嚴天皇
延文 1356年三月
康安 1361年三月
貞治 1362年九月
應安 1368年二月
永和 1375年二月 後圓融天皇
康曆 1379年三月
永德 1381年二月
至德 1384年二月 後小松天皇
嘉慶 1387年八月
康應 1389年二月
明德 1390年三月

 

室町時代-明德統一年號 儒略曆 天皇
應永 1394年七月 後小松天皇
正長 1428年四月 稱光天皇
永享 1429年九月 後花園天皇
嘉吉 1441年二月
文安 1444年二月
寶德 1449年七月
享德 1452年七月
康正 1455年七月
長祿 1457年九月
寬正 1460年十二月
文正 1466年二月 後土御門天皇
應仁 1467年三月
文明 1469年四月
長享 1487年七月
延德 1489年八月
明應 1492年七月
文龜 1501年二月 後柏原天皇
永正 1504年二月
大永 1521年八月
享祿 1528年八月 後奈良天皇
天文 1532年七月
弘治 1555年十月
永祿 1558年二月 正親町天皇

 

安土桃山時代-年號 儒略曆 天皇
元龜 1570年四月 正親町天皇
天正 1573年七月
文祿 1592年十二月 後陽成天皇
慶長 1596年十月

 

江戶時代-年號 儒略曆 天皇
元和 1615年七月 後水尾天皇
寬永 1624年二月
正保 1644年十二月 後光明天皇
慶安 1648年二月
承應 1652年九月
明曆 1655年四月 後西天皇
萬治 1658年七月
寬文 1661年四月
延寶 1673年九月 靈元天皇
天和 1681年九月
貞享 1684年二月
元祿 1688年九月 東山天皇
寶永 1704年三月
正德 1711年四月 中御門天皇
享保 1716年六月
元文 1736年四月 櫻町天皇
寬保 1741年二月
延享 1744年二月
寬延 1748年七月 桃園天皇
寶曆 1751年十月
明和 1764年六月 後櫻町天皇
安永 1772年十一月 後桃園天皇
天明 1781年四月 光格天皇
寬政 1789年正月
享和 1801年二月
文化 1804年二月
文政 1818年四月 仁孝天皇
天保 1830年十二月
弘化 1844年十二月
嘉永 1848年二月 孝明天皇
安政 1854年十一月
萬延 1860年三月
文久 1861年二月
元治 1864年二月
慶應 1865年四月

 

一世一元-年號 儒略曆 天皇
明治 1868年舊曆9月 明治天皇
大正 1912年7月 大正天皇
昭和 1926年12月 昭和天皇
平成 1989年1月 明仁天皇
令和 2019年5月 德仁天皇

 

禮拜行星

禮拜 行星 希臘神祇
禮拜日SUNDAY 日曜日 太陽神
禮拜壹MONDAY 月曜日 月光女神
禮拜貳TUESDAY 火曜日 戰神
禮拜三WEDNESDAY 水曜日 神使
禮拜肆THURSDAY 木曜日 天神
禮拜伍FRIDAY 金曜日 愛神
禮拜陸SATURDAY 土曜日 農神

 

馬騮分桃

馬騮分桃
馬騮分桃
馬騮分桃
馬騮分桃
馬騮分桃
馬騮分桃
馬騮分桃

『甲』『乙』『丙』『丁』『戊』伍祗『馬騮仔』相約摘桃,日落後斟酌,聽朝再蒞分桃.

入夜後『甲』『馬騮』先蒞, 左等右等其它『馬騮仔』都未蒞,先将桃『平分5份』, 仲多出『1個桃』, 佢覚得自己甘辛苦,多喫『1個桃』都應份, 喫多出蒞『1個桃』後兼拎走『1份桃』. 净低『4份桃』推翻埋一堆.

『乙』『馬騮』跟住蒞, 先将桃『平分5份』, 仲係多出『1個桃』, 喫多出蒞『1個桃』後再拎走『1份桃』. 净低『4份桃』推翻埋一堆.

其它『馬騮仔』相繼前後腳蒞, 『分桃伍份』,多出『壹個桃』喫咗落肚, 後拎走『壹份桃』. 净落『4份桃』堆翻埋一堆.

 

問『甲』『乙』『丙』『丁』『戊』伍祗『馬騮仔』至小摘幾多桃?

問『戊』馬騮走後,仲剩幾多桃?

 

此題出自英國物理學家『保羅·狄拉克』. 系電腦時代,變得喫生菜咁喫.

『分桃伍份』,多出『壹個桃』喫咗落肚, 後拎走『壹份桃』.

即『x = x – 1 – (x / 5)』

 

bool test(int x)

{

// 多出『壹個桃』吃咗落肚, 後拎走『壹份桃』.

if ((x % 5) != 1)// 『甲』

return false;

x = x – 1 – (x / 5);

 

if ((x % 5) != 1)// 『乙』

return false;

x = x – 1 – (x / 5);

 

if ((x % 5) != 1)// 『丙』

return false;

x = x – 1 – (x / 5);

 

if ((x % 5) != 1)// 『丁』

return false;

x = x – 1 – (x / 5);

 

if ((x % 5) != 1)//『戊』

return false;

return true;

}

自1開始,暴力測試.

    for (x = 1; ; ++x)  {

if (test(x) == true) {

printf(“桃總量=%i\r\n”, x);

break;

}

}

 

問『戊』馬騮走後, 仲剩幾多桃 ?

int caleX5 (int x){

// 多出『壹個桃』喫咗落肚, 後拎走『壹份桃』.

x = x – 1 – (x / 5);

x = x – 1 – (x / 5);

x = x – 1 – (x / 5);

x = x – 1 – (x / 5);

x = x – 1 – (x / 5);

return x;

}

 

 

遊戲輵-角度比效

遊戲輵-角度比效
遊戲輵-角度比效

首先角度格式為『0<= A <360』

小於0

while(angle < 0.0f)

angle = angle + 360.0f;

大於等於360

while(angle >= 360.0f)

angle = angle – 360.0f;

事因正圓分360份,即360度.360度即係0度.

當夾角誇越0度, 即BEGIN > END, 要延展角度. 即加360度.

bool Compute_Angle_In_RAC(float angle,float begin,float end){
float    _angle = Format_Angle(angle);//格式角

float    _begin = Format_Angle(begin);//格式角

float    _end  = Format_Angle(end);//格式角

    if(_begin > _end){

_end   = _end + 360;

if(_angle > 0 && _angle < end )

_angle = _angle + 360;

}

    if( _angle >= _begin && _angle <= _end )// 夾角落㸃

return true;

return false;

}

 

 

紋理拼圖

紋理拼圖
紋理拼圖

2D游戲動画幀, 由多幅關鍵幀(keyFrame) 組成. 逐幀渲染產生動画卡通.『幀動画』亦哎呌『紋理』texture. 将多幅『幀動画』存放係單壹紋理.OpenGL可提高渲染速度, 係显存記憶體1MB年代可能冇用. 事因渲染皆係電脑記憶體運作.

係显存記憶體大幅增長, OpenGL渲染係显存記憶體完成. 减小『紋理』載入量, 單壹紋理存放多幅『幀動画』,可提高渲染速度.

係3D游戲亦可用相同技術提飛渲染效率.

void zoom_textcoord_model3D(TEXTURE_PTR texture,int index,int size,VECTOR2D_PTR dest,VECTOR2D_PTR sour,int count,int flag)

 

texture 紋理
index 關鍵幀索引
size 關鍵幀寬高解像
dest 纹理隊列
sour 原始纹理隊列
count 纹理頂點量

計單元格

int cell = texture->width / size;

計索引

int  i  = index % cell;// 橫索引
int  j  = index / cell;// 行索引

計缩放率0.0f < zoom < 1.0f

float    zoom    = (float)size / (float)texture->width;

計『幀』偏移.

float offsetX = (float)zoom * (float)i;
float offsetY = (float)zoom * (float)j;

遍歴UV紋理頂㸃

    for (int p = 0; p < count; ++p){

缩細後移動

dest[p].u = sour[p].u * zoom + offsetX ;
dest[p].v = sour[p].v * zoom + offsetY;

纹理返转

if (flag & MODEL3D_TEXTURE_FLIP)

dest[p].v = 1 – (sour[p].v * zoom + offsetY);}

 

SKYBOX天幕

天幕SKYBOX
天幕SKYBOX
天幕SKYBOX
天幕SKYBOX

『天幕SKYBOX』指巨立方體, 係內籠貼天幕紋理,『天幕紋理』可能係『地平線』『室內』『宇宙』. 『天幕SKYBOX』原㸃與3D相機位置重合. 係遠睇時正确.

由陸幅紋理『顶』『底』『前』『後』『左』『右』組成. 以前『天幕SKYBOX』紋理分陸幅位圖存檔.

陸幅位圖存係單壹『紋理』效率更高. 将『紋理』平分拾陸等分. 足够擺两組『天幕』紋理. 『日頭』『晚黑』各壹. 似上圖咁.

紋理索引:0~15 『日頭』 『晚黑』
顶up 0 8
底dn 1 9
前ft 7 15
后bk 5 13
左lt 6 14
右rt 4 12

定義『天幕SKYBOX』

typedef struct SKYBOX_TYP {
VECTOR3D  pos; 位置
VECTOR3D  rot; 旋轉
TEXTURE_PTR texture; 天幕纹理
float     size; 天幕大细
//TEXTURE_REGION region[16]; 纹理区域
VECTOR3D  vertex_array[36]   ; 天幕顶点
VECTOR2D  texCoord_array[36] ; 天幕紋理
}SKYBOX, *SKYBOX_PTR;

手エ构建『天幕SKYBOX』立方體『3D頂㸃』同『UV紋理』. 正方形以两三角形組成. 紋理左上角[u0, v0], 紋理右下角[u1,v1].天幕大细『size』.

天『UV紋理』 『xyz頂㸃』
texCoord[0]=[u1, v1] vertex_array[0]=[-size, size, -size]
texCoord[1]=[u0, v1] vertex_array[1]=[size, size, -size]
texCoord[2]=[u0, v0] vertex_array[2]=[size, size, size]
texCoord[3]=[u1, v1] vertex_array[3]=[-size, size, -size]
texCoord[4]=[u0, v0] vertex_array[4]=[size, size, size]
texCoord[5]=[u1, v0] vertex_array[5]=[-size, size, size]

 

地『UV紋理』 『xyz頂㸃』
texCoord[6]=[u1, v1] vertex_array[6]=[size, -size, -size]
texCoord[7]=[u0, v1] vertex_array[7]=[-size, -size, -size]
texCoord[8]=[u0, v0] vertex_array[8]=[-size, -size, size]
texCoord[9]=[u1, v1] vertex_array[9]=[size, -size, -size]
texCoord[10]=[u0, v0] vertex_array[10]=[-size, -size, size]
texCoord[11]=[u1, v0] vertex_array[11]=[size, -size, size]

 

前『UV紋理』 『xyz頂㸃』
texCoord[12]=[u0, v0] vertex_array[12]=[-size, -size, -size]
texCoord[13]=[u1, v0] vertex_array[13]=[size, -size, -size]
texCoord[14]=[u1, v1] vertex_array[14]=[size, size, -size]
texCoord[15]=[u0, v0] vertex_array[15]=[-size, -size, -size]
texCoord[16]=[u1, v1] vertex_array[16]=[size, size, -size]
texCoord[17]=[u0, v1] vertex_array[17]=[-size, size, -size]

 

后『UV紋理』 『xyz頂㸃』
texCoord[18]=[u0, v0] vertex_array[18]=[size, -size, size]
texCoord[19]=[u1, v0] vertex_array[19]=[-size, -size, size]
texCoord[20]=[u1, v1] vertex_array[20]=[-size, size, size]
texCoord[21]=[u0, v0] vertex_array[21]=[size, -size, size]
texCoord[22]=[u1, v1] vertex_array[22]=[-size, size, size]
texCoord[23]=[u0, v1] vertex_array[23]=[size, size, size]

 

右『UV紋理』 『xyz頂㸃』
texCoord[24]=[u1, v0] vertex_array[24]=[size, -size, size]
texCoord[25]=[u1, v1] vertex_array[25]=[size, size, size]
texCoord[26]=[u0, v1] vertex_array[26]=[size, size, -size]
texCoord[27]=[u1, v0] vertex_array[27]=[size, -size, size]
texCoord[28]=[u0, v1] vertex_array[28]=[size, size, -size]
texCoord[29]=[u0, v0] vertex_array[29]=[size, -size, -size]

 

左『UV紋理』 『xyz頂㸃』
texCoord[30]=[u1, v0] vertex_array[30]=[-size, -size, -size]
texCoord[31]=[u1, v1] vertex_array[31]=[-size, size, -size]
texCoord[32]=[u0, v1] vertex_array[32]=[-size, size, size]
texCoord[33]=[u1, v0] vertex_array[33]=[-size, -size, -size]
texCoord[34]=[u0, v1] vertex_array[34]=[-size, size, size]
texCoord[35]=[u0, v0] vertex_array[35]=[-size, -size, size]

 

Android两指縮放

Android两指縮放
Android两指縮放

之前做Android 游戲皆单㸃触摸, 諗住係風水羅盤實現两指縮放.

触摸分叁動作『鬆』『撳』『拖』.

動作 注释
#define TOUCH_UP      1
#define TOUCH_DOWN    2
#define TOUCH_DRAGGED 3

雙手拾指, 除非用埋脚指

#define MAX_FINGER    10 拾指

定義TOUCH結构, 用蒞存拾指『方位』同『動作』

TOUCH結构 注释
typedef struct TOUCH_STR{
    int count; 手指量, 最多10指
    int action[MAX_FINGER]; 動作
    int x[MAX_FINGER]; X座標
    int y[MAX_FINGER]; Y座標
}TOUCH,*TOUCH_PTR;

用栈stack蒞存触摸,

#define MAX_TOUCH     32 棧高32
TOUCH touch_array[MAX_TOUCH] ; 触摸棧
int   touch_count; 棧頂

棧頂加壹, 每次存触摸『方位』同『動作』前調用

int Add_Touch(){

TOUCH_PTR touch;

int index;

if(touch_count >= MAX_TOUCH)

return touch_count;

index = touch_count;

++touch_count;// 棧頂加壹

touch = &touch_array[index];

touch->count = 0;

return touch_count;

}

棧頂减壹, 讀『方位』同『動作』後調用

int Sub_Touch(){

if(touch_count <= 0)

return touch_count;

–touch_count;

return touch_count;

}

存触摸『方位』同『動作』, finger係手指索引

bool Set_Touch(int finger,int action,float x,float y){

int index;

TOUCH_PTR touch;

index = touch_count-1; // 棧頂

touch = &touch_array[index];

if(touch->count < finger + 1)

touch->count = finger + 1;

touch->action[finger] = action;

touch->x[finger] = x ;

touch->y[finger] = y ;

return true;

}

讀触摸, 『方位』同『動作』, finger係手指索引

bool Get_Touch(int finger,int * action,int * x,int * y){

TOUCH_PTR  touch;

int index;

if(touch_count == 0)

return false;

index = touch_count – 1;

touch = &touch_array[index];

*action = touch->action[finger];

*x = touch->x[finger];

*y = touch->y[finger];

return true;

}

計两指(x0,y0)(x1,y1)縮放時中心位(cx,cy)

float cx = (x0 – x1)/2 + x1;
float cy = (y0 – y1)/2 + y1;

2D触摸坐标转屏幕坐标

VECTOR2D touchPoint2D; 2D触摸點(x,y)
VECTOR3D touchPoint3D; 3D触摸點(x,y,z)

触摸坐标转3D世界坐标

Init_VECTOR2D(&touchPoint2D, cx, cy);
TouchToWorld(camera3D, &touchPoint2D, &touchPoint3D);

計两指距,

Init_VECTOR2D(&v0,x0,y0);
Init_VECTOR2D(&v1,x1,y1);
Sub_VECTOR2D(&vdiff,&v0,&v1);
length = Length_VECTOR2D(&vdiff);

指距拉開放大, 两指行埋縮細. 通過移3D相機實現縮放.

if(_length > length ) y = Camera3D.pos.y + 2; 縮細
if(_length < length ) y = Camera3D.pos.y – 2; 放大

 

游戲輵-弧形碰撞

游戲輵-弧形碰撞
游戲輵-弧形碰撞

事因『風水羅盤』由弧扇形基座組成. 要開發弧扇形碰撞技術.

先定義弧扇結构, 『角度』『弧度』係硬幣两面, 係相, 可相互轉換換

角度 = 弧度 * 180.0/PI
弧度= 角度 * PI/180.0

弧扇形基座有两『弧度』相等弧形, 离中點距离唔同, 遠离中點弧.較埋中點弧,

typedef struct ARC2D_TYP { 弧扇結构
VECTOR2D center; 中心點
float angle; 角度
float rotate; 轉旋
float far; 最远點
float near; 最近點
}ARC2D, *ARC2D_PTR;  

首要判断命中㸃是咪係『最远點』『最近點』之間.

命中㸃

Init_VECTOR2D(&va,x,y);

計觸摸㸃同弧中心㸃距離

Sub_VECTOR2D(&vdiff, &arc->center, &va);

計向量長度

float length = Length_VECTOR2D(&vdiff);

判断命中弧線之間

if(length < arc->near || length > arc->far )

return false;

計落點位於弧扇夹角之間. 弧扇夹两邊長壹致. 即等邊三角形, 視同两直角三角形.

sin(a)= 對邊/斜邊.  
a= asinf (對邊/斜邊) asinf(弧度)

計弧扇邊長

Copy_VECTOR2D(&va,&vdiff);

Init_VECTOR2D(&vb,0,length);

Sub_VECTOR2D(&vdiff, &va, &vb);

cEdge = Length_VECTOR2D(&vdiff);

計va和vb之间的夹角

cAngle = RAD_TO_DEG( asinf((cEdge / 2) / bEdge) ) * 2;

判断命中弧形夹角之間

begin = (-arc->angle/2) + arc->rotate ;

end   = (arc->angle/2) + arc->rotate ;

return Compute_Angle_In_RAC(cAngle, begin, end); // 夹角落㸃

 

判断頂是咪係弧內

bool Compute_Angle_In_RAC(float angle,float begin,float end){

float offset;

angle = Format_Angle(angle);//格式角

begin = Format_Angle(begin);//格式角

end = Format_Angle(end);//格式角

if(_begin > _end){

_end   = _end + 360;

if(_angle > 0 && _angle < end )

_angle = _angle + 360;

}

 

if( _angle >= _begin && _angle <= _end )// 夹角落㸃

return true; return false;

}

 

歸壹角/格式角

float Format_Angle(float angle){

if(angle < 0)

angle = angle + 360;

else

if(angle >= 360)

angle = angle – 360;

return angle;

}

 

 

等腰三角形

等腰三角形
等腰三角形

『等腰三角形』相等兩邊呌『腰』, 另壹邊呌『底』. 兩『腰』夾角叫『頂角』. 『腰』『底』夾角叫『底角』. 兩『底角』角度相等.

『等腰三角形』 簡述
『腰』 『等腰三角形』相等兩邊呌『腰』
『底』 另壹條邊
『頂角』 兩『腰』夾角
『底角』 『腰』『底』夾角, 兩『底角』角度相等.

計『等腰三角形』『頂角』 『底角』

cos(底角)=(底長/2)/ 腰長
底角 = acosf((底長/2)/ 腰長)

『三角形』內角之和180度.

底角+底角+頂角= 180

頂角 = 180 – 底角* 2

 

阿拉伯與羅馬數字對應表

阿拉伯與羅馬數字對應表

在『阿拉伯』數字傳入歐洲時,其數字為古『羅馬』數字. 今用於鐘錶日曆,但『羅馬』數字冇『0』

『羅馬』數字四規

  1. 倍數重複
  2. 三倍限制
  3. 右加左減
  4. 加綫乘千
『羅馬』數字 記數規則 解話
1 表示1
1+1=2 兩個Ⅰ
1+1+1=3 三個Ⅰ
-1+5=4 Ⅴ左則Ⅰ
5 Ⅴ表示5
5+1=6 Ⅴ右則Ⅰ
5+1+1=7 Ⅴ右則兩個Ⅰ
5+1+1+1=8 Ⅴ右則三個Ⅰ
-1+10=12 Ⅹ左則Ⅰ
10 Ⅹ表示10
10+1=11 Ⅹ右則Ⅰ
10+1+1=12 Ⅹ右則兩個Ⅰ

 

『阿拉伯』數字 『古羅馬』數字 WORD便捷鍵
1 ALT+8544
2 ALT+8545
3 ALT+8546
4 ALT+8547
5 ALT+8548
6 ALT+8549
7 ALT+8550
8 ALT+8551
9 ALT+8552
10 ALT+8553
11 ALT+8554
12 ALT+8555
13 XIII
14 XIV
15 XV
16 XVI
17 XVII
18 XVIII
19 XIX
20 XX
21 XXI
30 XXX
40 XL
50 L ALT+8556
60 LX
70 LXX
80 LXXX
90 XC
100 C ALT+8557
200 CC
300 CCC
400 CD
500 D ALT+8558
600 DC
700 DCC
800 DCCC
900 CM/DCCCC
1,000 M ALT+8559
2,000 MM
3,000 MMM
4,000 MV
5,000 V
10,000 X
50,000 L
100,000 C
500,000 D
1,000,000 M

 

 

 

 

Android遊戲之3D矢量

Android遊戲之3D矢量

與『2D矢量』相比『3D矢量』僅是在x,y軸座標加上z軸座標.還有『點積』和『叉積』運算.與繞軸旋轉算法. 無左計算向量角度函式.

public class VECTOR3D {

3D浮點數座標

public float x,y,z;

角度轉弧度

public static float DEGREES_TO_RADIANS = ((1.0f/180.0f)* (float)Math.PI);

弧度轉角度

public static float RADIANS_TO_DEGREES = ((1.0f/(float)Math.PI)*180.0f);

用於繞軸旋轉

private static final float[] matrix = new float[16];

private static final float[] inVec = new float[16];

private static final float[] outVec = new float[16];

購造函式並設定x,y,z

public VECTOR3D(float x, float y,float z){

this.x = x;

this.y = y;

this.z = z;

}

拷貝3D矢量

public VECTOR3D Copy(){

VECTOR3D v;

v=new VECTOR3D(x,y,z);

return v;

}

重設3D矢量數值

public VECTOR3D set(VECTOR3D v){

this.x = v.x;

this.y = v.y;

this.z = v.z;

return this;

}

3D矢量加法運算

public VECTOR3D add(VECTOR3D v){

this.x = this.x + v.x;

this.y = this.y + v.y;

this.z = this.z + v.z;

return this;

}

3D矢量減法運算

public VECTOR3D sub(VECTOR3D v){

this.x = this.x – v.x;

this.y = this.y – v.y;

this.z = this.z – v.z;

return this;

}

3D矢量乘法(即縮放)

public VECTOR3D mul(float scalar){

this.x = this.x * scalar;

this.y = this.y * scalar;

this.z = this.z * scalar;

return this;

}

計算3D矢量長度

public float Len(){

float len;

len = (float) Math.sqrt(x*x+y*y+z*z);

return len;

}

3D矢量單位化,長度為1

public VECTOR3D normer(){

float len;

len = Len();

if(len != 0){

x = x / len;

y = y / len;

z = z / len;

}

return this;

}

繞某軸旋轉,先定義3D矢量,然後設置矩陣為零,然後用rotateM()旋轉,在乘以3D向量

public VECTOR3D rotate(float angle,float axisX,float axisY,float axisZ){

inVec[0] = x;

inVec[1] = y;

inVec[2] = z;

inVec[4] = 1;

Matrix.setIdentityM(matrix, 0);

Matrix.rotateM(outVec,0, angle, axisX, axisY, axisZ);// 選轉

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

x = outVec[0];

y = outVec[1];

z = outVec[2];

return this;

}

計算兩3D矢量之間距離

public float Dist(VECTOR3D v){

float distX = this.x – v.x;

float distY = this.y – v.y;

float distZ = this.z – v.z;

float dist = (float)Math.sqrt(distX*distX + distY*distY + distZ*distZ);

return dist;

}

計算兩個3D矢量之間距離平方

public float DistSquared(VECTOR3D v){

float distX = this.x – v.x;

float distY = this.y – v.y;

float distZ = this.z – v.z;

float dist = distX*distX + distY*distY + distZ*distZ;

return dist;

}

計算兩個3D向量叉積,叉積是一個向量,它與va和vb垂直.

void cross(VECTOR3D va, VECTOR3D vb){

x =  ( (va.y * vb.z) – (va.z * vb.y) );

y = -( (va.x * vb.z) – (va.z * vb.x) );

z =  ( (va.x * vb.y) – (va.y * vb.x) );

}

計算3D向量點積.返回值為浮點數

float dot(VECTOR3D v){

return( (x * v.x) + (y * v.y) + (z * v.z) );

}

3D向量取反數

VECTOR3D inverse(){

this.x = -this.x ;

this.y = -this.y ;

this.z = -this.z ;

return this;

}

}

 

AI之行走

AI之行走

AI也就是『人工智能』在遊戲中實現多數使用『狀態機』.通過定義大量狀態.然後通過條件判斷而切換當前狀態.從而實現對外界作出反應. 當『怪物』它會觀察四周.當你接近它時會另轉面走開.

首先定義下面幾個狀態

#define AI_IDLE       0 // 站立

#define AI_RUN        1 // 奔跑

#define AI_DEATH      3// 死亡

初此AI狀態變量設為站立

int ai = AI_IDLE;

『狀態機』判斷結構

if (ai == AI_IDLE) // 站立

{

}

else

if (ai == AI_RUN)// 奔跑

{

}

else

if (ai == AI_DEATH)// 死亡

{

}

 

站立轉身走開AI代碼

1.首先計算兩者距離

VECTOR3D distance = pos – player.pos;

length = Length_VECTOR3D(&distance);

2.計算『怪物』與『玩加』 矢量之間夾角

Normalize_VECTOR3D(&distance);// 長度歸一

VECTOR3D v;

Init_VECTOR3D(&v, 0, 0, -1);

angle = RAD_TO_DEG(Angle_VECTOR3D(&distance, &v0));// 角度

2.若距離小於10米則會轉身離開

if (length < 10  ){

ai = AI_RUN;// 奔跑

rot.y = (angle – 90) + ((rand() % 90) – 45);// 轉身走開.有45度隨機角度

}

 

遊戲建模之碰撞時間

遊戲建模之碰撞時間

『物體』運動核心是碰撞.你試想下當『物體』高速運動時有可能會穿越牆壁.這因遊戲世界中CPU會輪詢處理所有『物體』. 並只會分到有限『運算/時間』,所以每一次你都需要準確計算碰撞時間.通過不斷遞歸而確定最後移動位置

通過使用基於時間二維方程式進行碰撞檢測.

xf=x0+v0t+(1/2)at2

ax2+bx+c=0

利用係數替換可得到

a=(1/2)*a

b=v0

c=x0-xf

將其擴展可得到三維方程式

xt=cx+bxt+axt2

yt=cy+byt+ayt2

zt=cz+bzt+azt2

如果將三維方程應用於平面方程可得

Axt+Byt+C*zt+D=0

此方程說面如果物體與平面發生碰撞.其碰撞點位於(xt,yt,zt)通過代數運算可得到

(Aax+Bay+Caz)x2+(Abx+Bby+Cbz)x+(Acx+Bcy+Ccz)+D=0

這其實就是平面二次方程式(ax2+bx+c=0) ,其點積形式為:

ax2=(Aax+Bay+Caz)x2=N•(1/2)A

利用點積得到二次方程係數:

加速度係數: a=N•(0.5A)

速度係數:  b=N•V

距離係數:  c=N•X+D

有上序二次方程係數就可計算碰撞時間

float a = n % (acceleration * 0.5f);// 加速度係數

float b = n % velocity;// 速度係數

float c = n % position + D – radius;// 距離係數

若a=0加速度係數為零,碰撞時間等於距離係數除以速度係數.因為距離係數小於零所以要去負值.

collisionTime = -c/b;

若a!=≠0加速度係數不為零,可以使用二次方程計算碰撞時間:

x=(-b+√(b2-4ac) ) / 2a

在計算碰撞時間之前可先計算D=b2-4ac 若D小於零則無解.若D大於零則有解

float D = b * b – 4 * a*c;

if (D > 0) // 如果判斷式大於等於零

collisionTime = (-b – sqrtf(D)) / (2 * a); // 計算碰撞時間

因為發生碰撞物體會彈開,方向矢量產生返射需要重新計算位置.通過減去碰撞時間進行遞歸.直到『幀時間』為零

 

下面是『曲棍球』碰撞函式.

puck 是曲棍球.

table 是球臺

deltaTime是幀時間

void Update_Puck(PUCK_PTR puck, TABLE_PTR table, float deltaTime){

float  fastestTime = deltaTime;// 最早碰撞時間

float  collisionTime;// 碰撞時間

PLANE3D_PTR plane          = NULL;// 平面

PLANE3D_PTR planeCollision = NULL;// 碰撞平面

if (deltaTime <= 0.000f)// 遞歸

return;

// 對球臺四個圍邊檢查碰撞

for (int i = 0; i < 4; i++){

plane = &table->wall[i];// 平面

// 點積二次方程

float a = plane->n % (puck->acceleration * 0.5f);// 加速度係數

float b = plane->n % puck->velocity;// 速度係數

float c = plane->n % puck->position + plane->D – puck->radius;// 距離係數

if (a == 0 && b != 0 && c != 0){// 如果無加速度

// 碰撞時間等於距離除以速度

collisionTime = -c/b;// 碰撞時間

if (collisionTime >= 0 && collisionTime < fastestTime){// 發生碰撞

fastestTime = collisionTime;// 保存碰撞時間

planeCollision = plane;// 平面

}

}

else

if(a != 0){

// 加速度a不等於零

// 計算判別式

float D = b * b – 4 * a*c;

if (D > 0) {// 如果判斷式大於等於零

// 計算碰撞時間

collisionTime = (-b – sqrtf(D)) / (2 * a);

if (collisionTime >= 0.0f && collisionTime < fastestTime) {// 發生碰撞

fastestTime = collisionTime;

planeCollision = plane;

}

}

}

}// END FOR

// 速度設上限每秒800米

if (Length_VECTOR3D(&puck->velocity) > 800)

puck->velocity = Normalize_VECTOR3D(&puck->velocity) * 800;

// 如果冰球正移動,則應用磨擦力

if (Length_VECTOR3D(&puck->velocity) > 0)

puck->acceleration = -puck->velocity * 0.2f;// 計算加速度

// 計算當前位置

puck->position = puck->position + puck->velocity * fastestTime + puck->acceleration * (fastestTimefastestTime0.5f);

// 應用磨擦力

puck->velocity = puck->velocity + puck->acceleration * fastestTime;

// 如果發生碰撞,反轉速度

if (planeCollision != NULL)// 碰撞平面

puck->velocity = Reflection_VECTOR3D(&puck->velocity, &planeCollision->n);

// 遞歸調用

Update_Puck(puck, table, deltaTime – fastestTime);

}

遊戲建模之碰撞反應

遊戲建模之碰撞反應

若3D模型發生碰撞後需要計算碰撞反應,不通物體運動有不同碰撞反應.但物體多數以直線運動.物體彈回角度和碰撞角度相等.

入射角度:桌球運動方向與邊沿平面法線向量之間夾角.

反射角度:垂直於運動方向矢量

例:當桌球撞向邊沿.它將按撞擊角度與之對等『入射角度』彈開

方程並沒有考慮球體旋轉作用力與磨擦力.最終得到計算反射方向方程式

給定運動方向矢量I與垂直法線N求碰撞反射方向F

F = (I – N2 (I % N)) * | I |;

計算反射方向代碼,dir為射線方向,normal為碰撞面法線

VECTOR3D Reflection_VECTOR3D(VECTOR3D_PTR dir,VECTOR3D_PTR normal){

VECTOR3D vec ;

Normalize_VECTOR3D(dir, &vec); // 單為化方向向量

*dir = (vec – *normal * 2.0f * (vec % *normal)) * Length_VECTOR3D(dir);

return *dir;

}

遊戲建模-平面碰撞

遊戲建模-平面碰撞

平面是3D圖形學重要部分.平面有兩個重要概念.

1.3D平面都無窮遠延伸

2.所有平面都將整個空間分成兩個半空間.正半空間為法線指向空間,負半空間則是令一則空間.這個特性對於碰撞算法重要

平面描敘如下:

平面法線向量:n=(a,b,c)

平面任意點:p0=(x0,y0,z0)

平面任意點:p=(x,y,z)

平面與原點距離:d平面位移常量(plane-shift constant)

因為法線n與向量(p0->p)垂直. 因兩垂直向量點積為零:

n * (p0->p) = 0

轉為分量表示

(a,b,c)*(x-x0,y-y0,z-z0)=0

轉為『頂點』與『法線』表示

a(x-x0)+b(y-y0)+c*(z-z0)=0

ax+by+cz+(-ax0-by0-cz0)=0

令d=-ax0-by0-c*z0

『平面方程』如下:

ax+by+c*z+d=0

 

這足以定義平面結構

typedef struct PLANE3D_TYP{

VECTOR3D n;//平面法線向量(不必是單位向量)

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

POINT3D p0;//平面上最近原點的點

}PLANE3D,*PLANE3D_PTR;

 

判斷『點』位於『平面』那個半空

3D世界中『視點』、『角色』並不能穿越牆壁.要做到這步需判斷點位於平正空間(法線指向)還是負空間.

要判斷這點需要下面的平面方程

hs=a(x-x0)+b(y-y0)+c*(z-z0)

只需將點(x,y,z)帶入方程中並計算結果

如果hs=0則該點位於平面之上

如果hs>0則該點位於平面正半空間(法線指向)中

如果hs<0則該點位於平面負半空間中

float Compute_Point_In_Plane3D(PLANE3D_PTR plane,VECTOR3D_PTR pt){

float hs = plane->A * pt->x + plane->B * pt->y + plane->C * pt->z + plane->D;

return(hs); // 返回半空間值

}

 

計算平面與直線之相交點(3D空間)

平面『頂點』與『法線』方程如下:

a(x-x0)+b(y-y0)+c*(z-z0)=0

3D直線方程如下:

(x-x0)/a = (y-y0)/b = (z-z0)/c

計算多邊形法線與直線方向點積

double a = plane->n % (line->v);

若為零則直線與平面平行

VECTOR3D Intersect;

if (a == 0)

Intersect = line->p0;

計算相交點

Intersect = line->p0 – (line->v) * ((plane->n % line->p0 + plane->D) / a);

3D線段與3D平面交點函式:

bool Intersect_Line3D_Plane3D(PLANE3D_PTR plane, PARMLINE3D_PTR line,POINT3D_PTR pt){

// 計算直線方向與多邊形法線點積

double a = plane->n % (line->v);

if (a == 0)

return false;

// 計算相交點

*pt = line->p0 – (line->v) * ((plane->n % line->p0 + plane->D) / a);

return true;

}

 

計算頂點是否為於多邊形之上,

首先計算頂點與多邊形所有頂點之間角度總和.如果該頂點位於多邊形之上.那麼此頂點與多邊形所有頂點之間角度總和將等於或接近2PI

bool Intersect_Vector3D_Polygon3D(VECTOR3D_PTR polygon, int num,VECTOR3D_PTR v){

VECTOR3D segment1, segment2;// 頂點 到 多邊形頂點 矢量

double length1, length2;// 矢量長度

double sumAngle = 0;// 矢量之間角度總和

double cosAngle = 0;// 兩矢量余弦角

// 編曆多邊形所有頂點

for (int index = 0; index < num; ++index)     {

segment1 = polygon[index] – *v;

segment2 = polygon[(index+1) % num] – *v; // % num 確保數值環形加一

length1 = Length_VECTOR3D(&segment1);

length2 = Length_VECTOR3D(&segment2);// 矢量長度

//檢查頂點是否落在多邊形邊界上

if ( length1 * length2 <= 0.0000001f){

// 多邊形邊界被認為是多邊形內部

sumAngle = PI2; // pai * 2

break;

}

// 計算上述兩個矢量之間余弦角

cosAngle = (segment1 % segment2) / (length1 * length2);

// 將計算結果累加入角度總和

sumAngle = sumAngle + acosf(cosAngle);

}

if ((sumAngle <= PI2 + 0.0000001f) && (sumAngle >= PI2 – 0.0000001f))

return true;// 頂點與多邊形發生碰撞

else

return false;

return true;

}

 

使用三個頂點初始化(定義)3D平面!

void Init_PLANE3D(PLANE3D_PTR plane,VECTOR3D_PTR va,VECTOR3D_PTR vb,VECTOR3D_PTR vc){

VECTOR3D normalA = *vc – *va;// 計算頂點C->A向量

VECTOR3D normalB = *vc – *vb;// 計算頂點C->B向量

plane->n = Cross_VECTOR3D(&normalA, &normalB);// 計算兩個3D向量叉積

plane->D = Dot_VECTOR3D(&(-(*va)), &plane->n); //距離等於va求返後與n求點積

}

遊戲建模-矢量運算

遊戲建模-矢量運算

矢量(VECTOR)也稱『向量』其實是抽象『量』它在遊戲世界被頂義為『位置』『速度』『磨擦』『方向』『點』等等. 矢量通常有3種

矢量 分量 簡序
2D矢量 x,y 2D空間
3D矢量 x,y,z 3D空間
4D矢量 x,y,z,w 3D空間w總是為1.用於方陣運算

首先定義3D矢量結構:

typedef struct VECTOR3D_TYP{

float x,y,z;

}VECTOR3D,*VECTOR3D_PTR;

下面是3D矢量(VECTOR)運算函式庫.

 

計算3D矢量長度,矢量長度也稱為範數(norm).將其理解為原點(0,0,0)到矢量(x,y,z)之距離

float Length_VECTOR3D(VECTOR3D_PTR va){

return( (float)sqrtf(va->xva->x + va->yva->y + va->z*va->z) );

}

 

3D矢量進行歸一化(normalize),也就使其長度縮放為1,但同時方向保持不變.它通常被用於無需理會長度之運算如『方向』

void Normalize_VECTOR3D(VECTOR3D_PTR va){

// 1.首先計算長度

float length = sqrtf(va->xva->x + va->yva->y + va->z*va->z);

//2.矢量除以長度得到歸一化矢量

va->x= va->x/length;

va->y= va->y/length;

va->z= va->z/length;

}

 

3D矢量點積運算可以理解為矢量乘法.先將各分量相乘後再相加得到一個標量

float operator%(VECTOR3D va, VECTOR3D vb){

return((va.x * vb.x) + (va.y * vb.y) + (va.z * vb.z));

}

float Dot_VECTOR3D(VECTOR3D_PTR va, VECTOR3D_PTR vb){

return( (va->x * vb->x) + (va->y * vb->y) + (va->z * vb->z) );

}

叉積是另一種矢量乘法,叉積運算最小要有3個分量才有效.

VECTOR3D operator^(VECTOR3D va, VECTOR3D vb){

VECTOR3D vn;

vn.x = ((va.y * vb.z) – (va.z * vb.y));

vn.y = -((va.x * vb.z) – (va.z * vb.x));

vn.z = ((va.x * vb.y) – (va.y * vb.x));

return(vn);

}

VECTOR3D Cross_VECTOR3D(VECTOR3D_PTR va, VECTOR3D_PTR vb){

VECTOR3D vn;

vn.x =  ( (va->y * vb->z) – (va->z * vb->y) );

vn.y = -( (va->x * vb->z) – (va->z * vb->x) );

vn.z =  ( (va->x * vb->y) – (va->y * vb->x) );

return(vn);

}

 

計算兩個3D矢量va和vb之間夾角余弦值

float CosTh_VECTOR3D(VECTOR3D_PTR va, VECTOR3D_PTR vb){

return(Dot_VECTOR3D(va,vb)/(Length_VECTOR3D(va)*Length_VECTOR3D(vb)));

}

 

 

計算三角形法線

void Normal_VECTOR3D(VECTOR3D_PTR normal,VECTOR3D_PTR va, VECTOR3D_PTR vb, VECTOR3D_PTR vc){

VECTOR3D u, v, n;

float length;

u = *vb – *va;

v = *vc – *va;

n = u^v;//Cross_VECTOR3D(&u, &v, &n);// 計算叉積

length = sqrtf(n.xn.x + n.yn.y + n.z*n.z);

normal->x = n.x/length;

normal->y = n.y/length;

normal->z = n.z/length;

}

 

將兩個3D矢量相加(va + vb),如用於位置移動

VECTOR3D operator+(VECTOR3D va, VECTOR3D vb){

VECTOR3D vsum;

vsum.x = va.x + vb.x;

vsum.y = va.y + vb.y;

vsum.z = va.z + vb.z;

return (vsum);//返回相加結果!

}

 

將兩個3D矢量相減(va – vb),如用於位置移動

VECTOR3D operator-(VECTOR3D va, VECTOR3D vb){

VECTOR3D vdiff;

vdiff.x = va.x – vb.x;

vdiff.y = va.y – vb.y;

vdiff.z = va.z – vb.z;

return(vdiff);     //返回相減向量!

}

 

3D矢量反數,如返轉方向

VECTOR3D operator-(VECTOR3D v){

VECTOR3D negation;

negation.x = -v.x ;

negation.y = -v.y ;

negation.z = -v.z ;

return(negation);     //返回反數向量!

}

 

使用縮放因子k對3D矢量進行縮放如:位置=位置+速度*時間

VECTOR3D operator*(VECTOR3D va, float k){

VECTOR3D vscaled;

vscaled.x = k * va.x;

vscaled.y = k * va.y;

vscaled.z = k * va.z;

return vscaled;// 返回縮放後向量

}

 

3D矢量賦值

void Init_VECTOR3D(VECTOR3D_PTR v, float x,float y,float z) {

v->x = x;  v->y = y; v->z = z;

}

 

3D矢量拷貝

Copy_VECTOR3D(VECTOR3D_PTR vdst, VECTOR3D_PTR vsrc){

vdst->x = vsrc->x;  vdst->y = vsrc->y; vdst->z = vsrc->z;

}

 

3D矢量比較

bool operator==(VECTOR3D vdst, VECTOR3D vsrc){

if (vdst.x == vsrc.x && vdst.y == vsrc.y && vdst.z == vsrc.z)

return true;

else

return false;

}

 

3D向量不等比較

bool operator!=(VECTOR3D vdst, VECTOR3D vsrc)

{

if (vdst.x != vsrc.x ||         vdst.y != vsrc.y ||vdst.z != vsrc.z)

return true;

else

return false;

}

 

向量歸零(3D向量)無方向,無距離,代表位於原點

void Zero_VECTOR3D(VECTOR3D_PTR v) {

v->x = v->y = v->z = 0.0f;

}

計算兩矢量之間夾角

float Angle_VECTOR3D(VECTOR3D_PTR va, VECTOR3D_PTR vb){

return acosf(*va % *vb);

}

角度轉弧度

#define DEG_TO_RAD(ang) ((ang)*PI/180.0)

弧度轉角度

#define RAD_TO_DEG(rads) ((rads)*180.0/PI)

隨機數 x:下限,  y:上限.

#define RAND_RANGE(x,y) ( (x) + (rand()%((y)-(x)+1)))

隨機數: -1.0 ~ 1.0

#define FRAND_RANGE1()   (((float)rand()-(float)rand())/RAND_MAX)

隨機數 0~1

#define FRAND_RANGE() ((float)rand() / (float)RAND_MAX)

遊戲建模之邊界盒

遊戲建模之邊界盒

邊界球』雖然可解卻大部3D模型『碰撞測試』問題.單若3D模型是長條形則不適合如『牆體』『長劍』.『軸對齊坐標邊界盒』axis-aligned bounding box(AABB)引入則可解決這類問題.每個『邊界盒』均由3D模型『中心點』與『最遠點』、『最近點』所組成.通過遍歷每個3D模型頂點找出XYZ三軸上最遠頂點.定義3D邊界盒:

typedef struct AABB_TYP {

VECTOR3D center;// 中心點

VECTOR3D far;// 最遠

VECTOR3D near;// 最近

}AABB, *AABB_PTR;

 

『3D模型』最遠點與最近點可遍歷所有3D模型頂點獲得:

1.最遠點與最近點清零

VECTOR3D far = {0,0,0};// 最遠點

VECTOR3D near = {0,0,0};// 最近點

2.遍歷所有3D頂點

for (int index = 0; index < vertex_num; ++index){

3.XYZ三軸最遠點

if (far.x > vertex_array[index].x)

vertex_array[index].x = far.x;

if (far.y > vertex_array[index].y)

vertex_array[index].y = far.y;

if (far.z > vertex_array[index].z)

vertex_array[index].z = far.z;

4.XYZ三軸最近點

if (near.x > vertex_array[index].x)

vertex_array[index].x = near.x;

if (near.y > vertex_array[index].y)

vertex_array[index].y = near.y;

if (near.z > vertex_array[index].z)

vertex_array[index].z = near.z;

}

 

判斷頂點是否為於邊界盒

bool Compute_Point_In_AABB(AABB_PTR aabb, VECTOR3D_PTR point)

{

if ((point->x >= aabb->center.x + aabb->near.x && point->x <= aabb->center.x + aabb->far.x) &&

(point->y >= aabb->center.y + aabb->near.y && point->y <= aabb->center.y + aabb->far.y) &&

(point->z >= aabb->center.z + aabb->near.z && point->z <= aabb->center.z + aabb->far.z) )

return true;

return false;

}

遊戲建模之邊界球

遊戲建模之邊界球

在3D遊戲中常對『3D模型』進行多邊形『碰撞檢測』.例如武器擊中『牆體』或『怪物』.最容易最常用是『邊界球』進『碰撞檢測』.每個『邊界球』均由3D模型『中心點』與『半徑』. 這『半徑』並不一定是最長半徑,通常這個值只包裹核心部分.定義3D球體:

typedef struct SPHERE3D_TYP{

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

float    radius;// 球體半徑

}SPHERE3D,* SPHERE3D_PTR;

 

『3D模型』最大半徑與平均平徑可遍歷所有頂點而取得:

1.模型半徑前設為零

radius_avg = 0;// 平均半徑

radius_max = 0;// 最大半徑

2.遍歷3D模型所有頂點

for (int index = 0; index < vertex_num; ++index)

{

3.計算3D頂點與中心距離

float dist = (float)sqrt(vertex_array[index].x*vertex_array[index].x +

vertex_array[index].y*vertex_array[index].y +

vertex_array[index].z *vertex_array[index].z);

4.累加半徑

radius_avg = radius_avg + dist;

5.求得最大半徑

if (dist > radius_max)

radius_max = dist;

}

6.計算平均半徑

radius_avg = radius_avg / vertex_num;

 

要對兩『邊界球』進行『碰撞檢測』只需求得兩『邊界球』之距,然後與兩『邊界球』半徑之和進行比較:

bool Compute_Sphere3D_In_Sphere3D(SPHERE3D_PTR sphereA, SPHERE3D_PTR sphereB)

{1.計算兩頂點XYZ分量距離

float x = sphereA->x – sphereB->x;

float y = sphereA->y – sphereB->y;

float z = sphereA->z – sphereB->z;

2.球體距離

float dist = sqrtf(x*x + y * y + z * z);

3.半徑之和進行比較

if (dist < (sphereA->radius + sphereB->radius))

return true;// 球體重疊/碰撞

else

return false;//

}

FPS

FPS

FPS全稱為Frames Per Second.用於統計遊戲與影片每秒的渲染畫面(幀)次數.此值越高畫面越流暢,電影以每秒24格菲林進行播放.所以你的遊戲要流暢無停頓感.需要不低於24幀最好高於30幀.當然幀數越高越好.

FPS算法如下:

FPS = 100 * Frequency / (currentTime – startTime);

Frequency為時鐘頻率. currentTime與 startTime為前後兩次時鐘

 

Windows下你需要高精度計數器:

返回硬件級高精度時鐘頻率,若返回0代表系統不支持.

BOOL QueryPerformanceFrequency(LARGE_INTEGER *lpFrequency);

返回硬件級高精度計數器,若返回0代表系統不支持.

BOOL QueryPerformanceCounter (LARGE_INTEGER *lpCount);

LARGE_INTEGER:為64BIT結構

 

此兩個函式需要winbase.h頭文檔和Kernel32.LIB庫

#include <winbase.h>

#pragma comment(lib, “Kernel32.LIB”)

 

定義如下FPS結構:

typedef struct FPS_TYP {

LARGE_INTEGER  Frequency;// 計數器的頻率

LARGE_INTEGER  startTime;// 啟動時鐘

float Frames;// 每秒渲染幀數

int n;// 臨時幀計數器

}FPS,*FPS_PTR;

 

初此化高精度定時器

bool Init_FPS(FPS_PTR fps)

{

// 返回硬件支持的高精度計數器的頻率

if (QueryPerformanceFrequency(&fps->Frequency) == false)

return false;

// 獲取啟動時鐘

QueryPerformanceCounter(&fps->startTime);//

return true;

}

 

計算每秒渲染幀數,每100幀進行一次計算

float Get_FPS(FPS_PTR fps)

{

++fps->n;

if (fps->n > 100)

{

LARGE_INTEGER currentTime;

// 返回高精度計數器

QueryPerformanceCounter(&currentTime);

fps->Frames = (float)100 * (float)fps->Frequency.QuadPart / ((float)currentTime.QuadPart – (float)fps->startTime.QuadPart);

fps->startTime = currentTime;// 重置時間

fps->n = 0;

}

return fps->Frames;

}

 

计算两次测量所花费时间

float Get_Counter_FPS(FPS_PTR fps){

LARGE_INTEGER currentTime;//当前时钟

// 返回高精度计数器

QueryPerformanceCounter(&currentTime);

float seconds = ((float)currentTime.QuadPart – (float)fps->startTime.QuadPart) / (float)fps->Frequency.QuadPart;

fps->startTime = currentTime;

return seconds;

}

 

OpenGL簡介

OpenGL簡介

在DOS時代因為當時硬件品類小,程序直接控制硬件,但當硬件品類不斷增加,要對所有硬件進行支持變得不現實.所以便有OpenGL的出現,把硬件的支持交還給硬件開發商.

最初OpenGL由Silicon Graphics,Inc(SGI)開發的一個可以跨平臺使用的圖形編程接口, GL就是Graphics library的縮寫,最初用於UNIX工作站.

1992年OpenGL Architecture Review Board(ARB)委員會創建,由ATI,Compaq,Evans&Sutherland,Hewlett-packard,IBM,Intel,Intergraph,Nvidia,Microsoft,Silicon Graphics組成

1995年微軟在遊戲廠商進逼下不得已在WinNT中支持OpenGL

程式庫 簡介 下載點
OpenGL 標準OpenGL 下載1下載2
GLU (實用庫)OpenGL的補充

 

GLUT (OpenGL Utility Toolkit)應用工具包,與系統無關且便於移於移植.作為AUX庫的的替代品.

 

下載

 

下載並解壓後,更據文檔的擴展名拷貝到各自對應的VC目錄

文件 文檔類形 目錄
include files .h文檔 C:\Program Files\Microsoft Visual Studio\VC98\Include\GL
Library files .lib文檔 C:\Program Files\Microsoft Visual Studio\VC98\Lib
Executable files .dll文檔 C:\Program Files\Microsoft Visual Studio\VC98\Bin

 

程式頭文檔 程式庫文檔 程式二進制文檔 簡介
gl.h Opengl32.lib OPENGL32.DLL 標準OpenGL頭文件
glu.h Glu32.lib GLU32.DLL OpenGL實用工具庫
glaux.h GLAUX.LIB OpenGL輔助函數庫
glut.h glut.lib glut.dll OpenGL應用工具包
glut32.lib glut32.dll

 

放射性衰减

放射性衰減
放射性衰減

放射性衰减

放射性衰減,例如鈾在一個給定的單位時間內是按其品質的百分比衰減的,描述衰減率的方法是給出該物質品質衰減一半所用的時間週期.這個時間週期稱作該物質的半衰期.對於放射性衰減兩個半衰期並不購成一個全衰期.事實上在兩個半衰期的時間週期裏該物質衰減到原品質的(1/2)*(1/2)=1/4

最有名的放射性物質之一是碳-14,它常被用於確定有機物的年代,當一塊木頭或骨頭還是活著的有機體的一部分時它就積聚了放射性的碳-14,因而碳-14在該物體的含碳中佔有一定比例,而一旦有機體死亡它就不能在通過於外部環境獲得碳-14,如通過食物和呼吸.

通過測定該物體中碳-14所占的比例做比較就能估算出原來的碳-14已經衰減了多小,碳-14的半衰期大約是5730年,因此5730年後該物質所含的碳-14是它在世時的所在的一半既1/2.

11463年後含有的碳-14只剩下1/4. 17190年後只剩下1/8.

 

在一個時間週期t之後,碳-14所剩下的量可以寫成一個指數函數

公式:C=C0(1/2)(t/5370)

C0:碳-14原有的含量

1/2:衰減一半

5730:碳-14的半衰期5730年C

t:以年單位的時間

C:碳-14剩下的含量

 

核武器之鍶90

核武器之鍶90
核武器之鍶90

核武器之鍶90

在上世紀60代初(包括之前)所有的核武器都在大氣中進行試驗,它會釋放出放射性同位素鍶-90,當它進入當時在世的人的骨骼中,而鍶-90半衰期為29年,那麼如過你在1960年吸收了鍶-90到現在你的骨骼中還剩當初的百分之幾呢?

=(1/2)((2016-1960)/29)

= (1/2)((56)/29)

=0.26

=26%

答案是只剩當初的26%

蟋蟀与高温

蟋蟀与高温
蟋蟀与高温

蟋蟀與高溫

蟋蟀是一種昆蟲它令人驚訝的是只要在同一溫度下,蟋蟀叫聲頻率基本相同.也就說只要知到蟋蟀每分鐘叫聲頻率,就可計算出當時的穩度.下面會計算出一個表讓你可以快速查表.

從下面的公式可得知要蟋蟀發出叫聲不能低於5攝氏度,而58攝氏度,是天文臺有記錄以來的最溫高度,

 

公式:C=7T-35

C:蟋蟀每分鐘的叫聲頻率

T:攝氏溫度

下面是C代碼

float Cricket(float t)

{

float c;

c = 7*t-35;

return c;

}

 

void Crickets()

{

float t;

float c;

for (t=5; t<=58; ++t)

{

c = Cricket(t);

::printf(“溫度%i=蟋蟀叫聲%i\r\n”,(int)t,(int)c);

}

}

 

攝氏溫度 蟋蟀每分鐘的叫聲頻率
5 0
6 7
7 14
8 21
9 28
10 35
11 42
12 49
13 56
14 63
15 70
16 77
17 84
18 91
19 98
20 105
21 112
22 119
23 126
24 133
25 140
26 147
27 154
28 161
29 168
30 175
31 182
32 189
33 196
34 203
35 210
36 217
37 224
38 231
39 238
40 245
41 252
42 259
43 266
44 273
45 280
46 287
47 294
48 301
49 308
50 315
51 322
52 329
53 336
54 343
55 350
56 357
57 364
58 371

 

 

牛頓三定律-物體運動的物理學

牛頓三定律-物體運動的物理學
牛頓三定律-物體運動的物理學

牛頓三定律-物體運動的物理學

以撒·牛頓生於1643年1月4日終於1727年3月31日,享年85歲.

牛頓物體運動三個基本定律是遊戲開發重要基礎,下面我會簡單的講序.

 

牛頓第一運動定律: (即慣性定律)

一切物體在任何情況下,總是保持靜止或勻速直線運動壯態,直到受外力作用發生改變.物體會一直保持狀態不變,直到有外力的作用讓它變化.物體的滑行之所以會停下與它的摩擦力與阻力有關

  1. 作用力不是維持物體運動的原因
  2. 作用力是改變物體運動狀態的原因

 

 

牛頓第二運動定律:

物體的加速度跟物體所受的合外力成正比,跟物體的品質成反比,加速度的方向跟合外力的方向相同.

物體的加速度取決於兩個因素:作用於物體的力和物體本身的品質.如果其他的因素相同,則同樣的力作用於品質是其一倍的物體時,該物體的加速度慢一倍.

所以,要加速度變快就要需要更大的作用力或更小品質.或同時兩者.

運算式:f=ma

f:代表作用力

m:代表品質

a:代表加速度

 

 

 

牛頓第三運動定律:

兩個物體之間的作用力和反方向作用力,在同一直線上,大小相等,方向相反.

當物體運動時都包含作用力和反作用力,並且是對稱.

運算式:f=-f’

f:代表作用力

f’:代表反方向作用力

求花花

求花花
求花花
求花花
求花花

求花花

今在歐陽家群出現一條幼稚園大班的算術題,題目是一張圖.圖中的花具有權重相加合得一定的數值,三種花必須符合以下三個條件

  1. 紅花+紅花+紅花=60
  2. 紅花+藍花+藍花=30
  3. 藍花-黃花*2=3

求: 黃花+紅花*藍花/5*4=?

 

因為電腦是科學家經過幾百才得到強大運算器,下面我使用電腦求解這個問題,演算法超簡單無經過優化. 黃花1紅花權重20,五瓣花藍花權重5,四瓣藍花權重4 ,答案是81

 

//——————————————————————–

// 求花花

//——————————————————————–

int flowers()

{

int red=0;// 紅花

int blue = 0;// 藍花

int yellow=0;// 黃花

int x=0;

 

while(true)

{

if((red + red + red   == 60) )

{

if( red + blue + blue == 30)

{

if(blue – yellow*2  == 3 )

{

x = yellow + red * (blue/5*4);

break;// 求得答案

}

else

{

++yellow;// 黃花

}

}

else

{

++blue;//藍花

}

}

else

{

++red;// 紅花

}

}//END WHILE

 

return x;

}

 

一筐雞蛋

一筐雞蛋
一筐雞蛋

今日見老豆在看微信,而且不停的在紙上寫數位並按計算機,原來是三舅父群裏發了一條數學題,這是條數學題求筐裏雞蛋的個數,我一口答應由我來算,題目我在下面給出,這種題目非常適合使用電腦進行碰撞求結果.常細的C語言演算法我在下面給出,演算法思路就是雞蛋個數逐次加一,所有條件都附合就得出接果,我果台老爺機IBM-T60P瞬間就給我答案1449,我將結果告訴我老豆他立馬發上群威一威.

 

一筐雞蛋:求筐裏雞蛋的個數
一個一個拿,正好拿完.
二個二個拿,還剩一個.
三個三個拿,正好拿完.
四個四個拿,還剩一個.
五個五個拿,還差一個.
六個六個拿,還剩三個.
七個七個拿,正好拿完.
八個八個拿,還剩一個.
九個九個拿,正好拿完.

//——————————————————————–
//一筐雞蛋
//——————————————————————–
int egg()
{
int x[9];
int _x;// 雞蛋個數
int c;//拿蛋的次數

_x = 0;// 雞蛋個數
while(1)
{
++_x;// 雞蛋個數加一

for(c = 0; 1c   <= _x; ++c)
x[0] = 1
c;

for(c = 0; 2c+1 <= _x; ++c)
x[1] = 2
c+1;

for(c = 0; 3c   <= _x; ++c)
x[2] = 3
c;

for(c = 0; 4c+1 <= _x; ++c)
x[3] = 4
c+1;

for(c = 0; 5c-1 <= _x; ++c)
x[4] = 5
c-1;

for(c = 0; 6c+3 <= _x; ++c)
x[5] = 6
c+3;

for(c = 0; 7c   <= _x; ++c)
x[6] = 7
c;

for(c = 0; 8c+1 <= _x; ++c)
x[7] = 8
c+1;

for(c = 0; 9c   <= _x; ++c)
x[8] = 9
c;

if(_x == x[0] &&
_x == x[1] &&
_x == x[2] &&
_x == x[3] &&
_x == x[4] &&
_x == x[5] &&
_x == x[6] &&
_x == x[7] &&
_x == x[8] )
break;
}

return _x;
}

大端與小端

大端與小端
大端與小端

大端與小端

小人國的兩個派系因為水煮蛋時該從大的一端剝開還是小的一端剝開而爭論,發生六次判亂, 其中一個皇帝送了命,另一個丟了王位. 出自喬納森•斯威夫特的小說”格列佛遊記”

 

在1974年4月 Intel(英代爾)推出8080 CPU,它採用(Little-Endian)小端方式存取資料, 即低位優先,存取從最低位址開始按順序存放.因位Inter的X86的霸主地位,CPU運算都是小端, 稱為主機字節.

(Little-Endian)小端 存放0x22446688

低位地址                                            高位地址
——————————————————–>
————————————————-
|     88     |      66    |     44      |     22    |
————————————————-

 

在1974年8月Motorola(摩托羅拉)推出6800 CPU,它採用(Big-Endian)大端方式存取資料,即高位優先,存取從最高位址開始按順序存放.後來所大部分的網路資料均採用大端方式,稱為網路字節.

(Big-Endian)大端 存放0x22446688

低位地址                                            高位地址
——————————————————–>
————————————————-
|     22     |      44    |     66      |     88    |
————————————————-

 

自動駕駛汽車

自动驾驶汽车

自動駕駛需要一輛普通汽車上安裝三套系統.

  1. 硬體:超級電腦可同時處理大量汽車影片攝像機和雷達感測器以及鐳射測距器的資訊.
  2. 算發:人工智慧演算法
  3. 地圖:可不斷網路更新離線3D地圖.

影片攝像機:車身外部攝像機,用於識別人行道,自行車道等障礙物.

鐳射測距器:硬體車頂旋轉感應器對半徑60米內物體進行3D掃描,也獲的精確車身周邊3D地圖模型.

雷達感測器:幫助電腦確定車輛與障礙物的距離.

硬體和地圖早以不是問題,唯獨是人工智慧演算法多年冇突破.不過一旦突破電腦將有獨立思維與情感,終結者場面將在人世間重現.

自動駕駛要百分百保障車輛和人員安全,人工智能多用”狀態機”和”決策樹”,其他概率性演算法則多有失誤.

路面可能『大貨車』『細車』『單車』和『行人』橫穿馬路,要百分百識別各種路面情况從現在情况還不太可能.

2016年6月30日,美國佛羅裏達州,一輛特斯拉S型電動轎車在自動駕駛模式撞上大貨車車身,原因是高大的白色車身無法識別.

不過自動駕駛汽車將會大幅減少車禍的數量,因為他們遵守限速,路標,從不闖紅燈.

以現在技術完全可以自動控制方向盤,避免追尾相撞,自動泊車,變線警告,根據車流情況自動加速或減速.

在礦場裏卡車以可以由電腦操控全部自動運行.它們可以應付礦場裏有限交通量.由於成本可能更低,機器人卡車司機終究會全面取代人類司機工作.

你真想要冇『踏板』冇『方向盤』冇『手波』汽車?還有駕駛樂趣嗎?

排序算法-快速排序(三者取中划分)

排序算法-快速排序(三者取中劃分)

快速排序算法的一個改進版本,在數組取三個元素的中間進行劃分.這樣可以避免出現最壞的情況.

取數組的左邊,中間,右邊的元素.對這三個數進行排序.

#define less(A,B)     ((A)<(B)) // 小於比較

#define exch(A,B)     {int temp=A; A=B; B=temp;} // 交換

#define compexch(A,B) if(less(A,B)) exch(A,B) // 小於則交換

下面給出C代碼的實現.

// 劃分算法

//a:數組

//l:數組的左則索引

//r:數組的右則索引

void quicksort(int a[],int l,int r)

{

int i;

int temp;

// a[(l+r)/2] 與 a[r-1]交換

exch(a[(l+r)/2], a[r-1]);

// 取數組的左邊,中間,右邊的元素.對這三個數進行排序.

// 小於則交換

compexch(a[r-1],a[l]);

compexch(a[r],  a[l]);

compexch(a[r],  a[r-1]);

i = partition(a,l+1,r-1);

quicksort(a[],l,  i-1);

quicksort(a[],i+1,r);

}

// 劃分算法

//a:數組

//l:數組的左則索引

//r:數組的右則索引

int partition(int a[],int l,int r)

{

int i,j,v,t;

i = l;

j = r;

v = a[j];//選則最右則的元素作為劃分元素v

while(true)

{

while(a[i]<v)

++i;// i的左則小與v

while(v<a[j])

{

++j;// j的右則大與v

if(j==l)

break;// 跳出

}

if(i>=j)

break;// 兩個指針相遇跳出掃描.

// 交換i,j,交換那些使掃描停止的元素.

t=a[i];

a[i]=a[j];

a[j]=t;

}

// 交換i,r,保證v的左則小於於它,v的右則大於它.

t=a[i];

a[i]=a[r];

a[r]=t;

return i;

}

排序算法-快速排序(非递归)

排序算法-快速排序(非递归)

1.选则最右则的元素作为划分元素v,然后从左则扫描小于v的元素,然后从右则扫描大于v的元素.
交换那些使扫描停止的元素.
2.重复进行这样的过程直到两个指针相遇.
3.然后分别对左右两步分进行递归处理.最终得到一个排好序的数组.

// 全局数据
int stack[128];// 堆栈
int ps;// 堆栈指针
//初始化堆栈
void init()
{
ps = 0;
}

//堆栈是否为空
int IsEmpty()
{
if(ps == 0)
return 1;
else
return 0;
}

// 压入
void push(int v)
{
stack[ps]=v;
++ps;// 指针加一
}

// 弹出
int pop()
{
if(ps == 0)
return = 0;
–ps;// 指针减一
return stack[ps];
}

下面给出C代码的实现.
//快速排序(非递归)
//a:数组
//l:数组的左则索引
//r:数组的右则索引
void quicksort(int a[],int l,int r)
{
init();
push(l);
push(r);

while(IsEmpty())
{
l=pop();
r=pop();
if(r<=l)
continue;
i=partition(a,l,r);
if(i-l < r-i)
{
push(l);
push(i-1);

push(i+1);
push(r);
}
else
{
push(i+1);
push(r);

push(l);
push(i-1);
}
}

}

// 划分算法
//a:数组
//l:数组的左则索引
//r:数组的右则索引
int partition(int a[],int l,int r)
{
int i,j,v,t;
i = l;
j = r;
v = a[j];//选则最右则的元素作为划分元素v
while(true)
{
while(a[i]<v)
++i;// i的左则小与v

while(v<a[j])
{
++j;// j的右则大与v
if(j==l)
break;// 跳出
}

if(i>=j)
break;// 两个指针相遇跳出扫描.

// 交换i,j,交换那些使扫描停止的元素.
t=a[i];
a[i]=a[j];
a[j]=t;
}

// 交换i,r,保证v的左则小于于它,v的右则大于它.
t=a[i];
a[i]=a[r];
a[r]=t;

return i;
}

排序算法-快速排序

排序算法-快速排序
快速排序是由C.A.R.Hoare在1960年提出.对于大型数据,快速排序算法的性能是希尔排序的5到10倍.
快速排序是一种分而治之算法,它将素组划分成两部分,然后分别对两个部分进行排序.
1.选则最右则的元素作为划分元素v,然后从左则扫描小于v的元素,然后从右则扫描大于v的元素.
交换那些使扫描停止的元素.
2.重复进行这样的过程直到两个指针相遇.
3.然后分别对左右两步分进行递归处理.最终得到一个排好序的数组.

下面给出C代码的实现.
// 划分算法
//a:数组
//l:数组的左则索引
//r:数组的右则索引
int   partition(int a[],int l,int r)
{
int i,j,v,t;
i = l;
j = r;
v = a[j];//选则最右则的元素作为划分元素v
while(true)
{
while(a[i]<v)
++i;// i的左则小与v

while(v<a[j])
{
++j;// j的右则大与v
if(j==l)
break;// 跳出
}

if(i>=j)
break;// 两个指针相遇跳出扫描.

// 交换i,j,交换那些使扫描停止的元素.
t=a[i];
a[i]=a[j];
a[j]=t;
}

// 交换i,r,保证v的左则小于于它,v的右则大于它.
t=a[i];
a[i]=a[r];
a[r]=t;

return i;
}

//快速排序
//a:数组
//l:数组的左则索引
//r:数组的右则索引
void quicksort(int a[],int l,int r)
{
int i;
if(l<=0)
return ;
quicksort(a,l,  i-1);
quicksort(a,i+1,r);
}

//快速排序
//a:数组
//c:数组的长度
void quicksort(int a[],int c)
{
quicksort(a,0,c-1);
}

 

排序算法-希尔排序

排序算法-希尔排序
1.希尔排序是查入排序的扩展版.在扫描数据时,把移动的增量或减量由原来的1变成h.
2.h就是步长.对于每个h,对每个h单独使用插入排斥.

下面给出C代码的实现.
//a:数组
//l:数组的长度
void shellsort(int a[],int l)
{
int i,j;
int h;// 步长
int v;

// 计算步长
h=1;
while(h<=l/9)
h=3*h+1;

for(;h>0; h/=3)// 改边步长
{
for(i=h; i<=l; ++i)// 使用插入排斥
{
j=i;
v=a[i];
while(j>=h && v < a[j-h])
{
a[j]=a[j-h];
j-=h;
a[j]=v;
}
}
}
}

排序算法-冒泡排序

排序算法-冒泡排序
1.进行遍历,当遇到最小元素时,将它与左边的元素逐个交换.直到将最小的元素移到对列的最左边.
2.进行遍历,将第二小的元素放到数组的左边第二个元素中.
3.以此类推.
冒泡排序,实际是选择排序,但需要更多CPU开销.
冒泡排序排序的特点是容易实现,不过比插入排序和选择排序慢.

下面给出C代码的实现.
//a:数组
//l:数组的长度
void bubble(int a[],int l)
{
int i,j;// 索引
int temp;// 用于交换
for(i=0;i<l;++i)
{
for(j=0;j<i;–j)
{   // 小于比较
if(a[j-1]<a[j])
{// 进行交换
temp=a[j];
a[j]=a[j-1];
a[j-1]=temp;
}
}
}
}

排序算法-插入排序

1.将最小的元素放在最前.将最小元素作为关键字.
2.索引的左则是以排好序的,但不是处于最终位置.当碰到更小的数据向右移动腾出空间,插入较小的数据.
3.索引加一并重复上叙步骤.
3.当索引移到最右则时,则数组拍好序.
和选择排序不同的是,插入排序的运行时间和数据的原始排列顺序密切相关.
如果数据量比较大,而且已经排好序或几乎排好序,插入排序比选则排序好.

下面给出C代码的实现.
//a:数组
//l:数组的长度
void insertion(int a[],int l)
{
int i,j;// 索引
int temp;// 用于交换
int v;
// 将最小的元素放在最前.
for(i = l-1; i>0; –i)
{
// 进行小于比较
if(a[i-1] < a[i])
{// 交换
temp = a[i-1];
a[i-1] = a[i];
a[i] = temp;
}
}

for(i=2; i < l; ++i)
{
j = i;
v = a[i];
// 小于比较
while(v < a[j-1])
{// 向右移
a[j] = a[j-1];
j–;
a[j] = v;
}
}

}

排序算法之选择排序

排序算法之选择排序
它是一种最简单的排序算法,
1.选出数组中最小的元素,将它与数组中地一个元素交换.
2.然后找出次小元素,将它与数组中第二个元素进行交换.
3.重复这个方法,直到整个数组排序完毕.
选择排序的一个缺点是忽略有序部分.
当数组比较大,数据又比较小.则应选择改方法.
它与其它比算法相比,移动步数都要比选择排序要多.

下面给出C代码的实现.
//a:数组
//l:数组的长度
void selection(int a[],int l)
{
int i,j;//排序索引
for(i = 0; i < l; ++i)
{
int min = i;
for( j = i+1; j < l; ++j)
{   // 进行小于比较
if(a[j] < a[min])
min = j;
}
// 进行交换
int temp = a[i];
a[i] = a[min];
a[min] = temp;
}
}