﻿<?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;-随笔分类-3D引擎开发</title><link>http://www.cppblog.com/mybios/category/3310.html</link><description>游戏开发 C++ Cocos2d-x OpenGL DirectX 数学 计算机图形学 SQL Server
&lt;BR&gt;
&lt;BR&gt;</description><language>zh-cn</language><lastBuildDate>Sun, 17 Jul 2016 20:51:58 GMT</lastBuildDate><pubDate>Sun, 17 Jul 2016 20:51:58 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>使用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>魔兽争霸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>关于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>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>这段时间开发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></channel></rss>