﻿<?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;</title><link>http://www.cppblog.com/mybios/</link><description>游戏开发 C++ Cocos2d-x OpenGL DirectX 数学 计算机图形学 SQL Server
&lt;BR&gt;
&lt;BR&gt;</description><language>zh-cn</language><lastBuildDate>Fri, 13 Mar 2026 01:15:08 GMT</lastBuildDate><pubDate>Fri, 13 Mar 2026 01:15:08 GMT</pubDate><ttl>60</ttl><item><title>cocos2d-x脚本引擎（JavaScript、Lua等等）的大统一（方案概述）</title><link>http://www.cppblog.com/mybios/archive/2015/11/20/212299.html</link><dc:creator>李锦俊(mybios)</dc:creator><author>李锦俊(mybios)</author><pubDate>Fri, 20 Nov 2015 07:03:00 GMT</pubDate><guid>http://www.cppblog.com/mybios/archive/2015/11/20/212299.html</guid><wfw:comment>http://www.cppblog.com/mybios/comments/212299.html</wfw:comment><comments>http://www.cppblog.com/mybios/archive/2015/11/20/212299.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.cppblog.com/mybios/comments/commentRss/212299.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mybios/services/trackbacks/212299.html</trackback:ping><description><![CDATA[<div><span style="font-family: 微软雅黑; widows: auto; background-color: #ffffff;">&nbsp; &nbsp; cocos2d-x支持多种脚本引擎的绑定，例如支持lua（通过lua或luajit）、javascript（通过SpiderMonkey脚本引擎），分别对应libluacocos2d和libjscocos2d两个工程，每个工程里分别对应大量的自动绑定和手动绑定代码。如果需要增加一些引擎功能需要绑定到脚本的话，两个工程都需要修改代码，非常不便于维护。假如希望使用其他脚本引擎的话（例如google红红火火的V8，或者ms的chakra），那得多开几个工程，每个工程都需要实现几乎一样，但是又不一样的代码。现在我提出一种思想，来解决这类问题。</span></div><div style="font-family: 微软雅黑; widows: auto; background-color: #ffffff;"></div><div style="font-family: 微软雅黑; widows: auto; background-color: #ffffff;">&nbsp; &nbsp; 现有的脚本引擎多如牛毛，而不同企业间可能有不同的技术积累，希望选择不一样的脚本引擎，有的python蟒蛇派，有的是lua派，有的是ruby派，还有JavaScript、lua等等等等，所以，JavaScript和Lua不应该成为二选一。</div><div style="font-family: 微软雅黑; widows: auto; background-color: #ffffff;">而这些脚本引擎之间，有很多的共同点，例如都是弱类型语言，都是支持那么几种简单类型，都是使用GC机制来回收等等。</div><div style="font-family: 微软雅黑; widows: auto; background-color: #ffffff;">脚本引擎统一化，是把多个脚本引擎（lua、JavaScriptCore、chakra、v8、spidermonkey等等）通过同一套抽象接口进行封装，引擎的脚本绑定代码都通过抽象接口来编写。通过选择编译不同的实现层来实现脚本引擎间的切换，而不是每个脚本引擎都要写不一样的脚本绑定代码，这样能大大简化脚本绑定层的维护成本，并能保证所有脚本引擎的接口的绝对一致性，并让用户轻松选择使用哪个脚本引擎，而不限定于必须使用官方选择的引擎。</div><div style="font-family: 微软雅黑; widows: auto; background-color: #ffffff;"></div><div style="font-family: 微软雅黑; widows: auto; background-color: #ffffff;">&nbsp; &nbsp; 脚本引擎抽象层API的定义非常关键，概括起来我认为他必须符合以下要求：</div><div style="font-family: 微软雅黑; widows: auto; background-color: #ffffff;">1、<span style="background-color: inherit; line-height: 1.5;">抽象层的接口必须在各个脚本引擎之间都可以实现，例如：&#8220;创建字符串&#8221;这个接口，是任意脚本引擎都能实现。</span></div><div style="font-family: 微软雅黑; widows: auto; background-color: #ffffff;"><span style="background-color: inherit; line-height: 1.5;">2、</span><span style="background-color: inherit; line-height: 1.5;">抽象层在绑定脚本的过程中是足够用的，例如：我们需要导出一个C++的类，还需要导出类里的函数，还有特殊的结构体，甚至包含lambda表达式，这些都需要考虑进去抽象层定义的需求里。</span></div><div style="font-family: 微软雅黑; widows: auto; background-color: #ffffff;"><span style="background-color: inherit; line-height: 1.5;">3、抽象层还必须足够的薄，薄到运行时根本感觉不到他的存在。需要使用&#8220;宏&#8221;或者inline函数的方式来给这个抽象层减肥，坚决不使用C++类的方式来加厚他。</span></div><div style="font-family: 微软雅黑; widows: auto; background-color: #ffffff;"><span style="background-color: inherit; line-height: 1.5;">4、抽象层在使用的过程中必须足够简单，简单到就好像是一个单独的脚本引擎API一样，这些API看上去是大统一的，并且是脚本语言无关的。</span></div><div style="font-family: 微软雅黑; widows: auto; background-color: #ffffff;"></div><div style="font-family: 微软雅黑; widows: auto; background-color: #ffffff;">&nbsp; &nbsp; 在定义抽象层的过程中，我参考了很多别人的方案，最终，我使用&nbsp;了这么个方案：</div><div style="font-family: 微软雅黑; widows: auto; background-color: #ffffff;">1、使用C inline函数来定义API接口函数的声明，各个引擎的实现部分分别实现这些函数</div><div style="font-family: 微软雅黑; widows: auto; background-color: #ffffff;">2、定义一些基本类型，基本类型有各个脚本引擎来最终定义，但名字和意义都是统一的，初步定义了这些类型，每个类型在不同脚本引擎中对应的类型分别如下表：</div><div style="font-family: 微软雅黑; widows: auto; background-color: #ffffff;"><table border="1" cellpadding="2" cellspacing="0" style="font-size: inherit; border-collapse: collapse; margin-top: 10px; margin-bottom: 10px; width: 919px; background-color: inherit;"><tbody style="background-color: inherit;"><tr style="background-color: inherit;"><td valign="top" style="word-break: break-all; border-style: solid; border-color: #999999; padding: 5px 16px 5px 12px; min-height: 25px; min-width: 25px; height: 38px; width: 123px; background-color: inherit;">统一类型</td><td valign="top" style="word-break: break-all; border-style: solid; border-color: #999999; padding: 5px 16px 5px 12px; min-height: 25px; min-width: 25px; height: 38px; width: 123px; background-color: inherit;"><div style="min-width: 2px; background-color: inherit;">描述</div></td><td valign="top" style="word-break: break-all; border-style: solid; border-color: #999999; padding: 5px 16px 5px 12px; min-height: 25px; min-width: 25px; height: 38px; width: 122px; background-color: inherit;"><div style="min-width: 2px; background-color: inherit;">Lua</div></td><td valign="top" style="word-break: break-all; border-style: solid; border-color: #999999; padding: 5px 16px 5px 12px; min-height: 25px; min-width: 25px; height: 38px; width: 128px; background-color: inherit;"><div style="min-width: 2px; background-color: inherit;">JavaScript</div></td><td valign="top" style="word-break: break-all; border-style: solid; border-color: #999999; padding: 5px 16px 5px 12px; min-height: 25px; min-width: 25px; height: 38px; width: 128px; background-color: inherit;"><div style="min-width: 2px; background-color: inherit;">JavaScriptCore</div></td><td valign="top" style="word-break: break-all; border-style: solid; border-color: #999999; padding: 5px 16px 5px 12px; min-height: 25px; min-width: 25px; height: 38px; width: 193px; background-color: inherit;"><div style="min-width: 2px; background-color: inherit;">V8</div></td><td valign="top" style="word-break: break-all; border-style: solid; border-color: #999999; padding: 5px 16px 5px 12px; min-height: 25px; min-width: 25px; height: 38px; width: 104px; background-color: inherit;"><div style="min-width: 2px; background-color: inherit;">chakra</div></td></tr><tr style="background-color: inherit;"><td valign="top" style="word-break: break-all; border-style: solid; border-color: #999999; padding: 5px 16px 5px 12px; min-height: 25px; min-width: 25px; height: 78px; width: 123px; background-color: inherit;"><div style="min-width: 2px; background-color: inherit;">USValue</div></td><td valign="top" style="word-break: break-all; border-style: solid; border-color: #999999; padding: 5px 16px 5px 12px; min-height: 25px; min-width: 25px; height: 78px; width: 123px; background-color: inherit;"><div style="min-width: 2px; background-color: inherit;">表示脚本中的任意类型</div></td><td valign="top" style="word-break: break-all; border-style: solid; border-color: #999999; padding: 5px 16px 5px 12px; min-height: 25px; min-width: 25px; height: 78px; width: 122px; background-color: inherit;">任意类型<br style="background-color: inherit;" /><br style="background-color: inherit;" /></td><td valign="top" style="word-break: break-all; border-style: solid; border-color: #999999; padding: 5px 16px 5px 12px; min-height: 25px; min-width: 25px; height: 78px; width: 128px; background-color: inherit;"><div style="min-width: 2px; background-color: inherit;">Object</div></td><td valign="top" style="word-break: break-all; border-style: solid; border-color: #999999; padding: 5px 16px 5px 12px; min-height: 25px; min-width: 25px; height: 78px; width: 128px; background-color: inherit;"><div style="min-width: 2px; background-color: inherit;">JSValueRef</div></td><td valign="top" style="word-break: break-all; border-style: solid; border-color: #999999; padding: 5px 16px 5px 12px; min-height: 25px; min-width: 25px; height: 78px; width: 193px; background-color: inherit;"><div style="min-width: 2px; background-color: inherit;">v8::Local&lt;v8::Value&gt;</div><div style="min-width: 2px; background-color: inherit;"></div></td><td valign="top" style="word-break: break-all; border-style: solid; border-color: #999999; padding: 5px 16px 5px 12px; min-height: 25px; min-width: 25px; height: 78px; width: 104px; background-color: inherit;"><div style="min-width: 2px; background-color: inherit;">JsValueRef</div></td></tr><tr style="background-color: inherit;"><td valign="top" style="word-break: break-all; border-style: solid; border-color: #999999; padding: 5px 16px 5px 12px; min-height: 25px; min-width: 25px; height: 34px; width: 123px; background-color: inherit;"><div style="min-width: 2px; background-color: inherit;">USObject</div></td><td valign="top" style="word-break: break-all; border-style: solid; border-color: #999999; padding: 5px 16px 5px 12px; min-height: 25px; min-width: 25px; height: 34px; width: 123px; background-color: inherit;"><div style="min-width: 2px; background-color: inherit;">脚本对象，对象可以由key、value组成，可以拥有继承结构</div></td><td valign="top" style="word-break: break-all; border-style: solid; border-color: #999999; padding: 5px 16px 5px 12px; min-height: 25px; min-width: 25px; height: 34px; width: 122px; background-color: inherit;"><div style="min-width: 2px; background-color: inherit;">table</div></td><td valign="top" style="word-break: break-all; border-style: solid; border-color: #999999; padding: 5px 16px 5px 12px; min-height: 25px; min-width: 25px; height: 34px; width: 128px; background-color: inherit;"><div style="min-width: 2px; background-color: inherit;">Object</div></td><td valign="top" style="word-break: break-all; border-style: solid; border-color: #999999; padding: 5px 16px 5px 12px; min-height: 25px; min-width: 25px; height: 34px; width: 128px; background-color: inherit;"><div style="min-width: 2px; background-color: inherit;">JSObjectRef</div></td><td valign="top" style="word-break: break-all; border-style: solid; border-color: #999999; padding: 5px 16px 5px 12px; min-height: 25px; min-width: 25px; height: 34px; width: 193px; background-color: inherit;"><div style="min-width: 2px; background-color: inherit;">v8::Local&lt;v8::Object&gt;</div></td><td valign="top" style="word-break: break-all; border-style: solid; border-color: #999999; padding: 5px 16px 5px 12px; min-height: 25px; min-width: 25px; height: 34px; width: 104px; background-color: inherit;"><div style="min-width: 2px; background-color: inherit;">JsValueRef</div></td></tr><tr style="background-color: inherit;"><td valign="top" style="word-break: break-all; border-style: solid; border-color: #999999; padding: 5px 16px 5px 12px; min-height: 25px; min-width: 25px; height: 32px; width: 123px; background-color: inherit;"><div style="min-width: 2px; background-color: inherit;">USFunction</div></td><td valign="top" style="word-break: break-all; border-style: solid; border-color: #999999; padding: 5px 16px 5px 12px; min-height: 25px; min-width: 25px; height: 32px; width: 123px; background-color: inherit;"><div style="min-width: 2px; background-color: inherit;">脚本函数</div></td><td valign="top" style="word-break: break-all; border-style: solid; border-color: #999999; padding: 5px 16px 5px 12px; min-height: 25px; min-width: 25px; height: 32px; width: 122px; background-color: inherit;"><div style="min-width: 2px; background-color: inherit;">function</div></td><td valign="top" style="word-break: break-all; border-style: solid; border-color: #999999; padding: 5px 16px 5px 12px; min-height: 25px; min-width: 25px; height: 32px; width: 128px; background-color: inherit;"><div style="min-width: 2px; background-color: inherit;">Function</div></td><td valign="top" style="word-break: break-all; border-style: solid; border-color: #999999; padding: 5px 16px 5px 12px; min-height: 25px; min-width: 25px; height: 32px; width: 128px; background-color: inherit;"><div style="min-width: 2px; background-color: inherit;">JSObjectRef</div></td><td valign="top" style="word-break: break-all; border-style: solid; border-color: #999999; padding: 5px 16px 5px 12px; min-height: 25px; min-width: 25px; height: 32px; width: 193px; background-color: inherit;"><div style="min-width: 2px; background-color: inherit;">v8::Local&lt;v8::Function&gt;</div></td><td valign="top" style="word-break: break-all; border-style: solid; border-color: #999999; padding: 5px 16px 5px 12px; min-height: 25px; min-width: 25px; height: 32px; width: 104px; background-color: inherit;"><div style="min-width: 2px; background-color: inherit;">JsValueRef</div></td></tr><tr style="background-color: inherit;"><td valign="top" style="word-break: break-all; border-style: solid; border-color: #999999; padding: 5px 16px 5px 12px; min-height: 25px; min-width: 25px; height: 34px; width: 123px; background-color: inherit;"><div style="min-width: 2px; background-color: inherit;">USArray</div></td><td valign="top" style="word-break: break-all; border-style: solid; border-color: #999999; padding: 5px 16px 5px 12px; min-height: 25px; min-width: 25px; height: 34px; width: 123px; background-color: inherit;"><div style="min-width: 2px; background-color: inherit;">数组类型，下标从0开始</div></td><td valign="top" style="word-break: break-all; border-style: solid; border-color: #999999; padding: 5px 16px 5px 12px; min-height: 25px; min-width: 25px; height: 34px; width: 122px; background-color: inherit;"><div style="min-width: 2px; background-color: inherit;">table</div></td><td valign="top" style="word-break: break-all; border-style: solid; border-color: #999999; padding: 5px 16px 5px 12px; min-height: 25px; min-width: 25px; height: 34px; width: 128px; background-color: inherit;"><div style="min-width: 2px; background-color: inherit;">Array</div></td><td valign="top" style="word-break: break-all; border-style: solid; border-color: #999999; padding: 5px 16px 5px 12px; min-height: 25px; min-width: 25px; height: 34px; width: 128px; background-color: inherit;"><div style="min-width: 2px; background-color: inherit;">JSObjectRef</div></td><td valign="top" style="word-break: break-all; border-style: solid; border-color: #999999; padding: 5px 16px 5px 12px; min-height: 25px; min-width: 25px; height: 34px; width: 193px; background-color: inherit;"><div style="min-width: 2px; background-color: inherit;">v8::Local&lt;v8::Array&gt;</div></td><td valign="top" style="word-break: break-all; border-style: solid; border-color: #999999; padding: 5px 16px 5px 12px; min-height: 25px; min-width: 25px; height: 34px; width: 104px; background-color: inherit;"><div style="min-width: 2px; background-color: inherit;">JsValueRef</div></td></tr><tr style="background-color: inherit;"><td valign="top" style="word-break: break-all; border-style: solid; border-color: #999999; padding: 5px 16px 5px 12px; min-height: 25px; min-width: 25px; height: 34px; width: 123px; background-color: inherit;"><div style="min-width: 2px; background-color: inherit;">USMap</div></td><td valign="top" style="word-break: break-all; border-style: solid; border-color: #999999; padding: 5px 16px 5px 12px; min-height: 25px; min-width: 25px; height: 34px; width: 123px; background-color: inherit;"><div style="min-width: 2px; background-color: inherit;">键-值配对的map类型</div></td><td valign="top" style="word-break: break-all; border-style: solid; border-color: #999999; padding: 5px 16px 5px 12px; min-height: 25px; min-width: 25px; height: 34px; width: 122px; background-color: inherit;"><div style="min-width: 2px; background-color: inherit;">table</div></td><td valign="top" style="word-break: break-all; border-style: solid; border-color: #999999; padding: 5px 16px 5px 12px; min-height: 25px; min-width: 25px; height: 34px; width: 128px; background-color: inherit;"><div style="min-width: 2px; background-color: inherit;">Map</div></td><td valign="top" style="word-break: break-all; border-style: solid; border-color: #999999; padding: 5px 16px 5px 12px; min-height: 25px; min-width: 25px; height: 34px; width: 128px; background-color: inherit;"><div style="min-width: 2px; background-color: inherit;">JSObjectRef</div></td><td valign="top" style="word-break: break-all; border-style: solid; border-color: #999999; padding: 5px 16px 5px 12px; min-height: 25px; min-width: 25px; height: 34px; width: 193px; background-color: inherit;"><div style="min-width: 2px; background-color: inherit;">v8::Local&lt;v8::Object&gt;</div></td><td valign="top" style="word-break: break-all; border-style: solid; border-color: #999999; padding: 5px 16px 5px 12px; min-height: 25px; min-width: 25px; height: 34px; width: 104px; background-color: inherit;"><div style="min-width: 2px; background-color: inherit;">JsValueRef</div></td></tr><tr style="background-color: inherit;"><td valign="top" style="word-break: break-all; border-style: solid; border-color: #999999; padding: 5px 16px 5px 12px; min-height: 25px; min-width: 25px; height: 35px; width: 123px; background-color: inherit;"><div style="min-width: 2px; background-color: inherit;">USSet</div></td><td valign="top" style="word-break: break-all; border-style: solid; border-color: #999999; padding: 5px 16px 5px 12px; min-height: 25px; min-width: 25px; height: 35px; width: 123px; background-color: inherit;"><div style="min-width: 2px; background-color: inherit;">值作为键也作为值得列表，值不能重复</div></td><td valign="top" style="word-break: break-all; border-style: solid; border-color: #999999; padding: 5px 16px 5px 12px; min-height: 25px; min-width: 25px; height: 35px; width: 122px; background-color: inherit;"><div style="min-width: 2px; background-color: inherit;">table</div></td><td valign="top" style="word-break: break-all; border-style: solid; border-color: #999999; padding: 5px 16px 5px 12px; min-height: 25px; min-width: 25px; height: 35px; width: 128px; background-color: inherit;"><div style="min-width: 2px; background-color: inherit;">Set</div></td><td valign="top" style="word-break: break-all; border-style: solid; border-color: #999999; padding: 5px 16px 5px 12px; min-height: 25px; min-width: 25px; height: 35px; width: 128px; background-color: inherit;"><div style="min-width: 2px; background-color: inherit;">JSObjectRef</div></td><td valign="top" style="word-break: break-all; border-style: solid; border-color: #999999; padding: 5px 16px 5px 12px; min-height: 25px; min-width: 25px; height: 35px; width: 193px; background-color: inherit;"><div style="min-width: 2px; background-color: inherit;">v8::Local&lt;v8::Object&gt;</div></td><td valign="top" style="word-break: break-all; border-style: solid; border-color: #999999; padding: 5px 16px 5px 12px; min-height: 25px; min-width: 25px; height: 35px; width: 104px; background-color: inherit;"><div style="min-width: 2px; background-color: inherit;">JsValueRef</div></td></tr><tr style="background-color: inherit;"><td valign="top" style="word-break: break-all; border-style: solid; border-color: #999999; padding: 5px 16px 5px 12px; min-height: 25px; min-width: 25px; height: 46px; width: 123px; background-color: inherit;"><div style="min-width: 2px; background-color: inherit;">USNumber</div></td><td valign="top" style="word-break: break-all; border-style: solid; border-color: #999999; padding: 5px 16px 5px 12px; min-height: 25px; min-width: 25px; height: 46px; width: 123px; background-color: inherit;"><div style="min-width: 2px; background-color: inherit;">数值类型</div></td><td valign="top" style="word-break: break-all; border-style: solid; border-color: #999999; padding: 5px 16px 5px 12px; min-height: 25px; min-width: 25px; height: 46px; width: 122px; background-color: inherit;"><div style="min-width: 2px; background-color: inherit;">number</div></td><td valign="top" style="word-break: break-all; border-style: solid; border-color: #999999; padding: 5px 16px 5px 12px; min-height: 25px; min-width: 25px; height: 46px; width: 128px; background-color: inherit;"><div style="min-width: 2px; background-color: inherit;">Number</div></td><td valign="top" style="word-break: break-all; border-style: solid; border-color: #999999; padding: 5px 16px 5px 12px; min-height: 25px; min-width: 25px; height: 46px; width: 128px; background-color: inherit;"><div style="min-width: 2px; background-color: inherit;">JSValueRef</div></td><td valign="top" style="word-break: break-all; border-style: solid; border-color: #999999; padding: 5px 16px 5px 12px; min-height: 25px; min-width: 25px; height: 46px; width: 193px; background-color: inherit;"><div style="min-width: 2px; background-color: inherit;">v8::Local&lt;v8::Number&gt;</div></td><td valign="top" style="word-break: break-all; border-style: solid; border-color: #999999; padding: 5px 16px 5px 12px; min-height: 25px; min-width: 25px; height: 46px; width: 104px; background-color: inherit;"><div style="min-width: 2px; background-color: inherit;">JsValueRef</div></td></tr><tr style="background-color: inherit;"><td valign="top" style="word-break: break-all; border-style: solid; border-color: #999999; padding: 5px 16px 5px 12px; min-height: 25px; min-width: 25px; height: 35px; width: 123px; background-color: inherit;"><div style="min-width: 2px; background-color: inherit;">USBoolean</div></td><td valign="top" style="word-break: break-all; border-style: solid; border-color: #999999; padding: 5px 16px 5px 12px; min-height: 25px; min-width: 25px; height: 35px; width: 123px; background-color: inherit;"><div style="min-width: 2px; background-color: inherit;">bool类型</div></td><td valign="top" style="word-break: break-all; border-style: solid; border-color: #999999; padding: 5px 16px 5px 12px; min-height: 25px; min-width: 25px; height: 35px; width: 122px; background-color: inherit;"><div style="min-width: 2px; background-color: inherit;">boolean</div></td><td valign="top" style="word-break: break-all; border-style: solid; border-color: #999999; padding: 5px 16px 5px 12px; min-height: 25px; min-width: 25px; height: 35px; width: 128px; background-color: inherit;"><div style="min-width: 2px; background-color: inherit;">Boolean</div></td><td valign="top" style="word-break: break-all; border-style: solid; border-color: #999999; padding: 5px 16px 5px 12px; min-height: 25px; min-width: 25px; height: 35px; width: 128px; background-color: inherit;"><div style="min-width: 2px; background-color: inherit;">JSValueRef</div></td><td valign="top" style="word-break: break-all; border-style: solid; border-color: #999999; padding: 5px 16px 5px 12px; min-height: 25px; min-width: 25px; height: 35px; width: 193px; background-color: inherit;"><div style="min-width: 2px; background-color: inherit;">v8::Local&lt;v8::Boolean&gt;</div></td><td valign="top" style="word-break: break-all; border-style: solid; border-color: #999999; padding: 5px 16px 5px 12px; min-height: 25px; min-width: 25px; height: 35px; width: 104px; background-color: inherit;"><div style="min-width: 2px; background-color: inherit;">JsValueRef</div></td></tr><tr style="background-color: inherit;"><td valign="top" style="word-break: break-all; border-style: solid; border-color: #999999; padding: 5px 16px 5px 12px; min-height: 25px; min-width: 25px; height: 33px; width: 123px; background-color: inherit;"><div style="min-width: 2px; background-color: inherit;">USString</div></td><td valign="top" style="word-break: break-all; border-style: solid; border-color: #999999; padding: 5px 16px 5px 12px; min-height: 25px; min-width: 25px; height: 33px; width: 123px; background-color: inherit;"><div style="min-width: 2px; background-color: inherit;">字符串类型</div></td><td valign="top" style="word-break: break-all; border-style: solid; border-color: #999999; padding: 5px 16px 5px 12px; min-height: 25px; min-width: 25px; height: 33px; width: 122px; background-color: inherit;"><div style="min-width: 2px; background-color: inherit;">string</div></td><td valign="top" style="word-break: break-all; border-style: solid; border-color: #999999; padding: 5px 16px 5px 12px; min-height: 25px; min-width: 25px; height: 33px; width: 128px; background-color: inherit;"><div style="min-width: 2px; background-color: inherit;">String</div></td><td valign="top" style="word-break: break-all; border-style: solid; border-color: #999999; padding: 5px 16px 5px 12px; min-height: 25px; min-width: 25px; height: 33px; width: 128px; background-color: inherit;"><div style="min-width: 2px; background-color: inherit;">JSValueRef</div></td><td valign="top" style="word-break: break-all; border-style: solid; border-color: #999999; padding: 5px 16px 5px 12px; min-height: 25px; min-width: 25px; height: 33px; width: 193px; background-color: inherit;"><div style="min-width: 2px; background-color: inherit;">v8::Local&lt;v8::String&gt;</div></td><td valign="top" style="word-break: break-all; border-style: solid; border-color: #999999; padding: 5px 16px 5px 12px; min-height: 25px; min-width: 25px; height: 33px; width: 104px; background-color: inherit;"><div style="min-width: 2px; background-color: inherit;">JsValueRef</div></td></tr><tr style="background-color: inherit;"><td valign="top" style="word-break: break-all; border-style: solid; border-color: #999999; padding: 5px 16px 5px 12px; min-height: 25px; min-width: 25px; height: 34px; width: 123px; background-color: inherit;"><div style="min-width: 2px; background-color: inherit;">USBuffer</div></td><td valign="top" style="word-break: break-all; border-style: solid; border-color: #999999; padding: 5px 16px 5px 12px; min-height: 25px; min-width: 25px; height: 34px; width: 123px; background-color: inherit;"><div style="min-width: 2px; background-color: inherit;">内存块缓存对象</div></td><td valign="top" style="word-break: break-all; border-style: solid; border-color: #999999; padding: 5px 16px 5px 12px; min-height: 25px; min-width: 25px; height: 34px; width: 122px; background-color: inherit;"><div style="min-width: 2px; background-color: inherit;">string</div></td><td valign="top" style="word-break: break-all; border-style: solid; border-color: #999999; padding: 5px 16px 5px 12px; min-height: 25px; min-width: 25px; height: 34px; width: 128px; background-color: inherit;"><div style="min-width: 2px; background-color: inherit;">Int8Array</div></td><td valign="top" style="word-break: break-all; border-style: solid; border-color: #999999; padding: 5px 16px 5px 12px; min-height: 25px; min-width: 25px; height: 34px; width: 128px; background-color: inherit;"><div style="min-width: 2px; background-color: inherit;">JSValueRef</div></td><td valign="top" style="word-break: break-all; border-style: solid; border-color: #999999; padding: 5px 16px 5px 12px; min-height: 25px; min-width: 25px; height: 34px; width: 193px; background-color: inherit;"><div style="min-width: 2px; background-color: inherit;">v8::Local&lt;v8::Int8Array&gt;</div></td><td valign="top" style="word-break: break-all; border-style: solid; border-color: #999999; padding: 5px 16px 5px 12px; min-height: 25px; min-width: 25px; height: 34px; width: 104px; background-color: inherit;"><div style="min-width: 2px; background-color: inherit;">JsValueRef</div></td></tr><tr style="background-color: inherit;"><td valign="top" style="word-break: break-all; border-style: solid; border-color: #999999; padding: 5px 16px 5px 12px; min-height: 25px; min-width: 25px; height: 34px; width: 123px; background-color: inherit;"><div style="min-width: 2px; background-color: inherit;">USConstructor</div></td><td valign="top" style="word-break: break-all; border-style: solid; border-color: #999999; padding: 5px 16px 5px 12px; min-height: 25px; min-width: 25px; height: 34px; width: 123px; background-color: inherit;"><div style="min-width: 2px; background-color: inherit;">对象实例的构造器，用来导出C++类</div></td><td valign="top" style="word-break: break-all; border-style: solid; border-color: #999999; padding: 5px 16px 5px 12px; min-height: 25px; min-width: 25px; height: 34px; width: 122px; background-color: inherit;"><div style="min-width: 2px; background-color: inherit;">table</div></td><td valign="top" style="word-break: break-all; border-style: solid; border-color: #999999; padding: 5px 16px 5px 12px; min-height: 25px; min-width: 25px; height: 34px; width: 128px; background-color: inherit;"><div style="min-width: 2px; background-color: inherit;">Object</div></td><td valign="top" style="word-break: break-all; border-style: solid; border-color: #999999; padding: 5px 16px 5px 12px; min-height: 25px; min-width: 25px; height: 34px; width: 128px; background-color: inherit;"><div style="min-width: 2px; background-color: inherit;">JSValueRef</div></td><td valign="top" style="word-break: break-all; border-style: solid; border-color: #999999; padding: 5px 16px 5px 12px; min-height: 25px; min-width: 25px; height: 34px; width: 193px; background-color: inherit;"><div style="min-width: 2px; background-color: inherit;">v8::Local&lt;v8::Object&gt;</div></td><td valign="top" style="word-break: break-all; border-style: solid; border-color: #999999; padding: 5px 16px 5px 12px; min-height: 25px; min-width: 25px; height: 34px; width: 104px; background-color: inherit;"><div style="min-width: 2px; background-color: inherit;">JsValueRef</div></td></tr></tbody></table>3、定义一批API，用以对以上定义的基本类型进行创建、调用、修改等操作，例如创建的过程API定义成这种形式：<br /><br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #008080; ">&nbsp;1</span>&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;创建Null值</span><span style="color: #008000; "><br /></span><span style="color: #008080; ">&nbsp;2</span>&nbsp;<span style="color: #008000; "></span>&nbsp;&nbsp;&nbsp;&nbsp;inline&nbsp;USValue&nbsp;createUSNull();<br /><span style="color: #008080; ">&nbsp;3</span>&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;创建Undefined值</span><span style="color: #008000; "><br /></span><span style="color: #008080; ">&nbsp;4</span>&nbsp;<span style="color: #008000; "></span>&nbsp;&nbsp;&nbsp;&nbsp;inline&nbsp;USValue&nbsp;createUSUndefined();<br /><span style="color: #008080; ">&nbsp;5</span>&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;创建普通的对象</span><span style="color: #008000; "><br /></span><span style="color: #008080; ">&nbsp;6</span>&nbsp;<span style="color: #008000; "></span>&nbsp;&nbsp;&nbsp;&nbsp;inline&nbsp;USObject&nbsp;createUSObject();<br /><span style="color: #008080; ">&nbsp;7</span>&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;创建数组</span><span style="color: #008000; "><br /></span><span style="color: #008080; ">&nbsp;8</span>&nbsp;<span style="color: #008000; "></span>&nbsp;&nbsp;&nbsp;&nbsp;inline&nbsp;USArray&nbsp;createUSArray(<span style="color: #0000FF; ">int</span>&nbsp;length&nbsp;=&nbsp;0);<br /><span style="color: #008080; ">&nbsp;9</span>&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;创建Map</span><span style="color: #008000; "><br /></span><span style="color: #008080; ">10</span>&nbsp;<span style="color: #008000; "></span>&nbsp;&nbsp;&nbsp;&nbsp;inline&nbsp;USMap&nbsp;createUSMap();<br /><span style="color: #008080; ">11</span>&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;创建Set</span><span style="color: #008000; "><br /></span><span style="color: #008080; ">12</span>&nbsp;<span style="color: #008000; "></span>&nbsp;&nbsp;&nbsp;&nbsp;inline&nbsp;USSet&nbsp;createUSSet();<br /><span style="color: #008080; ">13</span>&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;创建字符串</span><span style="color: #008000; "><br /></span><span style="color: #008080; ">14</span>&nbsp;<span style="color: #008000; "></span>&nbsp;&nbsp;&nbsp;&nbsp;inline&nbsp;USString&nbsp;createUSString(<span style="color: #0000FF; ">const</span>&nbsp;<span style="color: #0000FF; ">char</span>&nbsp;*str,&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;length&nbsp;=&nbsp;-1);<br /><span style="color: #008080; ">15</span>&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;创建Buffer，将会拷贝数据到Buffer中，脚本引擎负责销毁</span><span style="color: #008000; "><br /></span><span style="color: #008080; ">16</span>&nbsp;<span style="color: #008000; "></span>&nbsp;&nbsp;&nbsp;&nbsp;inline&nbsp;USBuffer&nbsp;createUSBuffer(<span style="color: #0000FF; ">const</span>&nbsp;<span style="color: #0000FF; ">char</span>&nbsp;*buffer,&nbsp;size_t&nbsp;size);<br /><span style="color: #008080; ">17</span>&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;创建一个脚本函数，函数调用时会回调到callback，并带上data</span><span style="color: #008000; "><br /></span><span style="color: #008080; ">18</span>&nbsp;<span style="color: #008000; "></span>&nbsp;&nbsp;&nbsp;&nbsp;USFunction&nbsp;createUSFunction(USFunctionCallback&nbsp;callback,&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;*data&nbsp;=&nbsp;nullptr,&nbsp;<span style="color: #0000FF; ">const</span>&nbsp;<span style="color: #0000FF; ">char</span>&nbsp;*name&nbsp;=&nbsp;nullptr);<br /><span style="color: #008080; ">19</span>&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;创建数字</span><span style="color: #008000; "><br /></span><span style="color: #008080; ">20</span>&nbsp;<span style="color: #008000; "></span>&nbsp;&nbsp;&nbsp;&nbsp;inline&nbsp;USNumber&nbsp;createUSNumber(<span style="color: #0000FF; ">double</span>&nbsp;number);<br /><span style="color: #008080; ">21</span>&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;创建bool</span><span style="color: #008000; "><br /></span><span style="color: #008080; ">22</span>&nbsp;<span style="color: #008000; "></span>&nbsp;&nbsp;&nbsp;&nbsp;inline&nbsp;USBoolean&nbsp;createUSBoolean(<span style="color: #0000FF; ">bool</span>&nbsp;value);<br /><span style="color: #008080; ">23</span>&nbsp;<br /><span style="color: #008080; ">24</span>&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;创建对象构造器</span><span style="color: #008000; "><br /></span><span style="color: #008080; ">25</span>&nbsp;<span style="color: #008000; "></span>&nbsp;&nbsp;&nbsp;&nbsp;USConstructor&nbsp;USClassCreateConstructor(<span style="color: #0000FF; ">const</span>&nbsp;USClass&nbsp;&amp;cls);</div></div><div style="font-family: 微软雅黑; widows: auto; background-color: #ffffff;">&nbsp;</div><div style="font-family: 微软雅黑; widows: auto; background-color: #ffffff;">抽象层定义好后，需要经过大量的努力，才能在各个脚本引擎间的最终实现。当最终实现完毕后，就可以下一步工作：</div><div style="font-family: 微软雅黑; widows: auto; background-color: #ffffff;">1、把cocos2d-x对于自动绑定代码的template类进行修改，修改成使用统一脚本引擎的API</div><div style="font-family: 微软雅黑; widows: auto; background-color: #ffffff;">2、把cocos2d-x对于手动绑定的代码如法炮制</div><div style="font-family: 微软雅黑; widows: auto; background-color: #ffffff;">3、使用不同的引擎实现来编译</div><div style="font-family: 微软雅黑; widows: auto; background-color: #ffffff;"></div><div style="font-family: 微软雅黑; widows: auto; background-color: #ffffff;">经过这样如法炮制之后，最终cocos2d-x只剩下一套脚本绑定的工程，而通过选择不同的底层脚本引擎，却可以编译出完全不一样的脚本引擎版本。</div><div style="font-family: 微软雅黑; widows: auto; background-color: #ffffff;">经过cocos2d-x github社区的努力，最终应该会出现不同的fork，如python、ruby等等各种语言出现各种绑定版本，而这种绑定版本的出现，只需实现抽象层API的基本API即可。</div><div style="font-family: 微软雅黑; widows: auto; background-color: #ffffff;">至此cocos2d-x的脚本引擎统一即可完成大业。</div><div style="font-family: 微软雅黑; widows: auto; background-color: #ffffff;">但，事情还没完，我在下一篇中，将会讲到抽象API的详细定义，敬请期待下一篇。<br /><br /><br /><p style="box-sizing: border-box; margin-top: 10px; margin-bottom: 10px; line-height: 24px; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px;">如果本文对你的开发有所帮助，并且你手头恰好有零钱。</p><p style="box-sizing: border-box; margin-top: 10px; margin-bottom: 10px; 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 /><br /></p></div><div style="font-family: 微软雅黑; widows: auto; background-color: #ffffff;"></div><img src ="http://www.cppblog.com/mybios/aggbug/212299.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> 2015-11-20 15:03 <a href="http://www.cppblog.com/mybios/archive/2015/11/20/212299.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>tolua++导出C++类的一些问题和解决方法</title><link>http://www.cppblog.com/mybios/archive/2010/02/09/107616.html</link><dc:creator>李锦俊(mybios)</dc:creator><author>李锦俊(mybios)</author><pubDate>Tue, 09 Feb 2010 11:43:00 GMT</pubDate><guid>http://www.cppblog.com/mybios/archive/2010/02/09/107616.html</guid><wfw:comment>http://www.cppblog.com/mybios/comments/107616.html</wfw:comment><comments>http://www.cppblog.com/mybios/archive/2010/02/09/107616.html#Feedback</comments><slash:comments>7</slash:comments><wfw:commentRss>http://www.cppblog.com/mybios/comments/commentRss/107616.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mybios/services/trackbacks/107616.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 我在尝试导出Ogre的所有类接口到lua中使用，参考CEGUI的方法，使用的是tolua++来导出C++类对象。在使用过程中，遇到了一些问题。问题1：表现为tolua++编译错误，错误信息是：***curr code for error is $pfile "OgreBase/OgreVector2.h" 这里我编写了一个OgreBase.pkg文件（给tolua++用来生成导出导入lua的定义文...&nbsp;&nbsp;<a href='http://www.cppblog.com/mybios/archive/2010/02/09/107616.html'>阅读全文</a><img src ="http://www.cppblog.com/mybios/aggbug/107616.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> 2010-02-09 19:43 <a href="http://www.cppblog.com/mybios/archive/2010/02/09/107616.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>使用FreeType实现矢量字体的粗体、斜体、描边、阴影效果</title><link>http://www.cppblog.com/mybios/archive/2009/08/01/91869.html</link><dc:creator>李锦俊(mybios)</dc:creator><author>李锦俊(mybios)</author><pubDate>Sat, 01 Aug 2009 02:42:00 GMT</pubDate><guid>http://www.cppblog.com/mybios/archive/2009/08/01/91869.html</guid><wfw:comment>http://www.cppblog.com/mybios/comments/91869.html</wfw:comment><comments>http://www.cppblog.com/mybios/archive/2009/08/01/91869.html#Feedback</comments><slash:comments>8</slash:comments><wfw:commentRss>http://www.cppblog.com/mybios/comments/commentRss/91869.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mybios/services/trackbacks/91869.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 使用FreeType实现矢量字体的粗体、斜体、描边、阴影效果&nbsp;前言：Freetype是一个跨平台、开源的字体渲染器，网上很多文章介绍，本人就不啰嗦了。本文重点在于实现文章标题所属的各种效果，不是Freetype的基本使用方法介绍文档，所以对于Freetype不熟悉的同学们请先学习下Freetype的基本用法，才可以使用本文中所提及的方法。正文：用FreeType实现矢...&nbsp;&nbsp;<a href='http://www.cppblog.com/mybios/archive/2009/08/01/91869.html'>阅读全文</a><img src ="http://www.cppblog.com/mybios/aggbug/91869.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> 2009-08-01 10:42 <a href="http://www.cppblog.com/mybios/archive/2009/08/01/91869.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>关于天龙八部frame文件格式</title><link>http://www.cppblog.com/mybios/archive/2009/07/26/91270.html</link><dc:creator>李锦俊(mybios)</dc:creator><author>李锦俊(mybios)</author><pubDate>Sun, 26 Jul 2009 12:41:00 GMT</pubDate><guid>http://www.cppblog.com/mybios/archive/2009/07/26/91270.html</guid><wfw:comment>http://www.cppblog.com/mybios/comments/91270.html</wfw:comment><comments>http://www.cppblog.com/mybios/archive/2009/07/26/91270.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.cppblog.com/mybios/comments/commentRss/91270.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mybios/services/trackbacks/91270.html</trackback:ping><description><![CDATA[其实天龙八部frame文件就是.skeleton文件，只是扩展名不一样罢了，可以直接通过SkeletonManager::getSingleton().load("xxxx.frame")来载入的。载入后就是一个骨骼数据，这些骨骼数据对应了model文件中描述节点。<br />过来人都说技术只是一层纸，一捅就破。想当天花了很多时间去研究frame文件的二进制格式究竟是怎么来的，但始终未果。到头来发现竟然只是一个普通的.skeleton文件，脑后不禁冒出好几条黑色竖条。<br />现我把这层纸捅破了，望过来人不用再辛辛苦苦研究frame文件格式走弯路了。<br /><br /><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/91270.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> 2009-07-26 20:41 <a href="http://www.cppblog.com/mybios/archive/2009/07/26/91270.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>发布一个前段时间写的天龙八部GridInfo读取源码</title><link>http://www.cppblog.com/mybios/archive/2009/07/26/91267.html</link><dc:creator>李锦俊(mybios)</dc:creator><author>李锦俊(mybios)</author><pubDate>Sun, 26 Jul 2009 12:36:00 GMT</pubDate><guid>http://www.cppblog.com/mybios/archive/2009/07/26/91267.html</guid><wfw:comment>http://www.cppblog.com/mybios/comments/91267.html</wfw:comment><comments>http://www.cppblog.com/mybios/archive/2009/07/26/91267.html#Feedback</comments><slash:comments>5</slash:comments><wfw:commentRss>http://www.cppblog.com/mybios/comments/commentRss/91267.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mybios/services/trackbacks/91267.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 天龙八部GridInfo文件的格式已经有人公布了，在这里：http://www.mobilegamebase.com/blog/article.asp?id=17不过，此文中有点笔误的地方，就是那个nFirstLayerOP的位标记的描述有点错误，正确的应该如下：&nbsp;// 图片水平翻转，即左右翻转#define FLIP_HORIZINTAL 1&nbsp;// 图片垂直翻转，即上下翻转#...&nbsp;&nbsp;<a href='http://www.cppblog.com/mybios/archive/2009/07/26/91267.html'>阅读全文</a><img src ="http://www.cppblog.com/mybios/aggbug/91267.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> 2009-07-26 20:36 <a href="http://www.cppblog.com/mybios/archive/2009/07/26/91267.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Unreal3游戏引擎UObject源码阅读分析</title><link>http://www.cppblog.com/mybios/archive/2009/07/26/91196.html</link><dc:creator>李锦俊(mybios)</dc:creator><author>李锦俊(mybios)</author><pubDate>Sun, 26 Jul 2009 01:50:00 GMT</pubDate><guid>http://www.cppblog.com/mybios/archive/2009/07/26/91196.html</guid><wfw:comment>http://www.cppblog.com/mybios/comments/91196.html</wfw:comment><comments>http://www.cppblog.com/mybios/archive/2009/07/26/91196.html#Feedback</comments><slash:comments>8</slash:comments><wfw:commentRss>http://www.cppblog.com/mybios/comments/commentRss/91196.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mybios/services/trackbacks/91196.html</trackback:ping><description><![CDATA[<p>Unreal3（以下简称U3）是一个以脚本为主体的游戏引擎，所有代码几乎都为脚本服务，意味着所有源码都会提供相应的脚本函数在脚本中使用。<br />UObject是U3中很重要的一个基类，所有由UObject派生的类都可以导出到脚本中（不从UObject派生行不行？不知道呢），但我对U3的脚本不熟。暂且从C++角度来分析下UObject是如何实现的。<br />UObject顾名思义是一个&#8220;基本对象&#8221;，材质、mesh、文件、玩家等等都是从这个UObject继承而来，这个类做了很多事情：</p>
<p>1、属性的统一访问接口，脚本中就可以通过这个接口来访问属性了；<br />2、成员函数的统一访问接口，脚本中可以通过这些接口来调用UObject或其派生类的成员函数；<br />3、串行化的统一接口，实现了一个保存所有对象的UPackage包管理器，从而做到保存到二进制文件、从二进制文件读取，这样做的好处是持久化对象（比如游戏中的材质列表）的载入非常快速，由于是二进制格式，不需要任何字符串数据转换；<br />4、提供对象的垃圾回收功能；<br />5、提供编辑器的相应功能，如：对象的&#8220;属性&#8221;有各种编辑器所需的标记（是否可编辑CPF_Edit等）、对象在编辑器中的渲染DrawThumbnail、对象描述GetThumbnailDesc、对象选择IsSelected、是否更改了包MarkPackageDirty等等；<br />6、提供一个对象的管理器，这个对象管理器是通过UObject中的一堆静态函数来实现的，如：从管理器中查找一个对象StaticFindObject、分配一个对象StaticAllocateObject、从包中载入一个对象StaticLoadObject、根据类型来遍历管理器中的所有对象FObjectIterator/TObjectIterator、遍历所有选择了的对象TSelectedObjectIterator（编辑器使用）<br />7、提供配置管理器，通过UObject中的LoadConfig、SaveConfig实现<br />8、提供类描述信息，描述了这个类从哪个类派生、有什么属性、每个属性的访问方式、有什么函数，从而实现了动态类型判断、脚本属性访问、脚本函数访问、属性串行化等等<br />9、其他。。。。</p>
<p>简单分析下UObject中的各个成员变量的意义：<br />Index，用来记录这个UObject在所有UObject列表GObjObjects中的唯一索引<br />HashNext，用来记录全局UObject Hash表GObjHash中跟这个UObject 的Hash值相同的下一个UObject的指针，用来配合全局Hash表GObjHash通过StaticFindObject函数快速搜索一个指定名称的UObject<br />StateFrame，脚本相关的咚咚，还没看<br />_Linker，通过在包文件中载入时的载入器<br />_LinkerIndex，通过包文件载入时的UPackage包对象在GObjObjects中的唯一索引，相当于Outer-&gt;Index<br />Outer，这个对象所属的包<br />ObjectFlags，这个对象的一些标记，具体参见EObjectFlags枚举，不同标记来决定这个对象的一些行为，比如是否可以保存、是否可见等等<br />Name，对象名称，通过一个FName来实现，这个FName可是个好东西哦，字符串比较变成了一个Hash值比较<br />Class，用来描述这个类，就是以上第1、2、8点说到的。这个Class在调用UObject::StaticClass或派生类的StaticClass静态函数时会一次性初始化，意味着即使创建多少个UObject，但Class只会有一个实例，我们通过这个类，可以使用TFieldIterator的统一方式来遍历这个类的所有属性、函数。</p>
<p>UObject的静态变量，这些静态变量其实就是UObject对象管理器使用的变量，如果用Ogre的设计方法来做，就相当于另外一个class UObjectManager : public Singleton&lt;UObjectManager&gt;，然后在里面把这些静态变量拿到UObjectManager中去。简要分析下静态变量的意义：<br />GObjInitialized，对象管理器是否已经初始化，全局对象管理器只需要初始化一次就够了；<br />GObjNoRegister，调用StaticInit时会设置成1；<br />GObjBeginLoadCount，有多少个对象被BeginLoad了；<br />GObjRegisterCount，ProcessRegistrants中使用<br />GImportCount，还没细看哦<br />GObjHash，通过每个UObject的Name的Hash值取低12位作为索引值保存在GObjHash表中，Hash值的低12位相同的，只记录第一个在GObjHash表中，其他的通过链表方式使用UObject的HashNext来链接起来<br />GAutoRegister，自动注册的对象列表<br />GObjRoot，对象树种的顶层对象<br />GObjObjects，所有对象的列表</p>
<p>先说这么多了，继续学习。</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/91196.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> 2009-07-26 09:50 <a href="http://www.cppblog.com/mybios/archive/2009/07/26/91196.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>在VS2005调试器中显示Unreal3的数据</title><link>http://www.cppblog.com/mybios/archive/2009/05/24/85618.html</link><dc:creator>李锦俊(mybios)</dc:creator><author>李锦俊(mybios)</author><pubDate>Sun, 24 May 2009 09:13:00 GMT</pubDate><guid>http://www.cppblog.com/mybios/archive/2009/05/24/85618.html</guid><wfw:comment>http://www.cppblog.com/mybios/comments/85618.html</wfw:comment><comments>http://www.cppblog.com/mybios/archive/2009/05/24/85618.html#Feedback</comments><slash:comments>7</slash:comments><wfw:commentRss>http://www.cppblog.com/mybios/comments/commentRss/85618.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mybios/services/trackbacks/85618.html</trackback:ping><description><![CDATA[Unreal3引擎中，大量使用了自定义的模版或数据类型，比如TArray、FName、FString等等，对于这三种数据类型，我们无法在VS2005中直接查看他们的值（起码不能像std::vector/std::string一样直观查看）。<br>通过msdn，得知vs2005的autoexp.dat可以可以给自定义的数据类型编写可视化脚本从而实现直观的调试。<br>经过一番研究，实现了对Unreal3数据类型的直观的可视化调试，方法如下：<br><br>打开vs2005目录中的autoexp.dat文件<br><br>找到[AutoExpand]，在[AutoExpand]的下面添加一行:<br>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #000000">FNameEntry</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&lt;Name</span><span style="COLOR: #000000">,</span><span style="COLOR: #000000">su&gt;</span></div>
<br><br>翻到文件最后，添加以下代码到文件的最后：<br>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #000000"><br></span><span style="COLOR: #008000">;</span><span style="COLOR: #008000">&nbsp;Unreal格式的数组</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">TArray&lt;*&gt;{<br>&nbsp;&nbsp;&nbsp;&nbsp;children<br>&nbsp;&nbsp;&nbsp;&nbsp;(<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#array<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;expr&nbsp;:&nbsp;&nbsp;&nbsp;&nbsp;(($T1*)($c.Data))</span><span style="FONT-WEIGHT: bold; COLOR: #800000">[</span><span style="COLOR: #800000">$i</span><span style="FONT-WEIGHT: bold; COLOR: #800000">]</span><span style="COLOR: #000000">,</span><span style="COLOR: #000000">&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;size&nbsp;:&nbsp;&nbsp;&nbsp;&nbsp;$c.ArrayNum<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;)<br>&nbsp;&nbsp;&nbsp;&nbsp;)<br>&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;preview<br>&nbsp;&nbsp;&nbsp;&nbsp;(&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#(&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">[</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,</span><span style="COLOR: #000000">&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$c.ArrayNum&nbsp;</span><span style="COLOR: #000000">,</span><span style="COLOR: #000000"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">](</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,</span><span style="COLOR: #000000">&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#array<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;expr&nbsp;:&nbsp;(($T1*)($c.Data))</span><span style="FONT-WEIGHT: bold; COLOR: #800000">[</span><span style="COLOR: #800000">$i</span><span style="FONT-WEIGHT: bold; COLOR: #800000">]</span><span style="COLOR: #000000">,</span><span style="COLOR: #000000">&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;size&nbsp;:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$c.ArrayNum<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;)</span><span style="COLOR: #000000">,</span><span style="COLOR: #000000">&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">)</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;)<br>&nbsp;&nbsp;&nbsp;&nbsp;)<br>}<br><br></span><span style="COLOR: #008000">;</span><span style="COLOR: #008000">&nbsp;Unreal格式的FName</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">FName{<br>&nbsp;&nbsp;&nbsp;&nbsp;preview(</span><span style="FONT-WEIGHT: bold; COLOR: #800000">[</span><span style="COLOR: #800000">((FNameEntry**)FName.Names.Data)[$c.Index</span><span style="FONT-WEIGHT: bold; COLOR: #800000">]</span><span style="COLOR: #000000">])<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;stringview(</span><span style="FONT-WEIGHT: bold; COLOR: #800000">[</span><span style="COLOR: #800000">((FNameEntry**)FName.Names.Data)[$c.Index</span><span style="FONT-WEIGHT: bold; COLOR: #800000">]</span><span style="COLOR: #000000">])<br>}<br></span><span style="COLOR: #008000">;</span><span style="COLOR: #008000">&nbsp;Unreal格式的字符串</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">FString{<br>&nbsp;&nbsp;&nbsp;&nbsp;preview(</span><span style="FONT-WEIGHT: bold; COLOR: #800000">[</span><span style="COLOR: #800000">$c.Data,su</span><span style="FONT-WEIGHT: bold; COLOR: #800000">]</span><span style="COLOR: #000000">)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;stringview(</span><span style="FONT-WEIGHT: bold; COLOR: #800000">[</span><span style="COLOR: #800000">$c.Data,su</span><span style="FONT-WEIGHT: bold; COLOR: #800000">]</span><span style="COLOR: #000000">)<br>}</span></div>
<br>然后，到调试器里尽情看TArray、FString、FName等等平时不容易看的数据吧。效果图就不贴了。<br>此方法可以举一反三，用来实现对任意数据类型的查看。<br><br><br>
<img src ="http://www.cppblog.com/mybios/aggbug/85618.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> 2009-05-24 17:13 <a href="http://www.cppblog.com/mybios/archive/2009/05/24/85618.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>《软件调试》读书随笔续</title><link>http://www.cppblog.com/mybios/archive/2008/12/21/70006.html</link><dc:creator>李锦俊(mybios)</dc:creator><author>李锦俊(mybios)</author><pubDate>Sun, 21 Dec 2008 09:58:00 GMT</pubDate><guid>http://www.cppblog.com/mybios/archive/2008/12/21/70006.html</guid><wfw:comment>http://www.cppblog.com/mybios/comments/70006.html</wfw:comment><comments>http://www.cppblog.com/mybios/archive/2008/12/21/70006.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/mybios/comments/commentRss/70006.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mybios/services/trackbacks/70006.html</trackback:ping><description><![CDATA[711页 介绍了VC编译器对异常机制的实现方式<br>810页 利用DBGHELP函数回溯栈，可以可编程的记录当时的调用栈详细信息<br>814页 利用RTL函数回溯栈，非常快速的回溯栈，但只记录函数指针，不记录函数名和函数参数，后期如果要看函数名，需要通过PDB文件和UMDH这样的工具来翻译成函数名。但是对于大量的调用速度将会很快。<br>815页 讲述并实现了一个用来检视某地址被访问的记录，能记录下这个地址被访问的时间、调用堆栈等等信息。<br>824页 介绍了使用Windows性能监视器来编写性能监视功能的方法（如监视游戏FPS变化）<br>830页 介绍了/Gh/GH编译开关的作用：监视所有函数的进出 
<img src ="http://www.cppblog.com/mybios/aggbug/70006.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> 2008-12-21 17:58 <a href="http://www.cppblog.com/mybios/archive/2008/12/21/70006.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>《软件调试》读书随笔</title><link>http://www.cppblog.com/mybios/archive/2008/12/20/69933.html</link><dc:creator>李锦俊(mybios)</dc:creator><author>李锦俊(mybios)</author><pubDate>Sat, 20 Dec 2008 13:51:00 GMT</pubDate><guid>http://www.cppblog.com/mybios/archive/2008/12/20/69933.html</guid><wfw:comment>http://www.cppblog.com/mybios/comments/69933.html</wfw:comment><comments>http://www.cppblog.com/mybios/archive/2008/12/20/69933.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.cppblog.com/mybios/comments/commentRss/69933.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mybios/services/trackbacks/69933.html</trackback:ping><description><![CDATA[<p>几个非常有用的技术：<br>421页 ETW 架构，比较适合用来记录大量日志<br>699页 _heapchk()函数可以手工检查堆内容是否有缓存溢出<br>661页 低碎片堆，内核级别的小内存分配器<br>666页 栈回溯数据库，用来记录所有分配内存时的调用栈信息。</p>
<img src ="http://www.cppblog.com/mybios/aggbug/69933.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> 2008-12-20 21:51 <a href="http://www.cppblog.com/mybios/archive/2008/12/20/69933.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>介绍本近期出的好书《软件调试》</title><link>http://www.cppblog.com/mybios/archive/2008/12/13/69371.html</link><dc:creator>李锦俊(mybios)</dc:creator><author>李锦俊(mybios)</author><pubDate>Sat, 13 Dec 2008 14:18:00 GMT</pubDate><guid>http://www.cppblog.com/mybios/archive/2008/12/13/69371.html</guid><wfw:comment>http://www.cppblog.com/mybios/comments/69371.html</wfw:comment><comments>http://www.cppblog.com/mybios/archive/2008/12/13/69371.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.cppblog.com/mybios/comments/commentRss/69371.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mybios/services/trackbacks/69371.html</trackback:ping><description><![CDATA[《软件调试》，是2008年6月份出的新书，我觉得比较适合用C++用了比较长时间的人看，这可以提高他们的调试水平。其实，评价一个人是否是编程高手，主要还是看当程序出问题时调试能力。<br>这本书在当当网上打折后是96元。<br>以下是这本书的一些介绍：<br>ACM院士和调试技术先驱Jack B.Dennis教授做历史回顾计算机和操作系统领域资深专家David A.Solomon撰写序言。调试高手笔耕三载集十余年经验成百万言篇，业内专家鼎力相助，汇五十年精华补软件界空白。<br>　　您将学习到：<br>　　CPU的调试支持，包括异常、断点、单步执行、分支监视、JTAG、MCE等。<br>　　Windows操作系统中的调试设施，包括内核调试引擎、用户态调试予系统、验证器、Dr.Watson、WER、ETW、故障转储、WHEA等。<br>　　Visual C／C++编译器的调试支持，包括编译期检查、运行期检查，以及调试符号。<br>　　WinDBG调试器的发展历史、模块结构、工作模型、使用方法、主要调试功能的实现细节，以及遍布全书的应用实例。<br>　　内核调试、用户态调试、JIT调试、远程调试的原理、实现和用法。异常的概念、分发方法、处理方法（SEH、VEH、CppEH），未处理异常，以及编译器编译异常处理代码的方法。<br>　　调试符号的作用、产生过程、存储格式和使用方法。栈和堆的结构布局、工作原理和有关的软件问题，包括栈的自动增长和溢出，缓；中区溢出，溢出攻击，内存泄漏，堆崩溃等。<br>　　软件的可调试性和提高可调试性的方法。<br>　　此外，书中还诠释了很多较难理解的概念，思考了一系列耐人深思和具有普遍意义的问题。本书是对软件调试技术在过去50年中所取得成就的全面展示，也是笔者本人在软件设计和系统开发第一线奋战10多年的经验总结。本书适合每一位希望深刻理解软件和自由驾驭软件的人阅读，不论您是否直接参与软件开发和测试；不论您是热爱软件，还是憎恨软件；不论您是想发现软件中的瑕疵，还是想领略其中蕴含的智慧！<br>　　本书直面软件工程中的最困难任务——侦错<br>　　围绕软件世界中的最强大工具——调试器<br>　　全方位展示了软件调试技术的无比威力和无穷魅力<br>　　80个示例程序的源程序文件和项目文件<br>　　浏览符号文件的SymView工具<br>　　与内核调试引擎对话的KdTalker工具<br>　　直接浏览用户态转储文件的UdmpView工具<br>　　显示CPU执行轨迹（分支）的Cpuwhere工具<br>　　观察IDT、GDT和系统对象的SOZOOmer工具<br>　　本书是对软件调试技术在过去50年中所取得成就的全面展示，也是对作者本人在软件设计和系统开发第一线奋战10多年的经验总结。全书共分6篇30章，选取了大量具有代表性和普遍意义的技术细节进行讨论，包括CPU的调试支持、操作系统的调试支持、编译器的调试支持、WinDBG及其实现等，是学习软件调试技术的宝贵资料。该书可供各大专院校作为教材使用，也可供从事相关工作的人员作为参考用书使用。
<img src ="http://www.cppblog.com/mybios/aggbug/69371.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> 2008-12-13 22:18 <a href="http://www.cppblog.com/mybios/archive/2008/12/13/69371.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>魔兽争霸3自动拼接地形渲染源码与执行程序下载</title><link>http://www.cppblog.com/mybios/archive/2008/10/31/65636.html</link><dc:creator>李锦俊(mybios)</dc:creator><author>李锦俊(mybios)</author><pubDate>Fri, 31 Oct 2008 11:51:00 GMT</pubDate><guid>http://www.cppblog.com/mybios/archive/2008/10/31/65636.html</guid><wfw:comment>http://www.cppblog.com/mybios/comments/65636.html</wfw:comment><comments>http://www.cppblog.com/mybios/archive/2008/10/31/65636.html#Feedback</comments><slash:comments>14</slash:comments><wfw:commentRss>http://www.cppblog.com/mybios/comments/commentRss/65636.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mybios/services/trackbacks/65636.html</trackback:ping><description><![CDATA[这里发的源码是针对上次的文章的源码http://www.cppblog.com/mybios/archive/2008/10/26/65076.html<br /><a href="http://www.cppblog.com/Files/mybios/源码与执行程序.part01.rar">http://www.cppblog.com/Files/mybios/源码与执行程序.part01.rar</a><br /><a href="http://www.cppblog.com/Files/mybios/源码与执行程序.part02.rar">http://www.cppblog.com/Files/mybios/源码与执行程序.part02.rar</a><br /><a href="http://www.cppblog.com/Files/mybios/源码与执行程序.part03.rar">http://www.cppblog.com/Files/mybios/源码与执行程序.part03.rar</a><br /><a href="http://www.cppblog.com/Files/mybios/源码与执行程序.part04.rar">http://www.cppblog.com/Files/mybios/源码与执行程序.part04.rar</a><br /><a href="http://www.cppblog.com/Files/mybios/源码与执行程序.part05.rar">http://www.cppblog.com/Files/mybios/源码与执行程序.part05.rar</a><br /><br />发现有的人运行不了程序，是由于没安装vc2008的redist导致的。请下载安装之：<br /><a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=A5C84275-3B97-4AB7-A40D-3802B2AF5FC2&amp;displaylang=zh-cn">http://www.microsoft.com/downloads/details.aspx?FamilyID=A5C84275-3B97-4AB7-A40D-3802B2AF5FC2&amp;displaylang=zh-cn</a><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/65636.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> 2008-10-31 19:51 <a href="http://www.cppblog.com/mybios/archive/2008/10/31/65636.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>魔兽争霸3的自动拼接地形渲染方式</title><link>http://www.cppblog.com/mybios/archive/2008/10/26/65076.html</link><dc:creator>李锦俊(mybios)</dc:creator><author>李锦俊(mybios)</author><pubDate>Sun, 26 Oct 2008 04:16:00 GMT</pubDate><guid>http://www.cppblog.com/mybios/archive/2008/10/26/65076.html</guid><wfw:comment>http://www.cppblog.com/mybios/comments/65076.html</wfw:comment><comments>http://www.cppblog.com/mybios/archive/2008/10/26/65076.html#Feedback</comments><slash:comments>11</slash:comments><wfw:commentRss>http://www.cppblog.com/mybios/comments/commentRss/65076.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mybios/services/trackbacks/65076.html</trackback:ping><description><![CDATA[<p align="left">源码已发布，请打开下载<a href="http://www.cppblog.com/mybios/archive/2008/10/31/65636.html">http://www.cppblog.com/mybios/archive/2008/10/31/65636.html</a><br />上次发了个这样的图，结果被某些人鄙视了，很郁闷啊。<br /><br />我们把一个魔兽3的草地贴图提取出来，并且用下面的分块方法来标示每一块小贴图，然后通过一种特定的方式来组织这些小贴图，形成真正的地表贴图。<br />魔兽争霸编辑器中刷地表时，刷一格就会影响四个周围的渲染块，具体如何影响？请看下图：<br /><br />这是贴图的分块索引方法：<br /><img height="256" alt="" src="http://www.cppblog.com/images/cppblog_com/mybios/Lords_Grass.tga.jpg" width="512" border="0" /><br /><br /><br /><br />通过魔兽争霸地图编辑器点一下刷地表草之后，在地图中就会出现一小块绿色草地地表，请注意在图中我用数字1、2、4、8来表示四个渲染块对应的贴图索引，而这个1、2、4、8是固定的。代表的是相对于笔刷位置（笔刷位置是指周围四个渲染块中间位置）来说，左下角的角落贴图索引是1；右下角的角落贴图索引是2；左上角的角落贴图索引是4；右上角的角落贴图索引是8。如下图所示：<br /><img height="465" alt="" src="http://www.cppblog.com/images/cppblog_com/mybios/1.jpg" width="651" border="0" /><br /><br /><br />如果在已经有草地的地表旁边再点一下刷地表，会刷成如下图这个样子：<br />看明白8+4=12没有？这里是两个角落贴图索引相加后的结果，得到12，就从文章开头的索引贴图中找到12对应的小贴图贴上去。<br />2+1=3同理，用两个角落贴图索引相加后的结果3从索引贴图中找到3对应的小贴图贴上去。<br />这样得到的效果就会变成如下图：<br /><img height="531" alt="" src="http://www.cppblog.com/images/cppblog_com/mybios/2.jpg" width="923" border="0" /><br /><br /><br />这里有是更复杂的情况，有三个角落相加，1+8+4=13，不过道理都是一样的。<br /><img height="768" alt="" src="http://www.cppblog.com/images/cppblog_com/mybios/3.jpg" width="1034" border="0" /><br /><br />最后说一下四周都有贴图的情况，看到中间笔刷位置没有？笔刷左上方有一个贴图，对应的是贴图索引中的0，这是因为他四个角都填充了，所以就需要从0、16~31中随机选择一个小贴图贴上去以完整的填充整个渲染块：<br /><img height="768" alt="" src="http://www.cppblog.com/images/cppblog_com/mybios/4.JPG" width="899" border="0" /><br /><br />至此贴图选择的方法已经说完了。<br />至于渲染的方法，都是大同小异，这里就不多说了。</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/65076.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> 2008-10-26 12:16 <a href="http://www.cppblog.com/mybios/archive/2008/10/26/65076.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>刚完成了一个基于Ogre渲染的世界编辑器，发图留念</title><link>http://www.cppblog.com/mybios/archive/2008/03/09/44046.html</link><dc:creator>李锦俊(mybios)</dc:creator><author>李锦俊(mybios)</author><pubDate>Sun, 09 Mar 2008 14:55:00 GMT</pubDate><guid>http://www.cppblog.com/mybios/archive/2008/03/09/44046.html</guid><wfw:comment>http://www.cppblog.com/mybios/comments/44046.html</wfw:comment><comments>http://www.cppblog.com/mybios/archive/2008/03/09/44046.html#Feedback</comments><slash:comments>29</slash:comments><wfw:commentRss>http://www.cppblog.com/mybios/comments/commentRss/44046.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mybios/services/trackbacks/44046.html</trackback:ping><description><![CDATA[<p>这个世界编辑器，从一开始设计的时候就考虑使用即见即所得的形式来实现，地图载入、保存等等操作是独立封装在一个叫DisplaySystem的Dll中，而世界编辑器使用插件的形式来实现各种功能，如：地形编辑插件、网格插件、物件编辑插件、环境编辑插件等等。用插件的形式实现的好处很多，以后要增加新功能的时候世界编辑器本身的代码就不需要修改了。而且对于团队开发也很有利，一个人负责一个插件的开发就可以。<br />发几个图：<br /><br />以下是没有启用插件的模式：<br /><img src="http://www.cppblog.com/images/cppblog_com/mybios/WorldEditor.jpg" border="0"  alt="" /><br /><br />以下是启用了地形编辑器插件的模式：<br /><img src="http://www.cppblog.com/images/cppblog_com/mybios/TerrainEditor.jpg" border="0"  alt="" /><br /><br />以下是启用了物件编辑器插件的模式：<br /><img height="768" src="http://www.cppblog.com/images/cppblog_com/mybios/NoPlugins.jpg" width="1257" border="0"  alt="" /></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/44046.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> 2008-03-09 22:55 <a href="http://www.cppblog.com/mybios/archive/2008/03/09/44046.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Ogre 的渲染到纹理的关键的3个步骤</title><link>http://www.cppblog.com/mybios/archive/2007/12/27/39764.html</link><dc:creator>李锦俊(mybios)</dc:creator><author>李锦俊(mybios)</author><pubDate>Thu, 27 Dec 2007 13:06:00 GMT</pubDate><guid>http://www.cppblog.com/mybios/archive/2007/12/27/39764.html</guid><wfw:comment>http://www.cppblog.com/mybios/comments/39764.html</wfw:comment><comments>http://www.cppblog.com/mybios/archive/2007/12/27/39764.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/mybios/comments/commentRss/39764.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mybios/services/trackbacks/39764.html</trackback:ping><description><![CDATA[<p>好久没写技术的东西了。现在辗转间又回到了深圳工作，还是做我喜欢的游戏开发。奉献点东西给大家。</p>
<p><br />1、创建渲染目标纹理，关键要指定TU_RENDERTARGET参数，在创建这个渲染目标纹理的过程中，Ogre会自动调用&nbsp; Root::getSingleton().getRenderSystem()-&gt;attachRenderTarget把这个纹理添加到Root的渲染目标中，也就是说每帧都会渲染到这个纹理。<br />TexturePtr texture = TextureManager::getSingleton().createManual( "RttTex", <br />&nbsp;ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, TEX_TYPE_2D, <br />&nbsp;512, 512, 0, PF_R8G8B8, TU_RENDERTARGET );</p>
<p>2、获得渲染目标，有了渲染目标，才能给目标指定视口和摄像机<br />RenderTarget *rttTex = texture-&gt;getBuffer()-&gt;getRenderTarget();</p>
<p>3、给这个渲染目标指定摄像机，做了这步骤之后，每帧更新时就会把这个摄像机看到的东西渲染到texture中<br />Viewport *v = rttTex-&gt;addViewport( mReflectCam );</p>
<p>4、OK！</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/39764.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-12-27 21:06 <a href="http://www.cppblog.com/mybios/archive/2007/12/27/39764.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>魔兽3贴图方法</title><link>http://www.cppblog.com/mybios/archive/2007/08/28/31043.html</link><dc:creator>李锦俊(mybios)</dc:creator><author>李锦俊(mybios)</author><pubDate>Tue, 28 Aug 2007 10:57:00 GMT</pubDate><guid>http://www.cppblog.com/mybios/archive/2007/08/28/31043.html</guid><wfw:comment>http://www.cppblog.com/mybios/comments/31043.html</wfw:comment><comments>http://www.cppblog.com/mybios/archive/2007/08/28/31043.html#Feedback</comments><slash:comments>18</slash:comments><wfw:commentRss>http://www.cppblog.com/mybios/comments/commentRss/31043.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mybios/services/trackbacks/31043.html</trackback:ping><description><![CDATA[关键在于他的贴图的索引方式。如下所示。明眼人就能看出规律来。<br />只能说这么多了。公司有保密制度。请见谅！<br /><br /><img height="256" alt="" src="http://www.cppblog.com/images/cppblog_com/mybios/Lords_Grass.tga.jpg" width="512" border="0" /><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/31043.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-08-28 18:57 <a href="http://www.cppblog.com/mybios/archive/2007/08/28/31043.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>终于实现了魔兽3贴图算法，发图留念</title><link>http://www.cppblog.com/mybios/archive/2007/08/28/31021.html</link><dc:creator>李锦俊(mybios)</dc:creator><author>李锦俊(mybios)</author><pubDate>Tue, 28 Aug 2007 07:00:00 GMT</pubDate><guid>http://www.cppblog.com/mybios/archive/2007/08/28/31021.html</guid><wfw:comment>http://www.cppblog.com/mybios/comments/31021.html</wfw:comment><comments>http://www.cppblog.com/mybios/archive/2007/08/28/31021.html#Feedback</comments><slash:comments>10</slash:comments><wfw:commentRss>http://www.cppblog.com/mybios/comments/commentRss/31021.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mybios/services/trackbacks/31021.html</trackback:ping><description><![CDATA[魔兽3的地形贴图算法非常的巧妙。不过，认真观看他的地图编辑器和用工具导出他的地形贴图看看，还是可以摸出规律来的。<br /><br /><img height="627" alt="" src="http://www.cppblog.com/images/cppblog_com/mybios/WC3.JPG" width="808" border="0" /><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/31021.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-08-28 15:00 <a href="http://www.cppblog.com/mybios/archive/2007/08/28/31021.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><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的新版本</title><link>http://www.cppblog.com/mybios/archive/2007/07/18/28250.html</link><dc:creator>李锦俊(mybios)</dc:creator><author>李锦俊(mybios)</author><pubDate>Wed, 18 Jul 2007 01:21:00 GMT</pubDate><guid>http://www.cppblog.com/mybios/archive/2007/07/18/28250.html</guid><wfw:comment>http://www.cppblog.com/mybios/comments/28250.html</wfw:comment><comments>http://www.cppblog.com/mybios/archive/2007/07/18/28250.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.cppblog.com/mybios/comments/commentRss/28250.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mybios/services/trackbacks/28250.html</trackback:ping><description><![CDATA[我们现在用的是比较老的版本了，昨天特意到官网上问那个作者，终于得到了明确答复，说是8月中旬就会发布新版本。贴一些作者说的话：<br><br><span class=postbody><font size=2>Yeah, I'm currently hard at work on the core engine, as the editor is nearly complete. The major feature I need to add for the editor is the ability to add new object definitions without needing to go through text files, but I'm a bit burned out on the editor part so I'm taking a break and working on one of the biggest engine features that needs some work: handling meshes. <br><br>Basically I'm reworking the MeshGameObject class completely so it's more viable for large worlds. <br><br>As far as features go before I release alpha, the list is still sorta large. <br><br>1. Finish the physics system so that it can be used for character movement. <br>2. An attachment system to be able to specify attachment locations on an object and attach any other object to it. <br>3. Mesh animation, animation blending, animation sharing between objects. <br>4. Character class which plays animations based on current state (movement direction, velocity, jumping, strafing, etc.) <br>5. Redo the mesh system (in progress). This is a biggy and involves a lot crazy stuff that is too complex to explain in bullet point. Basically, will be using all of Ogre's advanced features for mesh lods, material lods, etc. but also tie into background resource loading, load only the lods that are necessary, track which lods are currently loaded, etc. <br>6. Ability to add, update and delete meta objects from the editor using property dialog functionality. Once a meta object is updated, call a function on all objects that use that meta data so they can update themselves with newest data. <br>7. Managed material system <br>8. Create plugins of all dlls and dynamically load. <br>9. Create a viewer application that is separate from the editor and can load any world file. <br>10. Update the lighting system, particle system, to use new fading code based on updated mesh code <br><br>Those are my major todos, once finished and tested I release alpha. I will likely update CVS after I get the meta objects finished though. I may also fit in the vegetation system before I release alpha. How long will the above list take? Based on my current speed of development, 3 months. <br><br>I have a core list of features that I think are necessary for an engine, and they include: <br><br>1. Physics simulation, character movement, vehicles, damage, explosions, breakable objects <br>2. Lighting - ambient occlusion, realtime lighting and shadows. Lighting manager is required to control ambient, shadows when moving from interior to exterior <br>3. Trees and vegetation <br>4. Dynamic environment. Sky transitioning, clouds, fog, global ambient, sun position and direction, sun glare, dynamic shadows <br>5. Networking using ReplicaNet. Run GOOF engine in server mode where it doesn't initialize any rendering systems. Update all objects to know whether they're being created on standalone server or not. <br>6. Sound management, 2d sounds, 3d sounds, sound line, background music. <br>7. Doors, triggers, elevators <br>8. In-game cutscenes <br>9. Background loading, resource garbage collection, forced loading <br>10. AI framework <br>11. Character inventory, equipping with 3 clothing types: shared skeleton, individual skeleton, attached to bone <br>12. Terrain with splatting <br><br>The above will take me years unless I have help </font><img alt=Smile src="http://www.ogre3d.org/phpBB2addons/images/smiles/icon_smile.gif" border=0><br><br><span class=postbody><font size=2>Oh yeah, the editor is very nice now, in my opinion. <br><br>Not only did I port to wxWidgets, I fixed and added a lot of general features to the GOOF Engine Editor Tool (the tool for creating scenes for the GOOF engine). <br><br>1. Multi select objects from the selection dialog <br>2. Ctrl drag to box select objects in the viewport, or Alt drag to box unselect, with selection lines to show what you're selecting. <br>3. Option to orient objects to the normal of the collided object when in drag mode. Means you can basically drag things up walls now if you're in a room and the object, such as a painting, will orient to the wall you drag it along. <br>4. Redid the movement axis manipulator so it now moves to exactly where you want it to move to instead of sliding along crazily. <br>5. Added a line that shows what you're linking to when you are in link mode. <br>6. Tree view for the select dialog, with scene hierarchy <br>7. Ability to click and edit partition properties from the same select dialog, and shows objects under their partition with the active partition listed at the top. <br>8. Obviously, all the wxWidgets stuff such as window snapping, toolbar, menu, automatic viewport resizing, view menu which lists windows, redid all the open/save functionality to support a standard file dialog, etc. <br><br>Fixed tons of bugs. Undo system works now. Linking and unlinking objects fixed. Deleting multiple objects fixed when there are parent/child relationships between objects. The movement axis manipulator fixed. Fixed dragging over other objects - the object used to jump around crazily. <br><br>Probably tons more as well, but this is what I remember off the top of my head. </font><br><br><img src="http://www.larabie.net/ogre/GOOFEditorSep29-06.JPG" border=0></span></span>
<img src ="http://www.cppblog.com/mybios/aggbug/28250.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-18 09:21 <a href="http://www.cppblog.com/mybios/archive/2007/07/18/28250.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>基于OGRE渲染引擎的地形插件PLSM2的编辑器GOOF</title><link>http://www.cppblog.com/mybios/archive/2007/07/06/27620.html</link><dc:creator>李锦俊(mybios)</dc:creator><author>李锦俊(mybios)</author><pubDate>Fri, 06 Jul 2007 12:28:00 GMT</pubDate><guid>http://www.cppblog.com/mybios/archive/2007/07/06/27620.html</guid><wfw:comment>http://www.cppblog.com/mybios/comments/27620.html</wfw:comment><comments>http://www.cppblog.com/mybios/archive/2007/07/06/27620.html#Feedback</comments><slash:comments>17</slash:comments><wfw:commentRss>http://www.cppblog.com/mybios/comments/commentRss/27620.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mybios/services/trackbacks/27620.html</trackback:ping><description><![CDATA[这个地形引擎相当的不错，支持无限大，自动分页，局部载入，支持多贴图。但是，我初次的使用过程中遇到了两个问题，第一是不知道如何增加纹理贴图的数量，第二是不知道为何分页的地方会有裂缝，看来要慢慢阅读他的源码才行。<br><br><img height=768 alt="" src="http://www.cppblog.com/images/cppblog_com/mybios/goof.JPG" width=996 border=0>
<img src ="http://www.cppblog.com/mybios/aggbug/27620.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-06 20:28 <a href="http://www.cppblog.com/mybios/archive/2007/07/06/27620.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>经过将近一个月的努力，服务器框架终于搭建起来了</title><link>http://www.cppblog.com/mybios/archive/2007/06/05/25605.html</link><dc:creator>李锦俊(mybios)</dc:creator><author>李锦俊(mybios)</author><pubDate>Tue, 05 Jun 2007 15:12:00 GMT</pubDate><guid>http://www.cppblog.com/mybios/archive/2007/06/05/25605.html</guid><wfw:comment>http://www.cppblog.com/mybios/comments/25605.html</wfw:comment><comments>http://www.cppblog.com/mybios/archive/2007/06/05/25605.html#Feedback</comments><slash:comments>20</slash:comments><wfw:commentRss>http://www.cppblog.com/mybios/comments/commentRss/25605.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mybios/services/trackbacks/25605.html</trackback:ping><description><![CDATA[<p>好久没更新blog了啊。找到新工作都已经很久了，本来在深圳做得好好的，公司突然又搬到杭州来了，没办法，跟着来了杭州。现在我做客户端逻辑与服务器引擎架构一起搞，好晕啊，天天加班做。幸好客户端是用现成的引擎，只是，不太喜欢现在这个引擎，Torque game engine advance，架构实在太差了，以后有机会一定要换成Ogre或Nebula2才行啊。<br><br>现在在开发一款全新的MMORPG游戏，现在是项目立项阶段，需要出技术演示，没办法啊，时间紧迫，我跟另外一个程序主管用了将近一个月完成了项目的第一个里程碑。完成了玩家登录、角色创建/删除、人物行走、多人在线、怪物生成与行走AI等等网络功能了，当然客户端方面也做好了。可惜项目主管不是我，图也不允许抓下来啊，对不起大家了。欢迎加QQ：30743734交流MMORPG开发。<br><br>明天爸爸要做肺部肿瘤切除手术了，祝愿他一切顺利啊，等他痊愈后我发誓要让他过上幸福的晚年生活。祝爸爸健康幸福。。。大伙们帮忙祝福一下吧，谢谢大家了。</p>
爸爸，请原谅儿子我的不孝，路途遥远，不能赶回来陪着您做手术，我以后一定会好好孝顺您的。 
<img src ="http://www.cppblog.com/mybios/aggbug/25605.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-06-05 23:12 <a href="http://www.cppblog.com/mybios/archive/2007/06/05/25605.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>VS2005类向导的问题</title><link>http://www.cppblog.com/mybios/archive/2006/12/31/17088.html</link><dc:creator>李锦俊(mybios)</dc:creator><author>李锦俊(mybios)</author><pubDate>Sun, 31 Dec 2006 07:51:00 GMT</pubDate><guid>http://www.cppblog.com/mybios/archive/2006/12/31/17088.html</guid><wfw:comment>http://www.cppblog.com/mybios/comments/17088.html</wfw:comment><comments>http://www.cppblog.com/mybios/archive/2006/12/31/17088.html#Feedback</comments><slash:comments>7</slash:comments><wfw:commentRss>http://www.cppblog.com/mybios/comments/commentRss/17088.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mybios/services/trackbacks/17088.html</trackback:ping><description><![CDATA[以前用VS 6和VS2003，类向导生成的都是虚析构函数，但是到了VS2005，默认就不是虚析构函数了。<br />这会带来什么问题？我今天就遇到了一次。当我用VS2005类向导生成一个类，如<br />class BaseClass<br />{<br />public:<br />    BaseClass(){};<br />   ~BaseClass(){};<br />   virtual void VFun() = 0;<br />}<br /><br />然后，再生成一个类继承于他<br />class ProblemClass : public BaseClass<br />{<br />public:<br />    ProblemClass (){};<br />   ~ProblemClass (){};<br />   virtual void VFun(){};<br />}<br /><br />然后，执行以下代码：<br /><br />BaseClass *pClass = new ProblemClass ;<br />delete pClass ;<br /><br />如无以外，在delete的时候就会出现堆错误<br /><img src ="http://www.cppblog.com/mybios/aggbug/17088.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-31 15:51 <a href="http://www.cppblog.com/mybios/archive/2006/12/31/17088.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>硬件兼容性的陷阱，DrawIndexedPrimitiveUP的用法</title><link>http://www.cppblog.com/mybios/archive/2006/12/25/16840.html</link><dc:creator>李锦俊(mybios)</dc:creator><author>李锦俊(mybios)</author><pubDate>Mon, 25 Dec 2006 07:11:00 GMT</pubDate><guid>http://www.cppblog.com/mybios/archive/2006/12/25/16840.html</guid><wfw:comment>http://www.cppblog.com/mybios/comments/16840.html</wfw:comment><comments>http://www.cppblog.com/mybios/archive/2006/12/25/16840.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.cppblog.com/mybios/comments/commentRss/16840.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mybios/services/trackbacks/16840.html</trackback:ping><description><![CDATA[好好的一个程序，在我的电脑（ELSA X800 256M显卡）上运行一切正常，拿到别的电脑（845G内置显卡）上。啊。花屏～～赶快调试，幸好公司的电脑也有这种内置显卡的电脑。赶快用远程调试。谁知这一调试，就花了我整整一个上午。。。赶快写下来。。。<br /><br />最终排差的原因是DrawIndexedPrimitiveUP最后一个参数<em>VertexStreamZeroStride</em> ，这个参数是用来指定顶点所占的字节数。我自作聪明的把顶点结构后增加了一个自己用的数据，如：正常的顶点结构<br />struct CUSTOMVERTEX<br />{<br /> FLOAT x, y, z,rhw;<br /> DWORD color;<br /> float u,v;<br />};<br /><br />我改了之后的顶点结构：<br />struct CUSTOMVERTEX<br />{<br /> FLOAT x, y, z,rhw;<br /> DWORD color;<br /> float u,v;<br />DWORD dwMyData; // 用来保存我自己用的数据<br />};<br /><br />结果，在我的显卡上一切正常，这个数据也有用，然后DrawIndexedPrimitiveUP的时候，也会根据最后的参数sizeof(CUSTOMVERTEX)顺利的读取相应的顶点。但是，拿到845G的内置显卡上就死活花屏。后来终于知道是这个原因，于是解决办法就是把dwMyData去掉，放到顶点结构外面去。<br /><br />顺便说说DrawIndexedPrimitiveUP的用法：<br /><strong>HRESULT DrawIndexedPrimitiveUP(</strong><br />  <b>D3DPRIMITIVETYPE</b><i>PrimitiveType</i><b>, // 图原的类型</b><br />  <b>UINT</b><i>MinVertexIndex</i><b>,  // 指定0</b><br />  <b>UINT</b><i>NumVertices</i><b>,  // 指定需要渲染的顶点的数量（如一个矩形可以由4个顶点组成，然后通过顶点索引来达到渲染2个三角形的效果，那么这里就应该填写4，而不是6）</b><br />  <b>UINT</b><i>PrimitiveCount</i><b>, // 要渲染的图原的数量（如一个矩形，由两个三角形组成，就应该填写2）</b><br />  <b>CONST void *</b><i>pIndexData</i><b>, // 索引数据指针</b><br />  <b>D3DFORMAT</b><i>IndexDataFormat</i><strong>, // 索引数据格式，一般为D3DFMT_INDEX16或D3DFMT_INDEX32</strong> <br />  <b>CONST void*</b><i>pVertexStreamZeroData</i><b>, // 顶点数据指针</b><br />  <b>UINT</b><i>VertexStreamZeroStride // 顶点大小一般为sizeof(顶点结构)</i><br /><b>);</b><br /><br />记得默认情况下渲染三角形的顺序是逆时针的（初学者经常范这个错误，本来想渲染一个矩形，结果一个三角形顺时间、另一个三角形逆时针，结果渲染出来只看到一个三角形了，被背面剔除掉了）。<br /><img src ="http://www.cppblog.com/mybios/aggbug/16840.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-25 15:11 <a href="http://www.cppblog.com/mybios/archive/2006/12/25/16840.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>3D 引擎中的 GUI 渲染优化补完</title><link>http://www.cppblog.com/mybios/archive/2006/12/24/16795.html</link><dc:creator>李锦俊(mybios)</dc:creator><author>李锦俊(mybios)</author><pubDate>Sun, 24 Dec 2006 06:14:00 GMT</pubDate><guid>http://www.cppblog.com/mybios/archive/2006/12/24/16795.html</guid><wfw:comment>http://www.cppblog.com/mybios/comments/16795.html</wfw:comment><comments>http://www.cppblog.com/mybios/archive/2006/12/24/16795.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/mybios/comments/commentRss/16795.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mybios/services/trackbacks/16795.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 昨天提到的我想到了个优化渲染的新方法。。今天花了一个早上终于实现了。5555其实不需要这么久，偏偏是一个小小的BUG花了我两个小时。马上进入正题吧。原来的GUI渲染系统是每个Window都继承于RenderCache，每个RenderCache中保存着需要渲染的矩形信息，然后每帧渲染的时候一个个矩形添加到渲染器中再动态修改顶点坐标（一个矩形对应6个顶点）。慢就慢在动态修改顶点！今天实现的新方法，就...&nbsp;&nbsp;<a href='http://www.cppblog.com/mybios/archive/2006/12/24/16795.html'>阅读全文</a><img src ="http://www.cppblog.com/mybios/aggbug/16795.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-24 14:14 <a href="http://www.cppblog.com/mybios/archive/2006/12/24/16795.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>3D 引擎中 GUI 渲染的优化</title><link>http://www.cppblog.com/mybios/archive/2006/12/23/16778.html</link><dc:creator>李锦俊(mybios)</dc:creator><author>李锦俊(mybios)</author><pubDate>Sat, 23 Dec 2006 14:32:00 GMT</pubDate><guid>http://www.cppblog.com/mybios/archive/2006/12/23/16778.html</guid><wfw:comment>http://www.cppblog.com/mybios/comments/16778.html</wfw:comment><comments>http://www.cppblog.com/mybios/archive/2006/12/23/16778.html#Feedback</comments><slash:comments>6</slash:comments><wfw:commentRss>http://www.cppblog.com/mybios/comments/commentRss/16778.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mybios/services/trackbacks/16778.html</trackback:ping><description><![CDATA[前几天的BLOG中说了一些我的3D引擎GUI的渲染部分原理，这几天做到ListCtrl控件的时候，当我添加很多Item进去的时候（几乎满屏的12Px汉字，一个汉字两个三角形，相当于上万个三角形了），FPS降得吓人，Debug版只有18FPS，Release版也只有60FPS。。优化、优化、还是优化！优化之后，FPS终于达到了令人满意的500FPS左右了。且听我慢慢说来。<br /><br />首先是用我的引擎内部剖析分析了代码的瓶颈（Profile这东西真的有用啊，让我很容易就找到了慢的原因，参见GPG3 1.17《实时的层次化性能评测》），发现处理时间主要被Cache算法和渲染两部份占了，于是，我在想，渲染慢是正常的（当时的想法比较弱智，后文有术），所以，我打算从Cache算法着手。首先是优化了ListCtrl的Cache算法，把那些在屏幕外的Item的Visible属性设置成false（我的算法中Visible为false，Cache部分算法就直接跳过），于是速度一下子就上来了，Release版本达到了130FPS。但是，还是慢啊。怎么办？剖析之后，发现大部分的处理时间都集中在渲染部分，我之前的想法是渲染慢是正常的，所以暂时无法解决。。。<br /><br />下班的时候，出去遛了一圈，路上突然想到了我渲染算法中另外一个跟渲染速度有关的东西，动态修改顶点数据！难道是这里的原因？回来后马上测试，把动态修改的代码屏蔽，直接每帧渲染10000三角形，妈呀，1000＋的FPS！完全否定了我之前的想法（渲染慢是正常的），唉，想想也是，每秒千万、上亿个三角形生成速度的显卡，对于区区一万个三角形怎么会慢呢...既然找到原因，就要优化啊，现在找到原因是因为动态修改顶点导致，想到了以前看过一篇文章说顶点数据存储的位置（即CreateVertexBuffer的D3DPool参数），说到做到，把原来的D3DPOOL_MANAGED改成D3DPOOL_SYSMEMORY，哇，速度一下子提升到360FPS左右！想起来原因也是简单的，既然要每帧Lock这么多数据，那么顶点数据需要从显存-&gt;CPU处理，然后CPU提交回显存，总线交换也太频繁了，如果改成SYSMEMORY的话，就只需要从CPU-&gt;显存就可以了。<br /><br />然后我又想，有没有更好的优化方法？答案是有的。。最快的修改内存数据的方法是什么？当然是直接读写内存啊！那么我想到了DrawPrimitiveUP！把顶点数据直接new出来，然后DrawPrimitiveUP提交！改成这样后，速度再度提升！达到惊人的500FPS！<br /><br />最后，我把DrawPrimitiveUP改成DrawIndexedPrimitiveUP，那么顶点数量也减少了。但是奇怪的是速度缺没有更快，反而慢了一点点（慢了5～10FPS左右），但是，我用了DrawIndexedPrimitiveUP，我之后还有更好的优化算法准备实现。通过DrawIndexedPrimitiveUP，但是还没做好。。所以先卖个关子了。明天搞好的话再写Blog。<br /><br />唉，回头看了下自己写的东西，乱七八糟。都不知道有没有人看得懂啊。不管了。知之为知之，不知为不知吧。呵呵，看不懂的请评论一下。<br /><br />写代码去了～～<img src ="http://www.cppblog.com/mybios/aggbug/16778.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-23 22:32 <a href="http://www.cppblog.com/mybios/archive/2006/12/23/16778.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>今天碰到了LINK2005的问题</title><link>http://www.cppblog.com/mybios/archive/2006/12/22/16719.html</link><dc:creator>李锦俊(mybios)</dc:creator><author>李锦俊(mybios)</author><pubDate>Fri, 22 Dec 2006 03:14:00 GMT</pubDate><guid>http://www.cppblog.com/mybios/archive/2006/12/22/16719.html</guid><wfw:comment>http://www.cppblog.com/mybios/comments/16719.html</wfw:comment><comments>http://www.cppblog.com/mybios/archive/2006/12/22/16719.html#Feedback</comments><slash:comments>15</slash:comments><wfw:commentRss>http://www.cppblog.com/mybios/comments/commentRss/16719.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mybios/services/trackbacks/16719.html</trackback:ping><description><![CDATA[烦人的错误。。搞了一个多小时才解决，写下来记录一下。<br /><br />解决办法：保证需要链接的几个项目的运行时库使用同一个类型就OK了！例如我的工程中有GameCore、Plugin_D3D9RenderSystem、Plugin_Win32Platform三个工程，那么就去设置每个工程的C/C++ -&gt;代码生成-&gt;运行时库，统一设置成&#8220;多线程 DLL(/MD)&#8221;，就可以了。如果其中一个不是MD，就会出现以下的错误。很烦人。希望同样遇到这个问题的朋友能少走弯路<br /><br />以下是链接错误信息：<br />msvcprt.lib(MSVCP80.dll) : error LNK2005: "public: int __thiscall std::ios_base::width(int)" (<a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#63;&#119;&#105;&#100;&#116;&#104;&#64;&#105;&#111;&#115;&#95;&#98;&#97;&#115;&#101;&#64;&#115;&#116;&#100;&#64;&#64;&#81;&#65;&#69;&#72;&#72;&#64;&#90;">?width@ios_base@std@@QAEHH@Z</a>) 已经在 Plugin_Win32Platform.lib(Win32InputSystem.obj) 中定义<br />msvcprt.lib(MSVCP80.dll) : error LNK2005: "public: int __thiscall std::ios_base::width(void)const " (<a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#63;&#119;&#105;&#100;&#116;&#104;&#64;&#105;&#111;&#115;&#95;&#98;&#97;&#115;&#101;&#64;&#115;&#116;&#100;&#64;&#64;&#81;&#66;&#69;&#72;&#88;&#90;">?width@ios_base@std@@QBEHXZ</a>) 已经在 Plugin_Win32Platform.lib(Win32InputSystem.obj) 中定义<br />msvcprt.lib(MSVCP80.dll) : error LNK2005: "public: int __thiscall std::ios_base::flags(void)const " (<a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#63;&#102;&#108;&#97;&#103;&#115;&#64;&#105;&#111;&#115;&#95;&#98;&#97;&#115;&#101;&#64;&#115;&#116;&#100;&#64;&#64;&#81;&#66;&#69;&#72;&#88;&#90;">?flags@ios_base@std@@QBEHXZ</a>) 已经在 Plugin_Win32Platform.lib(Win32InputSystem.obj) 中定义<br />msvcprt.lib(MSVCP80.dll) : error LNK2005: "public: bool __thiscall std::ios_base::good(void)const " (<a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#63;&#103;&#111;&#111;&#100;&#64;&#105;&#111;&#115;&#95;&#98;&#97;&#115;&#101;&#64;&#115;&#116;&#100;&#64;&#64;&#81;&#66;&#69;&#95;&#78;&#88;&#90;">?good@ios_base@std@@QBE_NXZ</a>) 已经在 Plugin_Win32Platform.lib(Win32InputSystem.obj) 中定义<br />msvcprt.lib(MSVCP80.dll) : error LNK2005: "public: int __thiscall std::ios_base::rdstate(void)const " (<a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#63;&#114;&#100;&#115;&#116;&#97;&#116;&#101;&#64;&#105;&#111;&#115;&#95;&#98;&#97;&#115;&#101;&#64;&#115;&#116;&#100;&#64;&#64;&#81;&#66;&#69;&#72;&#88;&#90;">?rdstate@ios_base@std@@QBEHXZ</a>) 已经在 Plugin_Win32Platform.lib(Win32InputSystem.obj) 中定义<br />msvcprt.lib(MSVCP80.dll) : error LNK2005: "public: static unsigned int __cdecl std::char_traits&lt;char&gt;::length(char const *)" (<a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#63;&#108;&#101;&#110;&#103;&#116;&#104;&#64;&#63;&#36;&#99;&#104;&#97;&#114;&#95;&#116;&#114;&#97;&#105;&#116;&#115;&#64;&#68;&#64;&#115;&#116;&#100;&#64;&#64;&#83;&#65;&#73;&#80;&#66;&#68;&#64;&#90;">?length@?$char_traits@D@std@@SAIPBD@Z</a>) 已经在 Plugin_Win32Platform.lib(Win32InputSystem.obj) 中定义<br />msvcprt.lib(MSVCP80.dll) : error LNK2005: "class std::basic_ostream&lt;wchar_t,struct std::char_traits&lt;wchar_t&gt; &gt; &amp; __cdecl std::operator&lt;&lt;&lt;wchar_t,struct std::char_traits&lt;wchar_t&gt;,class std::allocator&lt;wchar_t&gt; &gt;(class std::basic_ostream&lt;wchar_t,struct std::char_traits&lt;wchar_t&gt; &gt; &amp;,class std::basic_string&lt;wchar_t,struct std::char_traits&lt;wchar_t&gt;,class std::allocator&lt;wchar_t&gt; &gt; const &amp;)" (<a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#63;&#63;&#36;&#63;&#54;&#95;&#87;&#85;&#63;&#36;&#99;&#104;&#97;&#114;&#95;&#116;&#114;&#97;&#105;&#116;&#115;&#64;&#95;&#87;&#64;&#115;&#116;&#100;&#64;&#64;&#86;&#63;&#36;&#97;&#108;&#108;&#111;&#99;&#97;&#116;&#111;&#114;&#64;&#95;&#87;&#64;&#49;&#64;&#64;&#115;&#116;&#100;&#64;&#64;&#89;&#65;&#65;&#65;&#86;&#63;&#36;&#98;&#97;&#115;&#105;&#99;&#95;&#111;&#115;&#116;&#114;&#101;&#97;&#109;&#64;&#95;&#87;&#85;&#63;&#36;&#99;&#104;&#97;&#114;&#95;&#116;&#114;&#97;&#105;&#116;&#115;&#64;&#95;&#87;&#64;&#115;&#116;&#100;&#64;&#64;&#64;&#48;&#64;&#65;&#65;&#86;&#49;&#48;&#64;&#65;&#66;&#86;&#63;&#36;&#98;&#97;&#115;&#105;&#99;&#95;&#115;&#116;&#114;&#105;&#110;&#103;&#64;&#95;&#87;&#85;&#63;&#36;&#99;&#104;&#97;&#114;&#95;&#116;&#114;&#97;&#105;&#116;&#115;&#64;&#95;&#87;&#64;&#115;&#116;&#100;&#64;&#64;&#86;&#63;&#36;&#97;&#108;&#108;&#111;&#99;&#97;&#116;&#111;&#114;&#64;&#95;&#87;&#64;&#50;&#64;&#64;&#48;&#64;&#64;&#90;">??$?6_WU?$char_traits@_W@std@@V?$allocator@_W@1@@std@@YAAAV?$basic_ostream@_WU?$char_traits@_W@std@@@0@AAV10@ABV?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@0@@Z</a>) 已经在 Plugin_Win32Platform.lib(Win32InputSystem.obj) 中定义<br />msvcprt.lib(MSVCP80.dll) : error LNK2005: "public: wchar_t __thiscall std::basic_ios&lt;wchar_t,struct std::char_traits&lt;wchar_t&gt; &gt;::fill(void)const " (<a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#63;&#102;&#105;&#108;&#108;&#64;&#63;&#36;&#98;&#97;&#115;&#105;&#99;&#95;&#105;&#111;&#115;&#64;&#95;&#87;&#85;&#63;&#36;&#99;&#104;&#97;&#114;&#95;&#116;&#114;&#97;&#105;&#116;&#115;&#64;&#95;&#87;&#64;&#115;&#116;&#100;&#64;&#64;&#64;&#115;&#116;&#100;&#64;&#64;&#81;&#66;&#69;&#95;&#87;&#88;&#90;">?fill@?$basic_ios@_WU?$char_traits@_W@std@@@std@@QBE_WXZ</a>) 已经在 Plugin_Win32Platform.lib(Win32InputSystem.obj) 中定义<br />msvcprt.lib(MSVCP80.dll) : error LNK2005: "public: class std::basic_string&lt;wchar_t,struct std::char_traits&lt;wchar_t&gt;,class std::allocator&lt;wchar_t&gt; &gt; __thiscall std::basic_ostringstream&lt;wchar_t,struct std::char_traits&lt;wchar_t&gt;,class std::allocator&lt;wchar_t&gt; &gt;::str(void)const " (<a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#63;&#115;&#116;&#114;&#64;&#63;&#36;&#98;&#97;&#115;&#105;&#99;&#95;&#111;&#115;&#116;&#114;&#105;&#110;&#103;&#115;&#116;&#114;&#101;&#97;&#109;&#64;&#95;&#87;&#85;&#63;&#36;&#99;&#104;&#97;&#114;&#95;&#116;&#114;&#97;&#105;&#116;&#115;&#64;&#95;&#87;&#64;&#115;&#116;&#100;&#64;&#64;&#86;&#63;&#36;&#97;&#108;&#108;&#111;&#99;&#97;&#116;&#111;&#114;&#64;&#95;&#87;&#64;&#50;&#64;&#64;&#115;&#116;&#100;&#64;&#64;&#81;&#66;&#69;&#63;&#65;&#86;&#63;&#36;&#98;&#97;&#115;&#105;&#99;&#95;&#115;&#116;&#114;&#105;&#110;&#103;&#64;&#95;&#87;&#85;&#63;&#36;&#99;&#104;&#97;&#114;&#95;&#116;&#114;&#97;&#105;&#116;&#115;&#64;&#95;&#87;&#64;&#115;&#116;&#100;&#64;&#64;&#86;&#63;&#36;&#97;&#108;&#108;&#111;&#99;&#97;&#116;&#111;&#114;&#64;&#95;&#87;&#64;&#50;&#64;&#64;&#50;&#64;&#88;&#90;">?str@?$basic_ostringstream@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@std@@QBE?AV?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@2@XZ</a>) 已经在 Plugin_Win32Platform.lib(Win32InputSystem.obj) 中定义<br />msvcprt.lib(MSVCP80.dll) : error LNK2005: "public: __thiscall std::basic_ostringstream&lt;wchar_t,struct std::char_traits&lt;wchar_t&gt;,class std::allocator&lt;wchar_t&gt; &gt;::basic_ostringstream&lt;wchar_t,struct std::char_traits&lt;wchar_t&gt;,class std::allocator&lt;wchar_t&gt; &gt;(int)" (<a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#63;&#63;&#48;&#63;&#36;&#98;&#97;&#115;&#105;&#99;&#95;&#111;&#115;&#116;&#114;&#105;&#110;&#103;&#115;&#116;&#114;&#101;&#97;&#109;&#64;&#95;&#87;&#85;&#63;&#36;&#99;&#104;&#97;&#114;&#95;&#116;&#114;&#97;&#105;&#116;&#115;&#64;&#95;&#87;&#64;&#115;&#116;&#100;&#64;&#64;&#86;&#63;&#36;&#97;&#108;&#108;&#111;&#99;&#97;&#116;&#111;&#114;&#64;&#95;&#87;&#64;&#50;&#64;&#64;&#115;&#116;&#100;&#64;&#64;&#81;&#65;&#69;&#64;&#72;&#64;&#90;">??0?$basic_ostringstream@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@std@@QAE@H@Z</a>) 已经在 Plugin_Win32Platform.lib(Win32InputSystem.obj) 中定义<br />msvcprt.lib(MSVCP80.dll) : error LNK2005: "public: class std::basic_ostream&lt;wchar_t,struct std::char_traits&lt;wchar_t&gt; &gt; &amp; __thiscall std::basic_ostream&lt;wchar_t,struct std::char_traits&lt;wchar_t&gt; &gt;::operator&lt;&lt;(int)" (<a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#63;&#63;&#54;&#63;&#36;&#98;&#97;&#115;&#105;&#99;&#95;&#111;&#115;&#116;&#114;&#101;&#97;&#109;&#64;&#95;&#87;&#85;&#63;&#36;&#99;&#104;&#97;&#114;&#95;&#116;&#114;&#97;&#105;&#116;&#115;&#64;&#95;&#87;&#64;&#115;&#116;&#100;&#64;&#64;&#64;&#115;&#116;&#100;&#64;&#64;&#81;&#65;&#69;&#65;&#65;&#86;&#48;&#49;&#64;&#72;&#64;&#90;">??6?$basic_ostream@_WU?$char_traits@_W@std@@@std@@QAEAAV01@H@Z</a>) 已经在 Plugin_Win32Platform.lib(Win32InputSystem.obj) 中定义<br />msvcprt.lib(MSVCP80.dll) : error LNK2005: "public: __thiscall std::basic_string&lt;wchar_t,struct std::char_traits&lt;wchar_t&gt;,class std::allocator&lt;wchar_t&gt; &gt;::basic_string&lt;wchar_t,struct std::char_traits&lt;wchar_t&gt;,class std::allocator&lt;wchar_t&gt; &gt;(class std::basic_string&lt;wchar_t,struct std::char_traits&lt;wchar_t&gt;,class std::allocator&lt;wchar_t&gt; &gt; const &amp;)" (<a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#63;&#63;&#48;&#63;&#36;&#98;&#97;&#115;&#105;&#99;&#95;&#115;&#116;&#114;&#105;&#110;&#103;&#64;&#95;&#87;&#85;&#63;&#36;&#99;&#104;&#97;&#114;&#95;&#116;&#114;&#97;&#105;&#116;&#115;&#64;&#95;&#87;&#64;&#115;&#116;&#100;&#64;&#64;&#86;&#63;&#36;&#97;&#108;&#108;&#111;&#99;&#97;&#116;&#111;&#114;&#64;&#95;&#87;&#64;&#50;&#64;&#64;&#115;&#116;&#100;&#64;&#64;&#81;&#65;&#69;&#64;&#65;&#66;&#86;&#48;&#49;&#64;&#64;&#90;">??0?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@std@@QAE@ABV01@@Z</a>) 已经在 Plugin_Win32Platform.lib(Win32InputSystem.obj) 中定义<br />msvcprt.lib(MSVCP80.dll) : error LNK2005: "public: void __thiscall std::basic_ostream&lt;wchar_t,struct std::char_traits&lt;wchar_t&gt; &gt;::_Osfx(void)" (<a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#63;&#95;&#79;&#115;&#102;&#120;&#64;&#63;&#36;&#98;&#97;&#115;&#105;&#99;&#95;&#111;&#115;&#116;&#114;&#101;&#97;&#109;&#64;&#95;&#87;&#85;&#63;&#36;&#99;&#104;&#97;&#114;&#95;&#116;&#114;&#97;&#105;&#116;&#115;&#64;&#95;&#87;&#64;&#115;&#116;&#100;&#64;&#64;&#64;&#115;&#116;&#100;&#64;&#64;&#81;&#65;&#69;&#88;&#88;&#90;">?_Osfx@?$basic_ostream@_WU?$char_traits@_W@std@@@std@@QAEXXZ</a>) 已经在 Plugin_Win32Platform.lib(Win32InputSystem.obj) 中定义<br />msvcprt.lib(MSVCP80.dll) : error LNK2005: "public: class std::basic_ostream&lt;wchar_t,struct std::char_traits&lt;wchar_t&gt; &gt; * __thiscall std::basic_ios&lt;wchar_t,struct std::char_traits&lt;wchar_t&gt; &gt;::tie(void)const " (<a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#63;&#116;&#105;&#101;&#64;&#63;&#36;&#98;&#97;&#115;&#105;&#99;&#95;&#105;&#111;&#115;&#64;&#95;&#87;&#85;&#63;&#36;&#99;&#104;&#97;&#114;&#95;&#116;&#114;&#97;&#105;&#116;&#115;&#64;&#95;&#87;&#64;&#115;&#116;&#100;&#64;&#64;&#64;&#115;&#116;&#100;&#64;&#64;&#81;&#66;&#69;&#80;&#65;&#86;&#63;&#36;&#98;&#97;&#115;&#105;&#99;&#95;&#111;&#115;&#116;&#114;&#101;&#97;&#109;&#64;&#95;&#87;&#85;&#63;&#36;&#99;&#104;&#97;&#114;&#95;&#116;&#114;&#97;&#105;&#116;&#115;&#64;&#95;&#87;&#64;&#115;&#116;&#100;&#64;&#64;&#64;&#50;&#64;&#88;&#90;">?tie@?$basic_ios@_WU?$char_traits@_W@std@@@std@@QBEPAV?$basic_ostream@_WU?$char_traits@_W@std@@@2@XZ</a>) 已经在 Plugin_Win32Platform.lib(Win32InputSystem.obj) 中定义<br />msvcprt.lib(MSVCP80.dll) : error LNK2005: "public: void __thiscall std::basic_streambuf&lt;wchar_t,struct std::char_traits&lt;wchar_t&gt; &gt;::_Lock(void)" (<a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#63;&#95;&#76;&#111;&#99;&#107;&#64;&#63;&#36;&#98;&#97;&#115;&#105;&#99;&#95;&#115;&#116;&#114;&#101;&#97;&#109;&#98;&#117;&#102;&#64;&#95;&#87;&#85;&#63;&#36;&#99;&#104;&#97;&#114;&#95;&#116;&#114;&#97;&#105;&#116;&#115;&#64;&#95;&#87;&#64;&#115;&#116;&#100;&#64;&#64;&#64;&#115;&#116;&#100;&#64;&#64;&#81;&#65;&#69;&#88;&#88;&#90;">?_Lock@?$basic_streambuf@_WU?$char_traits@_W@std@@@std@@QAEXXZ</a>) 已经在 Plugin_Win32Platform.lib(Win32InputSystem.obj) 中定义<br />msvcprt.lib(MSVCP80.dll) : error LNK2005: "public: void __thiscall std::basic_streambuf&lt;wchar_t,struct std::char_traits&lt;wchar_t&gt; &gt;::_Unlock(void)" (<a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#63;&#95;&#85;&#110;&#108;&#111;&#99;&#107;&#64;&#63;&#36;&#98;&#97;&#115;&#105;&#99;&#95;&#115;&#116;&#114;&#101;&#97;&#109;&#98;&#117;&#102;&#64;&#95;&#87;&#85;&#63;&#36;&#99;&#104;&#97;&#114;&#95;&#116;&#114;&#97;&#105;&#116;&#115;&#64;&#95;&#87;&#64;&#115;&#116;&#100;&#64;&#64;&#64;&#115;&#116;&#100;&#64;&#64;&#81;&#65;&#69;&#88;&#88;&#90;">?_Unlock@?$basic_streambuf@_WU?$char_traits@_W@std@@@std@@QAEXXZ</a>) 已经在 Plugin_Win32Platform.lib(Win32InputSystem.obj) 中定义<br />msvcprt.lib(MSVCP80.dll) : error LNK2005: "public: unsigned short __thiscall std::basic_streambuf&lt;wchar_t,struct std::char_traits&lt;wchar_t&gt; &gt;::sputc(wchar_t)" (<a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#63;&#115;&#112;&#117;&#116;&#99;&#64;&#63;&#36;&#98;&#97;&#115;&#105;&#99;&#95;&#115;&#116;&#114;&#101;&#97;&#109;&#98;&#117;&#102;&#64;&#95;&#87;&#85;&#63;&#36;&#99;&#104;&#97;&#114;&#95;&#116;&#114;&#97;&#105;&#116;&#115;&#64;&#95;&#87;&#64;&#115;&#116;&#100;&#64;&#64;&#64;&#115;&#116;&#100;&#64;&#64;&#81;&#65;&#69;&#71;&#95;&#87;&#64;&#90;">?sputc@?$basic_streambuf@_WU?$char_traits@_W@std@@@std@@QAEG_W@Z</a>) 已经在 Plugin_Win32Platform.lib(Win32InputSystem.obj) 中定义<br />msvcprt.lib(MSVCP80.dll) : error LNK2005: "public: __thiscall std::basic_string&lt;wchar_t,struct std::char_traits&lt;wchar_t&gt;,class std::allocator&lt;wchar_t&gt; &gt;::~basic_string&lt;wchar_t,struct std::char_traits&lt;wchar_t&gt;,class std::allocator&lt;wchar_t&gt; &gt;(void)" (<a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#63;&#63;&#49;&#63;&#36;&#98;&#97;&#115;&#105;&#99;&#95;&#115;&#116;&#114;&#105;&#110;&#103;&#64;&#95;&#87;&#85;&#63;&#36;&#99;&#104;&#97;&#114;&#95;&#116;&#114;&#97;&#105;&#116;&#115;&#64;&#95;&#87;&#64;&#115;&#116;&#100;&#64;&#64;&#86;&#63;&#36;&#97;&#108;&#108;&#111;&#99;&#97;&#116;&#111;&#114;&#64;&#95;&#87;&#64;&#50;&#64;&#64;&#115;&#116;&#100;&#64;&#64;&#81;&#65;&#69;&#64;&#88;&#90;">??1?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@std@@QAE@XZ</a>) 已经在 Plugin_Win32Platform.lib(Plugin_Win32Platform.obj) 中定义<br />msvcprt.lib(MSVCP80.dll) : error LNK2005: "public: __thiscall std::basic_string&lt;wchar_t,struct std::char_traits&lt;wchar_t&gt;,class std::allocator&lt;wchar_t&gt; &gt;::basic_string&lt;wchar_t,struct std::char_traits&lt;wchar_t&gt;,class std::allocator&lt;wchar_t&gt; &gt;(wchar_t const *)" (<a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#63;&#63;&#48;&#63;&#36;&#98;&#97;&#115;&#105;&#99;&#95;&#115;&#116;&#114;&#105;&#110;&#103;&#64;&#95;&#87;&#85;&#63;&#36;&#99;&#104;&#97;&#114;&#95;&#116;&#114;&#97;&#105;&#116;&#115;&#64;&#95;&#87;&#64;&#115;&#116;&#100;&#64;&#64;&#86;&#63;&#36;&#97;&#108;&#108;&#111;&#99;&#97;&#116;&#111;&#114;&#64;&#95;&#87;&#64;&#50;&#64;&#64;&#115;&#116;&#100;&#64;&#64;&#81;&#65;&#69;&#64;&#80;&#66;&#95;&#87;&#64;&#90;">??0?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@std@@QAE@PB_W@Z</a>) 已经在 Plugin_Win32Platform.lib(Plugin_Win32Platform.obj) 中定义<br />msvcprt.lib(MSVCP80.dll) : error LNK2005: "public: __thiscall std::basic_string&lt;wchar_t,struct std::char_traits&lt;wchar_t&gt;,class std::allocator&lt;wchar_t&gt; &gt;::basic_string&lt;wchar_t,struct std::char_traits&lt;wchar_t&gt;,class std::allocator&lt;wchar_t&gt; &gt;(void)" (<a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#63;&#63;&#48;&#63;&#36;&#98;&#97;&#115;&#105;&#99;&#95;&#115;&#116;&#114;&#105;&#110;&#103;&#64;&#95;&#87;&#85;&#63;&#36;&#99;&#104;&#97;&#114;&#95;&#116;&#114;&#97;&#105;&#116;&#115;&#64;&#95;&#87;&#64;&#115;&#116;&#100;&#64;&#64;&#86;&#63;&#36;&#97;&#108;&#108;&#111;&#99;&#97;&#116;&#111;&#114;&#64;&#95;&#87;&#64;&#50;&#64;&#64;&#115;&#116;&#100;&#64;&#64;&#81;&#65;&#69;&#64;&#88;&#90;">??0?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@std@@QAE@XZ</a>) 已经在 Plugin_Win32Platform.lib(Win32InputSystem.obj) 中定义<br />msvcprt.lib(MSVCP80.dll) : error LNK2005: "public: void __thiscall std::basic_ostringstream&lt;wchar_t,struct std::char_traits&lt;wchar_t&gt;,class std::allocator&lt;wchar_t&gt; &gt;::`vbase destructor'(void)" (<a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#63;&#63;&#95;&#68;&#63;&#36;&#98;&#97;&#115;&#105;&#99;&#95;&#111;&#115;&#116;&#114;&#105;&#110;&#103;&#115;&#116;&#114;&#101;&#97;&#109;&#64;&#95;&#87;&#85;&#63;&#36;&#99;&#104;&#97;&#114;&#95;&#116;&#114;&#97;&#105;&#116;&#115;&#64;&#95;&#87;&#64;&#115;&#116;&#100;&#64;&#64;&#86;&#63;&#36;&#97;&#108;&#108;&#111;&#99;&#97;&#116;&#111;&#114;&#64;&#95;&#87;&#64;&#50;&#64;&#64;&#115;&#116;&#100;&#64;&#64;&#81;&#65;&#69;&#88;&#88;&#90;">??_D?$basic_ostringstream@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@std@@QAEXXZ</a>) 已经在 Plugin_Win32Platform.lib(Win32InputSystem.obj) 中定义<br />msvcprt.lib(MSVCP80.dll) : error LNK2005: "public: class std::basic_ostream&lt;wchar_t,struct std::char_traits&lt;wchar_t&gt; &gt; &amp; __thiscall std::basic_ostream&lt;wchar_t,struct std::char_traits&lt;wchar_t&gt; &gt;::flush(void)" (<a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#63;&#102;&#108;&#117;&#115;&#104;&#64;&#63;&#36;&#98;&#97;&#115;&#105;&#99;&#95;&#111;&#115;&#116;&#114;&#101;&#97;&#109;&#64;&#95;&#87;&#85;&#63;&#36;&#99;&#104;&#97;&#114;&#95;&#116;&#114;&#97;&#105;&#116;&#115;&#64;&#95;&#87;&#64;&#115;&#116;&#100;&#64;&#64;&#64;&#115;&#116;&#100;&#64;&#64;&#81;&#65;&#69;&#65;&#65;&#86;&#49;&#50;&#64;&#88;&#90;">?flush@?$basic_ostream@_WU?$char_traits@_W@std@@@std@@QAEAAV12@XZ</a>) 已经在 Plugin_Win32Platform.lib(Win32InputSystem.obj) 中定义<br />msvcprt.lib(MSVCP80.dll) : error LNK2005: "public: class std::basic_streambuf&lt;wchar_t,struct std::char_traits&lt;wchar_t&gt; &gt; * __thiscall std::basic_ios&lt;wchar_t,struct std::char_traits&lt;wchar_t&gt; &gt;::rdbuf(void)const " (<a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#63;&#114;&#100;&#98;&#117;&#102;&#64;&#63;&#36;&#98;&#97;&#115;&#105;&#99;&#95;&#105;&#111;&#115;&#64;&#95;&#87;&#85;&#63;&#36;&#99;&#104;&#97;&#114;&#95;&#116;&#114;&#97;&#105;&#116;&#115;&#64;&#95;&#87;&#64;&#115;&#116;&#100;&#64;&#64;&#64;&#115;&#116;&#100;&#64;&#64;&#81;&#66;&#69;&#80;&#65;&#86;&#63;&#36;&#98;&#97;&#115;&#105;&#99;&#95;&#115;&#116;&#114;&#101;&#97;&#109;&#98;&#117;&#102;&#64;&#95;&#87;&#85;&#63;&#36;&#99;&#104;&#97;&#114;&#95;&#116;&#114;&#97;&#105;&#116;&#115;&#64;&#95;&#87;&#64;&#115;&#116;&#100;&#64;&#64;&#64;&#50;&#64;&#88;&#90;">?rdbuf@?$basic_ios@_WU?$char_traits@_W@std@@@std@@QBEPAV?$basic_streambuf@_WU?$char_traits@_W@std@@@2@XZ</a>) 已经在 Plugin_Win32Platform.lib(Win32InputSystem.obj) 中定义<br />msvcprt.lib(MSVCP80.dll) : error LNK2005: "public: void __thiscall std::basic_ios&lt;wchar_t,struct std::char_traits&lt;wchar_t&gt; &gt;::setstate(int,bool)" (<a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#63;&#115;&#101;&#116;&#115;&#116;&#97;&#116;&#101;&#64;&#63;&#36;&#98;&#97;&#115;&#105;&#99;&#95;&#105;&#111;&#115;&#64;&#95;&#87;&#85;&#63;&#36;&#99;&#104;&#97;&#114;&#95;&#116;&#114;&#97;&#105;&#116;&#115;&#64;&#95;&#87;&#64;&#115;&#116;&#100;&#64;&#64;&#64;&#115;&#116;&#100;&#64;&#64;&#81;&#65;&#69;&#88;&#72;&#95;&#78;&#64;&#90;">?setstate@?$basic_ios@_WU?$char_traits@_W@std@@@std@@QAEXH_N@Z</a>) 已经在 Plugin_Win32Platform.lib(Win32InputSystem.obj) 中定义<br />msvcprt.lib(MSVCP80.dll) : error LNK2005: "public: class std::locale __thiscall std::ios_base::getloc(void)const " (<a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#63;&#103;&#101;&#116;&#108;&#111;&#99;&#64;&#105;&#111;&#115;&#95;&#98;&#97;&#115;&#101;&#64;&#115;&#116;&#100;&#64;&#64;&#81;&#66;&#69;&#63;&#65;&#86;&#108;&#111;&#99;&#97;&#108;&#101;&#64;&#50;&#64;&#88;&#90;">?getloc@ios_base@std@@QBE?AVlocale@2@XZ</a>) 已经在 Plugin_Win32Platform.lib(Win32InputSystem.obj) 中定义<br />msvcprt.lib(MSVCP80.dll) : error LNK2005: "public: static unsigned int __cdecl std::ctype&lt;wchar_t&gt;::_Getcat(class std::locale::facet const * *)" (<a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#63;&#95;&#71;&#101;&#116;&#99;&#97;&#116;&#64;&#63;&#36;&#99;&#116;&#121;&#112;&#101;&#64;&#95;&#87;&#64;&#115;&#116;&#100;&#64;&#64;&#83;&#65;&#73;&#80;&#65;&#80;&#66;&#86;&#102;&#97;&#99;&#101;&#116;&#64;&#108;&#111;&#99;&#97;&#108;&#101;&#64;&#50;&#64;&#64;&#90;">?_Getcat@?$ctype@_W@std@@SAIPAPBVfacet@locale@2@@Z</a>) 已经在 Plugin_Win32Platform.lib(Win32InputSystem.obj) 中定义<br />msvcprt.lib(MSVCP80.dll) : error LNK2005: "public: wchar_t __thiscall std::ctype&lt;wchar_t&gt;::widen(char)const " (<a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#63;&#119;&#105;&#100;&#101;&#110;&#64;&#63;&#36;&#99;&#116;&#121;&#112;&#101;&#64;&#95;&#87;&#64;&#115;&#116;&#100;&#64;&#64;&#81;&#66;&#69;&#95;&#87;&#68;&#64;&#90;">?widen@?$ctype@_W@std@@QBE_WD@Z</a>) 已经在 Plugin_Win32Platform.lib(Win32InputSystem.obj) 中定义<br />msvcprt.lib(MSVCP80.dll) : error LNK2005: "public: class std::locale::facet const * __thiscall std::locale::_Getfacet(unsigned int)const " (<a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#63;&#95;&#71;&#101;&#116;&#102;&#97;&#99;&#101;&#116;&#64;&#108;&#111;&#99;&#97;&#108;&#101;&#64;&#115;&#116;&#100;&#64;&#64;&#81;&#66;&#69;&#80;&#66;&#86;&#102;&#97;&#99;&#101;&#116;&#64;&#49;&#50;&#64;&#73;&#64;&#90;">?_Getfacet@locale@std@@QBEPBVfacet@12@I@Z</a>) 已经在 Plugin_Win32Platform.lib(Win32InputSystem.obj) 中定义<br />msvcprt.lib(MSVCP80.dll) : error LNK2005: "public: __thiscall std::locale::~locale(void)" (<a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#63;&#63;&#49;&#108;&#111;&#99;&#97;&#108;&#101;&#64;&#115;&#116;&#100;&#64;&#64;&#81;&#65;&#69;&#64;&#88;&#90;">??1locale@std@@QAE@XZ</a>) 已经在 Plugin_Win32Platform.lib(Win32InputSystem.obj) 中定义<br />msvcprt.lib(MSVCP80.dll) : error LNK2005: "public: void __thiscall std::locale::facet::_Register(void)" (<a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#63;&#95;&#82;&#101;&#103;&#105;&#115;&#116;&#101;&#114;&#64;&#102;&#97;&#99;&#101;&#116;&#64;&#108;&#111;&#99;&#97;&#108;&#101;&#64;&#115;&#116;&#100;&#64;&#64;&#81;&#65;&#69;&#88;&#88;&#90;">?_Register@facet@locale@std@@QAEXXZ</a>) 已经在 Plugin_Win32Platform.lib(Win32InputSystem.obj) 中定义<br />msvcprt.lib(MSVCP80.dll) : error LNK2005: "public: void __thiscall std::locale::facet::_Incref(void)" (<a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#63;&#95;&#73;&#110;&#99;&#114;&#101;&#102;&#64;&#102;&#97;&#99;&#101;&#116;&#64;&#108;&#111;&#99;&#97;&#108;&#101;&#64;&#115;&#116;&#100;&#64;&#64;&#81;&#65;&#69;&#88;&#88;&#90;">?_Incref@facet@locale@std@@QAEXXZ</a>) 已经在 Plugin_Win32Platform.lib(Win32InputSystem.obj) 中定义<br />msvcprt.lib(MSVCP80.dll) : error LNK2005: "public: __thiscall std::locale::id::operator unsigned int(void)" (<a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#63;&#63;&#66;&#105;&#100;&#64;&#108;&#111;&#99;&#97;&#108;&#101;&#64;&#115;&#116;&#100;&#64;&#64;&#81;&#65;&#69;&#73;&#88;&#90;">??Bid@locale@std@@QAEIXZ</a>) 已经在 Plugin_Win32Platform.lib(Win32InputSystem.obj) 中定义<br />msvcprt.lib(MSVCP80.dll) : error LNK2005: "public: static unsigned short __cdecl std::char_traits&lt;wchar_t&gt;::eof(void)" (<a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#63;&#101;&#111;&#102;&#64;&#63;&#36;&#99;&#104;&#97;&#114;&#95;&#116;&#114;&#97;&#105;&#116;&#115;&#64;&#95;&#87;&#64;&#115;&#116;&#100;&#64;&#64;&#83;&#65;&#71;&#88;&#90;">?eof@?$char_traits@_W@std@@SAGXZ</a>) 已经在 Plugin_Win32Platform.lib(Win32InputSystem.obj) 中定义<br />msvcprt.lib(MSVCP80.dll) : error LNK2005: "public: static bool __cdecl std::char_traits&lt;wchar_t&gt;::eq_int_type(unsigned short const &amp;,unsigned short const &amp;)" (<a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#63;&#101;&#113;&#95;&#105;&#110;&#116;&#95;&#116;&#121;&#112;&#101;&#64;&#63;&#36;&#99;&#104;&#97;&#114;&#95;&#116;&#114;&#97;&#105;&#116;&#115;&#64;&#95;&#87;&#64;&#115;&#116;&#100;&#64;&#64;&#83;&#65;&#95;&#78;&#65;&#66;&#71;&#48;&#64;&#90;">?eq_int_type@?$char_traits@_W@std@@SA_NABG0@Z</a>) 已经在 Plugin_Win32Platform.lib(Win32InputSystem.obj) 中定义<br />msvcprt.lib(MSVCP80.dll) : error LNK2005: "bool __cdecl std::operator&lt;&lt;wchar_t,struct std::char_traits&lt;wchar_t&gt;,class std::allocator&lt;wchar_t&gt; &gt;(class std::basic_string&lt;wchar_t,struct std::char_traits&lt;wchar_t&gt;,class std::allocator&lt;wchar_t&gt; &gt; const &amp;,class std::basic_string&lt;wchar_t,struct std::char_traits&lt;wchar_t&gt;,class std::allocator&lt;wchar_t&gt; &gt; const &amp;)" (<a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#63;&#63;&#36;&#63;&#77;&#95;&#87;&#85;&#63;&#36;&#99;&#104;&#97;&#114;&#95;&#116;&#114;&#97;&#105;&#116;&#115;&#64;&#95;&#87;&#64;&#115;&#116;&#100;&#64;&#64;&#86;&#63;&#36;&#97;&#108;&#108;&#111;&#99;&#97;&#116;&#111;&#114;&#64;&#95;&#87;&#64;&#49;&#64;&#64;&#115;&#116;&#100;&#64;&#64;&#89;&#65;&#95;&#78;&#65;&#66;&#86;&#63;&#36;&#98;&#97;&#115;&#105;&#99;&#95;&#115;&#116;&#114;&#105;&#110;&#103;&#64;&#95;&#87;&#85;&#63;&#36;&#99;&#104;&#97;&#114;&#95;&#116;&#114;&#97;&#105;&#116;&#115;&#64;&#95;&#87;&#64;&#115;&#116;&#100;&#64;&#64;&#86;&#63;&#36;&#97;&#108;&#108;&#111;&#99;&#97;&#116;&#111;&#114;&#64;&#95;&#87;&#64;&#50;&#64;&#64;&#48;&#64;&#48;&#64;&#90;">??$?M_WU?$char_traits@_W@std@@V?$allocator@_W@1@@std@@YA_NABV?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@0@0@Z</a>) 已经在 Plugin_Win32Platform.lib(Win32RenderWindow.obj) 中定义<br />msvcprt.lib(MSVCP80.dll) : error LNK2005: "protected: wchar_t const * __thiscall std::basic_string&lt;wchar_t,struct std::char_traits&lt;wchar_t&gt;,class std::allocator&lt;wchar_t&gt; &gt;::_Myptr(void)const " (<a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#63;&#95;&#77;&#121;&#112;&#116;&#114;&#64;&#63;&#36;&#98;&#97;&#115;&#105;&#99;&#95;&#115;&#116;&#114;&#105;&#110;&#103;&#64;&#95;&#87;&#85;&#63;&#36;&#99;&#104;&#97;&#114;&#95;&#116;&#114;&#97;&#105;&#116;&#115;&#64;&#95;&#87;&#64;&#115;&#116;&#100;&#64;&#64;&#86;&#63;&#36;&#97;&#108;&#108;&#111;&#99;&#97;&#116;&#111;&#114;&#64;&#95;&#87;&#64;&#50;&#64;&#64;&#115;&#116;&#100;&#64;&#64;&#73;&#66;&#69;&#80;&#66;&#95;&#87;&#88;&#90;">?_Myptr@?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@std@@IBEPB_WXZ</a>) 已经在 Plugin_Win32Platform.lib(Plugin_Win32Platform.obj) 中定义<br />msvcprt.lib(MSVCP80.dll) : error LNK2005: "public: wchar_t const * __thiscall std::basic_string&lt;wchar_t,struct std::char_traits&lt;wchar_t&gt;,class std::allocator&lt;wchar_t&gt; &gt;::c_str(void)const " (<a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#63;&#99;&#95;&#115;&#116;&#114;&#64;&#63;&#36;&#98;&#97;&#115;&#105;&#99;&#95;&#115;&#116;&#114;&#105;&#110;&#103;&#64;&#95;&#87;&#85;&#63;&#36;&#99;&#104;&#97;&#114;&#95;&#116;&#114;&#97;&#105;&#116;&#115;&#64;&#95;&#87;&#64;&#115;&#116;&#100;&#64;&#64;&#86;&#63;&#36;&#97;&#108;&#108;&#111;&#99;&#97;&#116;&#111;&#114;&#64;&#95;&#87;&#64;&#50;&#64;&#64;&#115;&#116;&#100;&#64;&#64;&#81;&#66;&#69;&#80;&#66;&#95;&#87;&#88;&#90;">?c_str@?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@std@@QBEPB_WXZ</a>) 已经在 Plugin_Win32Platform.lib(Win32LogSystem.obj) 中定义<br />msvcprt.lib(MSVCP80.dll) : error LNK2005: "protected: char const * __thiscall std::basic_string&lt;char,struct std::char_traits&lt;char&gt;,class std::allocator&lt;char&gt; &gt;::_Myptr(void)const " (<a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#63;&#95;&#77;&#121;&#112;&#116;&#114;&#64;&#63;&#36;&#98;&#97;&#115;&#105;&#99;&#95;&#115;&#116;&#114;&#105;&#110;&#103;&#64;&#68;&#85;&#63;&#36;&#99;&#104;&#97;&#114;&#95;&#116;&#114;&#97;&#105;&#116;&#115;&#64;&#68;&#64;&#115;&#116;&#100;&#64;&#64;&#86;&#63;&#36;&#97;&#108;&#108;&#111;&#99;&#97;&#116;&#111;&#114;&#64;&#68;&#64;&#50;&#64;&#64;&#115;&#116;&#100;&#64;&#64;&#73;&#66;&#69;&#80;&#66;&#68;&#88;&#90;">?_Myptr@?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@IBEPBDXZ</a>) 已经在 Plugin_Win32Platform.lib(Win32InputSystem.obj) 中定义<br />msvcprt.lib(MSVCP80.dll) : error LNK2005: "public: unsigned int __thiscall std::basic_string&lt;char,struct std::char_traits&lt;char&gt;,class std::allocator&lt;char&gt; &gt;::size(void)const " (<a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#63;&#115;&#105;&#122;&#101;&#64;&#63;&#36;&#98;&#97;&#115;&#105;&#99;&#95;&#115;&#116;&#114;&#105;&#110;&#103;&#64;&#68;&#85;&#63;&#36;&#99;&#104;&#97;&#114;&#95;&#116;&#114;&#97;&#105;&#116;&#115;&#64;&#68;&#64;&#115;&#116;&#100;&#64;&#64;&#86;&#63;&#36;&#97;&#108;&#108;&#111;&#99;&#97;&#116;&#111;&#114;&#64;&#68;&#64;&#50;&#64;&#64;&#115;&#116;&#100;&#64;&#64;&#81;&#66;&#69;&#73;&#88;&#90;">?size@?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QBEIXZ</a>) 已经在 Plugin_Win32Platform.lib(Win32InputSystem.obj) 中定义<br />msvcprt.lib(MSVCP80.dll) : error LNK2005: "public: char const * __thiscall std::basic_string&lt;char,struct std::char_traits&lt;char&gt;,class std::allocator&lt;char&gt; &gt;::c_str(void)const " (<a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#63;&#99;&#95;&#115;&#116;&#114;&#64;&#63;&#36;&#98;&#97;&#115;&#105;&#99;&#95;&#115;&#116;&#114;&#105;&#110;&#103;&#64;&#68;&#85;&#63;&#36;&#99;&#104;&#97;&#114;&#95;&#116;&#114;&#97;&#105;&#116;&#115;&#64;&#68;&#64;&#115;&#116;&#100;&#64;&#64;&#86;&#63;&#36;&#97;&#108;&#108;&#111;&#99;&#97;&#116;&#111;&#114;&#64;&#68;&#64;&#50;&#64;&#64;&#115;&#116;&#100;&#64;&#64;&#81;&#66;&#69;&#80;&#66;&#68;&#88;&#90;">?c_str@?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QBEPBDXZ</a>) 已经在 Plugin_Win32Platform.lib(Win32InputSystem.obj) 中定义<br />msvcprt.lib(MSVCP80.dll) : error LNK2005: "public: __thiscall std::basic_string&lt;char,struct std::char_traits&lt;char&gt;,class std::allocator&lt;char&gt; &gt;::~basic_string&lt;char,struct std::char_traits&lt;char&gt;,class std::allocator&lt;char&gt; &gt;(void)" (<a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#63;&#63;&#49;&#63;&#36;&#98;&#97;&#115;&#105;&#99;&#95;&#115;&#116;&#114;&#105;&#110;&#103;&#64;&#68;&#85;&#63;&#36;&#99;&#104;&#97;&#114;&#95;&#116;&#114;&#97;&#105;&#116;&#115;&#64;&#68;&#64;&#115;&#116;&#100;&#64;&#64;&#86;&#63;&#36;&#97;&#108;&#108;&#111;&#99;&#97;&#116;&#111;&#114;&#64;&#68;&#64;&#50;&#64;&#64;&#115;&#116;&#100;&#64;&#64;&#81;&#65;&#69;&#64;&#88;&#90;">??1?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAE@XZ</a>) 已经在 Plugin_Win32Platform.lib(Win32InputSystem.obj) 中定义<br />msvcprt.lib(MSVCP80.dll) : error LNK2005: "public: __thiscall std::basic_string&lt;char,struct std::char_traits&lt;char&gt;,class std::allocator&lt;char&gt; &gt;::basic_string&lt;char,struct std::char_traits&lt;char&gt;,class std::allocator&lt;char&gt; &gt;(char const *)" (<a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#63;&#63;&#48;&#63;&#36;&#98;&#97;&#115;&#105;&#99;&#95;&#115;&#116;&#114;&#105;&#110;&#103;&#64;&#68;&#85;&#63;&#36;&#99;&#104;&#97;&#114;&#95;&#116;&#114;&#97;&#105;&#116;&#115;&#64;&#68;&#64;&#115;&#116;&#100;&#64;&#64;&#86;&#63;&#36;&#97;&#108;&#108;&#111;&#99;&#97;&#116;&#111;&#114;&#64;&#68;&#64;&#50;&#64;&#64;&#115;&#116;&#100;&#64;&#64;&#81;&#65;&#69;&#64;&#80;&#66;&#68;&#64;&#90;">??0?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAE@PBD@Z</a>) 已经在 Plugin_Win32Platform.lib(Win32InputSystem.obj) 中定义<br />msvcprt.lib(MSVCP80.dll) : error LNK2005: "public: __thiscall std::basic_string&lt;char,struct std::char_traits&lt;char&gt;,class std::allocator&lt;char&gt; &gt;::basic_string&lt;char,struct std::char_traits&lt;char&gt;,class std::allocator&lt;char&gt; &gt;(class std::basic_string&lt;char,struct std::char_traits&lt;char&gt;,class std::allocator&lt;char&gt; &gt; const &amp;)" (<a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#63;&#63;&#48;&#63;&#36;&#98;&#97;&#115;&#105;&#99;&#95;&#115;&#116;&#114;&#105;&#110;&#103;&#64;&#68;&#85;&#63;&#36;&#99;&#104;&#97;&#114;&#95;&#116;&#114;&#97;&#105;&#116;&#115;&#64;&#68;&#64;&#115;&#116;&#100;&#64;&#64;&#86;&#63;&#36;&#97;&#108;&#108;&#111;&#99;&#97;&#116;&#111;&#114;&#64;&#68;&#64;&#50;&#64;&#64;&#115;&#116;&#100;&#64;&#64;&#81;&#65;&#69;&#64;&#65;&#66;&#86;&#48;&#49;&#64;&#64;&#90;">??0?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAE@ABV01@@Z</a>) 已经在 Plugin_Win32Platform.lib(Win32InputSystem.obj) 中定义<br />msvcprt.lib(MSVCP80.dll) : error LNK2005: "public: bool __thiscall std::ios_base::fail(void)const " (<a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#63;&#102;&#97;&#105;&#108;&#64;&#105;&#111;&#115;&#95;&#98;&#97;&#115;&#101;&#64;&#115;&#116;&#100;&#64;&#64;&#81;&#66;&#69;&#95;&#78;&#88;&#90;">?fail@ios_base@std@@QBE_NXZ</a>) 已经在 Plugin_Win32Platform.lib(Win32InputSystem.obj) 中定义<br />msvcprt.lib(MSVCP80.dll) : error LNK2005: "public: class std::basic_string&lt;wchar_t,struct std::char_traits&lt;wchar_t&gt;,class std::allocator&lt;wchar_t&gt; &gt; &amp; __thiscall std::basic_string&lt;wchar_t,struct std::char_traits&lt;wchar_t&gt;,class std::allocator&lt;wchar_t&gt; &gt;::erase(unsigned int,unsigned int)" (<a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#63;&#101;&#114;&#97;&#115;&#101;&#64;&#63;&#36;&#98;&#97;&#115;&#105;&#99;&#95;&#115;&#116;&#114;&#105;&#110;&#103;&#64;&#95;&#87;&#85;&#63;&#36;&#99;&#104;&#97;&#114;&#95;&#116;&#114;&#97;&#105;&#116;&#115;&#64;&#95;&#87;&#64;&#115;&#116;&#100;&#64;&#64;&#86;&#63;&#36;&#97;&#108;&#108;&#111;&#99;&#97;&#116;&#111;&#114;&#64;&#95;&#87;&#64;&#50;&#64;&#64;&#115;&#116;&#100;&#64;&#64;&#81;&#65;&#69;&#65;&#65;&#86;&#49;&#50;&#64;&#73;&#73;&#64;&#90;">?erase@?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@std@@QAEAAV12@II@Z</a>) 已经在 Plugin_Win32Platform.lib(Plugin_Win32Platform.obj) 中定义<br />msvcprt.lib(MSVCP80.dll) : error LNK2005: "public: void __thiscall std::basic_ios&lt;wchar_t,struct std::char_traits&lt;wchar_t&gt; &gt;::clear(int,bool)" (<a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#63;&#99;&#108;&#101;&#97;&#114;&#64;&#63;&#36;&#98;&#97;&#115;&#105;&#99;&#95;&#105;&#111;&#115;&#64;&#95;&#87;&#85;&#63;&#36;&#99;&#104;&#97;&#114;&#95;&#116;&#114;&#97;&#105;&#116;&#115;&#64;&#95;&#87;&#64;&#115;&#116;&#100;&#64;&#64;&#64;&#115;&#116;&#100;&#64;&#64;&#81;&#65;&#69;&#88;&#72;&#95;&#78;&#64;&#90;">?clear@?$basic_ios@_WU?$char_traits@_W@std@@@std@@QAEXH_N@Z</a>) 已经在 Plugin_Win32Platform.lib(Win32InputSystem.obj) 中定义<br />msvcprt.lib(MSVCP80.dll) : error LNK2005: "public: unsigned int __thiscall std::basic_string&lt;wchar_t,struct std::char_traits&lt;wchar_t&gt;,class std::allocator&lt;wchar_t&gt; &gt;::size(void)const " (<a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#63;&#115;&#105;&#122;&#101;&#64;&#63;&#36;&#98;&#97;&#115;&#105;&#99;&#95;&#115;&#116;&#114;&#105;&#110;&#103;&#64;&#95;&#87;&#85;&#63;&#36;&#99;&#104;&#97;&#114;&#95;&#116;&#114;&#97;&#105;&#116;&#115;&#64;&#95;&#87;&#64;&#115;&#116;&#100;&#64;&#64;&#86;&#63;&#36;&#97;&#108;&#108;&#111;&#99;&#97;&#116;&#111;&#114;&#64;&#95;&#87;&#64;&#50;&#64;&#64;&#115;&#116;&#100;&#64;&#64;&#81;&#66;&#69;&#73;&#88;&#90;">?size@?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@std@@QBEIXZ</a>) 已经在 Plugin_Win32Platform.lib(Plugin_Win32Platform.obj) 中定义<br />msvcprt.lib(MSVCP80.dll) : error LNK2005: "protected: wchar_t * __thiscall std::basic_string&lt;wchar_t,struct std::char_traits&lt;wchar_t&gt;,class std::allocator&lt;wchar_t&gt; &gt;::_Myptr(void)" (<a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#63;&#95;&#77;&#121;&#112;&#116;&#114;&#64;&#63;&#36;&#98;&#97;&#115;&#105;&#99;&#95;&#115;&#116;&#114;&#105;&#110;&#103;&#64;&#95;&#87;&#85;&#63;&#36;&#99;&#104;&#97;&#114;&#95;&#116;&#114;&#97;&#105;&#116;&#115;&#64;&#95;&#87;&#64;&#115;&#116;&#100;&#64;&#64;&#86;&#63;&#36;&#97;&#108;&#108;&#111;&#99;&#97;&#116;&#111;&#114;&#64;&#95;&#87;&#64;&#50;&#64;&#64;&#115;&#116;&#100;&#64;&#64;&#73;&#65;&#69;&#80;&#65;&#95;&#87;&#88;&#90;">?_Myptr@?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@std@@IAEPA_WXZ</a>) 已经在 Plugin_Win32Platform.lib(Plugin_Win32Platform.obj) 中定义<br />msvcprt.lib(MSVCP80.dll) : error LNK2005: "public: __thiscall std::basic_string&lt;char,struct std::char_traits&lt;char&gt;,class std::allocator&lt;char&gt; &gt;::basic_string&lt;char,struct std::char_traits&lt;char&gt;,class std::allocator&lt;char&gt; &gt;(void)" (<a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#63;&#63;&#48;&#63;&#36;&#98;&#97;&#115;&#105;&#99;&#95;&#115;&#116;&#114;&#105;&#110;&#103;&#64;&#68;&#85;&#63;&#36;&#99;&#104;&#97;&#114;&#95;&#116;&#114;&#97;&#105;&#116;&#115;&#64;&#68;&#64;&#115;&#116;&#100;&#64;&#64;&#86;&#63;&#36;&#97;&#108;&#108;&#111;&#99;&#97;&#116;&#111;&#114;&#64;&#68;&#64;&#50;&#64;&#64;&#115;&#116;&#100;&#64;&#64;&#81;&#65;&#69;&#64;&#88;&#90;">??0?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAE@XZ</a>) 已经在 Plugin_Win32Platform.lib(Win32InputSystem.obj) 中定义<br />msvcprt.lib(MSVCP80.dll) : error LNK2005: "public: int __thiscall std::basic_streambuf&lt;wchar_t,struct std::char_traits&lt;wchar_t&gt; &gt;::sputn(wchar_t const *,int)" (<a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#63;&#115;&#112;&#117;&#116;&#110;&#64;&#63;&#36;&#98;&#97;&#115;&#105;&#99;&#95;&#115;&#116;&#114;&#101;&#97;&#109;&#98;&#117;&#102;&#64;&#95;&#87;&#85;&#63;&#36;&#99;&#104;&#97;&#114;&#95;&#116;&#114;&#97;&#105;&#116;&#115;&#64;&#95;&#87;&#64;&#115;&#116;&#100;&#64;&#64;&#64;&#115;&#116;&#100;&#64;&#64;&#81;&#65;&#69;&#72;&#80;&#66;&#95;&#87;&#72;&#64;&#90;">?sputn@?$basic_streambuf@_WU?$char_traits@_W@std@@@std@@QAEHPB_WH@Z</a>) 已经在 Plugin_Win32Platform.lib(Win32InputSystem.obj) 中定义<br />msvcprt.lib(MSVCP80.dll) : error LNK2005: "public: static unsigned int __cdecl std::char_traits&lt;wchar_t&gt;::length(wchar_t const *)" (<a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#63;&#108;&#101;&#110;&#103;&#116;&#104;&#64;&#63;&#36;&#99;&#104;&#97;&#114;&#95;&#116;&#114;&#97;&#105;&#116;&#115;&#64;&#95;&#87;&#64;&#115;&#116;&#100;&#64;&#64;&#83;&#65;&#73;&#80;&#66;&#95;&#87;&#64;&#90;">?length@?$char_traits@_W@std@@SAIPB_W@Z</a>) 已经在 Plugin_Win32Platform.lib(Plugin_Win32Platform.obj) 中定义<br />msvcprt.lib(MSVCP80.dll) : error LNK2005: "public: class std::basic_string&lt;char,struct std::char_traits&lt;char&gt;,class std::allocator&lt;char&gt; &gt; &amp; __thiscall std::basic_string&lt;char,struct std::char_traits&lt;char&gt;,class std::allocator&lt;char&gt; &gt;::assign(char const *,unsigned int)" (<a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#63;&#97;&#115;&#115;&#105;&#103;&#110;&#64;&#63;&#36;&#98;&#97;&#115;&#105;&#99;&#95;&#115;&#116;&#114;&#105;&#110;&#103;&#64;&#68;&#85;&#63;&#36;&#99;&#104;&#97;&#114;&#95;&#116;&#114;&#97;&#105;&#116;&#115;&#64;&#68;&#64;&#115;&#116;&#100;&#64;&#64;&#86;&#63;&#36;&#97;&#108;&#108;&#111;&#99;&#97;&#116;&#111;&#114;&#64;&#68;&#64;&#50;&#64;&#64;&#115;&#116;&#100;&#64;&#64;&#81;&#65;&#69;&#65;&#65;&#86;&#49;&#50;&#64;&#80;&#66;&#68;&#73;&#64;&#90;">?assign@?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAEAAV12@PBDI@Z</a>) 已经在 Plugin_Win32Platform.lib(Win32InputSystem.obj) 中定义<br />msvcprt.lib(MSVCP80.dll) : error LNK2005: "public: class std::basic_string&lt;char,struct std::char_traits&lt;char&gt;,class std::allocator&lt;char&gt; &gt; &amp; __thiscall std::basic_string&lt;char,struct std::char_traits&lt;char&gt;,class std::allocator&lt;char&gt; &gt;::append(char const *,unsigned int)" (<a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#63;&#97;&#112;&#112;&#101;&#110;&#100;&#64;&#63;&#36;&#98;&#97;&#115;&#105;&#99;&#95;&#115;&#116;&#114;&#105;&#110;&#103;&#64;&#68;&#85;&#63;&#36;&#99;&#104;&#97;&#114;&#95;&#116;&#114;&#97;&#105;&#116;&#115;&#64;&#68;&#64;&#115;&#116;&#100;&#64;&#64;&#86;&#63;&#36;&#97;&#108;&#108;&#111;&#99;&#97;&#116;&#111;&#114;&#64;&#68;&#64;&#50;&#64;&#64;&#115;&#116;&#100;&#64;&#64;&#81;&#65;&#69;&#65;&#65;&#86;&#49;&#50;&#64;&#80;&#66;&#68;&#73;&#64;&#90;">?append@?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAEAAV12@PBDI@Z</a>) 已经在 Plugin_Win32Platform.lib(Win32InputSystem.obj) 中定义<br />libcpmt.lib(ios.obj) : error LNK2005: "public: static void __cdecl std::ios_base::_Addstd(class std::ios_base *)" (<a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#63;&#95;&#65;&#100;&#100;&#115;&#116;&#100;&#64;&#105;&#111;&#115;&#95;&#98;&#97;&#115;&#101;&#64;&#115;&#116;&#100;&#64;&#64;&#83;&#65;&#88;&#80;&#65;&#86;&#49;&#50;&#64;&#64;&#90;">?_Addstd@ios_base@std@@SAXPAV12@@Z</a>) 已经在 msvcprt.lib(MSVCP80.dll) 中定义<br />libcpmt.lib(ios.obj) : error LNK2005: "private: static void __cdecl std::ios_base::_Ios_base_dtor(class std::ios_base *)" (<a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#63;&#95;&#73;&#111;&#115;&#95;&#98;&#97;&#115;&#101;&#95;&#100;&#116;&#111;&#114;&#64;&#105;&#111;&#115;&#95;&#98;&#97;&#115;&#101;&#64;&#115;&#116;&#100;&#64;&#64;&#67;&#65;&#88;&#80;&#65;&#86;&#49;&#50;&#64;&#64;&#90;">?_Ios_base_dtor@ios_base@std@@CAXPAV12@@Z</a>) 已经在 msvcprt.lib(MSVCP80.dll) 中定义<br />libcpmt.lib(locale0.obj) : error LNK2005: "private: static class std::locale::_Locimp * __cdecl std::locale::_Getgloballocale(void)" (<a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#63;&#95;&#71;&#101;&#116;&#103;&#108;&#111;&#98;&#97;&#108;&#108;&#111;&#99;&#97;&#108;&#101;&#64;&#108;&#111;&#99;&#97;&#108;&#101;&#64;&#115;&#116;&#100;&#64;&#64;&#67;&#65;&#80;&#65;&#86;&#95;&#76;&#111;&#99;&#105;&#109;&#112;&#64;&#49;&#50;&#64;&#88;&#90;">?_Getgloballocale@locale@std@@CAPAV_Locimp@12@XZ</a>) 已经在 msvcprt.lib(MSVCP80.dll) 中定义<br />libcpmt.lib(locale0.obj) : error LNK2005: "private: static void __cdecl std::locale::facet::facet_Register(class std::locale::facet *)" (<a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#63;&#102;&#97;&#99;&#101;&#116;&#95;&#82;&#101;&#103;&#105;&#115;&#116;&#101;&#114;&#64;&#102;&#97;&#99;&#101;&#116;&#64;&#108;&#111;&#99;&#97;&#108;&#101;&#64;&#115;&#116;&#100;&#64;&#64;&#67;&#65;&#88;&#80;&#65;&#86;&#49;&#50;&#51;&#64;&#64;&#90;">?facet_Register@facet@locale@std@@CAXPAV123@@Z</a>) 已经在 msvcprt.lib(MSVCP80.dll) 中定义<br />libcpmt.lib(locale0.obj) : error LNK2005: "public: static void __cdecl std::_Locinfo::_Locinfo_dtor(class std::_Locinfo *)" (<a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#63;&#95;&#76;&#111;&#99;&#105;&#110;&#102;&#111;&#95;&#100;&#116;&#111;&#114;&#64;&#95;&#76;&#111;&#99;&#105;&#110;&#102;&#111;&#64;&#115;&#116;&#100;&#64;&#64;&#83;&#65;&#88;&#80;&#65;&#86;&#49;&#50;&#64;&#64;&#90;">?_Locinfo_dtor@_Locinfo@std@@SAXPAV12@@Z</a>) 已经在 msvcprt.lib(MSVCP80.dll) 中定义<br />libcpmt.lib(locale0.obj) : error LNK2005: "public: class std::basic_string&lt;char,struct std::char_traits&lt;char&gt;,class std::allocator&lt;char&gt; &gt; &amp; __thiscall std::basic_string&lt;char,struct std::char_traits&lt;char&gt;,class std::allocator&lt;char&gt; &gt;::operator=(char const *)" (<a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#63;&#63;&#52;&#63;&#36;&#98;&#97;&#115;&#105;&#99;&#95;&#115;&#116;&#114;&#105;&#110;&#103;&#64;&#68;&#85;&#63;&#36;&#99;&#104;&#97;&#114;&#95;&#116;&#114;&#97;&#105;&#116;&#115;&#64;&#68;&#64;&#115;&#116;&#100;&#64;&#64;&#86;&#63;&#36;&#97;&#108;&#108;&#111;&#99;&#97;&#116;&#111;&#114;&#64;&#68;&#64;&#50;&#64;&#64;&#115;&#116;&#100;&#64;&#64;&#81;&#65;&#69;&#65;&#65;&#86;&#48;&#49;&#64;&#80;&#66;&#68;&#64;&#90;">??4?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAEAAV01@PBD@Z</a>) 已经在 msvcprt.lib(MSVCP80.dll) 中定义<br />libcpmt.lib(locale0.obj) : error LNK2005: "private: static class std::locale::_Locimp * __cdecl std::locale::_Init(void)" (<a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#63;&#95;&#73;&#110;&#105;&#116;&#64;&#108;&#111;&#99;&#97;&#108;&#101;&#64;&#115;&#116;&#100;&#64;&#64;&#67;&#65;&#80;&#65;&#86;&#95;&#76;&#111;&#99;&#105;&#109;&#112;&#64;&#49;&#50;&#64;&#88;&#90;">?_Init@locale@std@@CAPAV_Locimp@12@XZ</a>) 已经在 msvcprt.lib(MSVCP80.dll) 中定义<br />libcpmt.lib(locale0.obj) : error LNK2005: "public: static void __cdecl std::_Locinfo::_Locinfo_ctor(class std::_Locinfo *,char const *)" (<a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#63;&#95;&#76;&#111;&#99;&#105;&#110;&#102;&#111;&#95;&#99;&#116;&#111;&#114;&#64;&#95;&#76;&#111;&#99;&#105;&#110;&#102;&#111;&#64;&#115;&#116;&#100;&#64;&#64;&#83;&#65;&#88;&#80;&#65;&#86;&#49;&#50;&#64;&#80;&#66;&#68;&#64;&#90;">?_Locinfo_ctor@_Locinfo@std@@SAXPAV12@PBD@Z</a>) 已经在 msvcprt.lib(MSVCP80.dll) 中定义<br />libcpmt.lib(xlock.obj) : error LNK2005: "public: __thiscall std::_Lockit::_Lockit(int)" (<a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#63;&#63;&#48;&#95;&#76;&#111;&#99;&#107;&#105;&#116;&#64;&#115;&#116;&#100;&#64;&#64;&#81;&#65;&#69;&#64;&#72;&#64;&#90;">??0_Lockit@std@@QAE@H@Z</a>) 已经在 msvcprt.lib(MSVCP80.dll) 中定义<br />libcpmt.lib(xlock.obj) : error LNK2005: "public: __thiscall std::_Lockit::~_Lockit(void)" (<a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#63;&#63;&#49;&#95;&#76;&#111;&#99;&#107;&#105;&#116;&#64;&#115;&#116;&#100;&#64;&#64;&#81;&#65;&#69;&#64;&#88;&#90;">??1_Lockit@std@@QAE@XZ</a>) 已经在 msvcprt.lib(MSVCP80.dll) 中定义<br />msvcprt.lib(MSVCP80.dll) : error LNK2005: "public: class std::basic_string&lt;wchar_t,struct std::char_traits&lt;wchar_t&gt;,class std::allocator&lt;wchar_t&gt; &gt; &amp; __thiscall std::basic_string&lt;wchar_t,struct std::char_traits&lt;wchar_t&gt;,class std::allocator&lt;wchar_t&gt; &gt;::assign(class std::basic_string&lt;wchar_t,struct std::char_traits&lt;wchar_t&gt;,class std::allocator&lt;wchar_t&gt; &gt; const &amp;)" (<a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#63;&#97;&#115;&#115;&#105;&#103;&#110;&#64;&#63;&#36;&#98;&#97;&#115;&#105;&#99;&#95;&#115;&#116;&#114;&#105;&#110;&#103;&#64;&#95;&#87;&#85;&#63;&#36;&#99;&#104;&#97;&#114;&#95;&#116;&#114;&#97;&#105;&#116;&#115;&#64;&#95;&#87;&#64;&#115;&#116;&#100;&#64;&#64;&#86;&#63;&#36;&#97;&#108;&#108;&#111;&#99;&#97;&#116;&#111;&#114;&#64;&#95;&#87;&#64;&#50;&#64;&#64;&#115;&#116;&#100;&#64;&#64;&#81;&#65;&#69;&#65;&#65;&#86;&#49;&#50;&#64;&#65;&#66;&#86;&#49;&#50;&#64;&#64;&#90;">?assign@?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@std@@QAEAAV12@ABV12@@Z</a>) 已经在 Plugin_Win32Platform.lib(Win32InputSystem.obj) 中定义<br />&nbsp;&nbsp; 正在创建库 ../Lib/GameCore.lib 和对象 ../Lib/GameCore.exp<br />../Bin/GameCore.dll : fatal error LNK1169: 找到一个或多个多重定义的符号<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/16719.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-22 11:14 <a href="http://www.cppblog.com/mybios/archive/2006/12/22/16719.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>这段时间开发3D引擎啊，正在做GUI部分</title><link>http://www.cppblog.com/mybios/archive/2006/12/19/16630.html</link><dc:creator>李锦俊(mybios)</dc:creator><author>李锦俊(mybios)</author><pubDate>Tue, 19 Dec 2006 13:30:00 GMT</pubDate><guid>http://www.cppblog.com/mybios/archive/2006/12/19/16630.html</guid><wfw:comment>http://www.cppblog.com/mybios/comments/16630.html</wfw:comment><comments>http://www.cppblog.com/mybios/archive/2006/12/19/16630.html#Feedback</comments><slash:comments>10</slash:comments><wfw:commentRss>http://www.cppblog.com/mybios/comments/commentRss/16630.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mybios/services/trackbacks/16630.html</trackback:ping><description><![CDATA[前段时间看了很多很多的3D相关的基础书，感觉上学到了很多东西，但是不知道做什么好。后来，用DXUT做了两个小游戏，连连看和纸牌，虽然都是2D的，但是感觉上还是觉得自己进步了。<br /><br />接下来的一段日子里，是时候继续学3D的东西了，于是萌生了个做游戏引擎的想法。我是个想做就做的人，虽然我也知道自己是不自量力，但是，只要我肯去做，即使做不好，也起码能学到东西啊，把学过的东西拿来用一番，就能有感觉了。<br /><br />说说引擎部分的构建，引擎部分的FrameWork主要参考了GPG3的1.2那个框架模式，采用Unicode编译，感觉上那个模式比较好用，但是太复杂了点，于是我简化了他，基本上只保留了任务系统。使用平台无关的插件方式把Win32和Direct3D9的模块做了出来（当然只封装了一小部分函数），把Ogre的基础库全部拿来主义（哈哈，主要就是数学库、工具库等等）。而声音引擎也留了接口，很好扩展了。<br /><br />然后，现在正在做GUI部分，主要还是说说GUI的渲染部分吧。GUI其中有两个我认为比较关键的地方，其一是渲染文字部分，其二是渲染窗口部分。下面说说我的做法<br />文字渲染部分：<br />我的做法是使用FreeType2读取TTF文件，然后当要渲染文字的时候，看哪个用到的文字就load哪个文字，先获得这个文字的大小，然后在贴图中找到一个空闲的区域（我的贴图大小是512×512，也可以设置），然后blt到贴图中，真正渲染的时候就把这个贴图纹理坐标贴到两个三角形上就完成了一个文字的渲染了。<br />在贴图中找空闲区域我有个比较特别的做法，就是每个需要渲染的文字维护一个RefCount引用计数，例如一个屏幕里10个“我”字，那么“我”的引用计数就是10，当“我”字不需要再渲染的时候（引用计数为0），此文字的贴图区域就可以被其他文字所覆盖。<br />窗口渲染部分：<br /><div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.cppblog.com/images/OutliningIndicators/None.gif" align="top" /><span style="COLOR: #000000"><br /><img src="http://www.cppblog.com/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000"> GAMECORE_EXPORT GUIRenderCache<br /><img id="Codehighlighter1_38_831_Open_Image" onclick="this.style.display='none'; Codehighlighter1_38_831_Open_Text.style.display='none'; Codehighlighter1_38_831_Closed_Image.style.display='inline'; Codehighlighter1_38_831_Closed_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ExpandedBlockStart.gif" align="top" /><img id="Codehighlighter1_38_831_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_38_831_Closed_Text.style.display='none'; Codehighlighter1_38_831_Open_Image.style.display='inline'; Codehighlighter1_38_831_Open_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ContractedBlock.gif" align="top" /></span><span id="Codehighlighter1_38_831_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/images/dot.gif" /></span><span id="Codehighlighter1_38_831_Open_Text"><span style="COLOR: #000000">{<br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" /></span><span style="COLOR: #0000ff">protected</span><span style="COLOR: #000000">:<br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />    </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> 不允许显式创建，只可以继承</span><span style="COLOR: #008000"><br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" /></span><span style="COLOR: #000000">    GUIRenderCache(</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">);<br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" /></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">:<br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />    </span><span style="COLOR: #0000ff">virtual</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">~</span><span style="COLOR: #000000">GUIRenderCache(</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">);<br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" /><br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />    </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> 添加到渲染队列</span><span style="COLOR: #008000"><br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" /></span><span style="COLOR: #000000">    </span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000"> AddCache(</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000"> GUIRenderQuad</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000"> quad)<br /><img id="Codehighlighter1_188_262_Open_Image" onclick="this.style.display='none'; Codehighlighter1_188_262_Open_Text.style.display='none'; Codehighlighter1_188_262_Closed_Image.style.display='inline'; Codehighlighter1_188_262_Closed_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="Codehighlighter1_188_262_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_188_262_Closed_Text.style.display='none'; Codehighlighter1_188_262_Open_Image.style.display='inline'; Codehighlighter1_188_262_Open_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ContractedSubBlock.gif" align="top" />    </span><span id="Codehighlighter1_188_262_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/images/dot.gif" /></span><span id="Codehighlighter1_188_262_Open_Text"><span style="COLOR: #000000">{<br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />        m_vtGUIRenderQuad.insert(GUIRenderQuadPtr(</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000"> GUIRenderQuad(quad)));<br /><img src="http://www.cppblog.com/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />    }</span></span><span style="COLOR: #000000"><br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" /><br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" /><br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />    </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> 渲染需要Cache队列</span><span style="COLOR: #008000"><br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" /></span><span style="COLOR: #000000">    </span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000"> RenderCache(</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">)<br /><img id="Codehighlighter1_307_612_Open_Image" onclick="this.style.display='none'; Codehighlighter1_307_612_Open_Text.style.display='none'; Codehighlighter1_307_612_Closed_Image.style.display='inline'; Codehighlighter1_307_612_Closed_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="Codehighlighter1_307_612_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_307_612_Closed_Text.style.display='none'; Codehighlighter1_307_612_Open_Image.style.display='inline'; Codehighlighter1_307_612_Open_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ContractedSubBlock.gif" align="top" />    </span><span id="Codehighlighter1_307_612_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/images/dot.gif" /></span><span id="Codehighlighter1_307_612_Open_Text"><span style="COLOR: #000000">{<br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />        </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> 从新Cache队列</span><span style="COLOR: #008000"><br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" /></span><span style="COLOR: #000000">        </span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">(m_bDirty)<br /><img id="Codehighlighter1_341_401_Open_Image" onclick="this.style.display='none'; Codehighlighter1_341_401_Open_Text.style.display='none'; Codehighlighter1_341_401_Closed_Image.style.display='inline'; Codehighlighter1_341_401_Closed_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="Codehighlighter1_341_401_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_341_401_Closed_Text.style.display='none'; Codehighlighter1_341_401_Open_Image.style.display='inline'; Codehighlighter1_341_401_Open_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ContractedSubBlock.gif" align="top" />        </span><span id="Codehighlighter1_341_401_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/images/dot.gif" /></span><span id="Codehighlighter1_341_401_Open_Text"><span style="COLOR: #000000">{<br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />            ClearCacheList();<br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />            DoCache();<br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />            m_bDirty </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">false</span><span style="COLOR: #000000">;<br /><img src="http://www.cppblog.com/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />        }</span></span><span style="COLOR: #000000"><br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />        </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> 添加到渲染器</span><span style="COLOR: #008000"><br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" /></span><span style="COLOR: #000000">        </span><span style="COLOR: #0000ff">for</span><span style="COLOR: #000000">(VectorGUIRenderQuad::const_iterator iter </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> m_vtGUIRenderQuad.begin() ; iter </span><span style="COLOR: #000000">!=</span><span style="COLOR: #000000"> m_vtGUIRenderQuad.end() ; iter </span><span style="COLOR: #000000">++</span><span style="COLOR: #000000">)<br /><img id="Codehighlighter1_537_609_Open_Image" onclick="this.style.display='none'; Codehighlighter1_537_609_Open_Text.style.display='none'; Codehighlighter1_537_609_Closed_Image.style.display='inline'; Codehighlighter1_537_609_Closed_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="Codehighlighter1_537_609_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_537_609_Closed_Text.style.display='none'; Codehighlighter1_537_609_Open_Image.style.display='inline'; Codehighlighter1_537_609_Open_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ContractedSubBlock.gif" align="top" />        </span><span id="Codehighlighter1_537_609_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/images/dot.gif" /></span><span id="Codehighlighter1_537_609_Open_Text"><span style="COLOR: #000000">{<br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />            Systems::GetSingleton().GetGUIRendererSystem()</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">AddCache(</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">iter);<br /><img src="http://www.cppblog.com/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />        }</span></span><span style="COLOR: #000000"><br /><img src="http://www.cppblog.com/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />    }</span></span><span style="COLOR: #000000"><br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />    </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> 清空cache队列</span><span style="COLOR: #008000"><br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" /></span><span style="COLOR: #000000">    </span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000"> ClearCacheList(</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">)<br /><img id="Codehighlighter1_656_688_Open_Image" onclick="this.style.display='none'; Codehighlighter1_656_688_Open_Text.style.display='none'; Codehighlighter1_656_688_Closed_Image.style.display='inline'; Codehighlighter1_656_688_Closed_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="Codehighlighter1_656_688_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_656_688_Closed_Text.style.display='none'; Codehighlighter1_656_688_Open_Image.style.display='inline'; Codehighlighter1_656_688_Open_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ContractedSubBlock.gif" align="top" />    </span><span id="Codehighlighter1_656_688_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/images/dot.gif" /></span><span id="Codehighlighter1_656_688_Open_Text"><span style="COLOR: #000000">{<br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />        m_vtGUIRenderQuad.clear();<br /><img src="http://www.cppblog.com/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />    }</span></span><span style="COLOR: #000000"><br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" /></span><span style="COLOR: #0000ff">protected</span><span style="COLOR: #000000">:<br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" /><br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />    </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> Cache需要渲染的项目</span><span style="COLOR: #008000"><br /><img id="Codehighlighter1_742_743_Open_Image" onclick="this.style.display='none'; Codehighlighter1_742_743_Open_Text.style.display='none'; Codehighlighter1_742_743_Closed_Image.style.display='inline'; Codehighlighter1_742_743_Closed_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="Codehighlighter1_742_743_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_742_743_Closed_Text.style.display='none'; Codehighlighter1_742_743_Open_Image.style.display='inline'; Codehighlighter1_742_743_Open_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ContractedSubBlock.gif" align="top" /></span><span style="COLOR: #000000">    </span><span style="COLOR: #0000ff">virtual</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000"> DoCache()</span><span id="Codehighlighter1_742_743_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/images/dot.gif" /></span><span id="Codehighlighter1_742_743_Open_Text"><span style="COLOR: #000000">{}</span></span><span style="COLOR: #000000">;<br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" /><br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />    VectorGUIRenderQuad m_vtGUIRenderQuad;    </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> 渲染队列</span><span style="COLOR: #008000"><br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" /></span><span style="COLOR: #000000">    </span><span style="COLOR: #0000ff">bool</span><span style="COLOR: #000000"> m_bDirty; </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> 需要重新Cache需要渲染的项目</span><span style="COLOR: #008000"><br /><img src="http://www.cppblog.com/images/OutliningIndicators/ExpandedBlockEnd.gif" align="top" /></span><span style="COLOR: #000000">}</span></span><span style="COLOR: #000000">;<br /><img src="http://www.cppblog.com/images/OutliningIndicators/None.gif" align="top" /></span></div><br /><br /><br />每个Window（一个Window是一个抽象类，Static/Button/Dialog等等所有窗口都是继承于Window）都继承于GUIRenderCache对象，当窗口的某个属性（如WindowText）改变时，就会把m_bDirty标记设置成true。每帧渲染的时候调用RenderCache。那么如果窗口的属性没有改变，就只需要把m_vtGUIRenderQuad的东西渲染出来；如果属性改变了（即m_bDirty为true），则调用DoCache，由继承类（如Static/Button等）改写这个函数，计算贴图坐标、三角形坐标等等东西都放在这个函数里。总的来说，Cache之后速度会比Cache之前快起码一半以上。<br /><br />好了，睡觉去了。<img src ="http://www.cppblog.com/mybios/aggbug/16630.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-19 21:30 <a href="http://www.cppblog.com/mybios/archive/2006/12/19/16630.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>顶点声明</title><link>http://www.cppblog.com/mybios/archive/2006/12/02/15891.html</link><dc:creator>李锦俊(mybios)</dc:creator><author>李锦俊(mybios)</author><pubDate>Sat, 02 Dec 2006 08:42:00 GMT</pubDate><guid>http://www.cppblog.com/mybios/archive/2006/12/02/15891.html</guid><wfw:comment>http://www.cppblog.com/mybios/comments/15891.html</wfw:comment><comments>http://www.cppblog.com/mybios/archive/2006/12/02/15891.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/mybios/comments/commentRss/15891.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mybios/services/trackbacks/15891.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 顶点声明																																																																从概念上讲，顶点声明是对顶点直接内存访问（DMA）以及图形流水线的														tessellator												引擎进行编程的一种方法。顶点声明简要地表示了数据的布局及...&nbsp;&nbsp;<a href='http://www.cppblog.com/mybios/archive/2006/12/02/15891.html'>阅读全文</a><img src ="http://www.cppblog.com/mybios/aggbug/15891.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:42 <a href="http://www.cppblog.com/mybios/archive/2006/12/02/15891.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>【转贴】DXUT编程指南(四):通过DXUT使用设备</title><link>http://www.cppblog.com/mybios/archive/2006/11/22/15531.html</link><dc:creator>李锦俊(mybios)</dc:creator><author>李锦俊(mybios)</author><pubDate>Wed, 22 Nov 2006 03:35:00 GMT</pubDate><guid>http://www.cppblog.com/mybios/archive/2006/11/22/15531.html</guid><wfw:comment>http://www.cppblog.com/mybios/comments/15531.html</wfw:comment><comments>http://www.cppblog.com/mybios/archive/2006/11/22/15531.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/mybios/comments/commentRss/15531.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mybios/services/trackbacks/15531.html</trackback:ping><description><![CDATA[
		<p>
				<font size="5">通过DXUT使用设备</font>
				<br />DirectX设备的创建在DXUT中得到了改进。你可以让你的应用程序直接创建设备而其它有框架提供的特征仍然可用。<br /><a href="http://blog.csdn.net/ntwilford/archive/2006/08/02/1009763.aspx#创建设备">创建设备</a><br /><a href="http://blog.csdn.net/ntwilford/archive/2006/08/02/1009763.aspx#使用你自己的设备">选择最佳的设备设置<br />修改可用的设备设置<br />降为软件顶点处理<br />使用你自己的设备</a></p>
		<p>
				<font size="4">
						<a name="创建设备">
						</a>创建设备</font>
				<br />典型地，你将通过标准的Direct3D方法创建设备<br />HRESULT CreateDevice(<br />    UINT                  Adapter,<br />    D3DDEVTYPE            DeviceType,<br />    HWND                  hFocusWindow,<br />    DWORD                 BehaviorFlags,<br />    D3DPRESENT_PARAMETERS *pPresentationParameters,<br />    IDirect3DDevice9      **ppReturnedDeviceInterface<br />);<br />这个方法需要有效的适配器，设备类型(HAL or REF),窗口句柄，行为标志(software/hardware vertex processing 和其它驱动标志)，以及呈现参数(presentation parameters).此外，D3DPRESENT_PARAMETER结构体还拥有大量的成员指定后备缓冲区，多重采样设定，交换效果，窗口模式，深度模版缓冲，刷新率，呈现间隔，以及呈现标志。<br />为所有这些参数选择有效的设定是具有挑战性的。框架通过DXUTCreateDevice函数简化了这一选择过程。<br />HRESULT DXUTCreateDevice(<br />    UINT AdapterOrdinal  = D3DADAPTER_DEFAULT,<br />    BOOL bWindowed       = TRUE,<br />    INT nSuggestedWidth  = 640,<br />    INT nSuggestedHeight = 480,<br />    LPDXUTCALLBACKISDEVICEACCEPTABLE pCallbackIsDeviceAcceptable     = NULL,<br />    LPDXUTCALLBACKMODIFYDEVICESETTINGS pCallbackModifyDeviceSettings = NULL<br />);<br />最基本的用法是全部使用缺省参数调用：<br />DXUTCreateDevice();<br />通过这样的调用框架使用缺省设置创建一个在大多数情况下可用的设备。缺省的设置如下：<br /></p>
		<table>
				<tbody>
						<tr>
								<th>Direct3D Creation Flag</th>
								<th>Description</th>
								<th>Default Value from <strong>DXUTCreateDevice</strong></th>
						</tr>
						<tr>
								<td>AdapterFormat parameter of <a href="http://blog.csdn.net/ntwilford/archive/2006/08/02/IDirect3D9__CheckDeviceFormat.htm">CheckDeviceFormat</a></td>
								<td>Adapter surface format.</td>
								<td>Desktop display mode, or <a href="http://blog.csdn.net/ntwilford/archive/2006/08/02/D3DFORMAT.htm">D3DFMT_X8R8G8B8</a> if the desktop display mode is less than 32 bits.</td>
						</tr>
						<tr>
								<td>Adapter parameter of <strong>IDirect3D9::CreateDevice</strong></td>
								<td>Display adapter ordinal.</td>
								<td>
										<a href="http://blog.csdn.net/ntwilford/archive/2006/08/02/D3DADAPTER_DEFAULT.htm">D3DADAPTER_DEFAULT</a>
								</td>
						</tr>
						<tr>
								<td>
										<strong>D3DPRESENT_PARAMETERS</strong>. BackBufferCount</td>
								<td>Number of back buffers.</td>
								<td>2, indicating triple buffering.</td>
						</tr>
						<tr>
								<td>
										<strong>D3DPRESENT_PARAMETERS</strong>. BackBufferFormat</td>
								<td>Back buffer format.</td>
								<td>Desktop display mode, or <strong>D3DFMT_X8R8G8B8</strong> if the desktop display mode is less than 32 bits.</td>
						</tr>
						<tr>
								<td>
										<strong>D3DPRESENT_PARAMETERS</strong>. AutoDepthStencilFormat</td>
								<td>Depth format of the automatic depth-stencil surface that the device will create.</td>
								<td>
										<strong>D3DFMT_D16</strong> if the backbuffer format is 16 bits or less, or <strong>D3DFMT_D32</strong> otherwise.</td>
						</tr>
						<tr>
								<td>The DeviceType parameter of <strong>IDirect3D9::CreateDevice</strong></td>
								<td>Enumerated type of the device.</td>
								<td>D3DDEVTYPE_HAL if available, otherwise D3DDEVTYPE_REF or failure code if neither is available.</td>
						</tr>
						<tr>
								<td>
										<strong>D3DPRESENT_PARAMETERS</strong>. MultiSampleQuality</td>
								<td>Quality level.</td>
								<td>MultiSampleQuality = 0, indicating multisampling is disabled.</td>
						</tr>
						<tr>
								<td>
										<strong>D3DPRESENT_PARAMETERS</strong>. Flags</td>
								<td>Presentation parameters flags.</td>
								<td>
										<a href="http://blog.csdn.net/ntwilford/archive/2006/08/02/D3DPRESENTFLAG.htm">D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL</a>
								</td>
						</tr>
						<tr>
								<td>
										<strong>D3DPRESENT_PARAMETERS</strong>. PresentationInterval</td>
								<td>Presentation interval.</td>
								<td>
										<a href="http://blog.csdn.net/ntwilford/archive/2006/08/02/D3DPRESENT.htm">D3DPRESENT_INTERVAL_IMMEDIATE</a> for windowed mode, or <strong>D3DPRESENT_INTERVAL_DEFAULT</strong> for full-screen mode.</td>
						</tr>
						<tr>
								<td>
										<strong>D3DPRESENT_PARAMETERS</strong>. FullScreen_RefreshRateInHz</td>
								<td>Rate at which the display adapter refreshes the screen.</td>
								<td>0, indicating windowed mode.</td>
						</tr>
						<tr>
								<td>
										<strong>D3DPRESENT_PARAMETERS</strong>. BackBufferWidth and .BackBufferHeight</td>
								<td>Display mode resolution.</td>
								<td>640 x 480 pixels for windowed mode, or the desktop resolution for full-screen mode.</td>
						</tr>
						<tr>
								<td>
										<strong>D3DPRESENT_PARAMETERS</strong>. AutoDepthStencilFormat</td>
								<td>Stencil format of the automatic depth-stencil surface that the device will create.</td>
								<td>
										<strong>D3DFMT_D16</strong> if the backbuffer format is 16 bits or less, or <strong>D3DFMT_D32</strong> otherwise.</td>
						</tr>
						<tr>
								<td>
										<strong>D3DPRESENT_PARAMETERS</strong>. SwapEffect</td>
								<td>Swap effect.</td>
								<td>D3DSWAPEFFECT_DISCARD</td>
						</tr>
						<tr>
								<td>BehaviorFlags parameter of <strong>IDirect3D9::CreateDevice</strong></td>
								<td>Vertex processing flags.</td>
								<td>
										<a href="http://blog.csdn.net/ntwilford/archive/2006/08/02/D3DCREATE.htm">D3DCREATE_HARDWARE_VERTEXPROCESSING</a> if supported, otherwise <strong>D3DCREATE_SOFTWARE_VERTEXPROCESSING</strong>.</td>
						</tr>
						<tr>
								<td>
										<strong>D3DPRESENT_PARAMETERS</strong>. Windowed</td>
								<td>Windowed or full-screen mode.</td>
								<td>true, indicating windowed mode.</td>
						</tr>
						<tr>
								<td>hFocusWindow parameter of <strong>CreateDevice</strong></td>
								<td>Handle to the created window (see <a href="http://blog.csdn.net/ntwilford/archive/2006/08/02/Using_Application_Windows_with_DXUT.htm">Using Application Windows with DXUT</a>).</td>
								<td>hWndFocus parameter of <a href="http://blog.csdn.net/ntwilford/archive/2006/08/02/DXUTSetWindow.htm">DXUTSetWindow</a></td>
						</tr>
						<tr>
								<td>
										<strong>D3DPRESENT_PARAMETERS</strong>. hDeviceWindow</td>
								<td>Handle to the device window.</td>
								<td>hWndDeviceFullScreen or hWndDeviceWindowed parameters of <strong>DXUTSetWindow</strong></td>
						</tr>
						<tr>
								<td>
										<strong>D3DPRESENT_PARAMETERS</strong>. EnableAutoDepthStencil</td>
								<td>Depth-stencil buffer creation flag.</td>
								<td>true.</td>
						</tr>
				</tbody>
		</table>
		<br />应用程序可以通过参数传递给CreateDevice来更多的控制设备的创建，这将比使用缺省的方式更好。例如，你可以通过nSuggestedWidth and nSuggestedHeight参数改变窗口的尺寸。<br />DXUTCreateDevice(<br />    D3DADAPTER_DEFAULT,<br />    false,<br />    1024,<br />    786,<br />    NULL,<br />    NULL,<br />    NULL<br />);<br />要得到更多的控制权，应用程序可以使用这两个可选的回调函数，LPDXUTCALLBACKISDEVICEACCEPTABLE and LPDXUTCALLBACKMODIFYDEVICESETTINGS.<p><font size="4"><a name="选择最佳的设备设置"></a>选择最佳的设备设置</font><br />你可以使用IsDeviceAcceptable回调函数帮助框架为你的应用程序选择最佳的设备设置，就像下面的代码：<br />bool CALLBACK IsDeviceAcceptable(<br />D3DCAPS9*     pCaps,<br />D3DFORMAT     AdapterFormat,<br />D3DFORMAT     BackBufferFormat,<br />bool          bWindowed,<br />void*         pUserContext )<br />{<br />    // TODO: return true for acceptable settings and false otherwise.<br />    return true;<br />}<br />这个回调函数的模型基于LPDXUTCALLBACKISDEVICEACCEPTABLE原型(This callback function is modeled on the prototype LPDXUTCALLBACKISDEVICEACCEPTABLE)，框架为每个唯一的以下5个设置的有效组合调用这个函数一次：<br />D3DDEVTYPE DeviceType;<br />UINT       AdapterOrdinal;<br />D3DFORMAT  AdapterFormat;<br />D3DFORMAT  BackBufferFormat;<br />bool       Windowed;<br />注意适配器序号和设备类型没有直接的传入回调函数，而是分别作为D3DCAPS9结构体的成员。<br />通过这个回调函数，应用程序可以拒绝任何它不支持的或不想要的组合。例如，应用程序可以使用下面的代码拒绝16bits的后备缓冲区格式和所有至少不能支持像素着色器PS_2_0的设备： <br />bool CALLBACK IsDeviceAcceptable(<br />    D3DCAPS9*     pCaps,<br />    D3DFORMAT     AdapterFormat,<br />    D3DFORMAT     BackBufferFormat,<br />    bool          bWindowed )<br />{<br />    if( pCaps-&gt;PixelShaderVersion &lt; D3DPS_VERSION(2,0) )<br />     return false;<br />    if( BackBufferFormat == D3DFMT_X1R5G5B5 || BackBufferFormat == D3DFMT_R5G6B5 )<br />        return false;<br />    return true;<br />}</p><p>为每个唯一的组合调用回调函数后，框架排列剩下的可用组合，并选择它们当中最好的。排名较高的如下：<br />D3DDEVTYPE_HAL，获取硬件加速<br />如果应用程序以全屏模式显示，框架更趋向于使用匹配桌面格式的适配器格式，这样可以在全屏与窗口之间快速切换。例外的是，如果桌面显示模式小于32位，框架更趋向于D3DFMT_X8R8G8B8.<br />匹配适配器格式的后备缓冲区格式<br />在选择了这些排名高的组合后，要创建设备，行为标志和呈现参数仍然是需要的。对于这些设置,Direct3D使用上面表中的缺省值。</p><p><font size="4"><a name="修改可用的设备设置"></a>修改可用的设备设置</font><br />应用程序可以通过使用第二个可选的回调函数修改对框架可用的设置，这个函数是ModifyDeviceSettings:<br />bool CALLBACK ModifyDeviceSettings(<br />    DXUTDeviceSettings* pDeviceSettings,<br />    const D3DCAPS9*     pCaps )<br />{<br />    // TODO: Include device creation requirements here.  <br />    // 返回真创建设备返回False保持当前设置<br />    return true;<br />}<br />这个函数是基于原型LPDXUTCALLBACKMODIFYDEVICESETTINGS的。DXUTDeviceSettings结构体被框架定义为：<br />struct DXUTDeviceSettings<br />{<br />    UINT       AdapterOrdinal;<br />    D3DDEVTYPE DeviceType;<br />    D3DFORMAT  AdapterFormat;<br />    DWORD      BehaviorFlags;<br />    D3DPRESENT_PARAMETERS pp;<br />};</p><p>这个结构体包含了创建设备所需要的所有东西，除了窗口句柄,它被假定为先前创建的窗口的句柄。框架用有效的数据填充这个结构体，然后允许应用程序通过ModifyDeviceSettings回调函数改变设备创建的选择。<br />在这个回调函数中，应用程序可以在DXUTDeviceSettings结构体中改变行为标志以及呈现参数,乃至结构体中任何其它的东西。如果应用程序在回调函数中什么都不改变，设备会成功的创建。然而，对设备创建设置的任何改变都需要被设备支持，否则可能会导致设备创建失败。<br />比如，如果应用程序需要一个D3DFMT_D24S8的深度模板缓冲区格式，就必须验证设备是否支持，就像下面的代码：<br />bool CALLBACK ModifyDeviceSettings(<br />    DXUTDeviceSettings* pDeviceSettings,<br />    const D3DCAPS9*     pCaps )<br />{<br />    IDirect3D9* pD3D = DXUTGetD3DObject();<br />    if( SUCCEEDED( pD3D-&gt;CheckDeviceFormat(<br />         pDeviceSettings-&gt;AdapterOrdinal,<br />         pDeviceSettings-&gt;DeviceType,<br />         pDeviceSettings-&gt;AdapterFormat,<br />         D3DUSAGE_DEPTHSTENCIL,<br />         D3DRTYPE_SURFACE,<br />         D3DFMT_D24S8 ) ) )<br />    {<br />     if( SUCCEEDED( pD3D-&gt;CheckDepthStencilMatch(<br />             pDeviceSettings-&gt;AdapterOrdinal,<br />             pDeviceSettings-&gt;DeviceType,<br />             pDeviceSettings-&gt;AdapterFormat,<br />             pDeviceSettings-&gt;pp.BackBufferFormat,<br />             D3DFMT_D24S8 ) ) )<br />     {<br />         pDeviceSettings-&gt;pp.AutoDepthStencilFormat = D3DFMT_D24S8;<br />     }<br />    }<br />    <br />    return true;<br />}</p><p>候选的方案是，回调函数可以使用框架的CD3DEnumeration 对象验证D3DFMT_D24S8是否被支持：<br /> bool CALLBACK ModifyDeviceSettings(<br />    DXUTDeviceSettings* pDeviceSettings,<br />    const D3DCAPS9*     pCaps )<br />{<br />    CD3DEnumeration *pEnum = DXUTGetEnumeration();<br />    CD3DEnumDeviceSettingsCombo *pCombo;<br /> <br />    pCombo = pEnum-&gt;GetDeviceSettingsCombo( pDeviceSettings );<br /> <br />    if( pCombo-&gt;depthStencilFormatList.Contains( D3DFMT_D24S8 ) )<br />        pDeviceSettings-&gt;pp.AutoDepthStencilFormat = D3DFMT_D24S8;<br />        <br />    return true;<br />}</p><p>应用程序修改了设备的设置后，框架就会用新的设置创建设备。<br />DirectX April 2005 SDK Update中的更新，ModifyDeviceSettings 回调函数返回了一个bool值。如果应用程序返回true框架继续正常的创建设备。如果返回false框架不改变设备并且保持当前的设备，如果已经有一个存在的话。这允许应用程序能够拒绝框架将设备改变到程序不能使用的请求。例如，在多监视器的缺省配置下，在监视器之间拖动窗口会导致框架改变设备。然而，如果应用程序不能使用其它的设备的话，它应当可以拒绝改变，并继续使用当前的设备。</p><p><font size="4"><a name="回降到软件顶点处理"></a>回降到软件顶点处理</font><br />如果你设置一个Direct3D设备到支持像素处理却不支持顶点处理的硬件，你会因此需要改变行为标志。为了确保正确地降到软件顶点处理，谨防你不能拒绝一个基于IsDeviceAcceptable回调函数中顶点着色器版本的设备，并确保行为标志在ModifyDeviceSettings 回调函数中被正确调整。这儿有一个例子演示怎样做这些事情。<br />bool CALLBACK ModifyDeviceSettings( DXUTDeviceSettings* pDeviceSettings, <br />                                    const D3DCAPS9* pCaps )<br />{<br />    // If device doesn't support HW T&amp;L or doesn't support 1.1 vertex <br />    // shaders in HW, then switch to SWVP.<br />    if( (pCaps-&gt;DevCaps &amp; D3DDEVCAPS_HWTRANSFORMANDLIGHT) == 0 ||<br />         pCaps-&gt;VertexShaderVersion &lt; D3DVS_VERSION(1,1) )<br />    {<br />        pDeviceSettings-&gt;BehaviorFlags = D3DCREATE_SOFTWARE_VERTEXPROCESSING;<br />    }</p><p>    else<br />    {<br />        pDeviceSettings-&gt;BehaviorFlags = D3DCREATE_HARDWARE_VERTEXPROCESSING;<br />    }<br />    <br />    return true; <br />}</p><p><font size="4"><a name="使用你自己的设备"></a>使用你自己的设备</font><br />你没有必要依赖于框架来创建Direct3D设备。应用程序自己可以创建设备并将他传递给框架使用。就像应用程序可以覆盖框架的window creation 设置。简单的使用你想要的设置创建一个设备，然后调用 DXUTSetDevice函数让框架在你的设备上渲染。<br />注意：如果应用程序创建了不依赖于框架的设备，那么应用程序也必须在主循环执行完以后亲自的通过cleanup 释放设备接口。<br />另请参阅<br />通过DXUT作更高级的设备选择</p><img src ="http://www.cppblog.com/mybios/aggbug/15531.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-22 11:35 <a href="http://www.cppblog.com/mybios/archive/2006/11/22/15531.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>【转贴】EffectFramework</title><link>http://www.cppblog.com/mybios/archive/2006/11/20/15464.html</link><dc:creator>李锦俊(mybios)</dc:creator><author>李锦俊(mybios)</author><pubDate>Mon, 20 Nov 2006 08:54:00 GMT</pubDate><guid>http://www.cppblog.com/mybios/archive/2006/11/20/15464.html</guid><wfw:comment>http://www.cppblog.com/mybios/comments/15464.html</wfw:comment><comments>http://www.cppblog.com/mybios/archive/2006/11/20/15464.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/mybios/comments/commentRss/15464.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mybios/services/trackbacks/15464.html</trackback:ping><description><![CDATA[
		<p>
				<font face="宋体">
						<strong>Effect Framework</strong>
				</font>
		</p>
		<p>
				<strong>
						<font face="宋体">摘要</font>
				</strong>
		</p>
		<p>
				<font face="宋体">本文简要介绍了在DirectX 9 SDK中提供的Effect Framework支持，以及DirectX FX文件结构和Microsoft Hight Level Shading Language的基本知识。本文假定读者对DirectX Graphics有一定了解，并正在学习DirectX Effect Framework。希望能够与各位读者共同探讨、切磋。 </font>
		</p>
		<p>
				<font face="宋体">
						<strong>简介 </strong>
				</font>
		</p>
		<p>
				<font face="宋体">Effect的起源 </font>
		</p>
		<p>
				<font face="宋体">在计算机3维场景中，物体表面的材质代表了其光学特性。最简单的材质可以表现为Diffuse颜色，Specular颜色，Emissive颜色等信息的集合；而为了表现物体表面的细节，可以 在材质中加入一张纹理——这些就构成了最基本的材质信息。在以前的Direct3D程序中，这些信息可以直接传送给设备，由设备自动根据它们来计算物体表面的光学效果。但是， 仅仅有这些基本的材质信息，已经不足以满足游戏制作者的要求和游戏玩家的要求了——他们希望场景中的材质更加复杂，具有更多的细节，更加逼真。 </font>
		</p>
		<p>
				<font face="宋体">在Direct3D中，除了材质的概念，还存在一个渲染状态（Render State）的概念。在Direct3D Device中存在很多的渲染状态，它们可以在Direct3D进行渲染时控制渲染的流程和效 果，从而实现某些带有特效的材质。程序员可以通过IDirect3DDevice*::SetRenderState()方法来设置这些状态。所有的渲染状态都是一些特定的数值。对状态的设置可以通过硬 编码完成，即在程序中调用SetRenderState()方法，将设置什么样的状态“写死”在程序里，但是这样做的缺点就是太不灵活了——如果想要实现一种新的渲染状态，就需要修改 程序代码。所以更好的一种方法是将为了实现某一种特效材质的一些渲染状态值记录到一个“效果文件”中，通过在程序运行时读取该文件，从中分析出这些值，并将它们作为参 数调用SetRenderState()。这样，要想实现一种新的特效，只需修改“效果文件”而不用更改代码。 </font>
		</p>
		<p>
				<font face="宋体">Direct3D SDK是通过Effect Framework来支持这种机制的。而前面所述的“效果文件”在Direct3D中是以*.fx文件存在的。在fx文件中保存了为实现某一特效的渲染状态，包括状态名 称和它们的对应值。所以在9.0以前版本的DirectX中就已经有Effect Framework和FX文件了，早期的Effect Framework仅仅是为了实现对渲染状态进行控制。 但是随着计算机显示硬件技术的发展，图形处理单元（GPU）正在重复CPU所走过的路——新一代的GPU已经具有了可编程特性，程序员可以通过对GPU编写一段程序来控制其渲染的 输出效果。这种程序一般称为Shader程序。目前的Shader程序分成两种，Vertex Shader和Pixel Shader。Vertex Shader主要用于对3维网格模型的每一个顶点进行处理，而Pixel Shader主要用于对要绘制到屏幕上的每一个象素进行处理。通过Shader，程序员可以制作出相当丰富的实时渲染效果。</font>
		</p>
		<p>
				<font face="宋体">同CPU一样，对GPU编程也是借助一定的编程语言来进行的。 </font>
				<font face="宋体">在DirectX 8中，对GPU的编程是通过一种类似于汇编的语言进行的。而在DirectX 9中，使用了一种类似于C语言的高级语言——Microsoft High Level Shading Language (HLSL) 。</font>
		</p>
		<p>
				<font face="宋体">无论使用什么语言对GPU编程，都需要把编译好的Shader程序输送到显卡去。Direct3D Device可以通过SetVertexShader()和SetPixelShader()来向显卡输送Shader程序。然而，由 于Shader和材质具有十分紧密的关系——一般来说，一个Shader就是为了实现一种特殊的材质——最好是能够将Shader程序与材质进行整合。 所以，在DirectX 8和DirectX 9中，原来的Effect Framework发生了扩充——在原来的基础上加入了对Shader程序的支持。程序员可以把Vertex Shader和Pixel Shader程序以函数 的方式直接书写在FX文件中。</font>
		</p>
		<p>
				<font face="宋体"> .FX文件</font>
		</p>
		<p>
				<font face="宋体">FX文件中的内容大致可以分成几部分： </font>
		</p>
		<ul>
				<li>
						<font face="宋体">预编译标志 </font>
				</li>
				<li>
						<font face="宋体">变量表 </font>
				</li>
				<li>
						<font face="宋体">结构定义 </font>
				</li>
				<li>
						<font face="宋体">函数 </font>
				</li>
				<li>
						<font face="宋体">Technique </font>
				</li>
		</ul>
		<p>
				<font face="宋体">预编译标志：预编译标志包括 </font>
		</p>
		<ul>
				<li>
						<font face="宋体">#define </font>
				</li>
				<li>
						<font face="宋体">#elif </font>
				</li>
				<li>
						<font face="宋体">#else </font>
				</li>
				<li>
						<font face="宋体">#endif </font>
				</li>
				<li>
						<font face="宋体">#error </font>
				</li>
				<li>
						<font face="宋体">#if </font>
				</li>
				<li>
						<font face="宋体">#ifdef </font>
				</li>
				<li>
						<font face="宋体">#ifndef </font>
				</li>
				<li>
						<font face="宋体">#include </font>
				</li>
				<li>
						<font face="宋体">#line </font>
				</li>
				<li>
						<font face="宋体">#pragma </font>
				</li>
				<li>
						<font face="宋体">#undef </font>
				</li>
		</ul>
		<p>
				<font face="宋体">其中最常用到的是#include和#define，同C语言中的意义很相似：用#include可以在一个FX文件中引入另外一个或多个文件。#define可以定义FX文件中的宏替换。例如： </font>
		</p>
		<table cellspacing="5" cellpadding="0" width="500" bgcolor="#e0e0e0" border="0">
				<tbody>
						<tr>
								<td>
										<p>
												<span class="unnamed2">
														<font face="宋体">#include "helper_Funcs.fx"</font>
												</span>
												<font face="宋体">     <span class="unnamed1">//引入一个名为helper_funcs.fx的fx文件</span><br /><span class="unnamed2">#include "public_variables.fh</span>" <span class="unnamed1">//引入一个名为public_variables.fh的文件</span><br /><span class="unnamed2">#define MATRICES_COUNT 25</span>      <span class="unnamed1">//定义宏MATRICES_COUNT为25</span><br /><span class="unnamed2">#define VSHADER VShader_2_0</span>    <span class="unnamed1">//定义宏VSHADER为VShader_2_0</span></font>
										</p>
								</td>
						</tr>
				</tbody>
		</table>
		<p>
				<font face="宋体">#include带来的好处和C中也是一样的－您可以在一个头文件中定义一些公有变量、函数等，在其他文件中引用它们－就不用写很多遍了。例如： </font>
		</p>
		<p>
				<font face="宋体">文件public.fh: </font>
		</p>
		<table cellspacing="5" cellpadding="0" width="500" bgcolor="#e0e0e0" border="0">
				<tbody>
						<tr>
								<td>
										<p>
												<span class="unnamed2">
														<font face="宋体">mat4x4</font>
												</span>
												<font face="宋体"> matWorldViewProj; <span class="unnamed1">// 4x4世界－视－投影变换矩阵</span><br /></font>
												<span class="unnamed2">
														<font face="宋体">float3</font>
												</span>
												<font face="宋体"> lightPosisiton;   <span class="unnamed1">// 三维光源位置向量</span><br /><span class="unnamed2">float4</span> lightColor;     <span class="unnamed1">  // 光源的颜色</span><br /><span class="unnamed2">float</span> time;              <span class="unnamed1">// 当前时间</span></font>
										</p>
								</td>
						</tr>
				</tbody>
		</table>
		<p>
				<font face="宋体">//定义一个名为VS_OUTPUT的结构。关于结构体定义，下文中会有介绍 <br /></font>
		</p>
		<table width="500" bgcolor="#e0e0e0" border="0">
				<tbody>
						<tr>
								<td>
										<span class="unnamed2">
												<font face="宋体">struct</font>
										</span>
										<font face="宋体"> VS_INPUT <br />{<br />    <span class="unnamed2">float4</span> LocalPos : POSITION; <br />    <span class="unnamed2">float3</span> Normal : NORMAL; <br />    <span class="unnamed2">float4</span> Color : COLOR; <br />    <span class="unnamed2">float2</span> Texcoord : TEXCOORD0; <br />};</font>
								</td>
						</tr>
				</tbody>
		</table>
		<p>
		</p>
		<table cellspacing="0" cellpadding="0" width="500" bgcolor="#e0e0e0" border="0">
				<tbody>
						<tr>
								<td>
										<span class="unnamed2">
												<font face="宋体">struct VS_OUTPUT</font>
										</span>
										<font face="宋体">
												<br />{<br />   <span class="unnamed2"> float4</span> WorldPos : POSITION;<br />    <span class="unnamed2">float4</span> Color : COLOR; <br />    <span class="unnamed2">float2</span> Texcoord : TEXCOORD0; <br />}; </font>
								</td>
						</tr>
				</tbody>
		</table>
		<p>
		</p>
		<p>
				<font face="宋体">//定义一个名为CaculateWorldPosition的函数。关于函数定义，下文中会有介绍 <br /></font>
		</p>
		<table cellspacing="0" cellpadding="0" width="500" bgcolor="#e0e0e0" border="0">
				<tbody>
						<tr>
								<td>
										<span class="unnamed2">
												<font face="宋体">float3</font>
										</span>
										<font face="宋体"> CaculateWorldPosition( <span class="unnamed2">float4</span> LocalPos ) <br />{<br />    <span class="unnamed2">return</span> mul( LocalPos, matWorldViewProj); <br />}</font>
								</td>
						</tr>
				</tbody>
		</table>
		<p>
		</p>
		<p>
				<font face="宋体">这样，当我们在另外一个文件中include这个头文件时，上面所有的定义都可以直接使用了。 </font>
		</p>
		<p>
				<font face="宋体">文件client.fx: </font>
		</p>
		<table cellspacing="0" cellpadding="0" width="500" bgcolor="#e0e0e0" border="0">
				<tbody>
						<tr>
								<td>
										<p class="unnamed2">
												<font face="宋体">#include "public.fh" </font>
										</p>
										<p>
												<font face="宋体">
														<br />
														<span class="unnamed2">VS_OUTPUT</span> VS_main( VS_INPUT In ) <span class="unnamed1">// 可以直接使用结构体定义VS_OUTPUT和VS_INPUT </span><br />{ <br />    VS_OUTPUT Out = 0; <br />    Out.WorldPos = CaculateWorldPosition( In.LocalPos ); <span class="unnamed1">// 可以直接使用函数</span><br />    Out.Color = In.Color; <br />    Out.Texcoord = In.Texcoord; <br />} </font>
										</p>
								</td>
						</tr>
				</tbody>
		</table>
		<p> </p>
		<font face="宋体">
				<p>这样不仅可以复用代码，还可以使变量名、结构体、函数名的定义统一。 </p>
				<p>而#define不仅仅可以使某些常量具有比较有意义的名称，通过与#ifdef，#ifndef, #else, #endif等结合使用，还可以用来根据一些配置控制编译过程。 </p>
				<p>变量表</p>
				<p>每个FX文件都可以有若干参数变量，通过Effect Framework可以在程序中识别出这些参数的类型、名称和用途，这样就可以将程序中的一些参数输送到Effect中去，从而更加灵活 的控制效果。参数的类型很多，可以是int, float, matrix, texture等等。例如： </p>
		</font>
		<table cellspacing="0" cellpadding="0" width="500" bgcolor="#e0e0e0" border="0">
				<tbody>
						<tr>
								<td>
										<span class="unnamed2">
												<font face="宋体">matrix</font>
										</span>
										<font face="宋体"> matWorld;    <span class="unnamed1">//定义一个名为matWorld的矩阵类型参数变量</span><br /><span class="unnamed2">float</span> time;         <span class="unnamed1">//定义一个名为time的浮点类型参数变量 </span><br /><span class="unnamed2">texture</span> texDiffuse; <span class="unnamed1">//定义一个名为texDiffuse的纹理类型参数变量</span></font>
								</td>
						</tr>
				</tbody>
		</table>
		<font face="宋体">
				<p> </p>
				<p>另外，每个变量还有前缀修饰符、Semantic、Annotation等，限于篇幅，在这里不再赘述，具体的介绍请参考DirectX C++帮助文档的DirectX Graphics &gt; Reference &gt; HLSL Shader Reference &gt; Variable Declaration Syntax条目。 </p>
				<p>结构定义</p>
				<p>在FX文件中可以定义结构体，这些结构体一般用于Shader函数的参数和返回值。结构体的定义与C语言方式及其类似，例如： </p>
		</font>
		<table cellspacing="0" cellpadding="0" width="500" bgcolor="#e0e0e0" border="0">
				<tbody>
						<tr>
								<td>
										<span class="unnamed2">
												<font face="宋体">struct</font>
										</span>
										<font face="宋体"> VS_OUTPUT <span class="unnamed1">//结构名称 </span><br />{ <br />    <span class="unnamed2">float4</span> Pos : POSITION; <span class="unnamed1">//成员变量。</span><br />    <span class="unnamed2">float4</span> Color : COLOR; <br />   <span class="unnamed2"> float2</span> Texcoord : TEXCOORD0; <br />}; </font>
								</td>
						</tr>
				</tbody>
		</table>
		<font face="宋体">
				<p> </p>
				<p>上面每个成员变量后面的标识符是该变量的semantic，HLSL编译器根据这个标识符来确定该变量的用处。不一定非得是结构体成员变量才有semantic，一般来说Shader的输入输出参数变量都可以有semantic。</p>
				<p>函数</p>
				<p>函数部分是在Effect Framework加入了对Vertex Shader和Pixel Shader的扩充后才加入到FX文件中的。FX文件中的函数的内容可以用汇编形式书写，也可以用HLSL编写。目前一般 都是使用HLSL。用这种语言书写的函数与C语言函数十分类似，可以说，只要学过C语言，书写Shader函数就绰绰有余了。在同一个fx文件中可以定义很多函数，在函数中也可以互 相调用，但是最终Shader程序的入口将在fx文件的Technique部分中指定。对于哪个函数是Vertex shader函数，哪个是Pixel shader函数，也是在Technique中指定的。关于Technique，将在下文中介绍。 例子： </p>
		</font>
		<table cellspacing="0" cellpadding="0" width="500" bgcolor="#e0e0e0" border="0">
				<tbody>
						<tr>
								<td>
										<p>
												<span class="unnamed2">
														<font face="宋体">float4</font>
												</span>
												<font face="宋体"> CalcDiffuseColor( float3 Normal ) <br />{ <br />    <span class="unnamed2">float4</span> Color; ...<span class="unnamed1">//用于实现该函数功能的多条语句 </span><br />    <span class="unnamed2">return</span> Color; <br />} </font>
										</p>
										<p>
												<span class="unnamed2">
														<font face="宋体">VS_OUTPUT</font>
												</span>
												<font face="宋体"> Vertex_Shader( <span class="unnamed2">float4</span> InPos : POSITION, <br />                         <span class="unnamed2">float3</span> InNor : NORMAL, <br />                         <span class="unnamed2">float3</span> InTexcoord : TEXCOORD ) <br />{ <br />    <span class="unnamed2">VS_OUTPUT</span> Out; ...<span class="unnamed1">//用于实现该函数功能的多条语句 </span><br />    Out.Color = CalcDiffuseColor(InNor);<span class="unnamed1"> //函数调用 </span><br />    <span class="unnamed2">return</span> Out; <br />}</font>
										</p>
								</td>
						</tr>
				</tbody>
		</table>
		<font face="宋体">
				<p> </p>
				<p>正如上文中所说，Shader程序分为两种：Vertex shader和Pixel shader。在fx函数中就有两种相应的函数：Vertex shader函数和Pixel Shader函数。Vertex shader函数的输入参数是网格模型中的每一个顶点数据，其输出是经过该函数特殊处理的顶点数据；而Pixel Shader函数的输入，则是经过硬件光栅化过程后经过插值的Vertex shader输出结果。至于Pixel shader的输出，一般就是经过该函数计算得到的一个颜色值，即要画到后备缓冲中一个象素上的颜色值。但是这个“颜色值”有时并不一定代表颜色。而且对于支持多RenderTarget的硬件，Pixel shader还可以有多个输出，分别对应不同的RenderTarget。</p>
				<p>technique </p>
				<p>technique是FX文件的主体，是真正设置各种渲染状态的地方，也是指定所使用的Shader程序入口的地方。在理解Technique前首先要理解Pass的概念。Pass是Technique的组成部分 ，一个Pass就代表了绘制时的一遍。通常为了达到一种效果，仅仅绘制一遍网格模型是不够的，需要向framebuffer中多次绘制，并利用设置渲染状态中的BlendState进行Alpha混合。这就是经常提到的“Muli-pass Rendering”。但是随着硬件越来越强大，Shader程序的功能越来越强，目前的趋势是所有的特效材质都将可以用越来越少个Pass来完成。 一个technique中，可以存在一个或多个Pass，但是至少要有一个Pass时该technique才会起实际作用。当存在多个pass时，默认情况下在渲染时将会按照pass在文件中的前后顺序 作为渲染时的前后顺序。technique和Pass中的内容都是以大括号括起来。 </p>
				<p>technique的例子： </p>
		</font>
		<table cellspacing="0" cellpadding="0" width="500" bgcolor="#e0e0e0" border="0">
				<tbody>
						<tr>
								<td>
										<span class="unnamed2">
												<font face="宋体">technique</font>
										</span>
										<font face="宋体"> Tec_Shader_1_X <span class="unnamed1">//定义一个名为Tec_Shader_1_X的technique </span><br />{ <br />    pass P0 <span class="unnamed1">//一个名为P0的pass</span><br />    { <br />        VertexShader = compile vs_1_1 Vertex_Shader();<span class="unnamed1"> //设置Vertex Shader程序入口函数 </span><br />        PixelShader = compile ps_1_1 Pixel_Shader();   <span class="unnamed1">//设置Pixel Shader程序入口函数 </span><br />        AlphaBlendEnable= true;                       <span class="unnamed1"> //设置渲染状态        </span><br />        SrcBlend = SrcAlpha;  <br />        DestBlend = InvSrcAlpha; <br />        ... <span class="unnamed1">//其他设置</span><br />    } <br />    pass P1<span class="unnamed1"> //一个名为P1的pass</span><br />    { <br />        ... <br />    } <br />} </font>
								</td>
						</tr>
				</tbody>
		</table>
		<font face="宋体">
				<p> </p>
				<p>
						<strong>ID3DXEffect接口</strong>
				</p>
				<p>上面介绍了很多fx文件相关内容，但是在程序中如何读取和分析这些fx文件呢？在程序中对于读取fx文件，控制渲染状态、设置Shader程序等工作都是通过D3DX库中的ID3DXEffect接口来实现的。ID3DXEffect接口提供了大量的方法，基本上分为几个方面： </p>
				<ul>
						<li>获得Effect参数变量信息 
</li>
						<li>设置Effect参数变量 
</li>
						<li>获得technique信息 
</li>
						<li>设置当前使用的technique 
</li>
						<li>开始和结束使用当前的technique 
</li>
						<li>执行一个pass（渲染绘制遍） </li>
				</ul>
				<p>ID3DXEffect接口的创建： 通过D3DX库中的D3DXCreateEffectFromFile()函数，可以根据一个指定的文件的内容来创建一个ID3DXEffect接口。在该函数执行成功后，所创建的接口中就包含了文件里所对应的 所有内容，包括参数变量表、Shader程序、technique和pass等。 </p>
				<p>ID3DXEffect接口的使用： 通过该接口的方法可以获得FX文件中的所有信息，并设置参数变量和当前的technique。所有的参数变量、technique、pass、shader等等都有自己的名称，根据这些名称，通过调用ID3DXEffect::GetParameterByName()、ID3DXEffect::GetTechniqueByName()和ID3DXEffect::GetPassByName()等方法就可以获得这些对象的句柄，从而在调用 ID3DXEFFECT::Set***()进行设置时使用句柄而不是字符串进行索引来提高效率。</p>
				<p>通过ID3DXEffect::GetParameterDesc()、ID3DXEffect::GetTechniqueDesc()和GetPassDecs等方 法可以获得关于指定对象的所有细节描述信息。 D3DX库中定义了一个D3DXPARAMETER_DESC结构来专门表示参数的类型。通过ID3DXEffect::GetParameterDesc()方法，可以为一个参数获得这样一个结构的数据。 </p>
		</font>
		<table cellspacing="0" cellpadding="0" width="500" bgcolor="#e0e0e0" border="0">
				<tbody>
						<tr>
								<td>
										<span class="unnamed2">
												<font face="宋体">typedef struct</font>
										</span>
										<font face="宋体"> _D3DXPARAMETER_DESC <br />{ <br />    LPCSTR Name;               //参数变量名 <br />    LPCSTR Semantic;           //参数变量的Semantic <br />    D3DXPARAMETER_CLASS Class; //参数变量的类别，可以是标量、矢量、矩阵、对象和结构 <br />    D3DXPARAMETER_TYPE Type;   //参数变量的类型 <br />    UINT Rows;                 //数组型参数的行数 <br />    UINT Columns;              //数组型参数的列数 <br />    UINT Elements;             //数组中的元素个数 <br />    UINT Annotations;          //参数变量的Annotation个数 <br />    UINT StructMembers;        //结构型参数变量成员的个数 <br />    DWORD Flags;               //参数属性 <br />    UINT Bytes;                //参数大小，以字节记 <br />} D3DXPARAMETER_DESC; </font>
								</td>
						</tr>
				</tbody>
		</table>
		<font face="宋体">
				<p> </p>
				<p>其中的参数类型可以有下列几种： </p>
		</font>
		<table cellspacing="0" cellpadding="0" width="500" bgcolor="#e0e0e0" border="0">
				<tbody>
						<tr>
								<td>
										<span class="unnamed2">
												<font face="宋体">typedef</font>
										</span>
										<font face="宋体"> enum _D3DXPARAMETER_TYPE <br />{ <br />    D3DXPT_VOID, //Void型指针 <br />    D3DXPT_BOOL, //Bool型 <br />    D3DXPT_INT, //整型 <br />    D3DXPT_FLOAT, //浮点型 <br />    D3DXPT_STRING, //字符串 <br />    D3DXPT_TEXTURE, //纹理 <br />    D3DXPT_TEXTURE1D, //一维纹理 <br />    D3DXPT_TEXTURE2D, //二维纹理 <br />    D3DXPT_TEXTURE3D, //三维纹理 <br />    D3DXPT_TEXTURECUBE, //立方体环境纹理 <br />    D3DXPT_SAMPLER, //纹理取样器 <br />    D3DXPT_SAMPLER1D, //一维纹理取样器 <br />    D3DXPT_SAMPLER2D, //二维纹理取样器 <br />    D3DXPT_SAMPLER3D, //三维纹理取样器 <br />    D3DXPT_SAMPLERCUBE, //立方体环境纹理取样器 <br />    D3DXPT_PIXELSHADER, //Pixel Shader程序 <br />    D3DXPT_VERTEXSHADER, //Vertex Shader程序 <br />    D3DXPT_PIXELFRAGMENT, //Pixel Shader片断 <br />    D3DXPT_VERTEXFRAGMENT, //Vertex Shader片断 <br />    D3DXPT_FORCE_DWORD = 0x7fffffff <br />} D3DXPARAMETER_TYPE;</font>
								</td>
						</tr>
				</tbody>
		</table>
		<font face="宋体">
				<p> </p>
				<p>而真正要让Effect起作用，需要在绘制网格模型前后调用ID3DXEffect::BeginPass()和EndPass方法。在调用这两个函数之前和之后，还需调用ID3DXEffect::Begin()和 ID3DXEffect::End()方法来界定此次Effect设置的起止。大致的形式如下： </p>
		</font>
		<table cellspacing="0" cellpadding="0" width="500" bgcolor="#e0e0e0" border="0">
				<tbody>
						<tr>
								<td>
										<p>
												<font face="宋体">LPD3DXEffect pd3dEffect；<span class="unnamed1"> //ID3DXEffect接口指针 </span><br />... <span class="unnamed1">//初始化该指针 </span><br />... <span class="unnamed1">//程序中的其他部分</span><br />... </font>
										</p>
										<p>
												<font face="宋体">UINT numPasses;<span class="unnamed1"> //用于接受当前所使用的technique中的pass个数 </span><br />pd3dEffect-&gt;Begin( &amp; numPasses, 0 ) <span class="unnamed1">//开始使用当前的technique </span><br /><span class="unnamed2">for</span>( UINT iPass = 0; iPass &lt; numPasses; iPass ++ ) <br />{ <br />    <span class="unnamed1">//遍历所有的pass </span><br />    pd3dEffect-&gt;BeginPass( iPass ); <span class="unnamed1">//调用BeginPass </span><br />    DrawMesh();                     <span class="unnamed1">//然后进行模型的绘制。 </span><br />    pd3dEffect-&gt;EndPass();         <span class="unnamed1"> //调用EndPass </span><br />} <br />pd3dEffect-&gt;End();                 <span class="unnamed1"> //不要忘记结束当前technique </span></font>
										</p>
								</td>
						</tr>
				</tbody>
		</table>
		<font face="宋体">
				<p> </p>
				<p>
						<strong>3DS MAX对DirectX 9 Shader Material的支持；Effect数据获取和导出</strong>
				</p>
				<p>在FX文件中的参数，大部分都是用来调整FX文件所指定的Effect的一些细节，例如，一种带有凹凸纹理的效果，可能在FX中就有一个参数控制着凹凸不平的程度。而这些参数是需要由美工来调整的。另外，美工也需要有一个途径能够将FX文件定义的Effect赋予到一个模型或它的一部分上去。同时美工也应该能够实时的预览该Effect在模型上的实际效果。 在以前，实现这些要求只能通过自制效果预览器、模型编辑器或者为DCC软件编写插件来完成。这对于小的工作组和工期较短的项目来说是非常困难的。幸运的是，目前的DCC软件 已经开始为游戏制作提供丰富的支持功能。通过DCC软件自身就可以预览到实时Effect的效果，并调整其参数。在《龙的传说》这个项目中，我们使用3DS MAX 6.0来作为模型建立 工具和Shader预览工具。 </p>
				<p>在3DS MAX 6.0中，新加入了一种材质类型——DirectX 9 Shader材质。这种材质是基于FX文件的。一个FX文件就可以代表一种材质。它可以同MAX中的其他材质一样赋予到模型上 。在MAX的Viewport中可以实时地观察到FX文件中设计的效果。通过为FX中的参数设置特定的Semantic，可以将这些参数与MAX中的场景信息联系起来，如摄像机位置、世界变换矩 阵等。对于控制Effect效果的一些本地参数，可以通过为它们添加特定的Annotation，使MAX能够直接识别这些参数并在用户界面中显示它们的名称和调节控件。对应不同类型的参 数，MAX可以为它们生成不同的调节控件。这样，这种材质就和MAX的其他材质一样，可以更改纹理等等的参数了。 对于美工来说，通过这种用户界面就可以调整该FX材质的参数达到最好的效果。</p>
				<p>但是美工所调整的结果必须要能够保存下来才有意义。这个工作就得由程序员来完成了。要保存3DS MAX中编辑的所有内容，需要为3DS MAX编写文件导出插件，将其内部数据保存在特定格式的文件中。在《龙的传说》这个项目中，我们使用Microsoft DirectX .X 文件。如果从头开始写导出插件，工作量是相当大的；幸运的是，在Microsoft DirectX SDK Extra中提供了一个能够导出模型和3DS MAX标准材质到X文件的插件源代码。通过修改该源代码，可以使它能够导出DirectX 9 Shader材质。在3DS MAX 6 SDK中新增加了一个IDxMaterial接口，通过查询一个IMaterial接口是否为IDxMaterial接口，就可以确定该材质是否为DirectX 9 Shader材质。通过IDxMaterial接口可以获得该材质对应的FX文件的文件名，以及其参数信息。这样就可以将它们导出了。 </p>
				<p>
						<strong>.X文件中对Effect的支持；EffectInstance和EffectDefault</strong>
				</p>
				<p>Microsoft DirectX .X文件的格式是基于模板的、可扩展的文件格式。通过为其制定新的模板，就可以在其中加入新的内容。一般的.X文件中的内容有三维场景的物体层级关系、网格模型几何数据、材质信息、动画信息等。在DirectX的众多X文件模板中有一个模板是专门用来代表Effect的实例的。当一个FX文件的参数被美工加以调整从而具备一些特定的值之后，该 FX文件和这些参数值的集合就形成了一个Effect实例。该模板的定义如下： </p>
		</font>
		<table cellspacing="0" cellpadding="0" width="500" bgcolor="#e0e0e0" border="0">
				<tbody>
						<tr>
								<td>
										<span class="unnamed2">
												<font face="宋体">template</font>
												<font face="宋体">
												</font>
										</span>
										<font face="宋体"> EffectInstance <br />{ <br />    &lt; E331F7E4-0559-4cc2-8E99-1CEC1657928F &gt; <br />    STRING EffectFilename; <br />    [ ... ] <br />} </font>
								</td>
						</tr>
				</tbody>
		</table>
		<font face="宋体">
				<p> </p>
				<p>其中， EffectFilename代表了该Effect实例中的FX文件名， [ ... ]代表在其中可以插入任何X文件模板对应的数据。这样就可以代表任何类型的参数值。 </p>
				<p>然而要想让Direct3D程序能够识别[ ... ]中的内容，需要使用X文件模板中的EffectParam系列模板，包括EffectParamDWord, EffectParamFlaots, EffectParamString。通过这三种模板对应的数据，所有类型的Effect参数值都可以被记录在X文件中。 </p>
				<p>最后，EffectInstance数据需要被放置在Material数据中才可以被识别。</p>
				<p>Material模板： </p>
		</font>
		<table cellspacing="0" cellpadding="0" width="500" bgcolor="#e0e0e0" border="0">
				<tbody>
						<tr>
								<td>
										<span class="unnamed2">
												<font face="宋体">template</font>
										</span>
										<font face="宋体"> Material <br />{ <br />    &lt; 3D82AB4D-62DA-11CF-AB39-0020AF71E433 &gt; <br />    ColorRGBA faceColor; <br />    FLOAT power; <br />    ColorRGB specularColor; <br />    ColorRGB emissiveColor; <br />    [...] <br />} </font>
								</td>
						</tr>
				</tbody>
		</table>
		<font face="宋体">
				<p> </p>
				<p>前面的一些颜色模板表明在Material数据中这些颜色信息是必须有的，而最后的[ ... ]则代表可以插入任何X文件模板对应的数据。我们的EffectInstance数据就可以放置在这里 。 </p>
				<p>举一个简单的例子： </p>
		</font>
		<table cellspacing="0" cellpadding="0" width="500" bgcolor="#e0e0e0" border="0">
				<tbody>
						<tr>
								<td>
										<font face="宋体">Material { <span class="unnamed1">//材质 </span><br />    0.500000;0.500000;0.500000;1.000000;;<span class="unnamed1"> //faceColor</span><br />    0.000000;<span class="unnamed1"> //power</span><br />    0.900000;0.900000;0.900000;;<span class="unnamed1"> //specularColor</span><br />    0.000000;0.000000;0.000000;;<span class="unnamed1"> //emissiveColor</span><br />    EffectInstance <br />    {                            <span class="unnamed1">//[...]，这里是EffectInstance</span><br />        "SkyboxNew01.fx";       <span class="unnamed1"> //fx文件的文件名。通过D3DXCreateEffectFromFile()可以</span><br />                                <span class="unnamed1"> //建立该文件对应的D3DXEffect对象 <br />        //下面是EffectInstance中的[...] </span><br />        EffectParamString <br />        {                        <span class="unnamed1">//EffectParamString，即字符串型参数值</span> <br />            "TexCloudTop";      <span class="unnamed1"> //参数的名称，通过该名称调用ID3DXEffect::GetXXXByName()方法</span><br />                                 <span class="unnamed1">//可以得到与fx文件中对应的参数</span>。 <br />            "DarkClouds01.jpg"; <span class="unnamed1"> //参数的值 </span><br />        } <br />        EffectParamString <br />        {                        <span class="unnamed1">//同上 </span><br />            "TexCloudBottom"; <br />            "DarkClouds02.jpg"; <br />        } <br />        EffectParamFloats <br />        {                       <span class="unnamed1">//EffectParamFloats，即浮点数组型参数值</span><br />            "Brightness";       <span class="unnamed1">//参数名称</span><br />            1;                 <span class="unnamed1"> //浮点数组大小</span><br />            0.500000;          <span class="unnamed1"> //值 </span><br />        } <br />    } <br />} </font>
								</td>
						</tr>
				</tbody>
		</table>
		<font face="宋体">
				<p> </p>
				<p>当我们在程序中调用D3DXLoadMeshFromX()或D3DXLoadMeshHierarchyFromX()时，就可以通过其LPD3DXBUFFER *ppEffectInstances参数来接收到网格所用的所有EffectInstance的信息。</p>
				<p>在程序中，对应于X文件中的EffectInstance模板和EffectParam系列模板，有两个结构体用来代表Effect数据： </p>
		</font>
		<table cellspacing="0" cellpadding="0" width="500" bgcolor="#e0e0e0" border="0">
				<tbody>
						<tr>
								<td>
										<p>
												<span class="unnamed2">
														<font face="宋体">typedef struct</font>
												</span>
												<font face="宋体"> _D3DXEFFECTINSTANCE <br />{ <span class="unnamed1">//EffectInstance</span><br />    LPSTR pEffectFilename; <span class="unnamed1">//fx文件名</span><br />    DWORD NumDefaults; <span class="unnamed1">//参数个数</span><br />    LPD3DXEFFECTDEFAULT pDefaults; <span class="unnamed1">//参数数组</span><br />} D3DXEFFECTINSTANCE, *LPD3DXEFFECTINSTANCE; </font>
										</p>
										<font face="宋体">
												<p>
														<span class="unnamed2">typedef struct </span>_D3DXEFFECTDEFAULT <br />{ <span class="unnamed1">//EffectDefault，即EffectParam </span><br />    LPSTR pParamName;           <span class="unnamed1">//参数名 </span><br />    D3DXEFFECTDEFAULTTYPE Type;<span class="unnamed1"> //参数类型 </span><br />    DWORD NumBytes;             <span class="unnamed1">//参数大小，以字节记 </span><br />    LPVOID pValue;              <span class="unnamed1">//指向参数的值的指针 </span><br />} D3DXEFFECTDEFAULT, *LPD3DXEFFECTDEFAULT; </p>
												<p>需要注意的是，从文件中得到的参数类型只有以下几种： <br /><span class="unnamed2">typedef</span> enum _D3DXEFFECTDEFAULTTYPE <br />{ <br />    D3DXEDT_STRING = 1, <span class="unnamed1">//字符串 </span><br />    D3DXEDT_FLOATS = 2, <span class="unnamed1">//浮点数组 </span><br />    D3DXEDT_DWORD = 3,  <span class="unnamed1">//长整型 </span><br />    D3DXEDT_FORCE_DWORD = 0x7fffffff <span class="unnamed1">//此值不使用 </span><br />} D3DXEFFECTDEFAULTTYPE; </p>
										</font>
								</td>
						</tr>
				</tbody>
		</table>
		<font face="宋体">
				<p> </p>
				<p>在调用了D3DXLoadMeshFromX()和D3DXLoadMeshHierarchyFromX()之后，X文件中的所有Effect数据信息就以上述结构体的形式放置在ppEffectInstances中了。 另外，在从3DS MAX导出参数到X文件时，对于整型和浮点数组型的变量，它们的值将直接导出到X文件中去；而对于所有的纹理贴图文件参数，导出的仅仅是该文件的文件名。所以 在程序中需要再根据这些文件名来建立纹理对象。 在《龙的传说》中，我们使用一个自定义的CEffectInstance类来处理将文件名转换为纹理对象的过程。 一般来说，建立一个完整的CEffectInstance的过程如下： </p>
				<p>根据D3DXEFFECTINSTANCE结构中的pEffectFilename字符串寻找对应的FX文件; <br />根据该FX文件建立ID3DXEffect，并将指针保存在CEffectInstance中; <br />根据D3DXEFFECTINSTANCE结构中的pDefaults设置CEffectInstance中的参数信息： </p>
				<blockquote dir="ltr" style="MARGIN-RIGHT: 0px">
						<p>
								<br />对于长整型和浮点数组，直接拷贝； <br />对于字符串，首先调用ID3DXEffect接口中的GetParameterByName()和GetParameterDesc()方法，得到该参数的类型； 然后进一步判断： </p>
						<blockquote dir="ltr" style="MARGIN-RIGHT: 0px">
								<p>
										<br />如果确实是字符串参数，则直接拷贝 <br />如果是纹理参数，则将该字符串作为纹理文件名建立纹理对象，并将指针保存在CEffectInstance中。 </p>
						</blockquote>
				</blockquote>
				<p>而在最新推出的DirectX 9 SDK Summer 2004中，通过ID3DXEffect::BeginParameterBlock()和ID3DXEffect::EndParameterBlock()方法，我们可以将Effect参数设置过程统一绑定到一个ParamBlock句柄上。这样，在调用ID3DXEffect::Begin()之前就可以直接使用ID3DXEffect::ApplyParameterBlock()方法来设置所有被绑定的参数值。例如： </p>
				<p>[<strong>以前的做法</strong>]： </p>
				<p>在读取参数时：获得每一个参数的句柄 </p>
		</font>
		<table cellspacing="0" cellpadding="0" width="500" bgcolor="#e0e0e0" border="0">
				<tbody>
						<tr>
								<td>
										<font face="宋体">
												<p>hParam1 = pEffect-&gt;GetParameterByName( NULL, "LightPos" ); <br />hParam2 = pEffect-&gt;GetParameterByName( NULL, "LightColor" ); <br />...</p>
												<p class="unnamed1">在实时绘制时：分别设置每一个参数 </p>
												<p>pEffect-&gt;SetValue( hParam1, value1 ); <br />pEffect-&gt;SetValue( hParam2, value2 ); <br />... <br />pEffect-&gt;Begin(); <br /><span class="unnamed1">// 绘制</span><br />... </p>
										</font>
								</td>
						</tr>
				</tbody>
		</table>
		<font face="宋体">
				<p> </p>
				<p>[<strong>在DirectX 9 SDK Summer 2004中的做法</strong>]： </p>
				<p>在读取参数时：绑定所有参数设置到同一句柄 </p>
		</font>
		<table cellspacing="0" cellpadding="0" width="500" bgcolor="#e0e0e0" border="0">
				<tbody>
						<tr>
								<td>
										<p>
												<font face="宋体">hParam1 = pEffect-&gt;GetParameterByName( NULL, "LightPos" ); <br />hParam2 = pEffect-&gt;GetParameterByName( NULL, "LightColor" ); <br />...<br />pEffect-&gt;BeginParameterBlock();<span class="unnamed1"> // 开始绑定</span><br />pEffect-&gt;SetValue( hParam, value1 ); <br />pEffect-&gt;SetValue( hParam, value2 ); <br />... <br />hParamBlock = pEffect-&gt;EndParameterBlock(); <span class="unnamed1">// 结束绑定，返回句柄 </span></font>
										</p>
										<p class="unnamed1">
												<font face="宋体">在实时绘制时：统一设置绑定值 </font>
										</p>
										<font face="宋体">
												<p>pEffect-&gt;ApplyParameterBlock( hParamBlock ); <br />pEffect-&gt;Begin; <br /><span class="unnamed1">// 绘制 </span><br />... </p>
										</font>
								</td>
						</tr>
				</tbody>
		</table>
		<font face="宋体">
				<p> </p>
				<p>这样不仅简化了在读取时对参数的分析过程，而且提高了实际绘制时参数设置过程的效率。 </p>
				<p>
						<strong>总结</strong>
				</p>
				<p>以上就是一些对于在DirectX 9.0中对Effect Framework的使用的简要介绍。总之，使用Effect来替代以前的标准材质是目前实时图形领域的发展趋势。通过Effect Framework，程序员和美工可以为实时三维程序实现多种多样的材质效果和视觉效果。 由于内容实在太多，限于篇幅，本文只是对Effect Framework中相关概念的一个总体概括和简要介绍，所以显得有些晦涩。在以后的文章中，将分批对这个Framework以及在其之上进行工作的流程进行比较详细的介绍。</p>
		</font>
<img src ="http://www.cppblog.com/mybios/aggbug/15464.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 16:54 <a href="http://www.cppblog.com/mybios/archive/2006/11/20/15464.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>我到了游戏开发学习迷惘期，该如何是好？</title><link>http://www.cppblog.com/mybios/archive/2006/11/20/15447.html</link><dc:creator>李锦俊(mybios)</dc:creator><author>李锦俊(mybios)</author><pubDate>Mon, 20 Nov 2006 01:46:00 GMT</pubDate><guid>http://www.cppblog.com/mybios/archive/2006/11/20/15447.html</guid><wfw:comment>http://www.cppblog.com/mybios/comments/15447.html</wfw:comment><comments>http://www.cppblog.com/mybios/archive/2006/11/20/15447.html#Feedback</comments><slash:comments>14</slash:comments><wfw:commentRss>http://www.cppblog.com/mybios/comments/commentRss/15447.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mybios/services/trackbacks/15447.html</trackback:ping><description><![CDATA[        学游戏开发前前后后也有两个星期了。<br />        在这两个星期里，收获甚多，从最几本的经典几何知识到高等数学、线性代数都看了一遍，从Direct3D入门到Shader的编写也看了，甚至还学习了LUA脚本的编写和游戏引擎的架构，BSP、八叉树等等算法也看过了解了一下。<br />        学的东西这么多，但是真正能掌握的又有多少？自己无法掂量啊，那么接下去应该做什么好？很多人说应该做一个DEMO，甚至有人说试着自己做一个游戏引擎，还有人说要我试着做一个网游。<br />        确实，现在应该从实际出发了，要做点东西出来才能把学过的知识牢固掌握。但是，我现在觉得很迷惘，不知道做什么好，我打算春节过后去搞游戏开发，请大虾小虾们都给点意见如何？<img src ="http://www.cppblog.com/mybios/aggbug/15447.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 09:46 <a href="http://www.cppblog.com/mybios/archive/2006/11/20/15447.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>【转贴】Ogre的官僚主义批判</title><link>http://www.cppblog.com/mybios/archive/2006/11/19/15418.html</link><dc:creator>李锦俊(mybios)</dc:creator><author>李锦俊(mybios)</author><pubDate>Sun, 19 Nov 2006 00:40:00 GMT</pubDate><guid>http://www.cppblog.com/mybios/archive/2006/11/19/15418.html</guid><wfw:comment>http://www.cppblog.com/mybios/comments/15418.html</wfw:comment><comments>http://www.cppblog.com/mybios/archive/2006/11/19/15418.html#Feedback</comments><slash:comments>8</slash:comments><wfw:commentRss>http://www.cppblog.com/mybios/comments/commentRss/15418.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mybios/services/trackbacks/15418.html</trackback:ping><description><![CDATA[
		<div class="postbody">
				<p>Ogre的Manager真是多啊,就象个官僚公司,干事的没几个,一堆的Manager,个个丫还都是Singleton.说自己是Singleton却又public构造函数,让人来new它.在第1次被new的时候,偷偷地将this赋给静态成员ms_Singleton,第2次new它就要assert喊冤了,当然这都是叫Singleton的模板基类的那个构造函数干的(典型的小人行径,见不得光).Manager一多,本来不复杂的事,也变得复杂了.</p>
				<p>1.LogManager<br />a.全局单体LogManager组合Log指针Map集合,控制有多个Log对象,1个Log对象表达对一个Log文件的输入(老一套).<br />b.同时LogManager维护1个当前默认主事的Log对象mDefaultLog,以展现Log对象功能而隐藏自己实际是个Manager的身份(邀功自赏,其心可诛).<br />c.维护一个监控者接口LogListener列表,以履行作为一个Manager受外部监督的职责(实为推清责任).</p>
				<p>2.DynLibManager<br />a.全局单体DynLibManager组合DynLib*指针Map集合,控制多个DynLib对象,1个Dynlib表达对动态库的装载和卸载(典型的官僚主义,人浮于事,这点屁事都要有Manager).</p>
				<p>3.ResourceGroupManager<br />  a.全局单体ResourceGroupManager组合ResourceManager指针Map?Manager的Manager,靠,好大的官)<br />  b.一上任就安插了个亲信Manager,建立个叫General的ResourceManager.</p>
				<p>4.SceneManagerEnumerator<br />  a.连它都是系统单体,一个迭代器,小人得志啊,不说了,它可管着一堆SceneManager,惹不起.<br />  b.一开始就安排了什么事都作不了的SceneManager(基类)作默认SceneManager,大事小事都是它,室内室外一手包.</p>
				<p>5.一堆中层干部,一堆的MaterialManager,MeshManager,ParticleSystemManager,SkeletonManager......,都是Singleton,有的还是ResourceManager的门生,一开始都干了2件事.<br />a.定名分:向ResourceGroupManager注册说自己是某方面的Manager,_registerResourceManager.<br />b.要资源:向ResourceGroupManager要求控制对某种脚本的解析_registerScriptLoader(就是瓜分资源).<br />c.有个OverlayManager,ArchiveManager最牛,手下还有几个工厂给它干活,无非是自己作不了,又推给下级.</p>
				<p>6.一堆插件外劳,开始加载,这些外劳到系统中来当然要注册.</p>
				<p>7.透明实体mTransparentObjects按z序排序,不透明实体按material分组.</p>
				<p>8.我一开始认为Materail是个很聪明的概念,后来才发现上当受骗了,它管理了mTechniques数组,而Techniche管理了mPasses数组(Multipass render),最后实质的内容在Pass类中,Pass类表达了一个渲染的环境.由于这个官僚系统实在太官僚,所以按对象每次渲染是不可接受的(跨部门合作太多,相互扯皮),渲染状态切换频繁,效率极低,透明渲染z序混乱.所以需要按Materail分组和z轴分序,而RenderSystem的最重要方法接受RenderOperation参数.</p>
				<p>9.Pass和RenderOperation是两位最能干的劳动人民,都是受人管制的对象,整个系统的灵魂和核心,Pass封装了最重要的渲染状态(即进行glDrawXXX时管线所处的状态,着色系统),RenderOperation封装了带纹理几何渲染操作(glDrawElements几何系统),两者构成一个完整的渲染.即,先,调用SceneManager的setPass(在其中其仍将调用RenderSystem以设置管线状态),再,调用RenderSystem的_render.</p>
				<p>10.SceneManager的虚方法_findVisibleObjects是场景管理的核心,由它将Renderable分组,分透明和不透明分送入不同的渲染队列,Renderable组合RenderOperation和Pass(但出头的都是Materail),然后SceneManager对之排序,整理,送入RenderSystem渲染.</p>
				<p>11.SceneManager的_renderScene是基本渲染核心,它完成若干任务<br />   a.帧动画驱动_applySceneAnimations <br />   b.场景图更新_updateSceneGraph<br />   c.渲染队列更新,_findVisibleObjects更新主场景,_queueOverlaysForRendering更新上层主界面,_queueSkiesForRendering更新天空盒,最后_renderVisibleObjects.</p>
				<p>12.渲染队列RenderQueue,维护std::map&lt;RenderQueueGroupID, RenderQueueGroup*&gt;对象,以表达其内部的多个方面(世界,前景,背景)的渲染分队列.RenderQueueGroup再往下分std::map&lt;ushort, RenderPriorityGroup*, std::less&lt;ushort&gt; &gt;,以表达其(如前景)内部按ushort优先级维护渲染分队列.RenderPriorityGroup维护一个mTransparentPasses,若干个SolidRenderablePassMap.</p>
		</div>
<img src ="http://www.cppblog.com/mybios/aggbug/15418.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 08:40 <a href="http://www.cppblog.com/mybios/archive/2006/11/19/15418.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>【转贴】使用非2次方幂的图像纹理的问题</title><link>http://www.cppblog.com/mybios/archive/2006/11/19/15417.html</link><dc:creator>李锦俊(mybios)</dc:creator><author>李锦俊(mybios)</author><pubDate>Sun, 19 Nov 2006 00:26:00 GMT</pubDate><guid>http://www.cppblog.com/mybios/archive/2006/11/19/15417.html</guid><wfw:comment>http://www.cppblog.com/mybios/comments/15417.html</wfw:comment><comments>http://www.cppblog.com/mybios/archive/2006/11/19/15417.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://www.cppblog.com/mybios/comments/commentRss/15417.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mybios/services/trackbacks/15417.html</trackback:ping><description><![CDATA[
		<div class="postbody">
				<p>图像使用2次方是很讨厌的问题,不在技术难度上,而在技术妥协上.实际上要求美工作出2次方纹理,并且整张图的空间利用率要高,是很难的.<br />当有些策划丢过来奇奇怪怪的尺寸的图像,我都要吐血,当知道2n次方限制后,他们把图像尺寸扩大一下,再丢给我空余大量空白的2n次方纹理,再吐血.</p>
				<p>玻璃渣资源里标准的2n次方人物纹理,图像挤的满满的,每个身体部位纹理还是一个矩形,利用率之高不得不令人佩服,然而这对美工要求是极高的.<br />1024*768的图像是要拆成4*3的256*256图像的,而不是一整大张纹理,因为768不是2的n次方,更不要扩大为1024*1024,加大25%的内存.<br />还有Wow里Loading界面的图像都压成512*512,因为Loading图像模糊一点不要紧,很简单却都是很重要的细节.<br />所以当Wow运行在我Geforce2的显卡上时,我觉的很cool.</p>
				<p>Nvidia的驱动程序也很讨厌,实际Geforce6显卡才支持non power of two texture,Geforce 5200级的显卡,在硬件能力上不足以支持NPOT,但是最新的驱动程序使用了软件模式进行模拟支持,而软件模拟根本毫无实用价值,渲染变得超级缓慢,因为驱动程序每次纹理渲染都会很聪明地把非2次方尺寸图像自动Scale到2次方尺寸,对于一个800*600的图像,驱动程序在这个步骤就吃光了CPU.<br />所以总有些人喊着为什么OpenGL没有软件渲染支持,DX很体贴都有(实际上DX也没有,比如那个所谓的8层纹理),而我认为如果软件渲染能解决问题,那要硬件作什么!不能解决问题的方案我们支持它作什么!</p>
				<p>// OpenGL动态执行2n次方图像限制<br />inline int next_p2(int a)<br />{<br /> int rval=1;<br /> while(rval&lt;a) rval&lt;&lt;=1;<br /> return rval;<br />}</p>
				<p>int nWidthPowerOfTwo = next_p2(tex.nWidth);<br />int nHeightPowerOfTwo = next_p2(tex.nHeight);</p>
				<p>if(tex.nWidth == nWidthPowerOfTwo  &amp;&amp;  tex.nHeight == nHeightPowerOfTwo)<br />{ <br /> glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, nWidthPowerOfTwo, nHeightPowerOfTwo, 0, ilGetInteger(IL_IMAGE_FORMAT), GL_UNSIGNED_BYTE, ilGetData());<br /> tex.fScaleX = tex.fScaleY = 1.0f;<br />} <br />else<br />{ <br /> glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, nWidthPowerOfTwo, nHeightPowerOfTwo, 0, ilGetInteger(IL_IMAGE_FORMAT), GL_UNSIGNED_BYTE, NULL);<br /> glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, tex.nWidth, tex.nHeight, ilGetInteger(IL_IMAGE_FORMAT), GL_UNSIGNED_BYTE, ilGetData());<br /> tex.fScaleX = (float)tex.nWidth / (float)nWidthPowerOfTwo;<br /> tex.fScaleY = (float)tex.nHeight/ (float)nHeightPowerOfTwo;<br />}<br /><br />然而对这个问题,正确的解决方案是事先规划,强制执行,be clever.</p>
		</div>
<img src ="http://www.cppblog.com/mybios/aggbug/15417.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 08:26 <a href="http://www.cppblog.com/mybios/archive/2006/11/19/15417.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>【转贴】数据打包格式</title><link>http://www.cppblog.com/mybios/archive/2006/11/19/15416.html</link><dc:creator>李锦俊(mybios)</dc:creator><author>李锦俊(mybios)</author><pubDate>Sun, 19 Nov 2006 00:17:00 GMT</pubDate><guid>http://www.cppblog.com/mybios/archive/2006/11/19/15416.html</guid><wfw:comment>http://www.cppblog.com/mybios/comments/15416.html</wfw:comment><comments>http://www.cppblog.com/mybios/archive/2006/11/19/15416.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/mybios/comments/commentRss/15416.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mybios/services/trackbacks/15416.html</trackback:ping><description><![CDATA[
		<div align="left">　　游戏运行和显示的速度固然重要，不过我认为，在游戏中另外一个速度：游戏装入的速度也同样不可轻视。试想一个游戏，动不动就要装入数据，而且每次装入的时间都令人等到“心越来越慌”的地步，我想恐怕也没有什么人愿意玩下去的。<br /><br />　　选择一个好的打包数据格式，对于编程人员来说，是一件很重要的事情。一般来说，一个游戏的文件个数太多，并不是一件好事情，不光占用的硬盘空间大，而且严重的影响装入速度。不过这样做的优点也很明显：可以很详细的分类，可以大大的减小编程人员的工作量。另外一种做法是，把所有的数据全部放在一个文件里面，这样的做法和上面一种做法的优缺点正好相反，装入速度比较快（因为只要做一次文件打开的操作），但是由于所有数据都放在一起，文件数据的组织比较复杂，要求编程人员花费大量的精力去定位数据的格式和存放位置。因此，选择一个合适的数据打包格式，实际上就是在这两种情况之间选择一个平衡点，使它既不会对游戏的装入速度造成明显的影响，也不会给编程人员带来额外的负担。<br /><br />　　那么，对于一个游戏来说，数据应该怎么组织呢？其实现在有很多好的游戏，参考一下他们的数据文件就会发现这个平衡点其实很好找。现在大多数的游戏，基本上把游戏需要用到的数据分门别类的存放，每一类数据放在一个文件里面。比如说音乐放在一个文件里面，地形图素放在一个文件里面，精灵造型、动画放在一个文件里面，游戏需要用到的图片放在一个文件里面，人物的对话、事件说明放在一个文件里面……那么这些数据在文件里面怎么组织呢？<br /><br />　　还是一句话：分门别类。下面以游戏最基本的地形图素为例，说明数据的组织形式。一般说来，游戏的地图由很多大大小小的“图素”组成的，这些图素分为几层，每一层的图素基本上可以算作一类：比如说地面层可以算作一类，地上层可以算作一类，然后天空层（背景层）可以算作一类，部队、物品可以算作一类。而在地面层里面，又可以进一步的分类，比如说地形有山地，沙漠，草原，森林，河流，海洋……在游戏中，是可以分为场景的，一般的情况下，每个场景所涉及到的地形不会很多，总是以某一类典型地行为主，然后加入少量其他的地形作为点缀。针对这种情况，我们可以把同一类的地形连续的放在文件的某一个位置，这样我们在装入场景的时候，只要在这个位置一次读取这种地形的数据就可以了。一般游戏在制作的过程中都有一个场景生成器，或者叫作拚图器，它的作用就是生成地图——或者说生成场景。这个拚图器在初期的时候读人的数据肯定不是已经打包了的，因为美术还要对地形的基本图素进行某些修改。<br /><br />　　所以我认为，好的数据打包格式应该是基于拚图器的，他把每一种数据分门别类的连续存放在某一个文件之中或者文件的某一个位置，这样能够大大的加快程序读取数据的速度。这样几能够使游戏文件看起来很简洁，也会大大的有利于程序的开发。<br /></div>
<img src ="http://www.cppblog.com/mybios/aggbug/15416.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 08:17 <a href="http://www.cppblog.com/mybios/archive/2006/11/19/15416.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>