置頂隨筆
鑒于網(wǎng)上找資料是件痛苦的,所以我把我自己的一些電子書(shū),以及下載的一些小程序放在了郵箱里,跟大家分享,僅大家學(xué)習(xí)交流(這些資料一般已經(jīng)在網(wǎng)上廣為流傳,我想應(yīng)該沒(méi)有觸及版權(quán)的問(wèn)題吧,呵呵)。大家有需要的可以去郵箱去下,目前只放了一部分,以后會(huì)陸續(xù)添加郵箱地址和密碼如下:
賬號(hào):percyph1@163.com密碼:xcc123456
如果大家有c++,openGL,密碼學(xué)等等計(jì)算機(jī)方面的好資料,也可以發(fā)給我,我的郵箱是
percyph@163.com大家也可以回帖要資料,如果有的話(huà)我會(huì)第一時(shí)間發(fā)上。
相信來(lái)我這兒的朋友都是有素質(zhì)的,請(qǐng)不要?jiǎng)h除和移動(dòng)郵箱里的文件,謝謝!
目前已經(jīng)上傳的資料有:(以后會(huì)陸續(xù)更新)
VC編程助手(小軟件VC++ assistant,能使編程更方便)
C++Primer3(電子書(shū))
glut函數(shù)說(shuō)明(電子書(shū))
C++技能百練(經(jīng)典算法).rar
ROAM地形算法演示程序.rar
OpenGL 參考手冊(cè)
c&c++深層探索
C++必知必會(huì)
VC6.0編程實(shí)例精解
高質(zhì)量C++編程指南&編程新手真言&MFC類(lèi)庫(kù)詳解
Windows程序設(shè)計(jì)
MFC類(lèi)庫(kù)詳解.chm
C++ 數(shù)據(jù)結(jié)構(gòu)第三版
C++ 數(shù)據(jù)結(jié)構(gòu)第三版
程序員面試寶典&程序員超級(jí)開(kāi)發(fā)寶典
c++和OpenGL函數(shù)手冊(cè)
Essential C++中文版.pdf
Effective C++(電子書(shū))
C++編程思想(電子書(shū))
3.11號(hào)上傳(kuafoo發(fā)的) Windows環(huán)境下32位匯編語(yǔ)言.chm(2.78M)
深入淺出MFC
深入淺出MFC第二版
另外最近幾個(gè)月寫(xiě)的數(shù)據(jù)結(jié)構(gòu)的程序也傳上去了,有興趣的朋友可以看看!
里面包括:
線(xiàn)性表——靜態(tài)鏈表2009.7.30
線(xiàn)性表——鏈表的內(nèi)部類(lèi)實(shí)現(xiàn)2008.8
線(xiàn)性表——鏈表的友元類(lèi)實(shí)現(xiàn)2008.8
線(xiàn)性表——雙向鏈表2009.8.11
線(xiàn)性表——順序表2009.8.3
線(xiàn)性表——友元模板類(lèi)2009.8
約瑟夫問(wèn)題——四種解法2009.8.11(數(shù)組,鏈表,循環(huán)鏈表等)
隊(duì)列——隊(duì)列的順序表示循環(huán)隊(duì)列2009.8.11
隊(duì)列——鏈隊(duì)列2009.8.11
棧——漢諾塔2009.8.6
棧——進(jìn)制轉(zhuǎn)換2009.8.6
棧——括號(hào)匹配2009.8.6
棧——模板鏈棧2009.8.3
棧——模板順序棧2009.7
棧——順序棧2009.8.6
棧——算術(shù)表達(dá)式求值2009.7.13
棧——行編輯2009.8.6
二叉樹(shù)——二叉樹(shù)的常見(jiàn)操作2009.9.3
2010.3.9 更新
樹(shù)的應(yīng)用—仿DOS文件夾管理程序
200位大數(shù)乘法.rar
200位大數(shù)加法.rar
連連看單機(jī)程序MFC
2010年10月7日
我自己的畢業(yè)設(shè)計(jì)的1.0版本. 采用四叉樹(shù)LOD算法實(shí)現(xiàn)地形渲染.已經(jīng)傳至共享郵箱里,希望對(duì)學(xué)3D的朋友有幫助
2009年5月14日
質(zhì)數(shù)的定義
一個(gè)數(shù),如果只有1和它本身兩個(gè)因數(shù),這樣的數(shù)叫做質(zhì)數(shù),又稱(chēng)素?cái)?shù)。
在上文 《素?cái)?shù)算法大全,及C程序?qū)崿F(xiàn)優(yōu)化詳解 (一) 試除法》中我們已經(jīng)探討了求解素?cái)?shù)的一類(lèi)算法,并且將試除法從最初的低效版本優(yōu)化的高效的V2。那么,還有沒(méi)有其它更佳算法呢?這就是下面三藏要和大家探討的內(nèi)容
合數(shù)過(guò)濾篩選法
算法描述:我們知道,素?cái)?shù)N不能被2~(N-1)間的任何數(shù)整除;反過(guò)來(lái)看,只要能被2~(N-1)間的任何數(shù)整除的N,都不是素?cái)?shù)。所以我們可以采用一個(gè)簡(jiǎn)單的排除法:就是對(duì)N以?xún)?nèi)的所有數(shù),只要逐個(gè)去除值為2~(N-1)的倍數(shù)的數(shù),剩下的就是素?cái)?shù)。
C語(yǔ)言實(shí)現(xiàn)
// 合數(shù)過(guò)濾篩選法 Ver1
// 參數(shù):n 求解n以?xún)?nèi)(包括n)的素?cái)?shù)
// 返回值:n以?xún)?nèi)素?cái)?shù)個(gè)數(shù)
int CompositeNumFilterV1(int n)
{
int i, j;
// 素?cái)?shù)數(shù)量統(tǒng)計(jì)
int count = 0;
// 分配素?cái)?shù)標(biāo)記空間,結(jié)合后文思考為何+1
char* flag = (char*)malloc( n+1 );
// 初始化素?cái)?shù)標(biāo)記
for (i=2; i<=n; i++)
{
// 為什么*(p+i)要寫(xiě)成flag[i]呢?可讀性更佳爾
flag[i] = 1;
}
// 寫(xiě)程序要注意排版和留空,方便閱讀,也可減少出錯(cuò)幾率
// 以2~(N-1)為因子過(guò)濾合數(shù)
for (i=2; i < n; i++)
{
for (j=2; i*j <= n; j++)
{
// i*j是由i,j兩整數(shù)相乘而得,顯然不是素?cái)?shù)
flag[i*j] = 0;
}
}
// 統(tǒng)計(jì)素?cái)?shù)個(gè)數(shù)
for (i=2; i<=n; i++)
{
// 其實(shí)if(flag)就其同樣作用了,但這么寫(xiě)是有留言的
// 請(qǐng)參閱《C語(yǔ)言程序設(shè)計(jì)常見(jiàn)錯(cuò)誤剖析及解決之道》一文
if (1 == flag[i]) count++;
}
// 因輸出費(fèi)時(shí),且和算法核心相關(guān)不大,故略
// 釋放內(nèi)存,別忘了傳說(shuō)中的內(nèi)存泄漏
free(flag);
return count;
}
在上文給出的main函數(shù)中以不同參數(shù)調(diào)用CompositeNumFilterV1函數(shù),得到執(zhí)行結(jié)果如下:
[100000]以?xún)?nèi)素?cái)?shù)個(gè)數(shù):9592, 計(jì)算用時(shí):15毫秒
[1000000]以?xún)?nèi)素?cái)?shù)個(gè)數(shù):78498, 計(jì)算用時(shí):125毫秒
[5000000]以?xún)?nèi)素?cái)?shù)個(gè)數(shù):348513, 計(jì)算用時(shí):2578毫秒
[10000000]以?xún)?nèi)素?cái)?shù)個(gè)數(shù):664579, 計(jì)算用時(shí):6281毫秒
注:因程序是非獨(dú)占性運(yùn)行的,所以時(shí)間不是完全精確的,但基本能反映實(shí)情
顯然,比上文中的試除法要快,而且誰(shuí)都可以看到上例是一個(gè)未經(jīng)優(yōu)化的粗陋版本,好多地方是三藏故意采用比較低效做法,為了與后文的優(yōu)化版比較,凸顯優(yōu)化之重要,也為了初學(xué)者記住別采用類(lèi)似低效做法,下面我們開(kāi)始優(yōu)化之旅
優(yōu)化分析
上面CompositeNumFilterV1函數(shù)存在的問(wèn)題有:
- 在外層循環(huán),需要一直執(zhí)行到n-1嗎?不要,因?yàn)閚/2~n-1間的數(shù)顯然不能整出n
- 在內(nèi)層循環(huán)中重復(fù)使用i*j顯然是低效的,考慮到計(jì)算機(jī)中加減運(yùn)算速度比乘除快,可以考慮變乘法為加法
- 在循環(huán)修改flag過(guò)程中,其實(shí)有很多數(shù)會(huì)被重復(fù)計(jì)算若干次,比如6=2*3=3*2,會(huì)被重復(fù)置0,類(lèi)似操作很多,所以我們得設(shè)法避免或減少flag重復(fù)置0
據(jù)上述分析,我們可將程序優(yōu)化如下:
// 合數(shù)過(guò)濾篩選法 Ver2
// 參數(shù):n 求解n以?xún)?nèi)(包括n)的素?cái)?shù)
// 返回值:n以?xún)?nèi)素?cái)?shù)個(gè)數(shù)
int CompositeNumFilterV2(int n)
{
int i, j;
// 素?cái)?shù)數(shù)量統(tǒng)計(jì)
int count = 0;
// 分配素?cái)?shù)標(biāo)記空間,明白+1原因了吧,因?yàn)槔速M(fèi)了一個(gè)flag[0]
char* flag = (char*)malloc( n+1 );
// 初始化素?cái)?shù)標(biāo)記,要高效點(diǎn)咯
flag[2] = 1;
// 注意是i<n不是上例中的i<=n了,理由自思
for (i=3; i<n; i++)
{
flag[i++] = 1;
// 偶數(shù)自然不是素?cái)?shù),直接置0好了
flag[i] = 0;
}
// n為奇數(shù)
if (n%2 != 0)
{
flag[n] = 1;
}
// 從3開(kāi)始filter,因?yàn)?的倍數(shù)早在初始化時(shí)代就干掉了
// 到n/2止的理由還要說(shuō)嗎
for (i=3; i <= n/2; i++)
{
// i是合數(shù),請(qǐng)歇著吧,因?yàn)槟墓ぷ髟缬心馁|(zhì)因子代勞了
if (0 == flag[i]) continue;
// 從i的2倍開(kāi)始過(guò)濾,變乘法為加法
for (j=i+i; j <= n; j+=i)
{
flag[j] = 0;
}
}
// 統(tǒng)計(jì)素?cái)?shù)個(gè)數(shù)
for (i=2; i<=n; i++)
{
if (flag[i]) count++;
}
// 因輸出費(fèi)時(shí),且和算法核心相關(guān)不大,故略
// 釋放內(nèi)存,別忘了傳說(shuō)中的內(nèi)存泄漏
free(flag);
return count;
}
再來(lái)調(diào)用CompositeNumFilterV2得到執(zhí)行結(jié)果:
[100000]以?xún)?nèi)素?cái)?shù)個(gè)數(shù):9592, 計(jì)算用時(shí):n太小,時(shí)間精度不夠
[1000000]以?xún)?nèi)素?cái)?shù)個(gè)數(shù):78498, 計(jì)算用時(shí):31毫秒
[5000000]以?xún)?nèi)素?cái)?shù)個(gè)數(shù):348513, 計(jì)算用時(shí):453毫秒
[10000000]以?xún)?nèi)素?cái)?shù)個(gè)數(shù):664579, 計(jì)算用時(shí):1062毫秒
[100000000]以?xún)?nèi)素?cái)?shù)個(gè)數(shù):5761455, 計(jì)算用時(shí):12973毫秒
哇哇,比昨天的試除發(fā)快了好多倍,可見(jiàn)算法的威力,值得好好學(xué)習(xí),別說(shuō)學(xué)算法沒(méi)用咯。
上例著那個(gè)計(jì)算一億以?xún)?nèi)的素?cái)?shù)只要約13秒,應(yīng)該算不錯(cuò)了,今天是否可以休息了呢?No,我們要追求極限!
int CompositeNumFilterV3(int n)
{
int i, j;
// 素?cái)?shù)數(shù)量統(tǒng)計(jì)
int count = 0;
// 分配素?cái)?shù)標(biāo)記空間,明白+1原因了吧,因?yàn)槔速M(fèi)了一個(gè)flag[0]
char* flag = (char*)malloc( n+1 );
// 干嘛用的,請(qǐng)仔細(xì)研究下文
int mpLen = 2*3*5*7*11*13;
char magicPattern[mpLen];
// 奇怪的代碼,why,思考無(wú)法代勞,想!
for (i=0; i<mpLen; i++)
{
magicPattern[i++] = 1;
magicPattern[i++] = 0;
magicPattern[i++] = 0;
magicPattern[i++] = 0;
magicPattern[i++] = 1;
magicPattern[i] = 0;
}
for (i=4; i<=mpLen; i+=5)
magicPattern[i] = 0;
for (i=6; i<=mpLen; i+=7)
magicPattern[i] = 0;
for (i=10; i<=mpLen; i+=11)
magicPattern[i] = 0;
for (i=12; i<=mpLen; i+=13)
magicPattern[i] = 0;
// 新的初始化方法,將2,3,5,7,11,13的倍數(shù)全干掉
// 而且采用memcpy以mpLen長(zhǎng)的magicPattern來(lái)批量處理
int remainder = n%mpLen;
char* p = flag+1;
char* pstop = p+n-remainder;
while (p < pstop)
{
memcpy(p, magicPattern, mpLen);
p += mpLen;
}
if (remainder > 0)
{
memcpy(p, magicPattern, remainder);
}
flag[2] = 1;
flag[3] = 1;
flag[5] = 1;
flag[7] = 1;
flag[11] = 1;
flag[13] = 1;
// 從17開(kāi)始filter,因?yàn)?,3,5,7,11,13的倍數(shù)早被kill了
// 到n/13止的,哈哈,少了好多吧
int stop = n/13;
for (i=17; i <= stop; i++)
{
// i是合數(shù),請(qǐng)歇著吧,因?yàn)槟墓ぷ髟缬心馁|(zhì)因子代勞了
if (0 == flag[i]) continue;
// 從i的17倍開(kāi)始過(guò)濾
int step = i*2;
for (j=i*17; j <= n; j+=step)
{
flag[j] = 0;
}
}
// 統(tǒng)計(jì)素?cái)?shù)個(gè)數(shù)
for (i=2; i<=n; i++)
{
if (flag[i]) count++;
}
// 因輸出費(fèi)時(shí),且和算法核心相關(guān)不大,故略
// 釋放內(nèi)存,別忘了傳說(shuō)中的內(nèi)存泄漏
free(flag);
return count;
}
再看CompositeNumFilterV3執(zhí)行結(jié)果:
[1000000]以?xún)?nèi)素?cái)?shù)個(gè)數(shù):78498, 計(jì)算用時(shí):15毫秒
[5000000]以?xún)?nèi)素?cái)?shù)個(gè)數(shù):348513, 計(jì)算用時(shí):203毫秒
[10000000]以?xún)?nèi)素?cái)?shù)個(gè)數(shù):664579, 計(jì)算用時(shí):515毫秒
[100000000]以?xún)?nèi)素?cái)?shù)個(gè)數(shù):5761455, 計(jì)算用時(shí):6421毫秒
再次優(yōu)化后速度提升了又一倍左右,三藏不禁有點(diǎn)滿(mǎn)足了,睡覺(jué)也!
轉(zhuǎn)自:http://www.doforfun.net/article/20090504/543.htm
經(jīng)常有初學(xué)者詢(xún)問(wèn)求解N內(nèi)所有素?cái)?shù)(質(zhì)數(shù))的問(wèn)題,對(duì)此,網(wǎng)上的解答也很多,但很多要么不夠?qū)I(yè),要么只有程序沒(méi)有算法解析,所以三藏大廈對(duì)此問(wèn)題做個(gè)小結(jié),探討一下求解素?cái)?shù)的常見(jiàn)算法,同時(shí)給出相應(yīng)的C語(yǔ)言程序及其解析。為了方便初學(xué)者理解,本文將從易到難闡述不同算法,高手可以直接看后面的高效算法
質(zhì)數(shù)的定義
一個(gè)數(shù),如果只有1和它本身兩個(gè)因數(shù),這樣的數(shù)叫做質(zhì)數(shù),又稱(chēng)素?cái)?shù)。
試除判斷法
算法描述:從上述定義可知,素?cái)?shù)不能被1和它本身之外的數(shù)整除,所以,判斷一個(gè)數(shù)x是否素?cái)?shù)只要看它是否能被2~sqrt(x)間的數(shù)整除即可;而求N內(nèi)所有素?cái)?shù)則是循環(huán)重復(fù)上述過(guò)程。
C語(yǔ)言實(shí)現(xiàn):
#include <time.h>
#include <malloc.h>
#define N 100000
// 簡(jiǎn)單試除判斷法 Ver1
int SimpleDivisionV1(int n)
{
int i,j;
// 素?cái)?shù)數(shù)量統(tǒng)計(jì)
int count = 0;
// 分配存放結(jié)果的空間
int* primes = (int*)malloc( sizeof(int)*n );
// 2是素?cái)?shù)誰(shuí)都知道,不算了
primes[count++] = 2;
// 循環(huán)計(jì)算3~n間的數(shù)
for (i=3; i<=n; i++)
{
// 為什么是sqrt(i),思考一下
for (j=2; j<=sqrt(i); j++)
{
// i被j整除,顯然不是素?cái)?shù)了
if (i%j == 0) break;
}
// i不能被2~sqrt(i)間的數(shù)整除,素?cái)?shù)也
if (j > sqrt(i))
{
primes[count++] = i;
}
}
// 因輸出費(fèi)時(shí),且和算法核心相關(guān)不大,故略
// 釋放內(nèi)存,別忘了傳說(shuō)中的內(nèi)存泄漏
free(primes);
return count;
}
void main()
{
int count;
clock_t start, end;
// time函數(shù)不夠精確,用clock湊合一下吧
start = clock();
count = SimpleDivisionV1(N);
end = clock();
printf("[%d]以?xún)?nèi)素?cái)?shù)個(gè)數(shù):%d, 計(jì)算用時(shí):%d毫秒\n", N, count, end-start);
getch();
}
計(jì)算結(jié)果:
[100000]以?xún)?nèi)素?cái)?shù)個(gè)數(shù):9592, 計(jì)算用時(shí):468毫秒
[1000000]以?xún)?nèi)素?cái)?shù)個(gè)數(shù):78498, 計(jì)算用時(shí):10859毫秒
[5000000]以?xún)?nèi)素?cái)?shù)個(gè)數(shù):348513, 計(jì)算用時(shí):103560毫秒
噢噢,算算十萬(wàn)還行,百萬(wàn)就10秒多了,而且時(shí)間增長(zhǎng)很快,這不行,得優(yōu)化一下!
優(yōu)化分析:
仔細(xì)研究一下SimpleDivisionV1我們可以發(fā)現(xiàn)以下幾個(gè)問(wèn)題:
- 在循環(huán)條件中重復(fù)調(diào)用sqrt(i)顯然是比較浪費(fèi)時(shí)間的
- 判斷素?cái)?shù),真的需要拿2~sqrt(i)間的所有整數(shù)去除嗎?我們知道,合數(shù)都可以分解成若干質(zhì)數(shù),所以只要2~sqrt(i)間的質(zhì)數(shù)不能整除i即可
根據(jù)上面兩點(diǎn),我們可將SimpleDivisionV1升級(jí)為SimpleDivisionV2,如下
// 簡(jiǎn)單試除判斷法 Ver2
int SimpleDivisionV2(int n)
{
int i, j, k, stop;
// 素?cái)?shù)數(shù)量統(tǒng)計(jì)
int count = 0;
// 分配存放結(jié)果的空間
int* primes = (int*)malloc( sizeof(int)*n );
// 2是素?cái)?shù)誰(shuí)都知道,不算了
primes[count++] = 2;
stop = count;
// 循環(huán)計(jì)算3~n間的數(shù)
for (i=3; i<=n; i++)
{
k = sqrt(i);
// 在循環(huán)條件中重復(fù)調(diào)用sqrt是低效做法,故引入k
while (primes[stop] <= k && stop < count)
stop++;
// stop干什么用,思考一下
for (j=0; j<stop; j++)
{
if (i%primes[j] == 0) break;
}
// i不能被2~sqrt(i)間的素?cái)?shù)整除,自然也不能被其他數(shù)整除,素?cái)?shù)也
if (j == stop)
{
primes[count++] = i;
}
}
// 因輸出費(fèi)時(shí),且和算法核心相關(guān)不大,故略
// 釋放內(nèi)存,別忘了傳說(shuō)中的內(nèi)存泄漏
free(primes);
return count;
}
然后將main中調(diào)用的函數(shù)替換為SimpleDivisionV2,在看一下執(zhí)行結(jié)果:
[100000]以?xún)?nèi)素?cái)?shù)個(gè)數(shù):9592, 計(jì)算用時(shí):46毫秒
[1000000]以?xún)?nèi)素?cái)?shù)個(gè)數(shù):78498, 計(jì)算用時(shí):546毫秒
[5000000]以?xún)?nèi)素?cái)?shù)個(gè)數(shù):348513, 計(jì)算用時(shí):3515毫秒
[10000000]以?xún)?nèi)素?cái)?shù)個(gè)數(shù):664579, 計(jì)算用時(shí):8000毫秒
很開(kāi)心的看到,經(jīng)過(guò)優(yōu)化,速度提高了幾十倍,尤其是時(shí)間增長(zhǎng)曲線(xiàn)的坡度變小了,N值越大,V2函數(shù)比V1的效率就越高
對(duì)于試除判斷這種質(zhì)數(shù)算法來(lái)說(shuō),三藏認(rèn)為SimpleDivisionV2基本已經(jīng)接近極限,不大可能有量級(jí)上的突破了,有興趣的朋友可以自己進(jìn)一步優(yōu)化。初學(xué)者除了參看上述例子外,可以嘗試做各種修改及細(xì)節(jié)優(yōu)化,也可以將除法變乘法,多加練習(xí)是學(xué)習(xí)編程的好方法。
雖然,上例中V2已經(jīng)比V1快了很多了,但隨著N的增大,耗時(shí)還是不少,那么我們還有更好的方法嗎?
2009年4月1日
轉(zhuǎn)自:
http://hi.baidu.com/sunguangran/blog/item/ded90ced94779dd2b31cb11c.html終于搞明白gluPerspective和gluLookAt的關(guān)系了
函數(shù)原型
gluLookAt(GLdoble eyex,GLdouble eyey,GLdouble eyez,GLdouble centerx,GLdouble centery,GLdouble centerz,GLdouble upx,GLdouble upy,GLdouble upz);
gluPerspective(GLdouble fovy,GLdouble aspect,GLdouble zNear,GLdouble zFar)
一個(gè)一個(gè)來(lái),首先得設(shè)置gluPerspective,來(lái)看看它的參數(shù)都表示什么意思
fovy,這個(gè)最難理解,我的理解是,眼睛睜開(kāi)的角度,即,視角的大小,如果設(shè)置為0,相當(dāng)你閉上眼睛了,所以什么也看不到,如果為180,那么可以認(rèn)為你的視界很廣闊,
aspect,這個(gè)好理解,就是實(shí)際窗口的縱橫比,即x/y
zNear,這個(gè)呢,表示你近處,的裁面,
zFar表示遠(yuǎn)處的裁面,
如果還沒(méi)有理解就繼續(xù)看,
我們知道,遠(yuǎn)處的東西看起來(lái)要小一些,近處的東西看起來(lái)會(huì)大一些,這就是透視原理
如下圖所示
假設(shè)那兩條線(xiàn)表示公路,理論上講,它們的兩條邊是平行的,
但現(xiàn)實(shí)情況中,它們?cè)谶h(yuǎn)方(可以無(wú)限遠(yuǎn))總要相交于一點(diǎn),
實(shí)際線(xiàn)段AB的長(zhǎng)度=CD的長(zhǎng)度,只是在此例中使用了透視角,故會(huì)有如上的效果,是不是很接近現(xiàn)實(shí)的情況?
結(jié)合我們剛才這兩個(gè)函數(shù)
zNear,眼睛距離近處的距離,假設(shè)為10米遠(yuǎn),請(qǐng)不要設(shè)置為負(fù)值,OpenGl就傻了,不知道怎么算了,
zFar表示遠(yuǎn)處的裁面,假設(shè)為1000米遠(yuǎn),
就是這兩個(gè)參數(shù)的意義了,
再解釋下那個(gè)"眼睛睜開(kāi)的角度"是什么意思,
首先假設(shè)我們現(xiàn)在距離物體有50個(gè)單位距離遠(yuǎn)的位置,
在眼睛睜開(kāi)角度設(shè)置為45時(shí),請(qǐng)看大屏幕:
我們可以看到,在遠(yuǎn)處一個(gè)球,,很好玩哈,
現(xiàn)在我們將眼睛再?gòu)堥_(kāi)點(diǎn)看,將"眼睛睜開(kāi)的角度"設(shè)置為178
(180度表示平角,那時(shí)候我們將什么也看不到,眼睛睜太大了,眼大無(wú)神)
我們只看到一個(gè)點(diǎn),,,,,,,,,,,,,,,,,,,,,,,,,,,
因?yàn)槲覀兛吹姆秶罅?這個(gè)球本身大小沒(méi)有改變,但是它在我們的"視界"內(nèi)太小了,
反之,我們將眼睛閉小些,改為1度看看會(huì)出現(xiàn)什么情況呢?

在我們距離該物體3000距離遠(yuǎn),"眼睛睜開(kāi)的角度"為1時(shí),我們似乎走進(jìn)了這個(gè)球內(nèi),這個(gè)是不是類(lèi)似于相機(jī)的焦距?
當(dāng)我們將"透視角"設(shè)置為0時(shí),我們相當(dāng)于閉上雙眼,這個(gè)世界清靜了,
我們什么也看不到,,,,,,,,,
現(xiàn)在來(lái)看gluLookAt(GLdoble eyex,GLdouble eyey,GLdouble eyez,GLdouble centerx,GLdouble centery,GLdouble centerz,GLdouble upx,GLdouble upy,GLdouble upz);
它共接受三對(duì)坐標(biāo),
分別為eye,center,up
故名思義,eye表示我們眼睛在"世界坐標(biāo)系"中的位置,
center表示眼睛"看"的那個(gè)點(diǎn)的坐標(biāo),
最后那個(gè)up坐標(biāo)表示觀察者本身的方向,如果將觀察點(diǎn)比喻成我們的眼睛,那么這個(gè)up則表示我們是正立還是倒立異或某一個(gè)角度在看,所看的影像大不相同,故此時(shí)需要指明我們現(xiàn)在正立,那么X,Z軸為0,Y軸為正即可,通常將其設(shè)置為1,只要表示一個(gè)向上的向量(方向)即可
球是畫(huà)在世界坐標(biāo)系的原點(diǎn)上的,即O(0,0,0)坐標(biāo)上,我們的眼睛位于觀察點(diǎn)A(0,0,100),Z軸向屏幕里看去的方向?yàn)樨?fù),屏幕外我們的位置,Z軸為正值,其實(shí)很好理解,即我們距離原點(diǎn)的距離,設(shè)置100,將觀察到如下圖所示的影像
如果我們向前或向后移動(dòng),則相應(yīng)的圖像會(huì)變大或變小,這里其實(shí)就是運(yùn)用了透視原理,近處的物體大,遠(yuǎn)處的物體小,實(shí)際物體的大小是不變的,
同理改變center坐標(biāo)(眼睛看去的那個(gè)點(diǎn),可簡(jiǎn)單理解為視線(xiàn)的終點(diǎn))也會(huì)影響球的大小,同樣可以認(rèn)為是改變了物體與觀察點(diǎn)的距離所致,
最后那個(gè)up坐標(biāo)表示觀察者本身的方向,如果將觀察點(diǎn)比喻成我們的眼睛,那么這個(gè)up則表示我們是正立還是倒立異或某一個(gè)角度在看,所看的影像大不相同,故此時(shí)需要指明我們現(xiàn)在正立,那么X,Z軸為0,Y軸為正即可,通常將其設(shè)置為1,只要表示一個(gè)向上的向量(方向)即可,我們指定0.1f或0.00001f異或1000.0f,效果是一樣的,只要能表示方向即可,
以上理解了之后,來(lái)做一個(gè)測(cè)試
透視圖不變,最遠(yuǎn)處仍為3000,近處為0.1
gluPerspective // 設(shè)置透視圖
(45, // 透視角設(shè)置為 45 度,在Y方向上以角度為單位的視野
(GLfloat)x/(GLfloat)y, // 窗口的寬與高比
0.1f, // 視野透視深度:近點(diǎn)1.0f
3000.0f // 視野透視深度:始點(diǎn)0.1f遠(yuǎn)點(diǎn)1000.0f
);將我們的觀察點(diǎn)置于A(0,10,0),
將觀察位置(視線(xiàn)終點(diǎn))坐標(biāo)置于(0,0,0)
然后在原點(diǎn)開(kāi)始繪圖,畫(huà)一個(gè)V字形,并將Z軸的值從-1000遞增加到+1000,增量為10,
代碼如下
glColor3f(0.5f, 0.7f, 1.0f);
glBegin(GL_LINES);
for(int i=-1000;i<=1000;i+=10)
{
glVertex3f(0,0,i);
glVertex3f(10,10,i);
glVertex3f(0,0,i);
glVertex3f(-10,10,i);
}
glEnd();
F5運(yùn)行效果如下圖

上圖證實(shí)了我們的推測(cè)
//---------------------------------------------
//生成網(wǎng)絡(luò)
glColor3f(0.5f, 0.7f, 1.0f);
int x=(int)(40*2);
glBegin(GL_LINES);
for(int i=-x;i<=x;i+=4)
{
glVertex3i(-x,0,i);
glVertex3i(x,0,i);
glVertex3i(i,0,x);
glVertex3i(i,0,-x);
}
glEnd();
//生成球體
GLUquadricObj * pObj;
pObj = gluNewQuadric();
gluQuadricDrawStyle(pObj,GLU_LINE);
gluQuadricNormals(pObj,GLU_SMOOTH);
=============================================================
以下是個(gè)小總結(jié):
1、模視矩陣(ModelView Matrix)的作用是將模型從局部坐標(biāo)系變換到世界坐標(biāo)系,并最終變換到視點(diǎn)坐標(biāo)系中。它由模型變換矩陣和視點(diǎn)變換矩陣組成。
2、gluLookAt影響的是視點(diǎn)矩陣,它顯式的標(biāo)明了視點(diǎn)坐標(biāo)系與世界坐標(biāo)系的關(guān)系,即視點(diǎn)被安置在世界坐標(biāo)系的哪個(gè)位置,視線(xiàn)的方向朝向何處。
3、gluPerspective用于規(guī)定視景體范圍,與模視矩陣無(wú)關(guān),它影響的是投影矩陣和規(guī)一化矩陣。投影矩陣的作用是使模型產(chǎn)生近大遠(yuǎn)小的效果,規(guī)一化矩陣是將模型的z值規(guī)一化到0~1之間。
4、在編程的時(shí)候,需要glMatrixMode來(lái)指定矩陣堆棧的類(lèi)型,然后對(duì)該矩陣進(jìn)行修改。
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
的作用是初始化模視矩陣,將坐標(biāo)原點(diǎn)重新設(shè)置在世界坐標(biāo)系的原點(diǎn)。之后的glTranslate、glScale、glRotate都會(huì)改變模視矩陣中的模型變換矩陣。而glLookAt則設(shè)置視點(diǎn)變換矩陣。它們共同作用,使得模型能在世界坐標(biāo)系中正確安放,并能從合適的角度去觀察。
2009年3月31日
一個(gè)Vector模板類(lèi),開(kāi)始的時(shí)候是這樣寫(xiě)的:
template <class T>
class Vector
{
public:
Vector(unsigned n=8):_size(n),_data(new T[_size]){}
//.........
protected:
T* _data;
unsigned _size;
};
結(jié)果一運(yùn)行,機(jī)子就慢了,打開(kāi)任務(wù)管理器,占內(nèi)存超大。后來(lái)想起來(lái)初始化列表是按照成員變量的聲明順序初始化的,所以在構(gòu)造函數(shù)里_data數(shù)組先被初始化,這時(shí)_size沒(méi)被初始化,即_size還是個(gè)隨機(jī)值,估計(jì)隨機(jī)的很大,呵呵,比方說(shuō)_size為1234567,于是就申請(qǐng)了1234567的內(nèi)存。。。。
于是修改如下就OK了:
template <class T>
class Vector
{
public:
Vector(unsigned n=8):_size(n),_data(new T[_size]){}
//.........
protected:
unsigned _size;//先聲明_size,先初始化它
T* _data;
};
昨天寫(xiě)個(gè)類(lèi),碰到個(gè)問(wèn)題,我這里用簡(jiǎn)單的例子說(shuō)明,比方說(shuō)寫(xiě)個(gè)學(xué)生類(lèi),性別用枚舉來(lái)表示,然后有個(gè)獲得性別的函數(shù)GetGender(),返回值類(lèi)型為Gender。
class Student
{
enum Gender{MALE,FEMALE};
//...
Gender GetGender();
};
函數(shù)的實(shí)現(xiàn)如下
Gender Student::GetGender
{//...
}
結(jié)果出錯(cuò)。感覺(jué)挺莫名其妙的,呵呵。后來(lái)一琢磨,改成了
Student::Gender Student::GetGender
{//...
}
成功!!!!這個(gè)寫(xiě)法有意思.^_^
2009年3月6日
鑒于網(wǎng)上找資料是件痛苦的,所以我把我自己的一些電子書(shū),以及下載的一些小程序放在了郵箱里,跟大家分享,僅大家學(xué)習(xí)交流(這些資料一般已經(jīng)在網(wǎng)上廣為流傳,我想應(yīng)該沒(méi)有觸及版權(quán)的問(wèn)題吧,呵呵)。大家有需要的可以去郵箱去下,目前只放了一部分,以后會(huì)陸續(xù)添加郵箱地址和密碼如下:
賬號(hào):percyph1@163.com密碼:xcc123456
如果大家有c++,openGL,密碼學(xué)等等計(jì)算機(jī)方面的好資料,也可以發(fā)給我,我的郵箱是
percyph@163.com大家也可以回帖要資料,如果有的話(huà)我會(huì)第一時(shí)間發(fā)上。
相信來(lái)我這兒的朋友都是有素質(zhì)的,請(qǐng)不要?jiǎng)h除和移動(dòng)郵箱里的文件,謝謝!
目前已經(jīng)上傳的資料有:(以后會(huì)陸續(xù)更新)
VC編程助手(小軟件VC++ assistant,能使編程更方便)
C++Primer3(電子書(shū))
glut函數(shù)說(shuō)明(電子書(shū))
C++技能百練(經(jīng)典算法).rar
ROAM地形算法演示程序.rar
OpenGL 參考手冊(cè)
c&c++深層探索
C++必知必會(huì)
VC6.0編程實(shí)例精解
高質(zhì)量C++編程指南&編程新手真言&MFC類(lèi)庫(kù)詳解
Windows程序設(shè)計(jì)
MFC類(lèi)庫(kù)詳解.chm
C++ 數(shù)據(jù)結(jié)構(gòu)第三版
C++ 數(shù)據(jù)結(jié)構(gòu)第三版
程序員面試寶典&程序員超級(jí)開(kāi)發(fā)寶典
c++和OpenGL函數(shù)手冊(cè)
Essential C++中文版.pdf
Effective C++(電子書(shū))
C++編程思想(電子書(shū))
3.11號(hào)上傳(kuafoo發(fā)的) Windows環(huán)境下32位匯編語(yǔ)言.chm(2.78M)
深入淺出MFC
深入淺出MFC第二版
另外最近幾個(gè)月寫(xiě)的數(shù)據(jù)結(jié)構(gòu)的程序也傳上去了,有興趣的朋友可以看看!
里面包括:
線(xiàn)性表——靜態(tài)鏈表2009.7.30
線(xiàn)性表——鏈表的內(nèi)部類(lèi)實(shí)現(xiàn)2008.8
線(xiàn)性表——鏈表的友元類(lèi)實(shí)現(xiàn)2008.8
線(xiàn)性表——雙向鏈表2009.8.11
線(xiàn)性表——順序表2009.8.3
線(xiàn)性表——友元模板類(lèi)2009.8
約瑟夫問(wèn)題——四種解法2009.8.11(數(shù)組,鏈表,循環(huán)鏈表等)
隊(duì)列——隊(duì)列的順序表示循環(huán)隊(duì)列2009.8.11
隊(duì)列——鏈隊(duì)列2009.8.11
棧——漢諾塔2009.8.6
棧——進(jìn)制轉(zhuǎn)換2009.8.6
棧——括號(hào)匹配2009.8.6
棧——模板鏈棧2009.8.3
棧——模板順序棧2009.7
棧——順序棧2009.8.6
棧——算術(shù)表達(dá)式求值2009.7.13
棧——行編輯2009.8.6
二叉樹(shù)——二叉樹(shù)的常見(jiàn)操作2009.9.3
2010.3.9 更新
樹(shù)的應(yīng)用—仿DOS文件夾管理程序
200位大數(shù)乘法.rar
200位大數(shù)加法.rar
連連看單機(jī)程序MFC
分三塊來(lái)講述:
1 首先: 在C中定義一個(gè)結(jié)構(gòu)體類(lèi)型要用typedef:
typedef struct Student
{
int a;
}Stu;
于是在聲明變量的時(shí)候就可:Stu stu1;
如果沒(méi)有typedef就必須用struct Student stu1;來(lái)聲明
這里的Stu實(shí)際上就是struct Student的別名。
另外這里也可以不寫(xiě)Student(于是也不能struct Student stu1;了)
typedef struct
{
int a;
}Stu;
但在c++里很簡(jiǎn)單,直接
struct Student
{
int a;
};
于是就定義了結(jié)構(gòu)體類(lèi)型Student,聲明變量時(shí)直接Student stu2;
===========================================
2其次:在c++中如果用typedef的話(huà),又會(huì)造成區(qū)別:
struct Student
{
int a;
}stu1;//stu1是一個(gè)變量
typedef struct Student2
{
int a;
}stu2;//stu2是一個(gè)結(jié)構(gòu)體類(lèi)型
使用時(shí)可以直接訪(fǎng)問(wèn)stu1.a
但是stu2則必須先 stu2 s2;
然后 s2.a=10;
===========================================
3 掌握上面兩條就可以了,不過(guò)最后我們探討個(gè)沒(méi)多大關(guān)系的問(wèn)題
如果在c程序中我們寫(xiě):
typedef struct
{
int num;
int age;
}aaa,bbb,ccc;
這算什么呢?
我個(gè)人觀察編譯器(VC6)的理解,這相當(dāng)于
typedef struct
{
int num;
int age;
}aaa;
typedef aaa bbb;
typedef aaa ccc;
也就是說(shuō)aaa,bbb,ccc三者都是結(jié)構(gòu)體類(lèi)型。聲明變量時(shí)用任何一個(gè)都可以,在c++中也是如此。但是你要注意的是這個(gè)在c++中如果寫(xiě)掉了typedef關(guān)鍵字,那么aaa,bbb,ccc將是截然不同的三個(gè)對(duì)象。
2009年3月3日
*再次聲明"glut"函數(shù)詳解系列轉(zhuǎn)自:
阿杰--江南暖冬int glutVideoResizeGet(GLenum param);
返回glut視頻大小調(diào)整的信息.
參數(shù):
param:
GLUT_VIDEO_RESIZE_POSSIBLE:如果底層支持視頻大小調(diào)整,則返回非0值,否則返回0.如果返回0,則其他視頻大小調(diào)整函數(shù)的調(diào)用將不起作用.
GLUT_VIDEO_RESIZE_IN_USE
GLUT_VIDEO_RESIZE_X_DELTA
GLUT_VIDEO_RESIZE_Y_DELTA
GLUT_VIDEO_RESIZE_WIDTH_DELTA
GLUT_VIDEO_RESIZE_HEIGHT_DELTA
GLUT_VIDEO_RESIZE_X
GLUT_VIDEO_RESIZE_Y
GLUT_VIDEO_RESIZE_WIDTH
GLUT_VIDEO_RESIZE_HEIGHT
后面幾個(gè)常量值在網(wǎng)上沒(méi)有搜到解釋.
//*******************************************************************************************
void glutSetupVideoResizing(void);
void glutStopVideoResizing(void);
void glutVideoResize(int x, int y, int width, int height);
void glutVideoPan(int x, int y, int width, int height);
我把glut的頭文件中的所有函數(shù)都整理了一遍,只可惜 video resize sub-API中的幾個(gè)函數(shù)網(wǎng)上都沒(méi)有具體的介紹,本菜鳥(niǎo)也無(wú)能為力,幸好這些函數(shù)都不是常用的,我想一般用不著.除了和視頻有關(guān)的API,前面幾個(gè)帖子的內(nèi)容已經(jīng)基本把glut的所有函數(shù)都過(guò)了一遍,本專(zhuān)題也就算是完成了,以后如果找到相關(guān)資料,會(huì)把這里的補(bǔ)上,也希望達(dá)人能夠指點(diǎn)一二.
所謂游戲模式其實(shí)就是一種全屏模式,這里可以對(duì)該模式下的屏幕顯示方式進(jìn)行簡(jiǎn)單設(shè)置.詳見(jiàn)下面具體解釋.
//*******************************************************************************************
void glutGameModeString(const char *string);
通過(guò)一個(gè)字符串對(duì)game mode(游戲模式,也即全屏模式)進(jìn)行設(shè)置,即對(duì)屏幕進(jìn)行設(shè)置.
參數(shù):
string:一個(gè)指向字符串的指針,字符串的內(nèi)容即是對(duì)屏幕的設(shè)置.字符串的格式如下所示:
"W*H"
"W*H:Bpp"
"W*H@Rr"
"W*H:Bpp@Rr"
"@Rr"
":Bpp"
"Bpp:@Rr"
(注:W:屏幕寬度,以像素單位;H:屏幕高度,以像素為單位;Bpp:每個(gè)像素的內(nèi)存大小(位數(shù));Rr:屏幕的刷新率.)
例子:
1.如果我們只關(guān)心屏幕大小(800*600)而不關(guān)心每個(gè)像素的內(nèi)存占用和刷新頻率,可以寫(xiě)成:
glutGameModeString("800*600");
2.如果只想把每個(gè)像素的內(nèi)存占用設(shè)置成32位,可以寫(xiě)成:
glutGameModeString(":32");
3.如果只想把刷新率設(shè)置成75赫茲,可以寫(xiě)成:
glutGameModeString("@75");
4.如果前三種情況都考慮,可以寫(xiě)成:
glutGameModeString("800*600:32@75");
其他情況按照上面給出的字符串格式寫(xiě)出即可.
注:
1.這個(gè)函數(shù)只是對(duì)硬件的請(qǐng)求,如果設(shè)置不合法,則將被忽略.
2.這個(gè)函數(shù)并不返回錯(cuò)誤值,如果要獲得錯(cuò)誤信息,則要用glutGameModeGet()函數(shù).
//*******************************************************************************************
int glutEnterGameMode(void);
進(jìn)入相應(yīng)的game mode,即讓glutGameModeString()的設(shè)置生效.
//*******************************************************************************************
void glutLeaveGameMode(void);
離開(kāi)glutGameModeString()設(shè)置的game mode.
//*******************************************************************************************
int glutGameModeGet(GLenum mode);
檢測(cè)設(shè)置的模式是否有效
參數(shù):
mode:
GLUT_GAME_MODE_ACTIVE:如果程序運(yùn)行在game mode,則返回非0值,如果運(yùn)行在窗口模式,則返回0.
GLUT_GAME_MODE_POSSIBLE:判斷glutAameModeString()的設(shè)置是否有效,如果有效則返回非0值,否則返回0.但是glut手冊(cè)中有一個(gè)警告,即使這個(gè)設(shè)置是有效的,也不能保證屏幕設(shè)置可以一定成功生效.
GLUT_GAME_MODE_WIDTH:返回屏幕的寬度.
GLUT_GAME_MODE_HEIGHT:返回屏幕的高度.
GLUT_GAME_MODE_PIXEL_DEPTH:返回當(dāng)前模式下每個(gè)像素所占用的內(nèi)存空間(位數(shù)).
GLUT_GAME_MODE_REFRESH_RATE:返回實(shí)際的刷新率(單位赫茲).
GLUT_GAME_MODE_DISPLAY_CHANGED:正如前面所說(shuō),不能保證屏幕顯示模式一定根據(jù)設(shè)置發(fā)生改變,這個(gè)常量可以用來(lái)測(cè)試是否真的進(jìn)入了game mode(先前是窗口模式下的情況下),如果先前已經(jīng)是game mode,則可以用來(lái)測(cè)試設(shè)置是否發(fā)生改變.返回非0值表示進(jìn)入了game mode或設(shè)置已經(jīng)發(fā)生改變,否則返回0.