﻿<?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++博客-&lt;font size=5&gt;李锦俊(mybios)的blog&lt;/font&gt;-随笔分类-C++</title><link>http://www.cppblog.com/mybios/category/3029.html</link><description>游戏开发 C++ Cocos2d-x OpenGL DirectX 数学 计算机图形学 SQL Server
&lt;BR&gt;
&lt;BR&gt;</description><language>zh-cn</language><lastBuildDate>Sun, 17 Jul 2016 21:45:47 GMT</lastBuildDate><pubDate>Sun, 17 Jul 2016 21:45:47 GMT</pubDate><ttl>60</ttl><item><title>关于CEGUI的String的调试问题</title><link>http://www.cppblog.com/mybios/archive/2007/07/29/28914.html</link><dc:creator>李锦俊(mybios)</dc:creator><author>李锦俊(mybios)</author><pubDate>Sun, 29 Jul 2007 02:17:00 GMT</pubDate><guid>http://www.cppblog.com/mybios/archive/2007/07/29/28914.html</guid><wfw:comment>http://www.cppblog.com/mybios/comments/28914.html</wfw:comment><comments>http://www.cppblog.com/mybios/archive/2007/07/29/28914.html#Feedback</comments><slash:comments>11</slash:comments><wfw:commentRss>http://www.cppblog.com/mybios/comments/commentRss/28914.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mybios/services/trackbacks/28914.html</trackback:ping><description><![CDATA[CEGUI的String不是std::string或std::wstring，而是自己实现的一个字符串类，他的功能跟std的string很接近。<br>但是，他支持unicode，内部存储是使用utf32编码规范来存储unicode字符，也就是说&nbsp;typedef&nbsp;&nbsp;uint32&nbsp;utf32; utf32*&nbsp;&nbsp;d_buffer;用这个32位无符号整型的数组来保存unicode字符串。优点是显而易见的，就是世界上所有字符都可以包囊进去，毕竟是32位啊！但是，缺点也出来了，有两点：<br>第一、内存占用过多，一个字符就要占4个字节，也太浪费了点；<br>第二、调试不方便，由于VS2005的调试窗口只支持ansi和utf16的格式，所以，CEGUI的String在调试器中只能看到一堆数字数组，而看不到字符，这是很郁闷的，每次要查看都要翻到内存那里看，而且还一堆乱码，超级麻烦。<br><br>解决办法：修改String类，使用utf16来代替CEGUI的utf32。<br>优点：<br>解决了内存占用过多的问题，一个字符只要2个字节就可以了；<br>解决了调试问题，VS2005直接支持utf16的显示。<br>缺点：<br>可能不支持全世界的字符，因为utf16不能表示超过16位的字符，但是，对于大多数国家的字符来说，已经足够了，毕竟windows2000/xp也是基于utf16编码的。<br><br>然后，下面是修改后的字符串类：<a title=CEGUIString href="http://www.cppblog.com/Files/mybios/CEGUIString.rar">CEGUIString</a><br>
<img src ="http://www.cppblog.com/mybios/aggbug/28914.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/mybios/" target="_blank">李锦俊(mybios)</a> 2007-07-29 10:17 <a href="http://www.cppblog.com/mybios/archive/2007/07/29/28914.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>在windows下使用patch工具更新源码</title><link>http://www.cppblog.com/mybios/archive/2007/07/28/28900.html</link><dc:creator>李锦俊(mybios)</dc:creator><author>李锦俊(mybios)</author><pubDate>Sat, 28 Jul 2007 09:09:00 GMT</pubDate><guid>http://www.cppblog.com/mybios/archive/2007/07/28/28900.html</guid><wfw:comment>http://www.cppblog.com/mybios/comments/28900.html</wfw:comment><comments>http://www.cppblog.com/mybios/archive/2007/07/28/28900.html#Feedback</comments><slash:comments>4</slash:comments><wfw:commentRss>http://www.cppblog.com/mybios/comments/commentRss/28900.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mybios/services/trackbacks/28900.html</trackback:ping><description><![CDATA[经常在网上看到有人发布patch文件来更新他们的开源代码，例如cegui、ogre等都使用这种形式来修bug或者增加一些小功能。<br />但是，我们下载到的patch文件，貌似是linux/unix的diff工具生成的，要用linux/unix的patch工具才能把补丁文件更新到源码中。<br />后来，我发现了个windows下可以使用的patch工具，网址如下：<a href="http://gnuwin32.sourceforge.net/packages/patch.htm">http://gnuwin32.sourceforge.net/packages/patch.htm</a><br />使用是很简单的，用命令行方式执行：<br />patch 源文件 补丁文件<br /><br />例如我们有源文件test.cpp，下载了个补丁文件test.patch，那么执行patch test.cpp test.patch，就会自动把patch里的内容更新到test.cpp中去了。<br /><br />PS：cygwin貌似也有这个工具吧。。以前看过里面好像还有diff工具，可以生成patch文件，呵呵。<br /><div><p style="margin-top: 10px; margin-bottom: 10px; box-sizing: border-box; line-height: 24px; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px;">如果本文对你的开发有所帮助，并且你手头恰好有零钱。</p><p style="margin-top: 10px; margin-bottom: 10px; box-sizing: border-box; line-height: 24px; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px;">不如打赏我一杯咖啡，鼓励我继续分享优秀的文章。<br /><img src="http://www.cppblog.com/images/cppblog_com/mybios/222.jpg" border="0" alt="" /><br /><br /><br /><br /></p></div><img src ="http://www.cppblog.com/mybios/aggbug/28900.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/mybios/" target="_blank">李锦俊(mybios)</a> 2007-07-28 17:09 <a href="http://www.cppblog.com/mybios/archive/2007/07/28/28900.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>关于GOOF的bug问题</title><link>http://www.cppblog.com/mybios/archive/2007/07/16/28157.html</link><dc:creator>李锦俊(mybios)</dc:creator><author>李锦俊(mybios)</author><pubDate>Mon, 16 Jul 2007 14:53:00 GMT</pubDate><guid>http://www.cppblog.com/mybios/archive/2007/07/16/28157.html</guid><wfw:comment>http://www.cppblog.com/mybios/comments/28157.html</wfw:comment><comments>http://www.cppblog.com/mybios/archive/2007/07/16/28157.html#Feedback</comments><slash:comments>10</slash:comments><wfw:commentRss>http://www.cppblog.com/mybios/comments/commentRss/28157.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mybios/services/trackbacks/28157.html</trackback:ping><description><![CDATA[<p>使用了几天GOOF，发现他存在很多bug啊，什么缓存溢出，数组越界之类的。。很明显这个框架没有真正用在一个项目上的。我列举几个大问题吧。好让大家别到处碰壁。<br />bool EnvironmentGameSystem::save(DataElementPtr element)这个函数没有实现，所以无法保存环境信息。<br /><br />还有<br />&nbsp;void GridPartition::enumerateConnectedPartitions(vector&lt;CorePartition*&gt;&amp; connected)<br />&nbsp;{<br />&nbsp;&nbsp;//get surrounding grid cells within a certain radius<br />&nbsp;&nbsp;float loadRadius = mGridPartitionMgr-&gt;getGridCellLoadRadius();</p>
<p>&nbsp;&nbsp;//enumerate partitions<br />&nbsp;&nbsp;vector&lt;CorePartition*&gt; partitions;<br />&nbsp;&nbsp;mGridPartitionMgr-&gt;enumeratePartitions(partitions);</p>
<p>&nbsp;&nbsp;//iterate through and check distance<br />&nbsp;&nbsp;for(vector&lt;CorePartition*&gt;::iterator itr = partitions.begin(); itr != partitions.end(); ++itr)<br />&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;float distance = Vector3(getWorldPosition() - (*itr)-&gt;getWorldPosition()).length();<br />&nbsp;&nbsp;&nbsp;// add by 李锦俊 2007-7-16<br />&nbsp;&nbsp;&nbsp;// 不要返回自己作为邻居，会产生bug<br />&nbsp;&nbsp;&nbsp;if(distance &lt; loadRadius &amp;&amp; *itr != this)<br />&nbsp;&nbsp;&nbsp;&nbsp;connected.push_back(*itr);<br />&nbsp;&nbsp;}<br />&nbsp;}<br /><br />再给出一个比较严重的bug<br />GOOFTranslationManipulator.h中的<br />&nbsp;&nbsp;// add by 李锦俊 2007-7-12<br />&nbsp;&nbsp;// 不要用魔术数，搞到缓存溢出<br />&nbsp;&nbsp;SceneNode* mNode[AT_LAST];<br />&nbsp;&nbsp;Entity* mEnt[AT_LAST];<br />&nbsp;&nbsp;Entity* mConeEnt[AT_LAST];<br />&nbsp;&nbsp;CollisionShapePtr mCol[AT_LAST];<br />&nbsp;&nbsp;AxisManipulatorHandle* mHandle[AT_LAST];<br /><br />另外，CorePartition中的setSkyboxMaterial、setGlobalAmbient之类的代码貌似没用。准备弃之。<br /></p>
<br />&nbsp;&nbsp;&nbsp;&nbsp;// add by 李锦俊 2007-7-16<br />&nbsp;&nbsp;&nbsp;&nbsp;// 这个算法暂时有问题，先屏蔽，以后再慢慢解决<br />&nbsp;&nbsp;&nbsp;&nbsp;//disable static geometry until it is fixed<br />&nbsp;&nbsp;&nbsp;&nbsp;if(false)// getStaticGeometryRule() == SGR_ALWAYS || (getStaticGeometryRule() == SGR_WHEN_NOT_PROX_IMMEDIATE &amp;&amp; getPartition()-&gt;getProximity() != CorePartition::PROX_IMMEDIATE)) <br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;willConvertToStaticGeometry = true;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;getPartition()-&gt;addObjectToConvertToStaticGeometry(this);<br />&nbsp;&nbsp;&nbsp;&nbsp;}<img src ="http://www.cppblog.com/mybios/aggbug/28157.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/mybios/" target="_blank">李锦俊(mybios)</a> 2007-07-16 22:53 <a href="http://www.cppblog.com/mybios/archive/2007/07/16/28157.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>VS2003下编译Windows计算器</title><link>http://www.cppblog.com/mybios/archive/2006/12/02/15889.html</link><dc:creator>李锦俊(mybios)</dc:creator><author>李锦俊(mybios)</author><pubDate>Sat, 02 Dec 2006 08:10:00 GMT</pubDate><guid>http://www.cppblog.com/mybios/archive/2006/12/02/15889.html</guid><wfw:comment>http://www.cppblog.com/mybios/comments/15889.html</wfw:comment><comments>http://www.cppblog.com/mybios/archive/2006/12/02/15889.html#Feedback</comments><slash:comments>4</slash:comments><wfw:commentRss>http://www.cppblog.com/mybios/comments/commentRss/15889.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mybios/services/trackbacks/15889.html</trackback:ping><description><![CDATA[工程已经放上，<a href="http://www.cppblog.com/Files/mybios/calc.rar">下载回去编译就行</a>，放个贴图：<br /><br /><img height="309" alt="Calc.JPG" src="http://www.cppblog.com/images/cppblog_com/mybios/ArticlePics/Calc.JPG" width="480" border="0" /><img src ="http://www.cppblog.com/mybios/aggbug/15889.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/mybios/" target="_blank">李锦俊(mybios)</a> 2006-12-02 16:10 <a href="http://www.cppblog.com/mybios/archive/2006/12/02/15889.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>今天遇到了郁闷的C函数，幸好遇到高手帮忙解决了</title><link>http://www.cppblog.com/mybios/archive/2006/11/30/15817.html</link><dc:creator>李锦俊(mybios)</dc:creator><author>李锦俊(mybios)</author><pubDate>Thu, 30 Nov 2006 08:30:00 GMT</pubDate><guid>http://www.cppblog.com/mybios/archive/2006/11/30/15817.html</guid><wfw:comment>http://www.cppblog.com/mybios/comments/15817.html</wfw:comment><comments>http://www.cppblog.com/mybios/archive/2006/11/30/15817.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/mybios/comments/commentRss/15817.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mybios/services/trackbacks/15817.html</trackback:ping><description><![CDATA[用C函数来转换Unicode和ANSI文字<br /><br />char sChar[MAX_PATH];<br />const WCHAR wChar[] = L"我的朋友";<br />// 把wChar这个Unicode字符串转换成ANSI字符串，保存到sChar，并且返回ANSI的字符串大小，如果失败，则返回-1<br />  wcstombs(sChar, wChar, MAX_PATH);<br /><br />这样是运行不过不去的，总是返回-1。<br /><br />后来经人提醒，需要在调用wcstombs之前要先设置代码页：<br /><br />char sChar[MAX_PATH];<br />const WCHAR wChar[] = L"我的朋友";<br /><br />// 设置代码页为默认代码页<br />  _tsetlocale(LC_ALL,_T(""));<br />// 把wChar这个Unicode字符串转换成ANSI字符串，保存到sChar，并且返回ANSI的字符串大小，如果失败，则返回-1<br />  wcstombs(sChar, wChar, MAX_PATH);<br /><br /><br />这样就可以了！不用调用烦人的WideCharToMultiByte！多好啊！<br />相反的函数：<strong>mbstowcs，可以从ANSI转换到Unicode</strong><img src ="http://www.cppblog.com/mybios/aggbug/15817.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/mybios/" target="_blank">李锦俊(mybios)</a> 2006-11-30 16:30 <a href="http://www.cppblog.com/mybios/archive/2006/11/30/15817.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>【转贴】C语言高效编程的几招</title><link>http://www.cppblog.com/mybios/archive/2006/11/21/15514.html</link><dc:creator>李锦俊(mybios)</dc:creator><author>李锦俊(mybios)</author><pubDate>Tue, 21 Nov 2006 09:26:00 GMT</pubDate><guid>http://www.cppblog.com/mybios/archive/2006/11/21/15514.html</guid><wfw:comment>http://www.cppblog.com/mybios/comments/15514.html</wfw:comment><comments>http://www.cppblog.com/mybios/archive/2006/11/21/15514.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://www.cppblog.com/mybios/comments/commentRss/15514.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mybios/services/trackbacks/15514.html</trackback:ping><description><![CDATA[引言：<br />　　编写高效简洁的C语言代码，是许多软件工程师追求的目标。本文就工作中的一些体会和经验做相关的阐述，不对的地方请各位指教。<br /><br />第1招：以空间换时间<br /><br />　　计算机程序中最大的矛盾是空间和时间的矛盾，那么，从这个角度出发逆向思维来考虑程序的效率问题，我们就有了解决问题的第1招——以空间换时间。<br />例如：字符串的赋值。<br />方法A，通常的办法：<br />#define LEN 32<br />char string1 [LEN];<br />memset (string1,0,LEN);<br />strcpy (string1,“This is a example!!”）;<br />方法B：<br />const char string2[LEN] =“This is a example!”;<br />char * cp;<br />cp = string2 ;<br />(使用的时候可以直接用指针来操作。)<br /><br />　　从上面的例子可以看出，A和B的效率是不能比的。在同样的存储空间下，B直接使用指针就可以操作了，而A需要调用两个字符函数才能完成。B的缺点在于灵活性没有A好。在需要频繁更改一个字符串内容的时候，A具有更好的灵活性；如果采用方法B，则需要预存许多字符串，虽然占用了大量的内存，但是获得了程序执行的高效率。<br /><br />　　如果系统的实时性要求很高，内存还有一些，那我推荐你使用该招数。<br /><br />　　该招数的变招——使用宏函数而不是函数。举例如下：<br />方法C：<br />#define bwMCDR2_ADDRESS 4<br />#define bsMCDR2_ADDRESS 17<br />int BIT_MASK(int __bf)<br />{<br />return ((1U &lt;&lt; (bw ## __bf)) - 1) &lt;&lt; (bs ## __bf);<br />}<br />void SET_BITS(int __dst, int __bf, int __val)<br />{<br />__dst = ((__dst) &amp; ~(BIT_MASK(__bf))) | \<br />(((__val) &lt;&lt; (bs ## __bf)) &amp; (BIT_MASK(__bf))))<br />}<br /><br />SET_BITS(MCDR2, MCDR2_ADDRESS, RegisterNumber);<br />方法D：<br />#define bwMCDR2_ADDRESS 4<br />#define bsMCDR2_ADDRESS 17<br />#define bmMCDR2_ADDRESS BIT_MASK(MCDR2_ADDRESS)<br />#define BIT_MASK(__bf) (((1U &lt;&lt; (bw ## __bf)) - 1) &lt;&lt; (bs ## __bf))<br />#define SET_BITS(__dst, __bf, __val) \<br />((__dst) = ((__dst) &amp; ~(BIT_MASK(__bf))) | \<br />(((__val) &lt;&lt; (bs ## __bf)) &amp; (BIT_MASK(__bf))))<br /><br />SET_BITS(MCDR2, MCDR2_ADDRESS, RegisterNumber);<br /><br />　　函数和宏函数的区别就在于，宏函数占用了大量的空间，而函数占用了时间。大家要知道的是，函数调用是要使用系统的栈来保存数据的，如果编译器里有栈检查选项，一般在函数的头会嵌入一些汇编语句对当前栈进行检查；同时，CPU也要在函数调用时保存和恢复当前的现场，进行压栈和弹栈操作，所以，函数调用需要一些CPU时间。而宏函数不存在这个问题。宏函数仅仅作为预先写好的代码嵌入到当前程序，不会产生函数调用，所以仅仅是占用了空间，在频繁调用同一个宏函数的时候，该现象尤其突出。<br /><br />　　D方法是我看到的最好的置位操作函数，是ARM公司源码的一部分，在短短的三行内实现了很多功能，几乎涵盖了所有的位操作功能。C方法是其变体，其中滋味还需大家仔细体会。<br /><br />第2招：数学方法解决问题<br /><br />　　现在我们演绎高效C语言编写的第二招——采用数学方法来解决问题。<br /><br />　　数学是计算机之母，没有数学的依据和基础，就没有计算机的发展，所以在编写程序的时候，采用一些数学方法会对程序的执行效率有数量级的提高。<br />举例如下，求 1~100的和。<br />方法E<br />int I , j;<br />for (I = 1 ;I&lt;=100; I ++）{<br />j += I;<br />}<br />方法F<br />int I;<br />I = (100 * (1+100)) / 2<br /><br />　　这个例子是我印象最深的一个数学用例，是我的计算机启蒙老师考我的。当时我只有小学三年级，可惜我当时不知道用公式 N×（N+1）/ 2 来解决这个问题。方法E循环了100次才解决问题，也就是说最少用了100个赋值，100个判断，200个加法（I和j）；而方法F仅仅用了1个加法，1 次乘法，1次除法。效果自然不言而喻。所以，现在我在编程序的时候，更多的是动脑筋找规律，最大限度地发挥数学的威力来提高程序运行的效率。<br /><br />第3招：使用位操作<br /><br />　　实现高效的C语言编写的第三招——使用位操作，减少除法和取模的运算。<br /><br />　　在计算机程序中，数据的位是可以操作的最小数据单位，理论上可以用“位运算”来完成所有的运算和操作。一般的位操作是用来控制硬件的，或者做数据变换使用，但是，灵活的位操作可以有效地提高程序运行的效率。举例如下：<br />方法G<br />int I,J;<br />I = 257 /8;<br />J = 456 % 32;<br />方法H<br />int I,J;<br />I = 257 &gt;&gt;3;<br />J = 456 - (456 &gt;&gt; 4 &lt;&lt; 4);<br /><br />　　在字面上好像H比G麻烦了好多，但是，仔细查看产生的汇编代码就会明白，方法G调用了基本的取模函数和除法函数，既有函数调用，还有很多汇编代码和寄存器参与运算；而方法H则仅仅是几句相关的汇编，代码更简洁，效率更高。当然，由于编译器的不同，可能效率的差距不大，但是，以我目前遇到的MS C ,ARM C 来看，效率的差距还是不小。相关汇编代码就不在这里列举了。<br />运用这招需要注意的是，因为CPU的不同而产生的问题。比如说，在PC上用这招编写的程序，并在PC上调试通过，在移植到一个16位机平台上的时候，可能会产生代码隐患。所以只有在一定技术进阶的基础下才可以使用这招。<br /><br />第4招：汇编嵌入<br /><br />　　高效C语言编程的必杀技，第四招——嵌入汇编。<br /><br />　　“在熟悉汇编语言的人眼里，C语言编写的程序都是垃圾”。这种说法虽然偏激了一些，但是却有它的道理。汇编语言是效率最高的计算机语言，但是，不可能靠着它来写一个操作系统吧?所以，为了获得程序的高效率，我们只好采用变通的方法 ——嵌入汇编，混合编程。<br /><br />　　举例如下，将数组一赋值给数组二,要求每一字节都相符。<br />char string1[1024],string2[1024];<br />方法I<br />int I;<br />for (I =0 ;I&lt;1024;I++)<br />*(string2 + I) = *(string1 + I)<br />方法J<br />#ifdef _PC_<br />int I;<br />for (I =0 ;I&lt;1024;I++)<br />*(string2 + I) = *(string1 + I);<br />#else<br />#ifdef _ARM_<br />__asm<br />{<br />MOV R0,string1<br />MOV R1,string2<br />MOV R2,#0<br />loop:<br />LDMIA R0!, [R3-R11]<br />STMIA R1!, [R3-R11]<br />ADD R2,R2,#8<br />CMP R2, #400<br />BNE loop<br />}<br />#endif<br /><br />　　方法I是最常见的方法，使用了1024次循环；方法J则根据平台不同做了区分，在ARM平台下，用嵌入汇编仅用128次循环就完成了同样的操作。这里有朋友会说，为什么不用标准的内存拷贝函数呢?这是因为在源数据里可能含有数据为0的字节，这样的话，标准库函数会提前结束而不会完成我们要求的操作。这个例程典型应用于LCD数据的拷贝过程。根据不同的CPU，熟练使用相应的嵌入汇编，可以大大提高程序执行的效率。<br /><br />　　虽然是必杀技，但是如果轻易使用会付出惨重的代价。这是因为，使用了嵌入汇编，便限制了程序的可移植性，使程序在不同平台移植的过程中，卧虎藏龙，险象环生！同时该招数也与现代软件工程的思想相违背，只有在迫不得已的情况下才可以采用。切记，切记。 <br /><br /><img src ="http://www.cppblog.com/mybios/aggbug/15514.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/mybios/" target="_blank">李锦俊(mybios)</a> 2006-11-21 17:26 <a href="http://www.cppblog.com/mybios/archive/2006/11/21/15514.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>【转贴】直接载入内存中的DLL</title><link>http://www.cppblog.com/mybios/archive/2006/11/21/15483.html</link><dc:creator>李锦俊(mybios)</dc:creator><author>李锦俊(mybios)</author><pubDate>Mon, 20 Nov 2006 16:45:00 GMT</pubDate><guid>http://www.cppblog.com/mybios/archive/2006/11/21/15483.html</guid><wfw:comment>http://www.cppblog.com/mybios/comments/15483.html</wfw:comment><comments>http://www.cppblog.com/mybios/archive/2006/11/21/15483.html#Feedback</comments><slash:comments>6</slash:comments><wfw:commentRss>http://www.cppblog.com/mybios/comments/commentRss/15483.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mybios/services/trackbacks/15483.html</trackback:ping><description><![CDATA[作者：<a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#110;&#106;&#106;&#97;&#110;&#101;&#64;&#50;&#49;&#99;&#110;&#46;&#99;&#111;&#109;">任明汉</a><p><a href="http://www.vckbase.com/code/downcode.asp?id=2358">下载源代码</a><br /><br /><img src="http://www.vckbase.com/document/image/paragraph.gif"  alt="" /><strong>前言</strong></p><p>　　你可能不希望在发布程序时附带上一个外部的 DLL，因为可能会有些用户在无意中把 DLL 删除了而造成 EXE 不能正确运行，也有可能该 DLL 会被别人拿去使用，也有可能，此 DLL 会成为破解者破解你的程序的突破口。无论出于何种原因，如果你想把一个 DLL 合并到一个 EXE 中的话，本文向你介绍这种方法。 <br /></p><hr /><img src="http://www.vckbase.com/document/image/paragraph.gif"  alt="" /><strong>Win32 程序调用 DLL 的机制</strong><br /><br />　　 Win32 EXE 在调用一个外部 DLL 中的函数时，首先要调用 LoadLibary 函数来载入此 DLL 到程序的进程地址空间。 如果 LoadLibary 载入此 DLL 成功，将返回一个该 DLL 的句柄。 这个句柄实际上就是该 DLL 在内存中的起始地址。 在载入 DLL 成功后，还必须调用 GetProcAddress 函数来获取要调用的函数的地址。然后再根据该地址来调用这个函数。<br />根据上述原理，我们可以把一个 DLL 作为资源文件放到 EXE 文件中，在程序运行时，分配一块内存，然后将此资源复制到该分配的内存中，并根据该内存地址计算得到相关的导出函数地址，然后，当我们需要调用某一函数时，可以用该函数在内存中的地址来调用它。 <br />程序实现。<br />　　首先，把要合并的 DLL 作为资源加入到项目的资源文件中，然后在程序运行时，从资源中载入该资源，以得到该 DLL 在内存中的位置： <br /><pre>LPVOID sRawDll; // 资源文件在内存中的地址 
HRSRC hRes; 
HMODULE hLibrary; 
HGLOBAL hResourceLoaded; 
char lib_name[MAX_PATH]; 
GetModuleFileName(hInstance, lib_name, MAX_PATH ); // 得到运行程序的名字 
hLibrary = LoadLibrary(lib_name);                  // 就象载入一个 DLL 一样载入运行程序到内存中 

if (NULL != hLibrary) 
{
	// 得到指定的资源文件在内存中的位置 
	hRes = FindResource(hLibrary, MAKEINTRESOURCE(IDR_DATA1), RT_RCDATA); 
	if (NULL != hRes) 
	{
		// 将资源文件载入内存 
		hResourceLoaded = LoadResource(hLibrary, hRes); 
		if (NULL != hResourceLoaded)&nbsp;
		{
			// 得到资源文件大小 
			SizeofResource(hLibrary, hRes); 

			// 锁定资源以得到它在内存中的地址 
			sRawDll = (LPVOID)LockResource(hResourceLoaded); 
		}
	}
	else return 1; 
	FreeLibrary(hLibrary);
}
else return 1; 
</pre>然后，从资源中载入 DLL 到内存函数 LoadPbDllFromMemory 将载入 DLL 到内存中， 该函数有两个参数，第一个参数是指向 DLL 资源在内存中的地址的指针，也就是前面代码中的 LockResource 函数的返回值。第二个参数是一个空的指针，如果函数 LoadPbDllFromMemory 运行成功，该指针将指向重新组合后的内存中的 DLL 的起始地址。该函数还有一个功能就是如果运行成功，它将手动地用 DLL_PROCESS_ATTACH 参数调用 DLL 的入口函数 DllMain 来初始化该 DLL。除此之外，它还会手动地载入合并的 DLL 的入口表中导入的 DLL 并调整它们在内存中的相对地址。以下是该函数代码:<pre>DWORD LoadPbDllFromMemory(LPVOID lpRawDll, LPVOID lpImageDll) 
{
	SYSTEM_INFO sSysInfo; 
	PIMAGE_DOS_HEADER dosHeader; 
	PIMAGE_NT_HEADERS pNTHeader; 
	PIMAGE_SECTION_HEADER section; 
	PIMAGE_IMPORT_DESCRIPTOR pImportDesc; 
	PIMAGE_IMPORT_BY_NAME pOrdinalName; 
	PIMAGE_BASE_RELOCATION baseReloc; 
	PDWORD lpLink; 
	unsigned char Protection[4096]; 
	HINSTANCE hDll; 
	WORD i; 
	DWORD ImagePages,fOldProtect,j,MaxLen,HdrLen,Addr1,Addr2,Pg,Pg1,Pg2; 
	char * sDllName; 

	if(NULL == lpRawDll) return 1 ; 

	dosHeader = (PIMAGE_DOS_HEADER)lpRawDll; 

	// Is this the MZ header? 
	if ((TRUE == IsBadReadPtr(dosHeader,sizeof (IMAGE_DOS_HEADER))) ||
				 (IMAGE_DOS_SIGNATURE != dosHeader-&gt;e_magic))&nbsp;
		return 2; 

	// Get the PE header. 
	pNTHeader = MakePtr(PIMAGE_NT_HEADERS,dosHeader,dosHeader-&gt;e_lfanew); 

	// Is this a real PE image? 
	if((TRUE == IsBadReadPtr(pNTHeader,sizeof ( IMAGE_NT_HEADERS))) || 
				( IMAGE_NT_SIGNATURE != pNTHeader-&gt;Signature)) 
		return 3 ; 

	if(( pNTHeader-&gt;FileHeader.SizeOfOptionalHeader != 
			sizeof(pNTHeader-&gt;OptionalHeader)) || 
		(pNTHeader-&gt;OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR32_MAGIC)) 
		return 4; 

	if (pNTHeader-&gt;FileHeader.NumberOfSections &lt; 1) return 5; 

	section = IMAGE_FIRST_SECTION( pNTHeader ); 
	int HeaderSize = sizeof(IMAGE_SECTION_HEADER); 

	// 节头长度 
	HdrLen = (DWORD)section - (DWORD)dosHeader + 
			HeaderSize * pNTHeader-&gt;FileHeader.NumberOfSections; 

	// 找出最大的节的长度,此节一般是代码所在的节(.text 节) 
	MaxLen = HdrLen; 
	int ii=0; 

	for (i = 0;i&lt;(DWORD)pNTHeader-&gt;FileHeader.NumberOfSections;i++)// find MaxLen 
	{
		if(MaxLen &lt; section[i].VirtualAddress + section[i].SizeOfRawData) 
		{
			MaxLen = section[i].VirtualAddress + section[i].SizeOfRawData; 
		}
		if(strcmp((const char *)section[i].Name,".rsrc") == 0) ii=i; 
	}

	GetSystemInfo(&amp;sSysInfo);
	ImagePages = MaxLen / sSysInfo.dwPageSize; 
	if (MaxLen % sSysInfo.dwPageSize) ImagePages++; 

	// 分配所需的内存 
	DWORD NeededMemory = ImagePages * sSysInfo.dwPageSize; 
	lpImageDll = VirtualAlloc(NULL, NeededMemory, MEM_COMMIT, PAGE_EXECUTE_READWRITE); 

	if (lpImageDll == NULL) return 6; // 分配内存失败 

	MoveMemory( lpImageDll, lpRawDll, HdrLen ); // 复制节头 

	DWORD OrgAddr = 0; 
	DWORD NewAddr = 0; 
	DWORD Size = 0; 

	// 复制 .text 节数据 
	for (i = 0;i&lt;pNTHeader-&gt;FileHeader.NumberOfSections;i++) 
	{
		OrgAddr = (DWORD)lpImageDll + (DWORD)section[i].VirtualAddress; 
		NewAddr = (DWORD)lpRawDll + (DWORD)section[i].PointerToRawData; 
		Size = (DWORD)section[i].SizeOfRawData; 
		MoveMemory((void *)OrgAddr, (void *)NewAddr, Size ); 
	}

	// 把指针指向新的 DLL 映像 
	dosHeader = (PIMAGE_DOS_HEADER) lpImageDll; // Switch to new image 
	pNTHeader = (PIMAGE_NT_HEADERS) ((DWORD)dosHeader + dosHeader-&gt;e_lfanew); 
	section = (PIMAGE_SECTION_HEADER) ((DWORD)pNTHeader + sizeof(IMAGE_NT_HEADERS)); 
	pImageBase = (PBYTE)dosHeader; 

	if((ii!=0) &amp;&amp; (IsNT()==TRUE)) 
	{
		section[ii].VirtualAddress = section[ii].VirtualAddress + (DWORD)lpRawDll; 
		section[ii].PointerToRawData = section[ii].PointerToRawData + (DWORD)lpRawDll; 
	}

	DWORD importsStartRVA; 

	// Look up where the imports section is (normally in the .idata section) 
	// but not necessarily so. Therefore, grab the RVA from the data dir. 
	importsStartRVA = GetImgDirEntryRVA(pNTHeader,IMAGE_DIRECTORY_ENTRY_IMPORT); 
	if ( !importsStartRVA )&nbsp;
	{
		VirtualFree(dosHeader,0, MEM_RELEASE); 
		return 7; 
	}

	pImportDesc = (PIMAGE_IMPORT_DESCRIPTOR) pNTHeader-&gt;
		OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress; 

	if(pImportDesc!= 0) 
		pImportDesc = (PIMAGE_IMPORT_DESCRIPTOR) ((DWORD)pImportDesc + (DWORD)dosHeader); 
	else&nbsp;
	{
		VirtualFree(dosHeader,0, MEM_RELEASE); 
		return 8; 
	}

	while (1) // 处理各入口表中的 DLL 
	{
		// 检查是否遇到了空的 IMAGE_IMPORT_DESCRIPTOR 
		if ((pImportDesc-&gt;TimeDateStamp==0 ) &amp;&amp; (pImportDesc-&gt;Name==0)) break; 

		// 从磁盘载入必须的 Dll, 
		// 注意,载入的 DLL 是合并的 DLL 的入口表中的 DLL, 
		// 不是合并到 EXE 中的 DLL 
		sDllName = (char *) (pImportDesc-&gt;Name + (DWORD)pImageBase); 
		hDll = GetModuleHandle(sDllName); 

		if (hDll == 0 ) hDll = LoadLibrary(sDllName); 

		if (hDll == 0 ) 
		{
			MessageBox(NULL, "Can''t find required Dll",
					"Error in LoadPbDllFromMemory()",0); 
			VirtualFree(dosHeader,0, MEM_RELEASE); 
			return 9; 
		}

		DWORD *lpFuncNameRef = (DWORD *) (pImportDesc-&gt;OriginalFirstThunk +
								 (DWORD)dosHeader); 
		DWORD *lpFuncAddr = (DWORD *) (pImportDesc-&gt;FirstThunk +
								 (DWORD)dosHeader); 

		while( *lpFuncNameRef != 0) 
		{
			pOrdinalName = (PIMAGE_IMPORT_BY_NAME) (*lpFuncNameRef +
						 (DWORD)dosHeader); 
			DWORD pIMAGE_ORDINAL_FLAG = 0x80000000; 

			if (*lpFuncNameRef &amp; pIMAGE_ORDINAL_FLAG) 
				*lpFuncAddr = (DWORD) GetProcAddress(hDll,
					 (const char *)(*lpFuncNameRef &amp; 0xFFFF)); 
			else
				*lpFuncAddr = (DWORD) GetProcAddress(hDll,
						 (const char *)pOrdinalName-&gt;Name); 

			if (lpFuncAddr == 0)&nbsp;
			{
				VirtualFree(dosHeader,0, MEM_RELEASE); 
				return 10;// Can''t GetProcAddress 
			}

			lpFuncAddr++;
			lpFuncNameRef++;
		}
		pImportDesc++;
	}

	DWORD TpOffset; 
	baseReloc = (PIMAGE_BASE_RELOCATION)((DWORD)pNTHeader-&gt;
　　　　 OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress); 

	if (baseReloc !=0) 
	{
		baseReloc = (PIMAGE_BASE_RELOCATION) ((DWORD)baseReloc + (DWORD)dosHeader); 
		while(baseReloc-&gt;VirtualAddress != 0) 
		{
			PWORD lpTypeOffset = (PWORD) ((DWORD)baseReloc +
					 sizeof(IMAGE_BASE_RELOCATION)); 
			while (lpTypeOffset &lt; (PWORD)((DWORD)baseReloc +
						 (DWORD)baseReloc-&gt;SizeOfBlock)) 
			{
				TpOffset = *lpTypeOffset &amp; 0xF000; 
				if(TpOffset == 0x3000) 
				{
					lpLink = (PDWORD) ((DWORD)dosHeader +
　　　　　　　　　　　　　　　　　　　　　　             baseReloc-&gt;VirtualAddress +
                                                      (*lpTypeOffset &amp; 0xFFF)); 
					*lpLink = (DWORD)dosHeader + 
                                            (*lpLink) - pNTHeader-&gt;OptionalHeader.ImageBase; 
				}
				else
				{
					if (TpOffset != 0)&nbsp;
					{
						VirtualFree(dosHeader,0, MEM_RELEASE); 
						return 10; 
					}
				}
				lpTypeOffset++;
			}
			baseReloc = (PIMAGE_BASE_RELOCATION)((DWORD)baseReloc + 
				(DWORD)baseReloc-&gt;SizeOfBlock); 
		}
	}

	// 取得原始的内存状态 
	memset(Protection,0,4096);
	for (i = 0;i&lt;=pNTHeader-&gt;FileHeader.NumberOfSections;i++) 
	{
		if (i == pNTHeader-&gt;FileHeader.NumberOfSections) 
		{
			Addr1 = 0; 
			Addr2 = HdrLen; 
			j = 0x60000000; 
		}
		else
		{
			Addr1 = section[i].VirtualAddress; 
			Addr2 = section[i].SizeOfRawData; 
			j = section[i].Characteristics; 
		}
		Addr2 += Addr1 - 1; 

		Pg1 = Addr1 / sSysInfo.dwPageSize; 
		Pg2 = Addr2 / sSysInfo.dwPageSize; 
		for(Pg = Pg1 ;Pg&lt;=Pg2;Pg++) 
		{
			if (j &amp; 0x20000000) Protection[Pg] |= 1; // Execute 
			if (j &amp; 0x40000000) Protection[Pg] |= 2; // Read 
			if (j &amp; 0x80000000) Protection[Pg] |= 4; // Write 
		}
	}

	// 恢复原始的内存状态 
	Addr1 = (DWORD)dosHeader; 
	for (Pg = 0 ;Pg&lt;= ImagePages;Pg++) 
	{
		switch(Protection[Pg])
		{
		case 2:&nbsp;
			fOldProtect = PAGE_READONLY; 
			break;
		case 3:&nbsp;
			fOldProtect = PAGE_EXECUTE_READ; 
			break;
		case 6:&nbsp;
			fOldProtect = PAGE_READWRITE; 
			break;
		default:&nbsp;
			// Ignore strange combinations
			fOldProtect = PAGE_EXECUTE_READWRITE;  
			break;
		}

		if (fOldProtect !=PAGE_EXECUTE_READWRITE) 
		{
			if (VirtualProtect((void *)Addr1, 
				sSysInfo.dwPageSize, 
				fOldProtect,
				&amp;fOldProtect) == 0) 
			{
				VirtualFree(dosHeader,0, MEM_RELEASE); 
				return 11; 
			}
		}
		Addr1 += sSysInfo.dwPageSize; 
	}

	EntryPoint = (LPENTRYPOINT) ((DWORD)pNTHeader-&gt;OptionalHeader.AddressOfEntryPoint +
				 (DWORD)dosHeader); 
	LPVOID lpReserved = 0; 
	EntryPoint((HINSTANCE)dosHeader, DLL_PROCESS_ATTACH, lpReserved); 
	lpImageDll2=lpImageDll;
	return 0; 
}
</pre>　　一但 DLL 被正确地载入到内存中，我们就可以通过自定义函数 GetProcAddressDirectly 来获取某函数在内存中的地址，并根据该地址来调用该函数，该函数也有两个参数，第一个参数是指向载入到内存中的 DLL 的起始地址的指针，第二个是要调用的函数的函数名。以下是 GetProcAddressDirectly 函数代码: <pre>DWORD GetProcAddressDirectly(PIMAGE_DOS_HEADER dosHeader, char * FuncName)  
{ 
	PIMAGE_NT_HEADERS pNTHeader;  
	PIMAGE_EXPORT_DIRECTORY pExportDir;  
	PWORD lpNameOrdinals;  
	LPDWORD lpFunctions;  
	DWORD * lpName;  
	char * lpExpFuncName;  
	DWORD i;  
	DWORD j;  
	char * lpFuncName;  

	if(dosHeader-&gt;e_magic != IMAGE_DOS_SIGNATURE) return 0;  

	pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)dosHeader + dosHeader-&gt;e_lfanew);  

	if (pNTHeader-&gt;Signature != IMAGE_NT_SIGNATURE) return 0;  

	if ((pNTHeader-&gt;FileHeader.SizeOfOptionalHeader != sizeof(pNTHeader-&gt;OptionalHeader)) ||  
		(pNTHeader-&gt;OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR32_MAGIC))  
		return 0;  

	DWORD exportsStartRVA, exportsEndRVA;  
	pImageBase = (PBYTE)dosHeader;  

	// Make pointers to 32 and 64 bit versions of the header.  
	pNTHeader = MakePtr( PIMAGE_NT_HEADERS, dosHeader,dosHeader-&gt;e_lfanew );  

	exportsStartRVA = GetImgDirEntryRVA(pNTHeader,IMAGE_DIRECTORY_ENTRY_EXPORT);  
	exportsEndRVA = exportsStartRVA +  
		GetImgDirEntrySize(pNTHeader, IMAGE_DIRECTORY_ENTRY_EXPORT);  

	// Get the IMAGE_SECTION_HEADER that contains the exports. This is  
	// usually the .edata section, but doesn''t have to be.  
	PIMAGE_SECTION_HEADER header;  
	header = GetEnclosingSectionHeader( exportsStartRVA, pNTHeader );  
	if ( !header ) return 0;  

	INT delta;  
	delta = (INT)(header-&gt;VirtualAddress - header-&gt;PointerToRawData);  
	pExportDir = (PIMAGE_EXPORT_DIRECTORY)GetPtrFromRVA(exportsStartRVA, 
				pNTHeader, pImageBase);  


	pExportDir =(PIMAGE_EXPORT_DIRECTORY) (pNTHeader-&gt;
	OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);  

	if (pExportDir == 0)  
	{ 
		MessageBox(NULL,"Error in GetProcAddressDirectly()",0,0);  
		return 0;  
	} 

	pExportDir =(PIMAGE_EXPORT_DIRECTORY) ((DWORD)pExportDir + (DWORD)dosHeader);  
	lpNameOrdinals =(PWORD)((DWORD)pExportDir-&gt;AddressOfNameOrdinals + (DWORD)dosHeader);  
	lpName =(LPDWORD) (pExportDir-&gt;AddressOfNames + (DWORD)dosHeader);  
	lpFunctions =(LPDWORD) (pExportDir-&gt;AddressOfFunctions + (DWORD)dosHeader);  
	lpFuncName = FuncName;  

	if(HIWORD(lpFuncName)!=0 )  
	{ 
		for( i = 0;i&lt;=pExportDir-&gt;NumberOfFunctions - 1;i++)  
		{ 
			DWORD entryPointRVA = *lpFunctions;  

			// Skip over gaps in exported function  
			if ( entryPointRVA == 0 ) continue; 
			for( j = 0;j&lt;=pExportDir-&gt;NumberOfNames-1;j++)  
			{ 
				if( lpNameOrdinals[j] == i)  
				{ 
					lpExpFuncName = (char *) (lpName[j] + 
							(DWORD)dosHeader);  
					if(strcmp((char *)lpExpFuncName,(char *)FuncName)==0)  
						return (DWORD) (lpFunctions[i] + 
								(DWORD)dosHeader);  
				} 
			} 
		} 
	} 
	else 
	{ 
		for (i = 0 ;i&lt;=pExportDir-&gt;NumberOfFunctions - 1;i++)  
		{ 
			if (lpFuncName == (char *)(pExportDir-&gt;Base + i))  
			{ 
				if (lpFunctions[i]) return (unsigned long) (lpFunctions[i] + 
							dosHeader);  
			} 
		} 
	} 
	return 0;  
}


</pre>在调用完函数后，不要忘记用 UnloadPbDllFromMemory 来从内存中移去 DLL 以释放分配的内存，该函数还会用 DLL_PROCESS_DETACH 参数调用 DLL 的入口函数 DllMain 来从调用进程的地址空间卸载该 DLL。 以下是 UnloadPbDllFromMemory 函数代码:<pre>DWORD UnloadPbDllFromMemory(PIMAGE_DOS_HEADER dosHeader) 
{
	PIMAGE_NT_HEADERS pNTHeader; 
	pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)dosHeader + (DWORD)dosHeader-&gt;e_lfanew); 
	EntryPoint = (LPENTRYPOINT)(pNTHeader-&gt;OptionalHeader.AddressOfEntryPoint +
					 (DWORD)dosHeader); 
	EntryPoint((HINSTANCE)dosHeader, DLL_PROCESS_DETACH, 0); 
	return VirtualFree(dosHeader, 0, MEM_RELEASE); 
}
</pre><hr /><strong><br /></strong><img src="http://www.vckbase.com/document/image/paragraph.gif"  alt="" /><strong>关于示例代码的说明</strong><p>　　在本文附带的示例代码中，合并了一个名为 hardware.dll 的动态连接库，该动态连接库是一个获取系统硬件信息的库文件，其中包括了以下函数:</p><pre>   getmac 		取得网卡 MAC 
   VolumeNumber 	取得硬盘卷标 
   changeres            改变屏幕分辩率 
   IsDiskInDrive        检查软驱中是否插有盘&nbsp;
   DPGetDefaultPrinter  取得默认的打印机名 
   DPSetDefaultPrinter  设置默认的打印机 
   getserial            取得硬盘的出厂序列号 
   getmetric            取得显示分辩率 
   PrintStringDirect    直接向打印机发送一个串 
   vfpbeep              让 PC 喇叭发声 
   getcpuid             取得 CPU ID 
   getbios              取得主板 BIOS ID 
</pre>　　在示例代码中，只调用了其中一个函数 getbios 来获取主板 BIOS ID， 这里说明一下，该函数实际上好象只能检测 AWARD 主板的 BIOS， 也就是说它是读取的是系统内存 0x000fex71 处的值。因为其它牌子的主板 BIOS 的位置稍有不同，但在程序中没有进行这方面的处理，所以在读其它牌子的主板 BIOS 时可能会有些问题(读出的内容可能不正确)。关于此 DLL 的内容和实现，也许我会在另一篇文章中论及。 <br />　 
<hr /><br /><img src="http://www.vckbase.com/document/image/paragraph.gif"  alt="" /><strong>局限<br />　　</strong>在我进行测试时，发现对于有些含有资源的 DLL，在 9x 平台下可能会有问题。<br /><p><img src="http://www.vckbase.com/document/image/paragraph.gif"  alt="" /><strong>题外话<br />　　</strong>另外，其它一些本文未提及的非主要的函数，请自行参见源代码中的注释。<br />再，本文涉及 PE 文件格式方面的知识，它们已经超出了本文的范围，具体信息可参见 MSDM 中的:</p><dir><li><em>Peering Inside the PE: A Tour of the Win32 Portable Executable File Format 一</em>文和 
</li><li><em>Microsoft Portable Executable and Common Object File Format Specification </em>一文 </li></dir><p><strong>特别感谢卢春明（Aming）在我编写本文时所作的一些技术方面的建议和指导</strong></p><br /><p style="margin-top: 10px; margin-bottom: 10px; box-sizing: border-box; line-height: 24px; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px;">如果本文对你的开发有所帮助，并且你手头恰好有零钱。</p><p style="margin-top: 10px; margin-bottom: 10px; box-sizing: border-box; line-height: 24px; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px;">不如打赏我一杯咖啡，鼓励我继续分享优秀的文章。<br /><img src="http://www.cppblog.com/images/cppblog_com/mybios/222.jpg" border="0" alt="" /><br /><br /><br /><br /></p><img src ="http://www.cppblog.com/mybios/aggbug/15483.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/mybios/" target="_blank">李锦俊(mybios)</a> 2006-11-21 00:45 <a href="http://www.cppblog.com/mybios/archive/2006/11/21/15483.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>【转贴】直接运行内存中的程序</title><link>http://www.cppblog.com/mybios/archive/2006/11/20/15452.html</link><dc:creator>李锦俊(mybios)</dc:creator><author>李锦俊(mybios)</author><pubDate>Mon, 20 Nov 2006 03:54:00 GMT</pubDate><guid>http://www.cppblog.com/mybios/archive/2006/11/20/15452.html</guid><wfw:comment>http://www.cppblog.com/mybios/comments/15452.html</wfw:comment><comments>http://www.cppblog.com/mybios/archive/2006/11/20/15452.html#Feedback</comments><slash:comments>6</slash:comments><wfw:commentRss>http://www.cppblog.com/mybios/comments/commentRss/15452.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mybios/services/trackbacks/15452.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 哈哈，想不到有人居然把这种代码也搞出来了。    Windows的PE加载器在启动程序的时候，会将磁盘上的文件加载到内存，然后做很多操作，如函数导入表重定位，变量预处理之类的。这位仁兄等于是自己写了一个PE加载器。直接将内存中的程序启动。记得以前的“红色代码”病毒也有相同的特性。    直接启动内存中的程序相当于加了一个壳，可以把程序加密保存，运行时解密到内存，然后启动，不过对于增加破解难度还要稍...&nbsp;&nbsp;<a href='http://www.cppblog.com/mybios/archive/2006/11/20/15452.html'>阅读全文</a><img src ="http://www.cppblog.com/mybios/aggbug/15452.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/mybios/" target="_blank">李锦俊(mybios)</a> 2006-11-20 11:54 <a href="http://www.cppblog.com/mybios/archive/2006/11/20/15452.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>【原创】魔兽争霸III 地图编辑器原理（关键是脚本）</title><link>http://www.cppblog.com/mybios/archive/2006/11/19/15404.html</link><dc:creator>李锦俊(mybios)</dc:creator><author>李锦俊(mybios)</author><pubDate>Sat, 18 Nov 2006 16:20:00 GMT</pubDate><guid>http://www.cppblog.com/mybios/archive/2006/11/19/15404.html</guid><wfw:comment>http://www.cppblog.com/mybios/comments/15404.html</wfw:comment><comments>http://www.cppblog.com/mybios/archive/2006/11/19/15404.html#Feedback</comments><slash:comments>9</slash:comments><wfw:commentRss>http://www.cppblog.com/mybios/comments/commentRss/15404.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mybios/services/trackbacks/15404.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: <font color="#ff0000">　　注意：本文纯属是本人从研究魔兽争霸III地图编辑器的过程中的一种猜想，所以，不当之处，还请高手指出。谢谢！</font><br><br>　　魔兽争霸III我以前玩得比较多，也听说他的地图编辑器非常牛X，以前也曾经想编辑个地图出来。但是，限于当时得水平问题，没有成功。直到最近在研究如何制作游戏的时候，打开魔兽争霸III的地图编辑器来看，突然有一种扩然开朗的感觉！哦！原来地图编辑器是这样出来的！闲话不多说！马上进入正题！<br><br>　　魔兽争霸III的地图编辑器使用了一个文件来代表一个地图，地图里包含了什么东西？我无从得知，但是，从他的编辑器上看，看到编辑器能对地图修改的东西，就可以大概猜想到有哪些东西。仔细看地图编辑器，看到有那么几个模块：地形编辑器、开关编辑器、声音编辑器、物体编辑器、战役编辑器、AI编辑器、物体管理器、输入管理器。我把我的理解逐一说来<a href="http://www.cppblog.com/mybios/archive/2006/11/19/15404.html">阅读全文</a>&nbsp;&nbsp;<a href='http://www.cppblog.com/mybios/archive/2006/11/19/15404.html'>阅读全文</a><img src ="http://www.cppblog.com/mybios/aggbug/15404.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/mybios/" target="_blank">李锦俊(mybios)</a> 2006-11-19 00:20 <a href="http://www.cppblog.com/mybios/archive/2006/11/19/15404.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>【转贴】一些高效代码片段</title><link>http://www.cppblog.com/mybios/archive/2006/11/18/15359.html</link><dc:creator>李锦俊(mybios)</dc:creator><author>李锦俊(mybios)</author><pubDate>Sat, 18 Nov 2006 07:17:00 GMT</pubDate><guid>http://www.cppblog.com/mybios/archive/2006/11/18/15359.html</guid><wfw:comment>http://www.cppblog.com/mybios/comments/15359.html</wfw:comment><comments>http://www.cppblog.com/mybios/archive/2006/11/18/15359.html#Feedback</comments><slash:comments>4</slash:comments><wfw:commentRss>http://www.cppblog.com/mybios/comments/commentRss/15359.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mybios/services/trackbacks/15359.html</trackback:ping><description><![CDATA[
		<strong>一个快速开方的函数<br /></strong>
		<pre class="code">
				<span class="coMULTI">
						<em>
								<font color="#808080">/* 来至 Quake 3 的源码 */</font>
						</em>
				</span>
				<span class="kw4">
						<font color="#993333">float</font>
				</span> CarmSqrt<span class="br0"><font color="#66cc66">(</font></span><span class="kw4"><font color="#993333">float</font></span> x<font color="#66cc66"><span class="br0">)</span><span class="br0">{</span></font><span class="kw4"><font color="#993333">union</font></span><span class="br0"><font color="#66cc66">{</font></span><span class="kw4"><font color="#993333">int</font></span> intPart;
		<span class="kw4"><font color="#993333">float</font></span> floatPart;
	<span class="br0"><font color="#66cc66">}</font></span> convertor;
	<span class="kw4"><font color="#993333">union</font></span><span class="br0"><font color="#66cc66">{</font></span><span class="kw4"><font color="#993333">int</font></span> intPart;
		<span class="kw4"><font color="#993333">float</font></span> floatPart;
	<span class="br0"><font color="#66cc66">}</font></span> convertor2;
	convertor.<span class="me1">floatPart</span> = x;
	convertor2.<span class="me1">floatPart</span> = x;
	convertor.<span class="me1">intPart</span> = 0x1FBCF800 + <span class="br0"><font color="#66cc66">(</font></span>convertor.<span class="me1">intPart</span> &gt;&gt; <span class="nu0"><font color="#cc66cc">1</font></span><span class="br0"><font color="#66cc66">)</font></span>;
	convertor2.<span class="me1">intPart</span> = 0x5f3759df - <span class="br0"><font color="#66cc66">(</font></span>convertor2.<span class="me1">intPart</span> &gt;&gt; <span class="nu0"><font color="#cc66cc">1</font></span><span class="br0"><font color="#66cc66">)</font></span>;
	<span class="kw1"><font color="#b1b100">return</font></span><span class="nu0"><font color="#cc66cc">0</font></span>.5f*<span class="br0"><font color="#66cc66">(</font></span>convertor.<span class="me1">floatPart</span> + <span class="br0"><font color="#66cc66">(</font></span>x * convertor2.<span class="me1">floatPart</span><font color="#66cc66"><span class="br0">)</span><span class="br0">)</span></font>;
<span class="br0"><font color="#66cc66">}</font></span></pre>
		<br />参考链接：<a href="http://greatsorcerer.go2.icpcn.com/info/fastsqrt.html" target="_blank" rel="nofollow"><img title="在新窗口中打开" height="11" alt="[External Link]" hspace="4" src="http://blog.codingnow.com/cloud//images/www.gif" width="11" border="0" /></a><a href="http://greatsorcerer.go2.icpcn.com/info/fastsqrt.html" rel="nofollow"><font color="#003399">http://greatsorcerer.go2.icpcn.com/info/fastsqrt.html</font></a><br /><font color="#003399"><hr noshade="" size="1" /></font><strong>快速 double 转整型 </strong><br /><pre class="code"><span class="kw4"><font color="#993333">union</font></span> luai_Cast <span class="br0"><font color="#66cc66">{</font></span><span class="kw4"><font color="#993333">double</font></span> l_d; <span class="kw4"><font color="#993333">long</font></span> l_l; <span class="br0"><font color="#66cc66">}</font></span>;
<span class="co2"><em><font color="#808080">#define lua_number2int(i,d) \</font></em></span><span class="br0"><font color="#66cc66">{</font></span><span class="kw4"><font color="#993333">volatile</font></span><span class="kw4"><font color="#993333">union</font></span> luai_Cast u; u.<span class="me1">l_d</span> = <span class="br0"><font color="#66cc66">(</font></span>d<span class="br0"><font color="#66cc66">)</font></span> + <span class="nu0"><font color="#cc66cc">6755399441055744</font></span>.<span class="nu0"><font color="#cc66cc">0</font></span>; <span class="br0"><font color="#66cc66">(</font></span>i<span class="br0"><font color="#66cc66">)</font></span> = u.<span class="me1">l_l</span>; <span class="br0"><font color="#66cc66">}</font></span></pre><br />参考链接：<a href="http://blog.codingnow.com/2006/02/double_to_int_magic_number.html" target="_blank"><img title="在新窗口中打开" height="11" alt="[InterWiki]" hspace="4" src="http://blog.codingnow.com/cloud//images/inter.gif" width="11" border="0" /></a><a href="http://blog.codingnow.com/2006/02/double_to_int_magic_number.html"><font color="#003399">double to int 神奇的 magic number</font></a><br /><font color="#003399"><hr noshade="" size="1" /></font><strong>RGB565 的 alpha 混合 </strong><br /><pre class="code"><span class="kw4"><font color="#993333">unsigned</font></span><span class="kw4"><font color="#993333">short</font></span> alpha_blender<span class="br0"><font color="#66cc66">(</font></span><span class="kw4"><font color="#993333">unsigned</font></span><span class="kw4"><font color="#993333">int</font></span> x,<span class="kw4"><font color="#993333">unsigned</font></span><span class="kw4"><font color="#993333">int</font></span> y,<span class="kw4"><font color="#993333">unsigned</font></span><span class="kw4"><font color="#993333">int</font></span> alpha<span class="br0"><font color="#66cc66">)</font></span><span class="br0"><font color="#66cc66">{</font></span>
	x = <span class="br0"><font color="#66cc66">(</font></span>x | <span class="br0"><font color="#66cc66">(</font></span>x&lt;&lt;<span class="nu0"><font color="#cc66cc">16</font></span><font color="#66cc66"><span class="br0">)</span><span class="br0">)</span></font> &amp; 0x7E0F81F;
	y = <span class="br0"><font color="#66cc66">(</font></span>y | <span class="br0"><font color="#66cc66">(</font></span>y&lt;&lt;<span class="nu0"><font color="#cc66cc">16</font></span><font color="#66cc66"><span class="br0">)</span><span class="br0">)</span></font> &amp; 0x7E0F81F;
	<span class="kw4"><font color="#993333">unsigned</font></span><span class="kw4"><font color="#993333">int</font></span> result = <font color="#66cc66"><span class="br0">(</span><span class="br0">(</span></font>x - y<span class="br0"><font color="#66cc66">)</font></span> * alpha / <span class="nu0"><font color="#cc66cc">32</font></span> + y<span class="br0"><font color="#66cc66">)</font></span> &amp; 0x7E0F81F;
	<span class="kw1"><font color="#b1b100">return</font></span><span class="br0"><font color="#66cc66">(</font></span><span class="kw4"><font color="#993333">unsigned</font></span><span class="kw4"><font color="#993333">short</font></span><font color="#66cc66"><span class="br0">)</span><span class="br0">(</span><span class="br0">(</span></font>result&amp;0xFFFF<span class="br0"><font color="#66cc66">)</font></span> | <span class="br0"><font color="#66cc66">(</font></span>result&gt;&gt;<span class="nu0"><font color="#cc66cc">16</font></span><font color="#66cc66"><span class="br0">)</span><span class="br0">)</span></font>;
<span class="br0"><font color="#66cc66">}</font></span></pre><br />参考链接：<a href="http://www.codingnow.com/2000/gamedev/tips/alphammx.htm" target="_blank"><img title="在新窗口中打开" height="11" alt="[InterWiki]" hspace="4" src="http://blog.codingnow.com/cloud//images/inter.gif" width="11" border="0" /></a><a href="http://www.codingnow.com/2000/gamedev/tips/alphammx.htm"><font color="#003399">64K 色的 Alpha 混合</font></a><br /><font color="#003399"><hr noshade="" size="1" /></font><strong>一个不错的字符串 hash 函数 </strong><br /><pre class="code"><span class="kw4"><font color="#993333">unsigned</font></span><span class="kw4"><font color="#993333">long</font></span> hash<span class="br0"><font color="#66cc66">(</font></span><span class="kw4"><font color="#993333">const</font></span><span class="kw4"><font color="#993333">char</font></span> *name,size_t len<span class="br0"><font color="#66cc66">)</font></span><span class="br0"><font color="#66cc66">{</font></span><span class="kw4"><font color="#993333">unsigned</font></span><span class="kw4"><font color="#993333">long</font></span> h=<span class="br0"><font color="#66cc66">(</font></span><span class="kw4"><font color="#993333">unsigned</font></span><span class="kw4"><font color="#993333">long</font></span><span class="br0"><font color="#66cc66">)</font></span>len;
	size_t step = <span class="br0"><font color="#66cc66">(</font></span>len&gt;&gt;<span class="nu0"><font color="#cc66cc">5</font></span><span class="br0"><font color="#66cc66">)</font></span>+<span class="nu0"><font color="#cc66cc">1</font></span>;
	<span class="kw1"><font color="#b1b100">for</font></span><span class="br0"><font color="#66cc66">(</font></span>size_t i=len; i&gt;=step; i-=step<span class="br0"><font color="#66cc66">)</font></span>
	    h = h ^ <font color="#66cc66"><span class="br0">(</span><span class="br0">(</span></font>h&lt;&lt;<span class="nu0"><font color="#cc66cc">5</font></span><span class="br0"><font color="#66cc66">)</font></span>+<span class="br0"><font color="#66cc66">(</font></span>h&gt;&gt;<span class="nu0"><font color="#cc66cc">2</font></span><span class="br0"><font color="#66cc66">)</font></span>+<span class="br0"><font color="#66cc66">(</font></span><span class="kw4"><font color="#993333">unsigned</font></span><span class="kw4"><font color="#993333">long</font></span><span class="br0"><font color="#66cc66">)</font></span>name<span class="br0"><font color="#66cc66">[</font></span>i-<span class="nu0"><font color="#cc66cc">1</font></span><font color="#66cc66"><span class="br0">]</span><span class="br0">)</span></font>;
	<span class="kw1"><font color="#b1b100">return</font></span> h;
<span class="br0"><font color="#66cc66">}</font></span></pre><br />一个方便的 hash 函数应该散列的比较开，计算速度跟字符串长度关系不大，又不能只计算字符串的开头或末尾。这里的算法是从 <a href="http://blog.codingnow.com/cloud/Lua5"><font color="#003399">Lua</font></a> 中看来的。<br /><hr noshade="" size="1" /><strong>关于脏矩形技术的演示 </strong><br />由于代码过长，单起一页：<a href="http://blog.codingnow.com/cloud/DirtyRect"><font color="#003399">脏矩形 demo</font></a><br />参考链接：<a href="http://blog.codingnow.com/2006/05/dirtyrect_demo.html" target="_blank" rel="nofollow"><img title="在新窗口中打开" height="11" alt="[External Link]" hspace="4" src="http://blog.codingnow.com/cloud//images/www.gif" width="11" border="0" /></a><a href="http://blog.codingnow.com/2006/05/dirtyrect_demo.html" rel="nofollow"><font color="#003399">Blog上的帖子：脏矩形演示demo</font></a><br /><font color="#003399"><hr noshade="" size="1" /></font><strong>UTF8 到 UTF16 的转换(单个字符) </strong><br /><pre class="code"><span class="kw4"><font color="#993333">int</font></span> UTF8toUTF16<span class="br0"><font color="#66cc66">(</font></span><span class="kw4"><font color="#993333">int</font></span> c<span class="br0"><font color="#66cc66">)</font></span><span class="br0"><font color="#66cc66">{</font></span><span class="kw4"><font color="#993333">signed</font></span><span class="kw4"><font color="#993333">char</font></span> *t=<span class="br0"><font color="#66cc66">(</font></span><span class="kw4"><font color="#993333">signed</font></span><span class="kw4"><font color="#993333">char</font></span>*<span class="br0"><font color="#66cc66">)</font></span>&amp;c;
	<span class="kw4"><font color="#993333">int</font></span> ret=*t &amp;<span class="br0"><font color="#66cc66">(</font></span>0x0f | <font color="#66cc66"><span class="br0">(</span><span class="br0">(</span></font>*t&gt;&gt;<span class="nu0"><font color="#cc66cc">1</font></span><span class="br0"><font color="#66cc66">)</font></span> &amp;0x1f<span class="br0"><font color="#66cc66">)</font></span> | ~<span class="br0"><font color="#66cc66">(</font></span>*t&gt;&gt;<span class="nu0"><font color="#cc66cc">7</font></span><font color="#66cc66"><span class="br0">)</span><span class="br0">)</span></font>;
	<span class="kw4"><font color="#993333">int</font></span> i;
	assert <font color="#66cc66"><span class="br0">(</span><span class="br0">(</span></font>*t &amp; 0xc0<span class="br0"><font color="#66cc66">)</font></span> != 0x80<span class="br0"><font color="#66cc66">)</font></span>;
	<span class="kw1"><font color="#b1b100">for</font></span><span class="br0"><font color="#66cc66">(</font></span>i=<span class="nu0"><font color="#cc66cc">1</font></span>;i&lt;<span class="nu0"><font color="#cc66cc">3</font></span>;i++<span class="br0"><font color="#66cc66">)</font></span><span class="br0"><font color="#66cc66">{</font></span><span class="kw1"><font color="#b1b100">if</font></span><font color="#66cc66"><span class="br0">(</span><span class="br0">(</span></font>t<span class="br0"><font color="#66cc66">[</font></span>i<span class="br0"><font color="#66cc66">]</font></span> &amp; 0xc0<span class="br0"><font color="#66cc66">)</font></span>!=0x80<span class="br0"><font color="#66cc66">)</font></span><span class="br0"><font color="#66cc66">{</font></span><span class="kw2"><strong>break</strong></span>;
		<span class="br0"><font color="#66cc66">}</font></span>
		ret=ret&lt;&lt;<span class="nu0"><font color="#cc66cc">6</font></span> | <span class="br0"><font color="#66cc66">(</font></span>t<span class="br0"><font color="#66cc66">[</font></span>i<span class="br0"><font color="#66cc66">]</font></span> &amp; 0x3f<span class="br0"><font color="#66cc66">)</font></span>;
	<span class="br0"><font color="#66cc66">}</font></span><span class="kw1"><font color="#b1b100">return</font></span> ret;
<span class="br0"><font color="#66cc66">}</font></span></pre><br />这只是一个字符的转换，如果转换字符串，可以再做一点优化。<img src ="http://www.cppblog.com/mybios/aggbug/15359.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/mybios/" target="_blank">李锦俊(mybios)</a> 2006-11-18 15:17 <a href="http://www.cppblog.com/mybios/archive/2006/11/18/15359.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>【转贴】泛型算法：Tips</title><link>http://www.cppblog.com/mybios/archive/2006/11/18/15333.html</link><dc:creator>李锦俊(mybios)</dc:creator><author>李锦俊(mybios)</author><pubDate>Sat, 18 Nov 2006 01:17:00 GMT</pubDate><guid>http://www.cppblog.com/mybios/archive/2006/11/18/15333.html</guid><wfw:comment>http://www.cppblog.com/mybios/comments/15333.html</wfw:comment><comments>http://www.cppblog.com/mybios/archive/2006/11/18/15333.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.cppblog.com/mybios/comments/commentRss/15333.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mybios/services/trackbacks/15333.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 从 STL 出现到现在已经这么多年了，泛型算法是它的重要组成，也是其中最“看起来很美”的东西之一。然而在真实的程序设计中，它往往成为程序员的心头一痛，因为一旦要用 for_each ，accumulate 之类的算法做一些稍微复杂一点的事情，你就会发现自己一个头变成两个大。								从 STL 出现到现在已经这么多年了，泛型算法是它的重要组成，也是其中最“看起来很美”的东西之一。...&nbsp;&nbsp;<a href='http://www.cppblog.com/mybios/archive/2006/11/18/15333.html'>阅读全文</a><img src ="http://www.cppblog.com/mybios/aggbug/15333.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/mybios/" target="_blank">李锦俊(mybios)</a> 2006-11-18 09:17 <a href="http://www.cppblog.com/mybios/archive/2006/11/18/15333.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>【转贴】PhysX SDK物理引擎开发包使用教程，基于OpenGL</title><link>http://www.cppblog.com/mybios/archive/2006/11/18/15327.html</link><dc:creator>李锦俊(mybios)</dc:creator><author>李锦俊(mybios)</author><pubDate>Sat, 18 Nov 2006 00:53:00 GMT</pubDate><guid>http://www.cppblog.com/mybios/archive/2006/11/18/15327.html</guid><wfw:comment>http://www.cppblog.com/mybios/comments/15327.html</wfw:comment><comments>http://www.cppblog.com/mybios/archive/2006/11/18/15327.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/mybios/comments/commentRss/15327.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mybios/services/trackbacks/15327.html</trackback:ping><description><![CDATA[
		<div class="con_sample">
				<p>AGEIA的PhysX处理器是世界上首款物理模拟处理器 (PPU), 该处理器将解除中央处理器进行物理模拟的负担。PhysX PPU 的设计构架基于顶点的多线程操作，允许游戏开发人员进行精确、流畅和动画创作和运动模拟，例如毛发、布料、液体、流体等。本文介绍了如何利用PhysX SDK物理引擎开发包来实现我们仿真的效果。</p>
		</div>
		<div class="con_all">
				<p>
				</p>
				<div style="LINE-HEIGHT: 150%">
						<span style="FONT-SIZE: 10.5pt">
								<br />AGEIA的PhysX处理器是世界上首款物理模拟处理器 (PPU), 该处理器将解除中央处理器进行物理模拟的负担。PhysX PPU 的设计构架基于顶点的多线程操作，允许游戏开发人员进行精确、流畅和动画创作和运动模拟，例如毛发、布料、液体、流体等。目前 AGEIA 的PhysX处理器是世界上第一款也是唯一一款专注于物理算法处理器的产品.<br /></span>
				</div>
				<div style="LINE-HEIGHT: 150%">
						<span style="FONT-SIZE: 10.5pt">利用PhysX SDK物理引擎开发包来实现我们仿真的效果时，一般需要以下几个步骤：</span>
				</div>
				<div style="MARGIN: 0cm 0cm 0pt 36pt; TEXT-INDENT: -36pt; LINE-HEIGHT: 150%">（1）<span style="FONT: 7pt 'Times New Roman'">    </span><span style="FONT-SIZE: 10.5pt">PrintControls();</span></div>
				<div style="MARGIN: 0cm 0cm 0pt 36pt; TEXT-INDENT: -36pt; LINE-HEIGHT: 150%">（2）<span style="FONT: 7pt 'Times New Roman'">    </span><span style="FONT-SIZE: 10.5pt">InitGlut(argc, argv);</span></div>
				<div style="MARGIN: 0cm 0cm 0pt 36pt; TEXT-INDENT: -36pt; LINE-HEIGHT: 150%">（3）<span style="FONT: 7pt 'Times New Roman'">    </span><span style="FONT-SIZE: 10.5pt">InitNx();</span></div>
				<div style="MARGIN: 0cm 0cm 0pt 36pt; TEXT-INDENT: -36pt; LINE-HEIGHT: 150%">（4）<span style="FONT: 7pt 'Times New Roman'">    </span><span style="FONT-SIZE: 10.5pt">glutMainLoop();</span></div>
				<div style="MARGIN: 0cm 0cm 0pt 36pt; TEXT-INDENT: -36pt; LINE-HEIGHT: 150%">（5）<span style="FONT: 7pt 'Times New Roman'">    </span><span style="FONT-SIZE: 10.5pt">ReleaseNx();</span></div>
				<div style="LINE-HEIGHT: 150%">
						<span style="FONT-SIZE: 10.5pt">其中最为主要的函数是InitNx（），也既是初始化PhysX，创建一个PhysX SDK实例以及建立我们的场景。下面具体分析各个函数的作用。</span>
				</div>
				<div style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: -21pt; LINE-HEIGHT: 150%">
						<span style="FONT-SIZE: 10.5pt">一．</span>
						<span style="FONT-SIZE: 10.5pt">PrintControls();</span>
				</div>
				<div style="MARGIN: 0cm 0cm 0pt 21pt; LINE-HEIGHT: 150%">
						<span style="FONT-SIZE: 10.5pt">显而易见，利用该函数的目的是在告诉玩家该如何进行操作。操作的按键可根据自己的喜好进行设置。</span>
				</div>
				<div style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: -21pt; LINE-HEIGHT: 150%">
						<span style="FONT-SIZE: 10.5pt">二．</span>
						<span style="FONT-SIZE: 10.5pt">InitGlut(argc, argv);</span>
				</div>
				<div style="MARGIN: 0cm 0cm 0pt 21pt; LINE-HEIGHT: 150%">
						<span style="FONT-SIZE: 10.5pt">PhysX是OpenGL上开发的，所以在初始化PhysX实例之前，必须建立一个OpenGL的框架。</span>
				</div>
				<div style="MARGIN: 0cm 0cm 0pt 42pt; TEXT-INDENT: -21pt; LINE-HEIGHT: 150%">
						<span style="FONT-SIZE: 10.5pt">①.<span style="FONT: 7pt 'Times New Roman'">    </span></span>
						<span style="FONT-SIZE: 10.5pt">glutInit(&amp;argc, argv) 用来初始化GLUT，并且处理任意的命令行变量</span>
				</div>
				<div style="MARGIN: 0cm 0cm 0pt 42pt; TEXT-INDENT: -21pt; LINE-HEIGHT: 150%">
						<span style="FONT-SIZE: 10.5pt">②.<span style="FONT: 7pt 'Times New Roman'">    </span></span>
						<span style="FONT-SIZE: 10.5pt">glutInitWindowSize(int width, int size) 指定了窗口以像素为单位的尺寸</span>
				</div>
				<div style="MARGIN: 0cm 0cm 0pt 42pt; TEXT-INDENT: -21pt; LINE-HEIGHT: 150%">
						<span style="FONT-SIZE: 10.5pt">③.<span style="FONT: 7pt 'Times New Roman'">    </span></span>
						<span style="FONT-SIZE: 10.5pt"> glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH) 建立一个带有双缓存、RGB颜色模型和很大缓存的窗口</span>
				</div>
				<div style="MARGIN: 0cm 0cm 0pt 42pt; TEXT-INDENT: -21pt; LINE-HEIGHT: 150%">
						<span style="FONT-SIZE: 10.5pt">④.<span style="FONT: 7pt 'Times New Roman'">    </span></span>
						<span style="FONT-SIZE: 10.5pt">glutCreateWindow（char* string） 创建一个具有OpenGL创建的窗口，string为该窗口的窗口名</span>
				</div>
				<div style="MARGIN: 0cm 0cm 0pt 42pt; TEXT-INDENT: -21pt; LINE-HEIGHT: 150%">
						<span style="FONT-SIZE: 10.5pt">⑤.<span style="FONT: 7pt 'Times New Roman'">    </span></span>
						<span style="FONT-SIZE: 10.5pt">glutSetWindow（）</span>
				</div>
				<div style="MARGIN: 0cm 0cm 0pt 42pt; TEXT-INDENT: -21pt; LINE-HEIGHT: 150%">
						<span style="FONT-SIZE: 10.5pt">⑥.<span style="FONT: 7pt 'Times New Roman'">    </span></span>
						<span style="FONT-SIZE: 10.5pt">glutDisplayFunc(RenderCallback) 渲染</span>
				</div>
				<div style="MARGIN: 0cm 0cm 0pt 6pt; TEXT-INDENT: 36pt; LINE-HEIGHT: 150%">
						<span style="FONT-SIZE: 10.5pt">ProcessCameraKeys();</span>
				</div>
				<div style="LINE-HEIGHT: 150%">
						<span style="FONT-SIZE: 10.5pt">     SetupCamera();</span>
				</div>
				<div style="LINE-HEIGHT: 150%">
						<span style="FONT-SIZE: 10.5pt">         <span style="COLOR: blue">if</span> (gScene &amp;&amp; !bPause)</span>
				</div>
				<div style="LINE-HEIGHT: 150%">
						<span style="FONT-SIZE: 10.5pt">     {</span>
				</div>
				<div style="LINE-HEIGHT: 150%">
						<span style="FONT-SIZE: 10.5pt">        GetPhysicsResults();</span>
				</div>
				<div style="TEXT-INDENT: -84pt; LINE-HEIGHT: 150%">
						<span style="FONT-SIZE: 10.5pt">ProcessInputs();根据选择的对象，给该对象施加前后、上下、左右不同方向的力，然后调用对象的方法addForce，产生不同的物理效果</span>
				</div>
				<div style="LINE-HEIGHT: 150%">
						<span style="FONT-SIZE: 10.5pt">        StartPhysics();</span>
				</div>
				<div style="LINE-HEIGHT: 150%">
						<span style="FONT-SIZE: 10.5pt">     }</span>
				</div>
				<div style="LINE-HEIGHT: 150%">
						<span style="FONT-SIZE: 10.5pt">    <span style="COLOR: green">// Display scene</span></span>
				</div>
				<div style="LINE-HEIGHT: 150%">
						<span style="FONT-SIZE: 10.5pt">     RenderActors(bShadows);</span>
				</div>
				<div style="MARGIN: 0cm 0cm 0pt 42pt; LINE-HEIGHT: 150%">
						<span style="FONT-SIZE: 10.5pt">调用函数DrawActor(NxActor* actor)将场景中的物体渲染出来，实在是在DrawActor(NxActor* actor)函数中根据物体形状调用不同形状的绘画函数将物体渲染出来的。在渲染的过程中，利用显示列表绘制不同形状的物体。在PhysX中，物体形状分为以下几种：NX_SHAPE_PLANE(面板状), NX_SHAPE_BOX(盒子状), NX_SHAPE_ SPHERE(球形状), NX_SHAPE_CAPSULE(胶囊状), NX_SHAPE_CONVEX(凸多边形状), NX_SHAPE_MESH(网状状)。</span>
				</div>
				<div style="MARGIN: 0cm 0cm 0pt 42pt; LINE-HEIGHT: 150%">
						<span style="FONT-SIZE: 10.5pt">当bShadows为true时，渲染物体的阴影；为false时就不绘制</span>
				</div>
				<div style="LINE-HEIGHT: 150%">
						<span style="FONT-SIZE: 10.5pt">     DrawForce(box, gForceVec, NxVec3(1,1,0));</span>
				</div>
				<div style="LINE-HEIGHT: 150%">
						<span style="FONT-SIZE: 10.5pt">        将物体受力的受力方向渲染出来</span>
				</div>
				<div style="MARGIN: 0cm 0cm 0pt 42pt; TEXT-INDENT: -21pt; LINE-HEIGHT: 150%">
						<span style="FONT-SIZE: 10.5pt">⑦.<span style="FONT: 7pt 'Times New Roman'">    </span></span>
						<span style="FONT-SIZE: 10.5pt">glutReshapeFunc(ReshapeCallback)</span>
				</div>
				<div style="MARGIN: 0cm 0cm 0pt 42pt; LINE-HEIGHT: 150%">
						<span style="FONT-SIZE: 10.5pt">设置窗口</span>
				</div>
				<div style="MARGIN: 0cm 0cm 0pt 42pt; TEXT-INDENT: -21pt; LINE-HEIGHT: 150%">
						<span style="FONT-SIZE: 10.5pt">⑧.<span style="FONT: 7pt 'Times New Roman'">    </span></span>
						<span style="FONT-SIZE: 10.5pt">glutIdleFunc(IdleCallback);</span>
				</div>
				<div style="MARGIN: 0cm 0cm 0pt 21pt; LINE-HEIGHT: 150%">
						<span style="FONT-SIZE: 10.5pt">   </span>
				</div>
				<div style="MARGIN: 0cm 0cm 0pt 42pt; TEXT-INDENT: -21pt; LINE-HEIGHT: 150%">
						<span style="FONT-SIZE: 10.5pt">⑨.<span style="FONT: 7pt 'Times New Roman'">    </span></span>
						<span style="FONT-SIZE: 10.5pt">glutKeyboardFunc(KeyboardCallback);</span>
				</div>
				<div style="MARGIN: 0cm 0cm 0pt 42pt; TEXT-INDENT: -21pt; LINE-HEIGHT: 150%">
						<span style="FONT-SIZE: 10.5pt">⑩.<span style="FONT: 7pt 'Times New Roman'">    </span></span>
						<span style="FONT-SIZE: 10.5pt">glutKeyboardUpFunc(KeyboardUpCallback);</span>
				</div>
				<div style="MARGIN: 0cm 0cm 0pt 42pt; TEXT-INDENT: -21pt; LINE-HEIGHT: 150%">
						<span style="FONT-SIZE: 10.5pt">⑪.<span style="FONT: 7pt 'Times New Roman'">    </span></span>
						<span style="FONT-SIZE: 10.5pt">glutSpecialFunc(SpecialCallback);</span>
				</div>
				<div style="MARGIN: 0cm 0cm 0pt 42pt; LINE-HEIGHT: 150%">
						<span style="FONT-SIZE: 10.5pt">在此，调用ResetNx（），重新渲染</span>
				</div>
				<div style="MARGIN: 0cm 0cm 0pt 42pt; TEXT-INDENT: -21pt; LINE-HEIGHT: 150%">
						<span style="FONT-SIZE: 10.5pt">⑫.<span style="FONT: 7pt 'Times New Roman'">    </span></span>
						<span style="FONT-SIZE: 10.5pt">glutMouseFunc(MouseCallback);</span>
				</div>
				<div style="MARGIN: 0cm 0cm 0pt 42pt; TEXT-INDENT: -21pt; LINE-HEIGHT: 150%">
						<span style="FONT-SIZE: 10.5pt">⑬.<span style="FONT: 7pt 'Times New Roman'">    </span></span>
						<span style="FONT-SIZE: 10.5pt">glutMotionFunc(MotionCallback);</span>
				</div>
				<div style="MARGIN: 0cm 0cm 0pt 42pt; TEXT-INDENT: -21pt; LINE-HEIGHT: 150%">
						<span style="FONT-SIZE: 10.5pt">⑭.<span style="FONT: 7pt 'Times New Roman'">    </span></span>
						<span style="FONT-SIZE: 10.5pt">MotionCallback(0,0);</span>
				</div>
				<div style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: -21pt; LINE-HEIGHT: 150%">
						<span style="FONT-SIZE: 10.5pt">三．</span>
						<span style="FONT-SIZE: 10.5pt">InitNx() 因为我们需要初始化PhysX SDK实例，并且建立我们需要的场景；所以我们需要设置以下几个变量，并且将它们设置为全局变量</span>
				</div>
				<div style="LINE-HEIGHT: 150%; TEXT-AUTOSPACE: ideograph-numeric">
						<span style="FONT-SIZE: 10.5pt">        </span>
						<span style="FONT-SIZE: 10.5pt; COLOR: black">NxPhysicsSDK*</span>
						<span style="FONT-SIZE: 10.5pt; COLOR: black">gPhysicsSDK = NULL;</span>
						<span style="FONT-SIZE: 10.5pt; COLOR: black">//PhysX SDK实例对象</span>
				</div>
				<div style="TEXT-INDENT: 36pt; LINE-HEIGHT: 150%">
						<span style="FONT-SIZE: 10.5pt; COLOR: black">NxScene*</span>
						<span style="FONT-SIZE: 10.5pt; COLOR: black">gScene = NULL;</span>
						<span style="FONT-SIZE: 10.5pt; COLOR: black">//场景对象</span>
				</div>
				<div style="TEXT-INDENT: 36pt; LINE-HEIGHT: 150%">
						<span style="FONT-SIZE: 10.5pt; COLOR: black">NxVec3</span>
						<span style="FONT-SIZE: 10.5pt; COLOR: black"> </span>
						<span style="FONT-SIZE: 10.5pt; COLOR: black">gDefaultGravity(0,-9.8,0);</span>
				</div>
				<div style="TEXT-INDENT: -15.75pt; LINE-HEIGHT: 150%">
						<span style="FONT-SIZE: 10.5pt; COLOR: black">***注意：坐标系的方向指向，在PhysX、OpenGL以及3DMax都有一些不一样，当运行里面的demo的时候就可以体会到。它们的坐标系分别如下：  <img alt="" src="http://p.blog.csdn.net/images/p_blog_csdn_net/skyman_2001/phisX.jpg" />  </span>
				</div>
				<div style="TEXT-INDENT: -15.75pt; LINE-HEIGHT: 150%">
						<span style="FONT-SIZE: 10.5pt; COLOR: black">  </span>
				</div>
				<p style="TEXT-INDENT: 36pt; LINE-HEIGHT: 150%">
						<span style="FONT-SIZE: 10.5pt; COLOR: black">
								<span>
								</span>
						</span>
				</p>
				<div style="TEXT-INDENT: 36pt; LINE-HEIGHT: 150%">
						<span style="FONT-SIZE: 10.5pt; COLOR: black">  </span>
						<span style="FONT-SIZE: 10.5pt; COLOR: black">下面就在InitNx（）中开始初始化实例以及建立场景.</span>
				</div>
				<div style="MARGIN: 0cm 0cm 0pt 63pt; TEXT-INDENT: -21pt; LINE-HEIGHT: 150%">
						<span style="FONT-SIZE: 10.5pt; COLOR: black">①.<span style="FONT: 7pt 'Times New Roman'">    </span></span>
						<span style="FONT-SIZE: 10.5pt; COLOR: black">实例化 physics SDK</span>
				</div>
				<div style="MARGIN: 0cm 0cm 0pt 42pt; TEXT-INDENT: 24pt; LINE-HEIGHT: 150%">
						<span style="FONT-SIZE: 10.5pt; COLOR: black">gPhysicsSDK = NxCreatePhysicsSDK(NX_PHYSICS_SDK_VERSION);</span>
				</div>
				<div style="MARGIN: 0cm 0cm 0pt 66pt; LINE-HEIGHT: 150%">
						<span style="FONT-SIZE: 10.5pt; COLOR: black">初始化完Physics SDK后，只是简单的一个实例。可以通过设置实例的物理参数来充实我们的模拟效果.</span>
				</div>
				<div style="MARGIN: 0cm 0cm 0pt 66pt; LINE-HEIGHT: 150%">
						<span style="FONT-SIZE: 10.5pt; COLOR: black">gPhysicsSDK-&gt;setParameter(NX_SKIN_WIDTH, 0.01);</span>
				</div>
				<div style="MARGIN: 0cm 0cm 0pt 63pt; TEXT-INDENT: -21pt; LINE-HEIGHT: 150%">
						<span style="FONT-SIZE: 10.5pt; COLOR: black">②.<span style="FONT: 7pt 'Times New Roman'">    </span></span>
						<span style="FONT-SIZE: 10.5pt; COLOR: black">创建场景</span>
				</div>
				<div style="LINE-HEIGHT: 150%; TEXT-AUTOSPACE: ideograph-numeric">
						<span style="FONT-SIZE: 10.5pt; COLOR: black">            </span>
						<span style="FONT-SIZE: 10.5pt; COLOR: black">NxSceneDesc sceneDesc;</span>
						<span style="FONT-SIZE: 10.5pt; COLOR: black">//场景表述表对象</span>
				</div>
				<div style="LINE-HEIGHT: 150%; TEXT-AUTOSPACE: ideograph-numeric">
						<span style="FONT-SIZE: 10.5pt; COLOR: black">    </span>
						<span style="FONT-SIZE: 10.5pt; COLOR: black">        </span>
						<span style="FONT-SIZE: 10.5pt; COLOR: black">sceneDesc.gravity = gDefaultGravity;</span>
				</div>
				<div style="LINE-HEIGHT: 150%; TEXT-AUTOSPACE: ideograph-numeric">
						<span style="FONT-SIZE: 10.5pt; COLOR: black">   </span>
						<span style="FONT-SIZE: 10.5pt; COLOR: black">     </span>
						<span style="FONT-SIZE: 10.5pt; COLOR: black">sceneDesc.broadPhase = NX_BROADPHASE_COHERENT;</span>
				</div>
				<div style="LINE-HEIGHT: 150%; TEXT-AUTOSPACE: ideograph-numeric">
						<span style="FONT-SIZE: 10.5pt; COLOR: black">   </span>
						<span style="FONT-SIZE: 10.5pt; COLOR: black">     </span>
						<span style="FONT-SIZE: 10.5pt; COLOR: black">sceneDesc.collisionDetection    = true;</span>
				</div>
				<div style="LINE-HEIGHT: 150%">
						<span style="FONT-SIZE: 10.5pt; COLOR: black">    </span>
						<span style="FONT-SIZE: 10.5pt; COLOR: black">        </span>
						<span style="FONT-SIZE: 10.5pt; COLOR: black">gScene = gPhysicsSDK-&gt;createScene(sceneDesc);</span>
				</div>
				<div style="LINE-HEIGHT: 150%">
						<span style="FONT-SIZE: 10.5pt; COLOR: black">在PhysX中，不管是创建场景还是创建各个物体角色时，都是先通过各自对应的描述器（翻译的不是很准确）设置场景和各个物体的物理参数，用来模拟真实的世界环境和物体。建立好表述器后，通过函数</span>
						<span style="FONT-SIZE: 10.5pt; COLOR: black">createSce</span>
						<span style="FONT-SIZE: 10.5pt; COLOR: black">ne（</span>
						<span style="FONT-SIZE: 10.5pt; COLOR: black">NxSceneDesc</span>
						<span style="FONT-SIZE: 10.5pt; COLOR: black">）函数就可以建立需要的场景对象。</span>
				</div>
				<div style="MARGIN: 0cm 0cm 0pt 60pt; LINE-HEIGHT: 150%">
						<span style="FONT-SIZE: 10.5pt; COLOR: black">一般情况下，场景描述器的参数就是设置重力加速度</span>
						<span style="FONT-SIZE: 10.5pt; COLOR: black">sceneDesc.gravity</span>
						<span style="FONT-SIZE: 10.5pt; COLOR: black">，是否进行碰撞检测</span>
						<span style="FONT-SIZE: 10.5pt; COLOR: black">collisionDetection</span>
						<span style="FONT-SIZE: 10.5pt; COLOR: black">, true为进行，</span>
						<span style="FONT-SIZE: 10.5pt">在PhysX SDK中描述器被广泛的应用. 描述器包括所有你创建物体的信息</span>
						<span style="FONT-SIZE: 10.5pt">broadphase-coherent</span>
						<span style="FONT-SIZE: 10.5pt">是三种碰撞检测中的一种。</span>
				</div>
				<div style="MARGIN: 0cm 0cm 0pt 24pt; TEXT-INDENT: 36pt; LINE-HEIGHT: 150%">
						<span style="FONT-SIZE: 10.5pt; COLOR: black">gPhysicsSDK-&gt;setParameter(NX_SKIN_WIDTH, 0.01);</span>
				</div>
				<div style="LINE-HEIGHT: 150%">
						<span style="FONT-SIZE: 10.5pt; COLOR: black">当相互碰撞的物体的材质都很软的时候，在现实中就会发现当发生碰撞的时候物体之间就会相互嵌入一部分，在这里我们就可以利用物理参数</span>
						<span style="FONT-SIZE: 10.5pt; COLOR: black">NX_SKIN_WIDTH</span>
						<span style="FONT-SIZE: 10.5pt; COLOR: black">，它的默认值为0.05m，该值越大，嵌入的就越多</span>
				</div>
				<div style="MARGIN: 0cm 0cm 0pt 60pt; LINE-HEIGHT: 150%"> </div>
				<div style="MARGIN: 0cm 0cm 0pt 60pt; LINE-HEIGHT: 150%">
						<span style="FONT-SIZE: 10.5pt; COLOR: black">同时，我们可以对场景中的所有物体创建材质。创建的材质定义了碰撞和物体材料的物理属性。比如反弹系数、静摩擦力、滑动摩擦力等。</span>
				</div>
				<div style="MARGIN: 0cm 0cm 0pt 60pt; LINE-HEIGHT: 150%"> </div>
				<div style="LINE-HEIGHT: 150%; TEXT-AUTOSPACE: ideograph-numeric">
						<span style="FONT-SIZE: 10.5pt; COLOR: black">    </span>
						<span style="FONT-SIZE: 10.5pt; COLOR: black">        </span>
						<span style="FONT-SIZE: 10.5pt; COLOR: black">// Create the default material</span>
						<span style="FONT-SIZE: 10.5pt; COLOR: black">通过材质索引创建一个材质的对象</span>
				</div>
				<div style="LINE-HEIGHT: 150%; TEXT-AUTOSPACE: ideograph-numeric">
						<span style="FONT-SIZE: 10.5pt; COLOR: black">    </span>
						<span style="FONT-SIZE: 10.5pt; COLOR: black">        </span>
						<span style="FONT-SIZE: 10.5pt; COLOR: black">NxMaterial* defaultMaterial = gScene-&gt;getMaterialFromIndex(0); </span>
				</div>
				<div style="LINE-HEIGHT: 150%; TEXT-AUTOSPACE: ideograph-numeric">
						<span style="FONT-SIZE: 10.5pt; COLOR: black">    </span>
						<span style="FONT-SIZE: 10.5pt; COLOR: black">       </span>
						<span style="FONT-SIZE: 10.5pt; COLOR: black">defaultMaterial-&gt;setRestitution(0.5);</span>
				</div>
				<div style="LINE-HEIGHT: 150%; TEXT-AUTOSPACE: ideograph-numeric">
						<span style="FONT-SIZE: 10.5pt; COLOR: black">    </span>
						<span style="FONT-SIZE: 10.5pt; COLOR: black">        </span>
						<span style="FONT-SIZE: 10.5pt; COLOR: black">defaultMaterial-&gt;setStaticFriction(0.5);</span>
				</div>
				<div style="LINE-HEIGHT: 150%; TEXT-AUTOSPACE: ideograph-numeric">
						<span style="FONT-SIZE: 10.5pt; COLOR: black">    </span>
						<span style="FONT-SIZE: 10.5pt; COLOR: black">       </span>
						<span style="FONT-SIZE: 10.5pt; COLOR: black">defaultMaterial-&gt;setDynamicFriction(0.5);</span>
				</div>
				<div style="MARGIN: 0cm 0cm 0pt 60pt; LINE-HEIGHT: 150%"> </div>
				<div style="MARGIN: 0cm 0cm 0pt 60pt; LINE-HEIGHT: 150%">
						<span style="FONT-SIZE: 10.5pt; COLOR: black">创建物体，以box为例</span>
				</div>
				<div style="MARGIN: 0cm 0cm 0pt 60pt; LINE-HEIGHT: 150%">
						<span style="FONT-SIZE: 10.5pt">NxActor* box = CreateBox(NxVec3(5,1,0));</span>
				</div>
				<div style="MARGIN: 0cm 0cm 0pt 24pt; TEXT-INDENT: 36pt; LINE-HEIGHT: 150%">
						<span style="FONT-SIZE: 10.5pt">NxActor* CreateBox(<span style="COLOR: blue">const</span> NxVec3&amp; pos)</span>
				</div>
				<div style="MARGIN: 0cm 0cm 0pt 24pt; TEXT-INDENT: 36pt; LINE-HEIGHT: 150%">
						<span style="FONT-SIZE: 10.5pt">{</span>
				</div>
				<div style="LINE-HEIGHT: 150%">
						<span style="FONT-SIZE: 10.5pt">        <span style="COLOR: green">// Add a single-shape actor to the scene</span></span>
				</div>
				<div style="LINE-HEIGHT: 150%">
						<span style="FONT-SIZE: 10.5pt">        NxActorDesc actorDesc;</span>
				</div>
				<div style="LINE-HEIGHT: 150%">
						<span style="FONT-SIZE: 10.5pt">        NxBodyDesc bodyDesc;</span>
				</div>
				<div style="LINE-HEIGHT: 150%"> </div>
				<div style="LINE-HEIGHT: 150%">
						<span style="FONT-SIZE: 10.5pt">        <span style="COLOR: green">// The actor has one shape, a box</span></span>
				</div>
				<div style="LINE-HEIGHT: 150%">
						<span style="FONT-SIZE: 10.5pt">        NxBoxShapeDesc boxDesc;</span>
				</div>
				<div style="LINE-HEIGHT: 150%">
						<span style="FONT-SIZE: 10.5pt">        boxDesc.dimensions.set(0.5,1,0.5);</span>
				</div>
				<div style="LINE-HEIGHT: 150%">
						<span style="FONT-SIZE: 10.5pt">        actorDesc.shapes.pushBack(&amp;boxDesc);</span>
				</div>
				<div style="LINE-HEIGHT: 150%"> </div>
				<div style="LINE-HEIGHT: 150%">
						<span style="FONT-SIZE: 10.5pt">        actorDesc.body = &amp;bodyDesc;</span>
				</div>
				<div style="LINE-HEIGHT: 150%">
						<span style="FONT-SIZE: 10.5pt">        actorDesc.density = 10;</span>
				</div>
				<div style="LINE-HEIGHT: 150%">
						<span style="FONT-SIZE: 10.5pt">        actorDesc.globalPose.t = pos;</span>
				</div>
				<div style="LINE-HEIGHT: 150%">
						<span style="FONT-SIZE: 10.5pt">        <span style="COLOR: blue">return</span> gScene-&gt;createActor(actorDesc); </span>
				</div>
				<div style="MARGIN: 0cm 0cm 0pt 60pt; LINE-HEIGHT: 150%">
						<span style="FONT-SIZE: 10.5pt">}</span>
				</div>
				<div style="LINE-HEIGHT: 150%">
						<span style="FONT-SIZE: 10.5pt">我们创建一个角色参与者box，它的类型为</span>
						<span style="FONT-SIZE: 10.5pt; COLOR: black">NxActor*</span>
						<span style="FONT-SIZE: 10.5pt; COLOR: black">。建立该对象的时候需要设置它的描述器，然后利用函数</span>
						<span style="FONT-SIZE: 10.5pt; COLOR: black">createActor(NxActorDesc actorDesc)</span>
						<span style="FONT-SIZE: 10.5pt; COLOR: black">将该对象加入场景中。每一个对象又有和自己形状相对应的描述器。利用它设置对象的物理参数。</span>
						<span style="FONT-SIZE: 10.5pt; COLOR: black">boxDesc</span>
						<span style="FONT-SIZE: 10.5pt; COLOR: black">该描述器描述了该盒子的长、宽、高分别为0.5，初始化的位置以及该盒子的密度。</span>
				</div>
				<div style="MARGIN: 0cm 0cm 0pt 63pt; TEXT-INDENT: -21pt; LINE-HEIGHT: 150%">
						<span style="FONT-SIZE: 10.5pt; COLOR: black">③.<span style="FONT: 7pt 'Times New Roman'">    </span></span>
						<span style="FONT-SIZE: 10.5pt; COLOR: black">创建完所有的物体对象时，调用</span>
						<span style="FONT-SIZE: 10.5pt">UpdateTime()</span>
						<span style="FONT-SIZE: 10.5pt">得到从上一帧渲染到现在经过的时间</span>
				</div>
				<div style="MARGIN: 0cm 0cm 0pt 63pt; TEXT-INDENT: -21pt; LINE-HEIGHT: 150%">
						<span style="FONT-SIZE: 10.5pt; COLOR: black">④.<span style="FONT: 7pt 'Times New Roman'">    </span></span>
						<span style="FONT-SIZE: 10.5pt; COLOR: black">当创建的场景成功，利用函数</span>
						<span style="FONT-SIZE: 10.5pt; COLOR: black">StartPhysics()</span>
						<span style="FONT-SIZE: 10.5pt; COLOR: black">开始它的第一帧模拟。</span>
				</div>
				<div style="LINE-HEIGHT: 150%; TEXT-AUTOSPACE: ideograph-numeric">
						<span style="FONT-SIZE: 10.5pt; COLOR: black">            </span>
						<span style="FONT-SIZE: 10.5pt; COLOR: black">void StartPhysics()</span>
				</div>
				<div style="MARGIN: 0cm 0cm 0pt 36pt; TEXT-INDENT: 36pt; LINE-HEIGHT: 150%; TEXT-AUTOSPACE: ideograph-numeric">
						<span style="FONT-SIZE: 10.5pt; COLOR: black">{</span>
				</div>
				<div style="MARGIN: 0cm 0cm 0pt 36pt; TEXT-INDENT: 36pt; LINE-HEIGHT: 150%; TEXT-AUTOSPACE: ideograph-numeric">
						<span style="FONT-SIZE: 10.5pt; COLOR: black">    // Update the time step</span>
				</div>
				<div style="LINE-HEIGHT: 150%; TEXT-AUTOSPACE: ideograph-numeric">
						<span style="FONT-SIZE: 10.5pt; COLOR: black">   </span>
						<span style="FONT-SIZE: 10.5pt; COLOR: black">        </span>
						<span style="FONT-SIZE: 10.5pt; COLOR: black">NxReal deltaTime = UpdateTime();</span>
				</div>
				<div style="LINE-HEIGHT: 150%; TEXT-AUTOSPACE: ideograph-numeric"> </div>
				<div style="LINE-HEIGHT: 150%; TEXT-AUTOSPACE: ideograph-numeric">
						<span style="FONT-SIZE: 10.5pt; COLOR: black">    </span>
						<span style="FONT-SIZE: 10.5pt; COLOR: black">           </span>
						<span style="FONT-SIZE: 10.5pt; COLOR: black">// Start collision and dynamics for delta time since the last frame</span>
				</div>
				<div style="LINE-HEIGHT: 150%; TEXT-AUTOSPACE: ideograph-numeric">
						<span style="FONT-SIZE: 10.5pt; COLOR: black">    </span>
						<span style="FONT-SIZE: 10.5pt; COLOR: black">           </span>
						<span style="FONT-SIZE: 10.5pt; COLOR: black">gScene-&gt;simulate(deltaTime);</span>
				</div>
				<div style="LINE-HEIGHT: 150%; TEXT-AUTOSPACE: ideograph-numeric">
						<span style="FONT-SIZE: 10.5pt; COLOR: black">    </span>
						<span style="FONT-SIZE: 10.5pt; COLOR: black">           </span>
						<span style="FONT-SIZE: 10.5pt; COLOR: black">gScene-&gt;flushStream();</span>
				</div>
				<div style="MARGIN: 0cm 0cm 0pt 36pt; TEXT-INDENT: 36pt; LINE-HEIGHT: 150%; TEXT-AUTOSPACE: ideograph-numeric">
						<span style="FONT-SIZE: 10.5pt; COLOR: black">}</span>
				</div>
				<div style="MARGIN: 0cm 0cm 0pt 36pt; TEXT-INDENT: 36pt; LINE-HEIGHT: 150%; TEXT-AUTOSPACE: ideograph-numeric">
						<span style="FONT-SIZE: 10.5pt; COLOR: black">simulate(deltaTime)</span>
						<span style="FONT-SIZE: 10.5pt; COLOR: black">是PhysX 解决物理学的关键</span>
				</div>
				<div style="LINE-HEIGHT: 150%">
						<span style="FONT-SIZE: 10.5pt">              </span>
						<span style="FONT-SIZE: 10.5pt; COLOR: black">flushStream()</span>
						<span style="FONT-SIZE: 10.5pt">对时间步进行仿真</span>
				</div>
				<div style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: -21pt; LINE-HEIGHT: 150%">
						<span style="FONT-SIZE: 10.5pt">四．</span>
						<span style="FONT-SIZE: 10.5pt">glutMainLoop()</span>
				</div>
				<div style="LINE-HEIGHT: 150%">
						<span style="FONT-SIZE: 10.5pt">程序将一直停留在glutMainLoop()中，直到用户自己结束。当场景一旦被渲染后，</span>
						<span style="FONT-SIZE: 10.5pt">在</span>
						<span style="FONT-SIZE: 10.5pt">每次</span>
						<span style="FONT-SIZE: 10.5pt">设置下一场景时</span>
						<span style="FONT-SIZE: 10.5pt">，</span>
						<span style="FONT-SIZE: 10.5pt">RenderCallback()</span>
						<span style="FONT-SIZE: 10.5pt">回调函数</span>
						<span style="FONT-SIZE: 10.5pt">将</span>
						<span style="FONT-SIZE: 10.5pt">被调用</span>
				</div>
				<div style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: -21pt; LINE-HEIGHT: 150%">
						<span style="FONT-SIZE: 10.5pt">五．</span>
						<span style="FONT-SIZE: 10.5pt">ReleaseNx()</span>
				</div>
				<div style="LINE-HEIGHT: 150%; TEXT-AUTOSPACE: ideograph-numeric">
						<span style="FONT-SIZE: 10.5pt">    <span style="COLOR: black">删除场景中所有的物体对象以及场景本身</span></span>
				</div>
				<div style="LINE-HEIGHT: 150%"> </div>
		</div>
<img src ="http://www.cppblog.com/mybios/aggbug/15327.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/mybios/" target="_blank">李锦俊(mybios)</a> 2006-11-18 08:53 <a href="http://www.cppblog.com/mybios/archive/2006/11/18/15327.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>