﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>C++博客-小虫虫的书架</title><link>http://www.cppblog.com/percyph/</link><description /><language>zh-cn</language><lastBuildDate>Thu, 23 Apr 2026 10:09:10 GMT</lastBuildDate><pubDate>Thu, 23 Apr 2026 10:09:10 GMT</pubDate><ttl>60</ttl><item><title>基于四叉树LOD的3D地形实现(OpenGL)</title><link>http://www.cppblog.com/percyph/archive/2010/10/07/128962.html</link><dc:creator>小虫虫</dc:creator><author>小虫虫</author><pubDate>Thu, 07 Oct 2010 15:26:00 GMT</pubDate><guid>http://www.cppblog.com/percyph/archive/2010/10/07/128962.html</guid><wfw:comment>http://www.cppblog.com/percyph/comments/128962.html</wfw:comment><comments>http://www.cppblog.com/percyph/archive/2010/10/07/128962.html#Feedback</comments><slash:comments>4</slash:comments><wfw:commentRss>http://www.cppblog.com/percyph/comments/commentRss/128962.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/percyph/services/trackbacks/128962.html</trackback:ping><description><![CDATA[我自己的毕业设计的1.0版本. 采用四叉树LOD算法实现地形渲染.已经传至共享邮箱里,希望对学3D的朋友有帮助
<img src ="http://www.cppblog.com/percyph/aggbug/128962.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/percyph/" target="_blank">小虫虫</a> 2010-10-07 23:26 <a href="http://www.cppblog.com/percyph/archive/2010/10/07/128962.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>（转）质数算法大全，及C程序实现优化详解 (二) 筛选法</title><link>http://www.cppblog.com/percyph/archive/2009/05/14/82963.html</link><dc:creator>小虫虫</dc:creator><author>小虫虫</author><pubDate>Thu, 14 May 2009 07:48:00 GMT</pubDate><guid>http://www.cppblog.com/percyph/archive/2009/05/14/82963.html</guid><wfw:comment>http://www.cppblog.com/percyph/comments/82963.html</wfw:comment><comments>http://www.cppblog.com/percyph/archive/2009/05/14/82963.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/percyph/comments/commentRss/82963.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/percyph/services/trackbacks/82963.html</trackback:ping><description><![CDATA[<p><strong>质数的定义</strong></p>
<p>一个数，如果只有1和它本身两个因数，这样的数叫做质数，又称素数。</p>
<p>在上文 《<a href="http://www.doforfun.net/article/20090504/543.htm" target=_blank>素数算法大全，及C程序实现优化详解 (一) 试除法</a>》中我们已经探讨了求解素数的一类算法，并且将试除法从最初的低效版本优化的高效的V2。那么，还有没有其它更佳算法呢？这就是下面三藏要和大家探讨的内容</p>
<p><strong>合数过滤筛选法</strong></p>
<p><strong>算法描述</strong>：我们知道，素数N不能被2~(N-1)间的任何数整除；反过来看，只要能被2~(N-1)间的任何数整除的N，都不是素数。所以我们可以采用一个简单的排除法：就是对N以内的所有数，只要逐个去除值为2~(N-1)的倍数的数，剩下的就是素数。</p>
<p><strong>C语言实现</strong></p>
<pre>// 合数过滤筛选法 Ver1 <br>// 参数：n 求解n以内(包括n)的素数<br>// 返回值：n以内素数个数 <br>int CompositeNumFilterV1(int n)<br>{<br>&nbsp;int i, j;<br>&nbsp;// 素数数量统计 <br>&nbsp;int count = 0;<br>&nbsp;// 分配素数标记空间，结合后文思考为何+1<br>&nbsp;char* flag = (char*)malloc( n+1 ); <br>&nbsp;<br>&nbsp;// 初始化素数标记 <br>&nbsp;for (i=2; i&lt;=n; i++)<br>&nbsp;{<br>&nbsp;&nbsp;// 为什么*(p+i)要写成flag[i]呢？可读性更佳尔 <br>&nbsp;&nbsp;flag[i] = 1;<br>&nbsp;}<br>&nbsp;<br>&nbsp;// 写程序要注意排版和留空，方便阅读，也可减少出错几率<br>&nbsp;// 以2~(N-1)为因子过滤合数 <br>&nbsp;for (i=2; i &lt; n; i++)<br>&nbsp;{<br>&nbsp;&nbsp;for (j=2; i*j &lt;= n; j++)<br>&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;// i*j是由i,j两整数相乘而得，显然不是素数<br>&nbsp;&nbsp;&nbsp;flag[i*j] = 0;<br>&nbsp;&nbsp;}<br>&nbsp;}<br>&nbsp;<br>&nbsp;// 统计素数个数<br>&nbsp;for (i=2; i&lt;=n; i++)<br>&nbsp;{<br>&nbsp;&nbsp;// 其实if(flag)就其同样作用了，但这么写是有留言的 <br>&nbsp;&nbsp;// 请参阅《C语言程序设计常见错误剖析及解决之道》一文 <br>&nbsp;&nbsp;if (1 == flag[i]) count++;<br>&nbsp;}<br>&nbsp;&nbsp;<br>&nbsp;// 因输出费时，且和算法核心相关不大，故略<br>&nbsp; <br>&nbsp;// 释放内存，别忘了传说中的内存泄漏 <br>&nbsp;free(flag);<br>&nbsp;<br>&nbsp;return count;<br>} </pre>
<p>在上文给出的main函数中以不同参数调用CompositeNumFilterV1函数，得到执行结果如下：</p>
<p>[100000]以内素数个数：9592, 计算用时：15毫秒<br>[1000000]以内素数个数：78498, 计算用时：125毫秒<br>[5000000]以内素数个数：348513, 计算用时：2578毫秒<br>[10000000]以内素数个数：664579, 计算用时：6281毫秒</p>
<p>注：因程序是非独占性运行的，所以时间不是完全精确的，但基本能反映实情</p>
<p>显然，比上文中的试除法要快，而且谁都可以看到上例是一个未经优化的粗陋版本，好多地方是三藏故意采用比较低效做法，为了与后文的优化版比较，凸显优化之重要，也为了初学者记住别采用类似低效做法，下面我们开始优化之旅</p>
<p><strong>优化分析</strong></p>
<p>上面CompositeNumFilterV1函数存在的问题有：</p>
<ol>
    <li>在外层循环，需要一直执行到n-1吗？不要，因为n/2~n-1间的数显然不能整出n
    <li>在内层循环中重复使用i*j显然是低效的，考虑到计算机中加减运算速度比乘除快，可以考虑变乘法为加法
    <li>在循环修改flag过程中，其实有很多数会被重复计算若干次，比如6=2*3=3*2，会被重复置0，类似操作很多，所以我们得设法避免或减少flag重复置0</li>
</ol>
<p>据上述分析，我们可将程序优化如下：</p>
<pre>// 合数过滤筛选法 Ver2 <br>// 参数：n 求解n以内(包括n)的素数<br>// 返回值：n以内素数个数 <br>int CompositeNumFilterV2(int n)<br>{<br>&nbsp;int i, j;<br>&nbsp;// 素数数量统计 <br>&nbsp;int count = 0;<br>&nbsp;// 分配素数标记空间，明白+1原因了吧，因为浪费了一个flag[0]<br>&nbsp;char* flag = (char*)malloc( n+1 ); <br>&nbsp;<br>&nbsp;// 初始化素数标记，要高效点咯<br>&nbsp;flag[2] = 1;<br>&nbsp;// 注意是i&lt;n不是上例中的i&lt;=n了，理由自思 <br>&nbsp;for (i=3; i&lt;n; i++)<br>&nbsp;{<br>&nbsp;&nbsp;flag[i++] = 1;<br>&nbsp;&nbsp;// 偶数自然不是素数，直接置0好了 <br>&nbsp;&nbsp;flag[i] = 0;<br>&nbsp;}<br>&nbsp;// n为奇数 <br>&nbsp;if (n%2 != 0)<br>&nbsp;{<br>&nbsp;&nbsp;flag[n] = 1;<br>&nbsp;}<br>&nbsp;<br>&nbsp;// 从3开始filter，因为2的倍数早在初始化时代就干掉了<br>&nbsp;// 到n/2止的理由还要说吗 <br>&nbsp;for (i=3; i &lt;= n/2; i++)<br>&nbsp;{<br>&nbsp;&nbsp;// i是合数，请歇着吧，因为您的工作早有您的质因子代劳了 <br>&nbsp;&nbsp;if (0 == flag[i]) continue;<br>&nbsp;&nbsp;<br>&nbsp;&nbsp;// 从i的2倍开始过滤，变乘法为加法&nbsp; <br>&nbsp;&nbsp;for (j=i+i; j &lt;= n; j+=i)<br>&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;flag[j] = 0;<br>&nbsp;&nbsp;}<br>&nbsp;}<br>&nbsp;<br>&nbsp;// 统计素数个数<br>&nbsp;for (i=2; i&lt;=n; i++)<br>&nbsp;{<br>&nbsp;&nbsp;if (flag[i]) count++;<br>&nbsp;}<br>&nbsp;&nbsp;<br>&nbsp;// 因输出费时，且和算法核心相关不大，故略<br>&nbsp; <br>&nbsp;// 释放内存，别忘了传说中的内存泄漏 <br>&nbsp;free(flag);<br>&nbsp;<br>&nbsp;return count;<br>} </pre>
<p>再来调用CompositeNumFilterV2得到执行结果：</p>
<p>[100000]以内素数个数：9592, 计算用时：n太小，时间精度不够<br>[1000000]以内素数个数：78498, 计算用时：31毫秒<br>[5000000]以内素数个数：348513, 计算用时：453毫秒<br>[10000000]以内素数个数：664579, 计算用时：1062毫秒<br>[100000000]以内素数个数：5761455, 计算用时：12973毫秒</p>
<p>哇哇，比昨天的试除发快了好多倍，可见算法的威力，值得好好学习，别说学算法没用咯。</p>
<p>上例着那个计算一亿以内的素数只要约13秒，应该算不错了，今天是否可以休息了呢？No，我们要追求极限！</p>
<pre>int CompositeNumFilterV3(int n)<br>{<br>&nbsp;int i, j;<br>&nbsp;// 素数数量统计 <br>&nbsp;int count = 0;<br>&nbsp;// 分配素数标记空间，明白+1原因了吧，因为浪费了一个flag[0]<br>&nbsp;char* flag = (char*)malloc( n+1 );<br>&nbsp;// 干嘛用的，请仔细研究下文<br>&nbsp;int mpLen = 2*3*5*7*11*13;<br>&nbsp;char magicPattern[mpLen];<br>&nbsp;// 奇怪的代码，why，思考无法代劳，想！ <br>&nbsp;for (i=0; i&lt;mpLen; i++)<br>&nbsp;{<br>&nbsp;&nbsp;magicPattern[i++] = 1;<br>&nbsp;&nbsp;magicPattern[i++] = 0;<br>&nbsp;&nbsp;magicPattern[i++] = 0;<br>&nbsp;&nbsp;magicPattern[i++] = 0;<br>&nbsp;&nbsp;magicPattern[i++] = 1;<br>&nbsp;&nbsp;magicPattern[i] = 0;<br>&nbsp;}<br>&nbsp;for (i=4; i&lt;=mpLen; i+=5)<br>&nbsp;&nbsp;magicPattern[i] = 0;<br>&nbsp;for (i=6; i&lt;=mpLen; i+=7)<br>&nbsp;&nbsp;magicPattern[i] = 0;<br>&nbsp;for (i=10; i&lt;=mpLen; i+=11)<br>&nbsp;&nbsp;magicPattern[i] = 0;<br>&nbsp;for (i=12; i&lt;=mpLen; i+=13)<br>&nbsp;&nbsp;magicPattern[i] = 0;<br>&nbsp;<br>&nbsp;// 新的初始化方法,将2,3,5,7,11,13的倍数全干掉<br>&nbsp;// 而且采用memcpy以mpLen长的magicPattern来批量处理 <br>&nbsp;int remainder = n%mpLen;<br>&nbsp;char* p = flag+1;<br>&nbsp;char* pstop = p+n-remainder;<br>&nbsp;while (p &lt; pstop)<br>&nbsp;{<br>&nbsp;&nbsp;memcpy(p, magicPattern, mpLen);<br>&nbsp;&nbsp;p += mpLen;<br>&nbsp;}<br>&nbsp;if (remainder &gt; 0)<br>&nbsp;{<br>&nbsp;&nbsp;memcpy(p, magicPattern, remainder);<br>&nbsp;}<br>&nbsp;flag[2] = 1;<br>&nbsp;flag[3] = 1;<br>&nbsp;flag[5] = 1;<br>&nbsp;flag[7] = 1;<br>&nbsp;flag[11] = 1;<br>&nbsp;flag[13] = 1;<br>&nbsp;<br>&nbsp;// 从17开始filter，因为2,3,5,7,11,13的倍数早被kill了 <br>&nbsp;// 到n/13止的，哈哈，少了好多吧<br>&nbsp;int stop = n/13;<br>&nbsp;for (i=17; i &lt;= stop; i++)<br>&nbsp;{<br>&nbsp;&nbsp;// i是合数，请歇着吧，因为您的工作早有您的质因子代劳了 <br>&nbsp;&nbsp;if (0 == flag[i]) continue;<br>&nbsp;&nbsp;<br>&nbsp;&nbsp;// 从i的17倍开始过滤<br>&nbsp;&nbsp;int step = i*2;<br>&nbsp;&nbsp;for (j=i*17; j &lt;= n; j+=step)<br>&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;flag[j] = 0;<br>&nbsp;&nbsp;}<br>&nbsp;}<br>&nbsp;<br>&nbsp;// 统计素数个数<br>&nbsp;for (i=2; i&lt;=n; i++)<br>&nbsp;{<br>&nbsp;&nbsp;if (flag[i]) count++;<br>&nbsp;}<br>&nbsp;&nbsp;<br>&nbsp;// 因输出费时，且和算法核心相关不大，故略<br>&nbsp; <br>&nbsp;// 释放内存，别忘了传说中的内存泄漏 <br>&nbsp;free(flag);<br>&nbsp;<br>&nbsp;return count;<br>}</pre>
<p>再看CompositeNumFilterV3执行结果：</p>
<p>[1000000]以内素数个数：78498, 计算用时：15毫秒<br>[5000000]以内素数个数：348513, 计算用时：203毫秒<br>[10000000]以内素数个数：664579, 计算用时：515毫秒<br>[100000000]以内素数个数：5761455, 计算用时：6421毫秒</p>
<p>再次优化后速度提升了又一倍左右，三藏不禁有点满足了，睡觉也！</p>
<img src ="http://www.cppblog.com/percyph/aggbug/82963.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/percyph/" target="_blank">小虫虫</a> 2009-05-14 15:48 <a href="http://www.cppblog.com/percyph/archive/2009/05/14/82963.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>(转)素数算法大全，及C程序实现优化详解 (一) 试除法</title><link>http://www.cppblog.com/percyph/archive/2009/05/14/82961.html</link><dc:creator>小虫虫</dc:creator><author>小虫虫</author><pubDate>Thu, 14 May 2009 07:46:00 GMT</pubDate><guid>http://www.cppblog.com/percyph/archive/2009/05/14/82961.html</guid><wfw:comment>http://www.cppblog.com/percyph/comments/82961.html</wfw:comment><comments>http://www.cppblog.com/percyph/archive/2009/05/14/82961.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/percyph/comments/commentRss/82961.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/percyph/services/trackbacks/82961.html</trackback:ping><description><![CDATA[<p>转自：<a href="http://www.doforfun.net/article/20090504/543.htm"><a href="http://www.doforfun.net/article/20090504/543.htm">http://www.doforfun.net/article/20090504/543.htm</a><br></a>经常有初学者询问求解N内所有素数（质数）的问题，对此，网上的解答也很多，但很多要么不够专业，要么只有程序没有算法解析，所以三藏大厦对此问题做个小结，探讨一下求解素数的常见算法，同时给出相应的C语言程序及其解析。为了方便初学者理解，本文将从易到难阐述不同算法，高手可以直接看后面的高效算法</p>
<p><strong>质数的定义</strong></p>
<p>一个数，如果只有1和它本身两个因数，这样的数叫做质数，又称素数。&nbsp;<br></p>
<p><strong>试除判断法</strong></p>
<p><strong>算法描述</strong>：从上述定义可知，素数不能被1和它本身之外的数整除，所以，判断一个数x是否素数只要看它是否能被2~sqrt(x)间的数整除即可；而求N内所有素数则是循环重复上述过程。</p>
<p><strong>C语言实现</strong>：</p>
<pre>#include &lt;time.h&gt;<br>#include &lt;malloc.h&gt; <br>#define N&nbsp;100000<br>// 简单试除判断法 Ver1 <br>int SimpleDivisionV1(int n)<br>{<br>&nbsp;int i,j;<br>&nbsp;// 素数数量统计 <br>&nbsp;int count = 0;<br>&nbsp;// 分配存放结果的空间 <br>&nbsp;int* primes = (int*)malloc( sizeof(int)*n ); <br>&nbsp;<br>&nbsp;// 2是素数谁都知道，不算了 <br>&nbsp;primes[count++] = 2;<br>&nbsp;// 循环计算3~n间的数 <br>&nbsp;for (i=3; i&lt;=n; i++)<br>&nbsp;{<br>&nbsp;&nbsp;// 为什么是sqrt(i)，思考一下 <br>&nbsp;&nbsp;for (j=2; j&lt;=sqrt(i); j++)<br>&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;// i被j整除，显然不是素数了 <br>&nbsp;&nbsp;&nbsp;if (i%j == 0) break;<br>&nbsp;&nbsp;}<br>&nbsp;&nbsp;// i不能被2~sqrt(i)间的数整除,素数也 <br>&nbsp;&nbsp;if (j &gt; sqrt(i))<br>&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;primes[count++] = i;<br>&nbsp;&nbsp;}<br>&nbsp;}<br>&nbsp;<br>&nbsp;// 因输出费时，且和算法核心相关不大，故略<br>&nbsp; <br>&nbsp;// 释放内存，别忘了传说中的内存泄漏 <br>&nbsp;free(primes);<br>&nbsp;<br>&nbsp;return count;<br>} <br><br>void main()<br>{<br>&nbsp;int count;<br>&nbsp;clock_t start, end;<br>&nbsp;// time函数不够精确，用clock凑合一下吧 <br>&nbsp;start = clock(); <br>&nbsp;count = SimpleDivisionV1(N);<br>&nbsp;<br>&nbsp;end = clock();<br>&nbsp;printf("[%d]以内素数个数：%d, 计算用时：%d毫秒\n", N, count, end-start);<br>&nbsp;getch();&nbsp;<br>}</pre>
<p>计算结果：<br>[100000]以内素数个数：9592, 计算用时：468毫秒<br>[1000000]以内素数个数：78498, 计算用时：10859毫秒<br>[5000000]以内素数个数：348513, 计算用时：103560毫秒</p>
<p>噢噢，算算十万还行，百万就10秒多了，而且时间增长很快，这不行，得优化一下！</p>
<p><strong>优化分析</strong>：</p>
<p>仔细研究一下SimpleDivisionV1我们可以发现以下几个问题：</p>
<ol>
    <li>在循环条件中重复调用sqrt(i)显然是比较浪费时间的
    <li>判断素数，真的需要拿2~sqrt(i)间的所有整数去除吗？我们知道，合数都可以分解成若干质数，所以只要2~sqrt(i)间的质数不能整除i即可</li>
</ol>
<p>根据上面两点，我们可将SimpleDivisionV1升级为SimpleDivisionV2，如下</p>
<pre>&nbsp;// 简单试除判断法 Ver2 <br>int SimpleDivisionV2(int n)<br>{<br>&nbsp;int i, j, k, stop;<br>&nbsp;// 素数数量统计 <br>&nbsp;int count = 0;<br>&nbsp;// 分配存放结果的空间 <br>&nbsp;int* primes = (int*)malloc( sizeof(int)*n ); <br>&nbsp;<br>&nbsp;// 2是素数谁都知道，不算了 <br>&nbsp;primes[count++] = 2;<br>&nbsp;stop = count;<br>&nbsp;// 循环计算3~n间的数 <br>&nbsp;for (i=3; i&lt;=n; i++)<br>&nbsp;{<br>&nbsp;&nbsp;k = sqrt(i);<br>&nbsp;&nbsp;// 在循环条件中重复调用sqrt是低效做法，故引入k <br>&nbsp;&nbsp;while (primes[stop] &lt;= k &amp;&amp; stop &lt; count)<br>&nbsp;&nbsp;&nbsp;stop++;<br>&nbsp;&nbsp;// stop干什么用，思考一下<br>&nbsp;&nbsp;for (j=0; j&lt;stop; j++)<br>&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;if (i%primes[j] == 0) break;<br>&nbsp;&nbsp;}<br>&nbsp;&nbsp;// i不能被2~sqrt(i)间的素数整除，自然也不能被其他数整除,素数也 <br>&nbsp;&nbsp;if (j == stop)<br>&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;primes[count++] = i;<br>&nbsp;&nbsp;}<br>&nbsp;}<br>&nbsp;<br>&nbsp;// 因输出费时，且和算法核心相关不大，故略<br>&nbsp; <br>&nbsp;// 释放内存，别忘了传说中的内存泄漏 <br>&nbsp;free(primes);<br>&nbsp;<br>&nbsp;return count;<br>} </pre>
<p>然后将main中调用的函数替换为SimpleDivisionV2，在看一下执行结果：</p>
<p>[100000]以内素数个数：9592, 计算用时：46毫秒<br>[1000000]以内素数个数：78498, 计算用时：546毫秒<br>[5000000]以内素数个数：348513, 计算用时：3515毫秒<br>[10000000]以内素数个数：664579, 计算用时：8000毫秒</p>
<p>很开心的看到，经过优化，速度提高了几十倍，尤其是时间增长曲线的坡度变小了，N值越大，V2函数比V1的效率就越高</p>
<p>对于试除判断这种质数算法来说，三藏认为SimpleDivisionV2基本已经接近极限，不大可能有量级上的突破了，有兴趣的朋友可以自己进一步优化。初学者除了参看上述例子外，可以尝试做各种修改及细节优化，也可以将除法变乘法，多加练习是学习编程的好方法。</p>
<p>虽然，上例中V2已经比V1快了很多了，但随着N的增大，耗时还是不少，那么我们还有更好的方法吗？</p>
<img src ="http://www.cppblog.com/percyph/aggbug/82961.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/percyph/" target="_blank">小虫虫</a> 2009-05-14 15:46 <a href="http://www.cppblog.com/percyph/archive/2009/05/14/82961.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>（转）gluPerspective和gluLookAt的关系</title><link>http://www.cppblog.com/percyph/archive/2009/04/01/78537.html</link><dc:creator>小虫虫</dc:creator><author>小虫虫</author><pubDate>Wed, 01 Apr 2009 03:03:00 GMT</pubDate><guid>http://www.cppblog.com/percyph/archive/2009/04/01/78537.html</guid><wfw:comment>http://www.cppblog.com/percyph/comments/78537.html</wfw:comment><comments>http://www.cppblog.com/percyph/archive/2009/04/01/78537.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/percyph/comments/commentRss/78537.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/percyph/services/trackbacks/78537.html</trackback:ping><description><![CDATA[转自： <a href="http://hi.baidu.com/sunguangran/blog/item/ded90ced94779dd2b31cb11c.html">http://hi.baidu.com/sunguangran/blog/item/ded90ced94779dd2b31cb11c.html</a><br><br>终于搞明白gluPerspective和gluLookAt的关系了<br><br>函数原型<br>gluLookAt(GLdoble eyex,GLdouble eyey,GLdouble eyez,GLdouble centerx,GLdouble centery,GLdouble centerz,GLdouble upx,GLdouble upy,GLdouble upz);<br><br>gluPerspective(GLdouble fovy,GLdouble aspect,GLdouble zNear,GLdouble zFar)<br><br>一个一个来,首先得设置gluPerspective,来看看它的参数都表示什么意思<br>fovy,这个最难理解,我的理解是,眼睛睁开的角度,即,视角的大小,如果设置为0,相当你闭上眼睛了,所以什么也看不到,如果为180,那么可以认为你的视界很广阔,<br>aspect,这个好理解,就是实际窗口的纵横比,即x/y<br>zNear,这个呢,表示你近处,的裁面,<br>zFar表示远处的裁面,<br><br>如果还没有理解就继续看,<br>我们知道,远处的东西看起来要小一些,近处的东西看起来会大一些,这就是透视原理<br>如下图所示<br>
<div forimg="1"><img class=blogimg src="http://hiphotos.baidu.com/kkun/pic/item/6d203a299bf5aef799250a2d.jpg" border=0 small="0"><br>
<div forimg="1"><img class=blogimg src="http://hiphotos.baidu.com/kkun/pic/item/493835fae74b34809e5146aa.jpg" border=0 small="0"></div>
<br><br>假设那两条线表示公路,理论上讲,它们的两条边是平行的,<br>但现实情况中,它们在远方(可以无限远)总要相交于一点,<br>实际线段AB的长度=CD的长度,只是在此例中使用了透视角,故会有如上的效果,是不是很接近现实的情况?<br><br>结合我们刚才这两个函数<br>zNear,眼睛距离近处的距离,假设为10米远,请不要设置为负值,OpenGl就傻了,不知道怎么算了,<br>zFar表示远处的裁面,假设为1000米远,<br>就是这两个参数的意义了,<br><br>再解释下那个"眼睛睁开的角度"是什么意思,<br>首先假设我们现在距离物体有50个单位距离远的位置,<br>在眼睛睁开角度设置为45时,请看大屏幕:<br>
<div forimg="1"><a href="http://hiphotos.baidu.com/kkun/pic/item/c68ac9ea62d178dad539c90c.jpg" target=_blank>
<div forimg="1"><img class=blogimg src="http://hiphotos.baidu.com/kkun/pic/item/746f352ab97c5e315343c10d.jpg" border=0 small="0"></div>
</a><br><br>我们可以看到,在远处一个球,,很好玩哈,<br>现在我们将眼睛再张开点看,将"眼睛睁开的角度"设置为178<br>(180度表示平角,那时候我们将什么也看不到,眼睛睁太大了,眼大无神)<br>
<div forimg="1"><img class=blogimg src="http://hiphotos.baidu.com/kkun/pic/item/102f01e9a22b6f36b80e2d17.jpg" border=0 small="0"></div>
<br><br>我们只看到一个点,,,,,,,,,,,,,,,,,,,,,,,,,,,<br>因为我们看的范围太大了,这个球本身大小没有改变,但是它在我们的"视界"内太小了,<br><br><br>反之,我们将眼睛闭小些,改为1度看看会出现什么情况呢?<br>
<div forimg="1"><img class=blogimg src="http://hiphotos.baidu.com/kkun/pic/item/ab45dab464dc607a8bd4b21e.jpg" border=0 small="0"><br><br>在我们距离该物体3000距离远,"眼睛睁开的角度"为1时,我们似乎走进了这个球内,这个是不是类似于相机的焦距?<br><br>当我们将"透视角"设置为0时,我们相当于闭上双眼,这个世界清静了,<br><br>我们什么也看不到,,,,,,,,,</div>
</div>
<br><br><br>现在来看gluLookAt(GLdoble eyex,GLdouble eyey,GLdouble eyez,GLdouble centerx,GLdouble centery,GLdouble centerz,GLdouble upx,GLdouble upy,GLdouble upz);<br><br>它共接受三对坐标,<br>分别为eye,center,up<br>故名思义,eye表示我们眼睛在"世界坐标系"中的位置,<br>center表示眼睛"看"的那个点的坐标,<br>最后那个up坐标表示观察者本身的方向,如果将观察点比喻成我们的眼睛,那么这个up则表示我们是正立还是倒立异或某一个角度在看,所看的影像大不相同,故此时需要指明我们现在正立,那么X,Z轴为0,Y轴为正即可,通常将其设置为1,只要表示一个向上的向量(方向)即可<br>球是画在世界坐标系的原点上的,即O(0,0,0)坐标上,我们的眼睛位于观察点A(0,0,100),Z轴向屏幕里看去的方向为负,屏幕外我们的位置,Z轴为正值,其实很好理解,即我们距离原点的距离,设置100,将观察到如下图所示的影像<br><a href="http://hiphotos.baidu.com/kkun/pic/item/c68ac9ea62d178dad539c90c.jpg" target=_blank>
<div forimg="1"><img class=blogimg src="http://hiphotos.baidu.com/kkun/pic/item/746f352ab97c5e315343c10d.jpg" border=0 small="0"></div>
</a><br>如果我们向前或向后移动,则相应的图像会变大或变小,这里其实就是运用了透视原理,近处的物体大,远处的物体小,实际物体的大小是不变的,<br><br>同理改变center坐标(眼睛看去的那个点,可简单理解为视线的终点)也会影响球的大小,同样可以认为是改变了物体与观察点的距离所致,<br><br>最后那个up坐标表示观察者本身的方向,如果将观察点比喻成我们的眼睛,那么这个up则表示我们是正立还是倒立异或某一个角度在看,所看的影像大不相同,故此时需要指明我们现在正立,那么X,Z轴为0,Y轴为正即可,通常将其设置为1,只要表示一个向上的向量(方向)即可,我们指定0.1f或0.00001f异或1000.0f,效果是一样的,只要能表示方向即可,<br><br><br><br><br>以上理解了之后,来做一个测试<br>透视图不变,最远处仍为3000,近处为0.1<br><br><em>gluPerspective&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; // 设置透视图<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; (45,&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; // 透视角设置为 45 度,在Y方向上以角度为单位的视野<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; (GLfloat)x/(GLfloat)y,&nbsp;&nbsp;&nbsp; // 窗口的宽与高比<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; 0.1f,&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; // 视野透视深度:近点1.0f<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; 3000.0f&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; // 视野透视深度:始点0.1f远点1000.0f<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; );</em><br><br>将我们的观察点置于A(0,10,0),<br>将观察位置(视线终点)坐标置于(0,0,0)<br>然后在原点开始绘图,画一个V字形,并将Z轴的值从-1000递增加到+1000,增量为10,<br>代码如下<br><em><br>&nbsp;&nbsp;&nbsp; glColor3f(0.5f, 0.7f, 1.0f);<br><br>&nbsp;&nbsp;&nbsp; glBegin(GL_LINES);<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; for(int i=-1000;i&lt;=1000;i+=10)<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; glVertex3f(0,0,i);<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; glVertex3f(10,10,i);<br><br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; glVertex3f(0,0,i);<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; glVertex3f(-10,10,i);<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; glEnd();<br></em><br>F5运行效果如下图<br>
<div forimg="1"><img class=blogimg src="http://hiphotos.baidu.com/kkun/pic/item/f1be800ad3acf337b1351dd9.jpg" border=0 small="0"><br><br>上图证实了我们的推测</div>
<br><br><br><br><br><br><br><br><br><br><br>//---------------------------------------------<br>&nbsp;&nbsp;&nbsp; //生成网络<br>&nbsp;&nbsp;&nbsp; glColor3f(0.5f, 0.7f, 1.0f);<br>&nbsp;&nbsp;&nbsp; int x=(int)(40*2);<br>&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; glBegin(GL_LINES);<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; for(int i=-x;i&lt;=x;i+=4)<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; glVertex3i(-x,0,i);<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; glVertex3i(x,0,i);<br><br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; glVertex3i(i,0,x);<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; glVertex3i(i,0,-x);<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; glEnd();<br><br>//生成球体<br>&nbsp;&nbsp;&nbsp; GLUquadricObj * pObj;<br>&nbsp;&nbsp;&nbsp; pObj = gluNewQuadric();<br>&nbsp;&nbsp;&nbsp; gluQuadricDrawStyle(pObj,GLU_LINE);<br>&nbsp;&nbsp;&nbsp; gluQuadricNormals(pObj,GLU_SMOOTH);<br><br>=============================================================<br>以下是个小总结：<br>1、模视矩阵（ModelView Matrix）的作用是将模型从局部坐标系变换到世界坐标系，并最终变换到视点坐标系中。它由模型变换矩阵和视点变换矩阵组成。<br>2、gluLookAt影响的是视点矩阵，它显式的标明了视点坐标系与世界坐标系的关系，即视点被安置在世界坐标系的哪个位置，视线的方向朝向何处。<br>3、gluPerspective用于规定视景体范围，与模视矩阵无关，它影响的是投影矩阵和规一化矩阵。投影矩阵的作用是使模型产生近大远小的效果，规一化矩阵是将模型的z值规一化到0~1之间。<br>4、在编程的时候，需要glMatrixMode来指定矩阵堆栈的类型，然后对该矩阵进行修改。<br>&nbsp;&nbsp; glMatrixMode(GL_MODELVIEW);<br>&nbsp;&nbsp; glLoadIdentity();<br>&nbsp;&nbsp; 的作用是初始化模视矩阵，将坐标原点重新设置在世界坐标系的原点。之后的glTranslate、glScale、glRotate都会改变模视矩阵中的模型变换矩阵。而glLookAt则设置视点变换矩阵。它们共同作用，使得模型能在世界坐标系中正确安放，并能从合适的角度去观察。<br><br></div>
<img src ="http://www.cppblog.com/percyph/aggbug/78537.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/percyph/" target="_blank">小虫虫</a> 2009-04-01 11:03 <a href="http://www.cppblog.com/percyph/archive/2009/04/01/78537.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>关于初始化列表的初始化顺序</title><link>http://www.cppblog.com/percyph/archive/2009/03/31/78444.html</link><dc:creator>小虫虫</dc:creator><author>小虫虫</author><pubDate>Tue, 31 Mar 2009 02:33:00 GMT</pubDate><guid>http://www.cppblog.com/percyph/archive/2009/03/31/78444.html</guid><wfw:comment>http://www.cppblog.com/percyph/comments/78444.html</wfw:comment><comments>http://www.cppblog.com/percyph/archive/2009/03/31/78444.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.cppblog.com/percyph/comments/commentRss/78444.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/percyph/services/trackbacks/78444.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 一个Vector模板类,开始的时候是这样写的：<br>template &lt;class T&gt;<br>class Vector<br>{<br>public:<br>&nbsp;&nbsp;&nbsp;&nbsp;Vector(unsigned n=8):_size(n),_data(new T[_size]){}<br>&nbsp;&nbsp; //.........<br>protected:<br>&nbsp;&nbsp;&nbsp;&nbsp;T*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; _data;<br>&nbsp;&nbsp;&nbsp; unsigned _size;<br>};<br>结果一运行，机子就慢了，打开任务管理器，占内存超大。后来想起来初始化列表是按照成员变量的声明顺序初始化的，所以在构造函数里_data数组先被初始化，这时_size没被初始化，即_size还是个随机值，估计随机的很大，呵呵，比方说_size为1234567，于是就申请了1234567的内存。。。。<br>于是修改如下就OK了：<br>template &lt;class T&gt;<br>class Vector<br>{<br>public:<br>&nbsp;&nbsp;&nbsp;&nbsp;Vector(unsigned n=8):_size(n),_data(new T[_size]){}<br>&nbsp;&nbsp; //.........<br>protected:<br>&nbsp;&nbsp;&nbsp; unsigned _size;//先声明_size，先初始化它<br>&nbsp;&nbsp;&nbsp;&nbsp;T*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; _data;<br>};
<img src ="http://www.cppblog.com/percyph/aggbug/78444.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/percyph/" target="_blank">小虫虫</a> 2009-03-31 10:33 <a href="http://www.cppblog.com/percyph/archive/2009/03/31/78444.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>碰到命名空间的问题</title><link>http://www.cppblog.com/percyph/archive/2009/03/31/78442.html</link><dc:creator>小虫虫</dc:creator><author>小虫虫</author><pubDate>Tue, 31 Mar 2009 02:25:00 GMT</pubDate><guid>http://www.cppblog.com/percyph/archive/2009/03/31/78442.html</guid><wfw:comment>http://www.cppblog.com/percyph/comments/78442.html</wfw:comment><comments>http://www.cppblog.com/percyph/archive/2009/03/31/78442.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/percyph/comments/commentRss/78442.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/percyph/services/trackbacks/78442.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 昨天写个类，碰到个问题，我这里用简单的例子说明，比方说写个学生类，性别用枚举来表示，然后有个获得性别的函数GetGender(),返回值类型为Gender。<br>class Student<br>{<br>enum Gender{MALE,FEMALE};<br>//...<br>Gender GetGender();<br>};<br>函数的实现如下<br>Gender Student::GetGender<br>{//...<br>}<br>结果出错。感觉挺莫名其妙的，呵呵。后来一琢磨，改成了<br>Student::Gender Student::GetGender<br>{//...<br>}<br>成功！！！！这个写法有意思.^_^&nbsp;&nbsp;&nbsp;&nbsp;
<img src ="http://www.cppblog.com/percyph/aggbug/78442.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/percyph/" target="_blank">小虫虫</a> 2009-03-31 10:25 <a href="http://www.cppblog.com/percyph/archive/2009/03/31/78442.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>资料分享声明</title><link>http://www.cppblog.com/percyph/archive/2009/03/06/75763.html</link><dc:creator>小虫虫</dc:creator><author>小虫虫</author><pubDate>Fri, 06 Mar 2009 10:32:00 GMT</pubDate><guid>http://www.cppblog.com/percyph/archive/2009/03/06/75763.html</guid><wfw:comment>http://www.cppblog.com/percyph/comments/75763.html</wfw:comment><comments>http://www.cppblog.com/percyph/archive/2009/03/06/75763.html#Feedback</comments><slash:comments>4</slash:comments><wfw:commentRss>http://www.cppblog.com/percyph/comments/commentRss/75763.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/percyph/services/trackbacks/75763.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 鉴于网上找资料是件痛苦的，所以我把我自己的一些电子书，以及下载的一些小程序放在了邮箱里，跟大家分享，仅大家学习交流（这些资料一般已经在网上广为流传，我想应该没有触及版权的问题吧，呵呵）。大家有需要的可以去邮箱去下，目前只放了一部分，以后会陆续添加邮箱地址和密码如下：<br><a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#112;&#101;&#114;&#99;&#121;&#112;&#104;&#49;&#64;&#49;&#54;&#51;&#46;&#99;&#111;&#109;">账号：percyph1@163.com</a><br>密码：xcc123456<br>如果大家有c++，openGL，密码学等等计算机方面的好资料，也可以发给我，我的邮箱是 <a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#112;&#101;&#114;&#99;&#121;&#112;&#104;&#64;&#49;&#54;&#51;&#46;&#99;&#111;&#109;">percyph@163.com</a><br>大家也可以回帖要资料，如果有的话我会第一时间发上。<br>相信来我这儿的朋友都是有素质的，请不要删除和移动邮箱里的文件，谢谢！<br><br>目前已经上传的资料有：（以后会陆续更新）<br><br>&nbsp;&nbsp; VC编程助手（小软件VC++ assistant，能使编程更方便）<br>&nbsp; &nbsp;C++Primer3（电子书）<br>&nbsp;&nbsp; glut函数说明（电子书）<br>&nbsp;&nbsp; C++技能百练（经典算法）.rar&nbsp;<br>&nbsp;&nbsp; ROAM地形算法演示程序.rar&nbsp;<br>&nbsp;&nbsp; OpenGL 参考手册<br>&nbsp;&nbsp; c&amp;c++深层探索&nbsp;<br>&nbsp;&nbsp; C++必知必会&nbsp;<br>&nbsp;&nbsp; VC6.0编程实例精解&nbsp;<br>&nbsp;&nbsp; 高质量C++编程指南&amp;编程新手真言&amp;MFC类库详解&nbsp;<br>&nbsp;&nbsp; Windows程序设计&nbsp;<br>&nbsp;&nbsp; MFC类库详解.chm&nbsp;<br>&nbsp;&nbsp; C++ 数据结构第三版&nbsp;<br>&nbsp;&nbsp; C++ 数据结构第三版&nbsp;<br>&nbsp;&nbsp; 程序员面试宝典&amp;程序员超级开发宝典&nbsp;<br>&nbsp;&nbsp; c++和OpenGL函数手册&nbsp;<br>&nbsp;&nbsp; Essential C++中文版.pdf&nbsp;<br>&nbsp;&nbsp; Effective C++(电子书)&nbsp;<br>&nbsp;&nbsp; C++编程思想（电子书） <br><br><span style="COLOR: #993300">3.11号上传（kuafoo发的）</span><br>&nbsp;&nbsp; Windows环境下32位汇编语言.chm(2.78M)<br>&nbsp;&nbsp; 深入浅出MFC<br>&nbsp;&nbsp; 深入浅出MFC第二版<br>&nbsp;&nbsp; <br>另外最近几个月写的数据结构的程序也传上去了，有兴趣的朋友可以看看！ <br>
<p>里面包括：</p>
<p>线性表——静态链表2009.7.30<br>线性表——链表的内部类实现2008.8<br>线性表——链表的友元类实现2008.8<br>线性表——双向链表2009.8.11<br>线性表——顺序表2009.8.3<br>线性表——友元模板类2009.8</p>
<p>约瑟夫问题——四种解法2009.8.11（数组，链表，循环链表等）<br>队列——队列的顺序表示循环队列2009.8.11<br>队列——链队列2009.8.11<br>栈——汉诺塔2009.8.6<br>栈——进制转换2009.8.6<br>栈——括号匹配2009.8.6<br>栈——模板链栈2009.8.3<br>栈——模板顺序栈2009.7<br>栈——顺序栈2009.8.6<br>栈——算术表达式求值2009.7.13<br>栈——行编辑2009.8.6<br>二叉树——二叉树的常见操作2009.9.3<br></p>
<p><span style="COLOR: #993300">2010.3.9 更新</span></p>
<p>树的应用—仿DOS文件夹管理程序</p>
<p>200位大数乘法.rar</p>
<p>200位大数加法.rar</p>
<p>连连看单机程序MFC<br></p>
<img src ="http://www.cppblog.com/percyph/aggbug/75763.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/percyph/" target="_blank">小虫虫</a> 2009-03-06 18:32 <a href="http://www.cppblog.com/percyph/archive/2009/03/06/75763.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>struct和typedef struct </title><link>http://www.cppblog.com/percyph/archive/2009/03/06/75742.html</link><dc:creator>小虫虫</dc:creator><author>小虫虫</author><pubDate>Fri, 06 Mar 2009 06:20:00 GMT</pubDate><guid>http://www.cppblog.com/percyph/archive/2009/03/06/75742.html</guid><wfw:comment>http://www.cppblog.com/percyph/comments/75742.html</wfw:comment><comments>http://www.cppblog.com/percyph/archive/2009/03/06/75742.html#Feedback</comments><slash:comments>20</slash:comments><wfw:commentRss>http://www.cppblog.com/percyph/comments/commentRss/75742.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/percyph/services/trackbacks/75742.html</trackback:ping><description><![CDATA[分三块来讲述：<br><span style="color: #940000;">1 首先：</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;在C中定义一个结构体类型要用typedef:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;typedef struct Student<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int a;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}Stu;<br>于是在声明变量的时候就可：Stu stu1;<br>如果没有typedef就必须用struct Student stu1;来声明<br>这里的Stu实际上就是struct Student的别名。<br>另外这里也可以不写Student（于是也不能struct Student stu1;了）<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;typedef struct<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int a;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}Stu;<br>但在c++里很简单，直接<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;struct Student<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int a;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;};<br>于是就定义了结构体类型Student，声明变量时直接Student stu2；<br>===========================================<br> <span style="color: #940000;">2其次：</span><br>在c++中如果用typedef的话，又会造成区别：<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; struct&nbsp;&nbsp; Student&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;&nbsp; a;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }stu1;//stu1是一个变量&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; typedef&nbsp;&nbsp; struct&nbsp;&nbsp; Student2&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;&nbsp; a;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}stu2;//stu2是一个结构体类型&nbsp;&nbsp; <br>使用时可以直接访问stu1.a<br>但是stu2则必须先&nbsp;&nbsp; stu2 s2;<br>然后&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; s2.a=10;<br>===========================================<br><span style="color: #940000;">3 </span>掌握上面两条就可以了，不过最后我们探讨个没多大关系的问题<br>如果在c程序中我们写：<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; typedef struct&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int num;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int age;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }aaa,bbb,ccc;<br>这算什么呢？<br>我个人观察编译器（VC6）的理解，这相当于<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; typedef struct&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int num;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int age;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }aaa；<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; typedef aaa bbb;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; typedef aaa ccc;<br>也就是说aaa,bbb,ccc三者都是结构体类型。声明变量时用任何一个都可以,在c++中也是如此。但是你要注意的是这个在c++中如果写掉了typedef关键字，那么aaa，bbb，ccc将是截然不同的三个对象。<img src ="http://www.cppblog.com/percyph/aggbug/75742.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/percyph/" target="_blank">小虫虫</a> 2009-03-06 14:20 <a href="http://www.cppblog.com/percyph/archive/2009/03/06/75742.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>（转）glut函数详解(13)--视频大小调整API</title><link>http://www.cppblog.com/percyph/archive/2009/03/03/75427.html</link><dc:creator>小虫虫</dc:creator><author>小虫虫</author><pubDate>Tue, 03 Mar 2009 07:41:00 GMT</pubDate><guid>http://www.cppblog.com/percyph/archive/2009/03/03/75427.html</guid><wfw:comment>http://www.cppblog.com/percyph/comments/75427.html</wfw:comment><comments>http://www.cppblog.com/percyph/archive/2009/03/03/75427.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/percyph/comments/commentRss/75427.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/percyph/services/trackbacks/75427.html</trackback:ping><description><![CDATA[*再次声明"glut"函数详解系列转自：<a href="http://old.blog.edu.cn/user3/zjdukang/archives/2007/1765182.shtml"><span id="blogname">阿杰－－江南暖冬</span></a><br>int glutVideoResizeGet(GLenum param);<br>返回glut视频大小调整的信息.<br>参数:<br>param:<br>&nbsp; GLUT_VIDEO_RESIZE_POSSIBLE:如果底层支持视频大小调整,则返回非0值,否则返回0.如果返回0,则其他视频大小调整函数的调用将不起作用.<br>&nbsp; GLUT_VIDEO_RESIZE_IN_USE<br>&nbsp; GLUT_VIDEO_RESIZE_X_DELTA<br>&nbsp; GLUT_VIDEO_RESIZE_Y_DELTA<br>&nbsp; GLUT_VIDEO_RESIZE_WIDTH_DELTA<br>&nbsp; GLUT_VIDEO_RESIZE_HEIGHT_DELTA<br>&nbsp; GLUT_VIDEO_RESIZE_X<br>&nbsp; GLUT_VIDEO_RESIZE_Y<br>&nbsp; GLUT_VIDEO_RESIZE_WIDTH<br>&nbsp; GLUT_VIDEO_RESIZE_HEIGHT<br>&nbsp;<br>后面几个常量值在网上没有搜到解释.<br><br>//*******************************************************************************************<br>void glutSetupVideoResizing(void);<br>&nbsp;<br>void glutStopVideoResizing(void);<br>&nbsp;<br>void glutVideoResize(int x, int y, int width, int height);<br>&nbsp;<br>void glutVideoPan(int x, int y, int width, int height);<br><br>我把glut的头文件中的所有函数都整理了一遍,只可惜 video resize sub-API中的几个函数网上都没有具体的介绍,本菜鸟也无能为力,幸好这些函数都不是常用的,我想一般用不着.除了和视频有关的API,前面几个帖子的内容已经基本把glut的所有函数都过了一遍,本专题也就算是完成了,以后如果找到相关资料,会把这里的补上,也希望达人能够指点一二.  <img src ="http://www.cppblog.com/percyph/aggbug/75427.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/percyph/" target="_blank">小虫虫</a> 2009-03-03 15:41 <a href="http://www.cppblog.com/percyph/archive/2009/03/03/75427.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>（转）glut函数详解(12)--游戏模式API</title><link>http://www.cppblog.com/percyph/archive/2009/03/03/75426.html</link><dc:creator>小虫虫</dc:creator><author>小虫虫</author><pubDate>Tue, 03 Mar 2009 07:38:00 GMT</pubDate><guid>http://www.cppblog.com/percyph/archive/2009/03/03/75426.html</guid><wfw:comment>http://www.cppblog.com/percyph/comments/75426.html</wfw:comment><comments>http://www.cppblog.com/percyph/archive/2009/03/03/75426.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/percyph/comments/commentRss/75426.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/percyph/services/trackbacks/75426.html</trackback:ping><description><![CDATA[所谓游戏模式其实就是一种全屏模式,这里可以对该模式下的屏幕显示方式进行简单设置.详见下面具体解释.<br>&nbsp;<br>//*******************************************************************************************<br>void glutGameModeString(const char *string);<br>通过一个字符串对game mode(游戏模式,也即全屏模式)进行设置,即对屏幕进行设置.<br>参数:<br>string:一个指向字符串的指针,字符串的内容即是对屏幕的设置.字符串的格式如下所示:<br>&nbsp; "W*H"<br>&nbsp; "W*H:Bpp"<br>&nbsp; "W*H@Rr"<br>&nbsp; "W*H:Bpp@Rr"<br>&nbsp; "@Rr"<br>&nbsp; ":Bpp"<br>&nbsp; "Bpp:@Rr"<br>(注:W:屏幕宽度,以像素单位;H:屏幕高度,以像素为单位;Bpp:每个像素的内存大小(位数);Rr:屏幕的刷新率.)<br>例子:<br>1.如果我们只关心屏幕大小(800*600)而不关心每个像素的内存占用和刷新频率,可以写成:<br>&nbsp;&nbsp;&nbsp; glutGameModeString("800*600");<br>2.如果只想把每个像素的内存占用设置成32位,可以写成:<br>&nbsp;&nbsp;&nbsp; glutGameModeString(":32");<br>3.如果只想把刷新率设置成75赫兹,可以写成:<br>&nbsp;&nbsp;&nbsp; glutGameModeString("@75");<br>4.如果前三种情况都考虑,可以写成:<br>&nbsp;&nbsp;&nbsp; glutGameModeString("800*600:32@75");<br>其他情况按照上面给出的字符串格式写出即可.<br>注:<br>&nbsp; 1.这个函数只是对硬件的请求,如果设置不合法,则将被忽略.<br>&nbsp; 2.这个函数并不返回错误值,如果要获得错误信息,则要用glutGameModeGet()函数.<br><br>//*******************************************************************************************<br>int glutEnterGameMode(void);<br><br>进入相应的game mode,即让glutGameModeString()的设置生效.<br><br>//*******************************************************************************************<br>void glutLeaveGameMode(void);<br><br>离开glutGameModeString()设置的game mode.<br><br>//*******************************************************************************************<br><br>int glutGameModeGet(GLenum mode);<br><br>检测设置的模式是否有效<br><br>参数:<br>mode:<br>&nbsp; GLUT_GAME_MODE_ACTIVE:如果程序运行在game mode,则返回非0值,如果运行在窗口模式,则返回0.<br>&nbsp; GLUT_GAME_MODE_POSSIBLE:判断glutAameModeString()的设置是否有效,如果有效则返回非0值,否则返回0.但是glut手册中有一个警告,即使这个设置是有效的,也不能保证屏幕设置可以一定成功生效.<br>&nbsp; GLUT_GAME_MODE_WIDTH:返回屏幕的宽度.<br>&nbsp; GLUT_GAME_MODE_HEIGHT:返回屏幕的高度.<br>&nbsp; GLUT_GAME_MODE_PIXEL_DEPTH:返回当前模式下每个像素所占用的内存空间(位数).<br>&nbsp; GLUT_GAME_MODE_REFRESH_RATE:返回实际的刷新率(单位赫兹).<br>&nbsp; GLUT_GAME_MODE_DISPLAY_CHANGED:正如前面所说,不能保证屏幕显示模式一定根据设置发生改变,这个常量可以用来测试是否真的进入了game mode(先前是窗口模式下的情况下),如果先前已经是game mode,则可以用来测试设置是否发生改变.返回非0值表示进入了game mode或设置已经发生改变,否则返回0.<br> <img src ="http://www.cppblog.com/percyph/aggbug/75426.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/percyph/" target="_blank">小虫虫</a> 2009-03-03 15:38 <a href="http://www.cppblog.com/percyph/archive/2009/03/03/75426.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>