﻿<?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++博客-Code Knight</title><link>http://www.cppblog.com/winmain/</link><description>Programming is so cool</description><language>zh-cn</language><lastBuildDate>Fri, 03 Apr 2026 17:26:37 GMT</lastBuildDate><pubDate>Fri, 03 Apr 2026 17:26:37 GMT</pubDate><ttl>60</ttl><item><title>搬家去博客园了</title><link>http://www.cppblog.com/winmain/archive/2010/05/16/115510.html</link><dc:creator>Code Knight</dc:creator><author>Code Knight</author><pubDate>Sun, 16 May 2010 04:57:00 GMT</pubDate><guid>http://www.cppblog.com/winmain/archive/2010/05/16/115510.html</guid><wfw:comment>http://www.cppblog.com/winmain/comments/115510.html</wfw:comment><comments>http://www.cppblog.com/winmain/archive/2010/05/16/115510.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/winmain/comments/commentRss/115510.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/winmain/services/trackbacks/115510.html</trackback:ping><description><![CDATA[<a href="http://www.cnblogs.com/CodeKnight/">http://www.cnblogs.com/CodeKnight/</a>
<img src ="http://www.cppblog.com/winmain/aggbug/115510.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/winmain/" target="_blank">Code Knight</a> 2010-05-16 12:57 <a href="http://www.cppblog.com/winmain/archive/2010/05/16/115510.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>一道面试题</title><link>http://www.cppblog.com/winmain/archive/2010/04/12/112332.html</link><dc:creator>Code Knight</dc:creator><author>Code Knight</author><pubDate>Mon, 12 Apr 2010 07:55:00 GMT</pubDate><guid>http://www.cppblog.com/winmain/archive/2010/04/12/112332.html</guid><wfw:comment>http://www.cppblog.com/winmain/comments/112332.html</wfw:comment><comments>http://www.cppblog.com/winmain/archive/2010/04/12/112332.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/winmain/comments/commentRss/112332.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/winmain/services/trackbacks/112332.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 最近面试遇到一道很怀念的题目，约瑟夫环，由于代码较多没有当时写在卷上，说了说思路，下来用模板实现了一下，使用双向循环链表，每到第五个kick out。注：模板未考虑非常规自定义类型的浅拷贝问题；另外代码没有优化，delnode效率有提升空间，有兴趣的改改看。&nbsp;&nbsp;1template&lt;class&nbsp;T&gt;&nbsp;&nbsp;2struct&nbsp;SNo...&nbsp;&nbsp;<a href='http://www.cppblog.com/winmain/archive/2010/04/12/112332.html'>阅读全文</a><img src ="http://www.cppblog.com/winmain/aggbug/112332.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/winmain/" target="_blank">Code Knight</a> 2010-04-12 15:55 <a href="http://www.cppblog.com/winmain/archive/2010/04/12/112332.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>LUA小记</title><link>http://www.cppblog.com/winmain/archive/2010/03/29/110919.html</link><dc:creator>Code Knight</dc:creator><author>Code Knight</author><pubDate>Mon, 29 Mar 2010 13:58:00 GMT</pubDate><guid>http://www.cppblog.com/winmain/archive/2010/03/29/110919.html</guid><wfw:comment>http://www.cppblog.com/winmain/comments/110919.html</wfw:comment><comments>http://www.cppblog.com/winmain/archive/2010/03/29/110919.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/winmain/comments/commentRss/110919.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/winmain/services/trackbacks/110919.html</trackback:ping><description><![CDATA[1，从luastate中取出LUA开放给C++调用的函数，arg[1]得到的总是LUA函数所带的参数个数，而arg[2]才是该LUA函数的第一个参数。<br>2，dostring可以直接用"a(1, 2)&#8220;的字符串来调用LUA开放给C++调用的诸如function a(x, y)的函数。
<img src ="http://www.cppblog.com/winmain/aggbug/110919.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/winmain/" target="_blank">Code Knight</a> 2010-03-29 21:58 <a href="http://www.cppblog.com/winmain/archive/2010/03/29/110919.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>CryEngine</title><link>http://www.cppblog.com/winmain/archive/2010/03/07/109136.html</link><dc:creator>Code Knight</dc:creator><author>Code Knight</author><pubDate>Sun, 07 Mar 2010 11:50:00 GMT</pubDate><guid>http://www.cppblog.com/winmain/archive/2010/03/07/109136.html</guid><wfw:comment>http://www.cppblog.com/winmain/comments/109136.html</wfw:comment><comments>http://www.cppblog.com/winmain/archive/2010/03/07/109136.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/winmain/comments/commentRss/109136.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/winmain/services/trackbacks/109136.html</trackback:ping><description><![CDATA[<p>CryEngine系列引擎玩家们并不陌生，从最初的单机游戏《孤岛惊魂》、《孤岛危机》到目前火热的网游《永恒之塔》等一系列大作都是由该系列1到2代引擎打造，目前，Crytek已经发布了该系列的第三代引擎&#8220;CryEngine 3&#8221;。</p>
<p>　　如下是最新公布的一段&#8220;CryEngine 3&#8221;引擎制作FPS游戏地图视频，从制作到演示仅长8分钟，看了让人瞠目结舌，唏嘘不已。</p>
<embed height=370 type=application/x-shockwave-flash pluginspage=http://www.macromedia.com/go/getflashplayer width=480 src=http://vhead.blog.sina.com.cn/player/outer_player.swf?auto=0&amp;vid=25220063&amp;uid=1503278774 allowscriptaccess="never" allowNetworking="internal" invokeurls="false" allownetworking="internal" allowfullscreen="true"></embed></object> 
<img src ="http://www.cppblog.com/winmain/aggbug/109136.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/winmain/" target="_blank">Code Knight</a> 2010-03-07 19:50 <a href="http://www.cppblog.com/winmain/archive/2010/03/07/109136.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转载]（观点）郎咸平与中国网游</title><link>http://www.cppblog.com/winmain/archive/2010/02/28/108627.html</link><dc:creator>Code Knight</dc:creator><author>Code Knight</author><pubDate>Sun, 28 Feb 2010 12:21:00 GMT</pubDate><guid>http://www.cppblog.com/winmain/archive/2010/02/28/108627.html</guid><wfw:comment>http://www.cppblog.com/winmain/comments/108627.html</wfw:comment><comments>http://www.cppblog.com/winmain/archive/2010/02/28/108627.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/winmain/comments/commentRss/108627.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/winmain/services/trackbacks/108627.html</trackback:ping><description><![CDATA[<p>转载自：<a href="http://data.gameres.com/article.game?id=139036" target=_blank><u><font color=#0066cc>http://data.gameres.com/article.game?id=139036</font></u></a><br>--------------------------------------</p>
<p>这篇文章纯属是去年看郎教授的讲座后的一时冲动，陆续写了很久。但很多观点现在看来值得商榷，可能是当时太激动了，就顺着郎教授的理论往下分析了一下。修改的工作量太大也没时间就放弃了，原样贴出来供大家参考。<br>---------------------------------------<br>产业链战争中的中国游戏业<br><br>《产业链阴谋》<br>在万众欢腾的北京奥运会闭幕后不久，一本名为《产业链阴谋》的图书悄悄进入市场，引发了一阵热潮。郎咸平教授再次向公众传输了他的新思想，让因生活在&#8220;世界工厂&#8221;而无比骄傲的国人用另一种视角重新看世界，重新认识中国制造业。随着年底金融海啸下南方工厂的大批倒闭及外汇储备的大量贬值，这种思想显得越来越珍贵。<br>而与此同时，中国网游业却一枝独秀，在寒冬中逆市增长，而且自主研发的市场占有率达到59%。形势似乎一片大好，情况真的是这样吗?<br>-------------------------------------------------------------<br>与制造业的相同点<br><br>中国企业家进口机器设备，利用廉价劳动力与原料，按照外国的配方或技术标准生产大量廉价商品，大部分出口。我们的企业更像是代工厂。而游戏业的情况又怎么样呢？来看看我们的一天吧。<br>在珠三角的代工厂，工人们按照标准开始生产X-box360主机的芯片、主板与外壳，技术架构与标准是IBM、ATI、SiS联合制定的，时尚的外观是美国旧金山的Astro Studios和日本大阪的Hers Experimental共同设计的。工厂把成品上交给新加坡公司伟创力、台湾公司纬创、以及加拿大公司天弘，最后交给微软验收，运往全世界的销售网点。<br>在上海育碧分公司，中国员工正忙着给X360游戏《末日战争》制作图像素材，有的负责模型，有的制作贴图，有的制作动画。<br>在北京某公司的游戏研发项目组，策划清一色使用着Microsoft的Office制作一个个扩展名为Doc、Xls的文件，程序员使用 Microsoft的VisualStudio2005，以ISO的ISO C为标准，或者直接在买来的Ogre、BigWorld或UE3引擎基础上略加修改，美工使用Painter、PS、3DSmax不断流水线生产出大批素材。<br>在上海的某网吧，网游消费者像往常一样打开以Intel、Nvidia芯片为核心+国产外围配件的电脑，进入Microsoft的 WindowsVista操作系统，路由器自动分配了一个符合IPv6标准的IP地址，消费者使用微软的IE进入美国发明的Internet，连接到电信服务商的IBM服务器再连接到目标网站的服务器，不久打开一个国产网游，实际采用了Ogre、BigWorld或UE3引擎+Microsoft的数据库+国产外皮。<br><br>一句话：我们按照美国标准代工制造了大量游戏机、按照外国人的要求为次世代游戏制作了很多美术素材，这些产值也能算入GDP与出口总额中去，但我们却没有得到任何实惠，国家没有正式的次世代主机市场，我们的企业无缘次世代。我们使用美国的工具软件按照美国的技术标准生产了一大堆国产网游，我们的消费者使用着美国标准的电脑玩着美国标准的国产网游，我们早已习以为常。<br>最早在中国设立研发中心的国际游戏巨头育碧，最终已将中国作为外包基地，主要是次世代美术。中国员工成了外企降低研发成本的重要环节。还有东星、维塔士、 EPIC等。产品多是家用游戏机的游戏，纯粹用于出口，因为国内没有这个市场。《生化震荡》《末日战争》等越来越次世代游戏中出现了国人的身影。以《洛城大灾难》这款X-box游戏为例，由美国总部进行游戏架构与视觉风格设计，香港工作室（Enlight Hong Kong Studio）负责编程与详细美术设定，而美术执行部分全部来自大陆工作室（Enlight China Studio），包括建模、贴图、骨骼动画与过场动画制作。也就是说，中国残存的单机游戏产业也就是美术外包了，这一点上就是IT民工，与广东那些造鞋造玩具的工厂没有本质区别，简直就是殖民地。只剩下大宇等寥寥几家还在苦苦支撑，其他的要么倒闭要么转型为网游。<br>这些情况是不正常的。金山董事长求伯君说过：&#8220;世界上没有哪一个民族愿意把作为信息产业灵魂的软件产业完全建立在他人的智慧上。全世界优秀软件的决战更是一种文化的碰撞，一场智慧的较量！&#8221;<br><br>从技术的角度讲，游戏产业链由硬件与软件两部分组成，分为芯片、操作系统、API、引擎与工具、硬件代工与软件外包，核心是摩尔定律。美国掌握着世界硬件的走向，摩尔定律推动着硬件的不断升级，也间接推动游戏技术的不断进化，次世代游戏的出现刺激人们升级硬件或购买新机器，于是一个软硬件互相促进的产业链形成了。CSDN社区有一种观点：软件产业基本形成&#8220;三梯队&#8221;的国际分工格局，外国牢牢控制着技术标准，决定技术的未来走向，攫取高额利润。美国掌握了最先进的软件技术，控制着软件开发平台和软件工具，在全球软件产业链中居于领先地位，如DX11、VS2008、3DSMax2009、 Office2007。而中国企业在技术竞争力上与外国巨头的差距是越来越大了。<br>中国消费者可以不买国产品牌的电脑，但却不得不在兼容机中使用Intel的酷睿2CPU，Nvidia的GeForce显卡，微软的 WindowsVista。中国玩家可以不玩外国游戏，但国产游戏中已经有不少用的是外国的Ogre、BigWorld或UE3引擎。核心技术永远操于敌手，我们只是生产外皮+组装而已。<br>我们的确生活在太平盛世，但也的确生活在没有硝烟的产业链战争之中，无声无息之中已经蕴含了无限杀机。核心技术操于敌手就是中国游戏业与制造业的共性。<br>-------------------------------------------------------<br>与制造业的差异<br><br>中国社会科学院研究员王立强认为，在开放的过程中，发展中国家的最大损失还不是国外的订单，而是自己的市场资源。5%的市场流失对国家发展就构成伤害，超过10%就构成实质性伤害，超过30%就可以造成无法弥补的伤害。我们国家的GDP每年都在以两位数的速度递增，进出口总额屡创新高。但中国进出口总额的 60%都来自外资企业或外资控股企业，其中高科技产品高达80%。国务院研究发展中心的研究报告指出，在中国已开放的产业中，每个产业排名前5位的企业几乎都由外资控制：中国28个主要产业中，外资在21个产业中拥有多数资产控制权。巨额利润被国外企业攫取，中国制造业的利润率仅2%，严重影响中国企业的积累与再循环能力，而且严重威胁国家的战略安全。而游戏业的情况与之不同。<br>中国游戏业的主体是网游，占据了99%。而网游与单机是不同的，这个市场暂时不是殖民地。中国网游市场暂时没有对外开放，而处于政府管制之中，政府就是巨大的保护伞，国家的一些政策限制了它的发展，也限制了外资的进入，所以目前民族产业发展较快。GameRES论坛上，有些资深从业者尖锐的指出：目前民族产业处于闭关自守下抢占国内市场的阶段。<br>在保护伞下，外资难以完全控制产业链，产业价值大部分流向本土企业。由于外资不能以任何方式参与运营，只能寻找本土的运营商进行合作，外国研发商的分成比例大约是25%，所以网游的产值没有完全流向外国，代理型企业的利润率是30%，自主研发的网游公司利润率达到60%以上。在2004年代理盛行的时候，外国游戏一度占据了市场的90%，吸走了大量资金。目前自主研发占据了59%，资金回笼的比例越来越大，情况对本土有利。即便是九城这样的纯代理型企业，在暴雪的盘剥之下，三年来通过《魔兽世界》也积累了10亿资金，保持了充裕的现金流，为日后自主研发转型奠定了雄厚的基础。<br><br>产业链也可以分为：电信运营商、游戏研发商、运营商、渠道商、媒体。产业链的上游是工具与流行内容，其中热门影视与文学外资没有控制，反而是国内企业通过收购控制了其中一部分，如盛大的起点文学网（盛大文学）。外资在工具占优势，掌控了大部分关键基础工具与平台，如WindowsVista、 VisualStudio2008、UE3、WACOM绘图板、酷睿2、高级服务器，这些是国内无力掌握的；中游是研发，外国占优势，但由于文化差异，外国游戏在国内的竞争力相对减弱了，在自主研发能力不断提高的今天，民族企业的对外依赖度大大降低，代理时的议价能力也相对提高，可以与对方进行博弈，代理难度也相对降低了；而下游是运营，外资无法介入，只能获得一部分分成。<br>与此同时，盛大等公司已经开始整合产业链，如上游的网游引擎、文学网，中游的工作室并购与合作，下游的渠道扩张与海外出口。在产业链战争中的战斗力指数正在不断增强。这些优势是外企无法获得的。<br>抛开复杂的技术问题，换一个视角，产业链战争的关键在于资金的流向。从资金的角度来看，外国势力在上游赚取了工具的钱，在中游获得了一些代理费，在下游获得了25%的运营分成。所以整体上，产业价值的六成以上都回到国内，产业链战争中我方占主导，有利于民族企业自身的资金积累与循环，而这恰恰是产业实力不断增强的关键。资金大部分流向国内就是中国游戏业与制造业的最大差异。<br>-----------------------------------------------------------<br>长远发展的隐患<br><br>表面上，中国游戏业取得了胜利，但除去政府的保护、国外的引擎与工具之外，又有几分功劳可以归功于自己的强大实力呢？<br>从品牌的角度来看，中国的知名游戏品牌还是太少，还有没世界级的游戏大作。这个问题始终难以解决，而这个问题不解决，民族网游企业就像是暴发户而不是世界公认的顶尖游戏商。自主研发的瓶颈有很多。而这几年的《劲舞团》《魔兽世界》代理权的恶性竞争事件恰恰说明了民族企业的实力薄弱。<br>从另一个角度看，中国IT业已经败了，软件业的85%、硬件的大半都已经不属于我们了。我们生存在外国的技术标准之下，处于产业链的下游与外缘，南北差异巨大，不对等。网游市场的局部胜利不能改变IT市场整体的劣势。<br>没有人能否认这个行业规模很大，发展迅速，但很多人都认为我们还是个弱国。没有自己的核心技术、平台、国际大作、王牌制作人、知名研发团队、大发行商，所以很难称为游戏强国，而只是殖民地或即将成为殖民地。<br>什么是游戏强国？日本有着NDS、Wii、PS3平台，以此平台标准按照标准游戏类型打造的众多标准化王牌游戏，全世界的游戏公司都要跟着这个标准开发并销售产品，软硬件共同创造巨大的产值。制定硬件标准、标准游戏类型，制定规则是一流企业的选择，这种优势是难以在短期赶上的。强国需要长期的渐进的积累，无数细节的锤炼，大跃进无用。美国日本这些强国用了38年时间才形成目前的局面。中国游戏业才不过14年，而且发展受到大环境限制，与国外差距巨大。<br><br>在政府的保护伞下，民族产业获得了暂时的主导地位。但问题在于，一旦这个市场的开放程度扩大，如外资可以以合资公司或独资公司方式参与运营，那么以暴雪的狼子野心来推测，整个产业价值流向外国的比例会大大提高，民族企业受到极大冲击。<br>中国有不少产业都是在市场的不断开放中被外资控制的，如化妆品、油料、机械、胶卷。民族企业的实力还不够强，就像是小孩子与职业拳击手对战，败多胜少。从这个角度来看，网游业与其他行业的情况极为类似，不同的是这个行业还处于保护伞之下，没有完全开放。但总会有开放的一天的。<br>中国网游业的发展近几年已经逐渐慢下来了，市场规模总有一天会走向停滞。它不会无限扩张下去，成熟的网游市场必然是低增长、低利润率与高竞争的。到那个时候，中国游戏业会走向哪里？<br><br>中国的游戏市场与任何国家都不相同，它以200亿元的网游市场为表层，以上千亿的元的家用机、掌机、PC单机地下水货、盗版市场为里层。目前国内企业只能从表层市场赚钱，而对地下市场无能为力。那个地下市场寄托着玩家对各平台单机游戏的热爱、有限收入的无奈、与对行业现状的妥协，也象征着未来发展的方向。虽然单机游戏业由盛转衰，彻底消亡，但人们的热情越发炽烈。<br>中国网游业的产值在全球游戏业中之占6%，我们始终与巨大的家用游戏机与掌机市场隔绝。我们的产业结构是世界上独一无二的中国特色的，没有哪个国家是如此地依赖网游。如今自主研发网游的瓶颈正与单机发展不力的情况密切相关，经验不足，缺乏可以利用的游戏原型，而只是一窝蜂地随大流，缺乏自己的独到思考与创造力。2004年匿名人士的一篇火爆网络引发无数转载的奇文《一篇令所有游戏圈的兄弟汗颜的文章》中说的已经很透彻了。<br>中国网游业能否在未来成为世界第一，还值得商榷。假设成功了，那时中国也未必就是游戏强国。因为网游在全球游戏业只是小弟，无法彻底取代庞大的单机市场。<br>单机游戏如何从如今的美术外包转向未来的重建国内单机游戏市场，杀入国际家用游戏机与掌机市场，这是未来必然要面临的问题。这也是中国要成为世界公认游戏强国的最大障碍。未来的产业链上游是游戏基础工具、平台制造、流行内容；中游是各平台各类型游戏研发；下游是销售、运营、培训、游戏衍生产业。那时的产业链战争会更加精彩，中国真正与国际接轨，在产业链战争中成为游戏强国。<br>--------------------------------------------------<br>参考资料<br>《产业链阴谋》作者：郎咸平<br>《利用外资八思》（来自《瞭望新闻周刊》）<br>《一篇令所有游戏圈的兄弟汗颜的文章》作者：网络匿名人士<br>《迷茫的程序员和中国软件业》（来自CSDN）作者：wfwonde (逆风沉沦) <br>阿健的动漫游戏教室（来自天涯博客）<br>百度百科<br>-----------------------------------------------</p>
<img src ="http://www.cppblog.com/winmain/aggbug/108627.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/winmain/" target="_blank">Code Knight</a> 2010-02-28 20:21 <a href="http://www.cppblog.com/winmain/archive/2010/02/28/108627.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转]CEGUI中的汉字显示实现</title><link>http://www.cppblog.com/winmain/archive/2010/02/27/108576.html</link><dc:creator>Code Knight</dc:creator><author>Code Knight</author><pubDate>Sat, 27 Feb 2010 13:38:00 GMT</pubDate><guid>http://www.cppblog.com/winmain/archive/2010/02/27/108576.html</guid><wfw:comment>http://www.cppblog.com/winmain/comments/108576.html</wfw:comment><comments>http://www.cppblog.com/winmain/archive/2010/02/27/108576.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/winmain/comments/commentRss/108576.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/winmain/services/trackbacks/108576.html</trackback:ping><description><![CDATA[<p>几日前，用&nbsp;<wbr>CEGUI做界面，发现无法应用CEGUI的window中setText()函数直接显示中文。上网google一下，原来经过简单的字符转化可以显示中文（偷着乐，CEGUI太方便了）。</p>
<p>&nbsp;<wbr></p>
<p>方法如下（引用）：http://blog.csdn.net/kun1234567/archive/2008/04/11/2282761.aspx</p>
<p>CEGUI使用utf8编码格式。这就意味着我们可以很简单的就显示中文。</p>
<p>&nbsp;<wbr></p>
<p>1、弄个包含中文的字体，在这里我借用大多数例子里的 &#8220;C：/windows/Font/simhei.ttf&#8221;文件。把这个文件拷贝到Datafiles文件夹的Font文件夹里。</p>
<p>&nbsp;<wbr></p>
<p>2、随便照着一个 .Font文件，自己写一个simhei.font文件。可以用TXT写，然后保存，有的朋友说需要保存为utf8编码格式，实际上是不需要的。</p>
<p>&nbsp;<wbr></p>
<p>3、同时注意修改你加载到程序里的scheme文件，将里面的字体文件设置成simhei.ttf。你也可以继续使用FirstWindow这个例子，这样的话直接修改源代码里的字体为simhei.tff。</p>
<p>&nbsp;<wbr></p>
<p>4、现在在程序里进行字符编码转换，我拿代码说明问题：</p>
<p>&nbsp;<wbr></p>
<p>std::wstring aa = L"123中文abcあいうえお";</p>
<p>char buff[128] = "";</p>
<p>WideCharToMultiByte( CP_UTF8, 0, aa.c_str(), aa.size(), buff, sizeof(buff), 0, 0);</p>
<p>button1-&gt;setText ( CEGUI::String ( CEGUI::utf8* )buff );</p>
<p>&nbsp;<wbr></p>
<p>原理是这样的，对于utf8来说，英文字符和ansi编码在内存布局上没什么区别，都是一个UCHAR。但是对于非英文字符，则是UCHAR+UCHAR+UCHAR。如果我们手工进行编码格式转换，会比较烦琐。</p>
<p>&nbsp;<wbr></p>
<p>比较偷懒的方法就是，我们先用WCHAR(unicode内存布局,UCHAR+UCHAR+UCHAR+UCHAR)来储存需要显示的字符串，然后调用Win32API来帮我们把宽字符转换成char(多字节字符集内存布局)。</p>
<p>&nbsp;<wbr></p>
<p>这就是基本方法了，然后我们可以根据这个转换方针，利用Win32API随意的转换字符编码格式，从而满足程序中的各种需求。</p>
<p>&nbsp;<wbr></p>
<p>&nbsp;<wbr></p>
<p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 通过此方法可以显示中文，还没来得急高兴就发现了第二个问题：这种方法显示中文速度太慢（显示几十个字需要等上7、8秒左右）。难道没有高效的方法吗？</p>
<p>于是继续Google(我很懒，别人能做的事情从来不麻烦自己，懒得跟踪代码)，结果还真让我找到了两篇相关的文章：一份是千里马肝的《游戏中汉字显示的实现与技巧》，另一份是免费打工仔的《让OGRE支持中文》。从中找到了原因：</p>
<p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 原来在游戏中，是将点阵字库或tif字体里的文字写进纹理，根据需求贴到指定的位置。英文的显示非常简单，只有26个字母，就算再加一些标点、符号什么的，用一张位图，就可以足以显示所有的单词了。而中文要像处理英文那样，把所有的汉字都保存在一张位图里，那么每一种字体都要生成一个巨型位图。在 GB2312中，一共有6000多个汉字，就算是用16*16，据说会有2.5M！（马肝兄说的，我没算过）</p>
<p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 继续Google，也没有找到解决问题的直接办法，唉，再懒也得自己上阵了。</p>
<p>通过跟踪调试，发现了问题所在，原来罪魁祸首就是他：</p>
<p>&nbsp;<wbr></p>
<p align=left>const FontGlyph *Font::getGlyphData (utf32 codepoint)</p>
<p align=left>{</p>
<p align=left>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> if (codepoint &gt; d_maxCodepoint)</p>
<p align=left>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> return 0;</p>
<p align=left>&nbsp;<wbr></p>
<p align=left>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> if (d_glyphPageLoaded)</p>
<p align=left>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> {</p>
<p align=left>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> uint page = codepoint / GLYPHS_PER_PAGE;</p>
<p align=left>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> uint mask = 1 &lt;&lt; (page &amp; (BITS_PER_UINT - 1));</p>
<p align=left>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> if (!(d_glyphPageLoaded [page / BITS_PER_UINT] &amp; mask))</p>
<p align=left>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> {</p>
<p align=left>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> d_glyphPageLoaded [page / BITS_PER_UINT] |= mask;</p>
<p align=left>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> rasterize (codepoint &amp; ~(GLYPHS_PER_PAGE - 1),</p>
<p align=left>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> codepoint | (GLYPHS_PER_PAGE - 1));</p>
<p align=left>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> }</p>
<p align=left>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> }</p>
<p align=left>&nbsp;<wbr></p>
<p align=left>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> CodepointMap::const_iterator pos = d_cp_map.find (codepoint);</p>
<p align=left>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> return (pos != d_cp_map.end()) ? &amp;pos-&gt;second : 0;</p>
<p>}</p>
<p>&nbsp;<wbr></p>
<p>原来CEGUI根据Unicode字符的编码顺序，为每256个字符分配一张纹理（例如编码0-255存放在纹理一，编码768-1023 存放在纹理四）。英文很容易搞定了，那么几个字符一张纹理就够了，可中文就得靠运气了，有时显示几个字就要生成几张纹理，还要将每张纹理用不需要的相邻字填满，劳民伤财！</p>
<p>发现了问题，我便按照千里马肝的思想对函数进行了改造，将使用的文字放入一张纹理中，因为纹理最大承载256个字，所以，当汉字超过256个时，则将不常用的去掉，将新的字符写入。</p>
<p>后来我发现汉字的引用没有太多的规律，常用的一千多汉字出现的概率没有那么悬殊（废话，要不怎么是常用呢!），没有办法很好地按照使用的频率将汉字限制在256个字以内，写进纹理，就索性一旦满了就将字全部释放掉，重新写入。（也需有我没找到，还请高手指教）</p>
<p>代码如下：</p>
<p align=left>const FontGlyph *Font::getGlyphData (utf32 codepoint)</p>
<p align=left>{</p>
<p align=left>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> if (codepoint &gt; d_maxCodepoint)</p>
<p align=left>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> return 0;</p>
<p align=left>&nbsp;<wbr></p>
<p align=left>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> if(codepoint &lt; 256)&nbsp;<wbr> //决定保留一张纹理放英文和字符</p>
<p align=left>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> {</p>
<p align=left>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> if (d_glyphPageLoaded)</p>
<p align=left>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> {</p>
<p align=left>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> uint page = codepoint / GLYPHS_PER_PAGE;</p>
<p align=left>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> uint mask = 1 &lt;&lt; (page &amp; (BITS_PER_UINT - 1));</p>
<p align=left>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> if (!(d_glyphPageLoaded [page / BITS_PER_UINT] &amp; mask))</p>
<p align=left>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> {</p>
<p align=left>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> d_glyphPageLoaded [page / BITS_PER_UINT] |= mask;</p>
<p align=left>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> rasterize (codepoint &amp; ~(GLYPHS_PER_PAGE - 1),</p>
<p align=left>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> codepoint | (GLYPHS_PER_PAGE - 1));</p>
<p align=left>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> }</p>
<p align=left>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> }</p>
<p align=left>&nbsp;<wbr></p>
<p align=left>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> CodepointMap::const_iterator pos = d_cp_map.find (codepoint);</p>
<p align=left>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> return (pos != d_cp_map.end()) ? &amp;pos-&gt;second : 0;</p>
<p align=left>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> }</p>
<p align=left>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> else //显示汉字啦</p>
<p align=left>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> {</p>
<p align=left>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> CodepointMap::const_iterator pos;</p>
<p align=left>&nbsp;<wbr></p>
<p align=left>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> pos = d_hz_map.find (codepoint);</p>
<p align=left>&nbsp;<wbr></p>
<p align=left>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> if(pos != d_hz_map.end())</p>
<p align=left>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> {</p>
<p align=left>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> return (pos != d_hz_map.end()) ? &amp;pos-&gt;second : 0;</p>
<p align=left>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> }</p>
<p align=left>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> else</p>
<p align=left>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> {</p>
<p align=left>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> rasterizeHZ(codepoint);</p>
<p align=left>&nbsp;<wbr></p>
<p align=left>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> pos = d_hz_map.find (codepoint);</p>
<p align=left>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> return (pos != d_hz_map.end()) ? &amp;pos-&gt;second : 0;</p>
<p align=left>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> }</p>
<p align=left>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> }</p>
<p align=left>}</p>
<p align=left>&nbsp;<wbr></p>
<p align=left>void FreeTypeFont::rasterizeHZ (utf32 codepoint)</p>
<p align=left>{</p>
<p align=left>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> int num;</p>
<p align=left>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> uint texsize = 512;</p>
<p align=left>&nbsp;<wbr></p>
<p align=left>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> if(d_hz_map.size() &lt; 256)</p>
<p align=left>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> {</p>
<p align=left>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> float adv = d_fontFace-&gt;glyph-&gt;metrics.horiAdvance * float(FT_POS_COEF);</p>
<p align=left>&nbsp;<wbr></p>
<p align=left>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> d_hz_map[codepoint] = FontGlyph (adv);</p>
<p align=left>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> }</p>
<p align=left>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> else</p>
<p align=left>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> {</p>
<p align=left>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> d_hz_map.clear();</p>
<p align=left>&nbsp;<wbr></p>
<p align=left>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> &nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> ImagesetManager::getSingleton ().destroyImageset (hzImageset-&gt;getName ());</p>
<p align=left>&nbsp;<wbr></p>
<p align=left>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> hzImageset = ImagesetManager::getSingleton ().createImageset (</p>
<p align=left>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> d_name + "_auto_glyph_images_" ,</p>
<p align=left>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> System::getSingleton ().getRenderer ()-&gt;createTexture ());</p>
<p align=left>&nbsp;<wbr></p>
<p align=left>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> d_glyphImages.push_back (hzImageset);</p>
<p align=left>&nbsp;<wbr></p>
<p align=left>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> float adv = d_fontFace-&gt;glyph-&gt;metrics.horiAdvance * float(FT_POS_COEF);</p>
<p align=left>&nbsp;<wbr></p>
<p align=left>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> d_hz_map[codepoint] = FontGlyph (adv);</p>
<p align=left>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> }</p>
<p align=left>&nbsp;<wbr></p>
<p align=left>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> CodepointMap::const_iterator hzInter&nbsp;<wbr> = d_hz_map.find(codepoint);</p>
<p align=left>&nbsp;<wbr></p>
<p align=left>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> if (!hzInter-&gt;second.getImage())</p>
<p align=left>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> {</p>
<p align=left>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> // Render the glyph</p>
<p align=left>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> if (FT_Load_Char (d_fontFace, hzInter-&gt;first, FT_LOAD_RENDER | FT_LOAD_FORCE_AUTOHINT |</p>
<p align=left>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> (d_antiAliased ? FT_LOAD_TARGET_NORMAL : FT_LOAD_TARGET_MONO)))</p>
<p align=left>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> {</p>
<p align=left>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> std::stringstream err;</p>
<p align=left>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> err &lt;&lt; "Font::loadFreetypeGlyph - Failed to load glyph for codepoint: ";</p>
<p align=left>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> err &lt;&lt; static_cast&lt;unsigned int&gt; (hzInter-&gt;first);</p>
<p align=left>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> err &lt;&lt; ".&nbsp;<wbr> Will use an empty image for this glyph!";</p>
<p align=left>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> Logger::getSingleton ().logEvent (err.str (), Errors);</p>
<p align=left>&nbsp;<wbr></p>
<p align=left>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> // Create a 'null' image for this glyph so we do not seg later</p>
<p align=left>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> Rect area(0, 0, 0, 0);</p>
<p align=left>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> Point offset(0, 0);</p>
<p align=left>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> String name;</p>
<p align=left>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> name += hzInter-&gt;first;</p>
<p align=left>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> hzImageset-&gt;defineImage(name, area, offset);</p>
<p align=left>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> ((FontGlyph &amp;)hzInter-&gt;second).setImage(&amp;hzImageset-&gt;getImage(name));</p>
<p align=left>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> }</p>
<p align=left>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> else</p>
<p align=left>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> {</p>
<p align=left>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> uint glyph_w = d_fontFace-&gt;glyph-&gt;bitmap.width + INTER_GLYPH_PAD_SPACE;</p>
<p align=left>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> uint glyph_h = d_fontFace-&gt;glyph-&gt;bitmap.rows + INTER_GLYPH_PAD_SPACE;</p>
<p align=left>&nbsp;<wbr></p>
<p align=left>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> // Check if glyph right margin does not exceed texture size</p>
<p align=left>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> uint x_next = m_nHZX + glyph_w;</p>
<p align=left>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> if (x_next &gt; texsize)</p>
<p align=left>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> {</p>
<p align=left>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> &nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> m_nHZX = INTER_GLYPH_PAD_SPACE;</p>
<p align=left>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> x_next = m_nHZX + glyph_w;</p>
<p align=left>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> m_nHZY = m_nHZYB;</p>
<p align=left>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> }</p>
<p align=left>&nbsp;<wbr></p>
<p align=left>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> // Check if glyph bottom margine does not exceed texture size</p>
<p align=left>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> uint y_bot = m_nHZY + glyph_h;</p>
<p align=left>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr></p>
<p align=left>&nbsp;<wbr></p>
<p align=left>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> // Copy rendered glyph to memory buffer in RGBA format</p>
<p align=left>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> &nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> drawGlyphToBuffer (hzmem_buffer + (m_nHZY * texsize) + m_nHZX, texsize);</p>
<p align=left>&nbsp;<wbr></p>
<p align=left>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> // Create a new image in the imageset</p>
<p align=left>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> Rect area(static_cast&lt;float&gt;(m_nHZX),</p>
<p align=left>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> static_cast&lt;float&gt;(m_nHZY),</p>
<p align=left>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> static_cast&lt;float&gt;(m_nHZX + glyph_w - INTER_GLYPH_PAD_SPACE),</p>
<p align=left>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> static_cast&lt;float&gt;(m_nHZY + glyph_h - INTER_GLYPH_PAD_SPACE));</p>
<p align=left>&nbsp;<wbr></p>
<p align=left>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> Point offset(d_fontFace-&gt;glyph-&gt;metrics.horiBearingX * static_cast&lt;float&gt;(FT_POS_COEF),</p>
<p align=left>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> -d_fontFace-&gt;glyph-&gt;metrics.horiBearingY * static_cast&lt;float&gt;(FT_POS_COEF));</p>
<p align=left>&nbsp;<wbr></p>
<p align=left>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> String name;</p>
<p align=left>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> name += hzInter-&gt;first;</p>
<p align=left>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> hzImageset-&gt;defineImage (name, area, offset);</p>
<p align=left>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> ((FontGlyph &amp;)hzInter-&gt;second).setImage (&amp;hzImageset-&gt;getImage (name));</p>
<p align=left>&nbsp;<wbr></p>
<p align=left>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> // Advance to next position</p>
<p align=left>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> m_nHZX = x_next;</p>
<p align=left>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> if (y_bot &gt; m_nHZYB)</p>
<p align=left>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> {</p>
<p align=left>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> m_nHZYB = y_bot;</p>
<p align=left>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> &nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> }</p>
<p align=left>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> }</p>
<p align=left>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> }</p>
<p align=left>&nbsp;<wbr></p>
<p align=left>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> // Copy our memory buffer into the texture and free it</p>
<p align=left>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> hzImageset-&gt;getTexture ()-&gt;loadFromMemory (hzmem_buffer, texsize, texsize, Texture::PF_RGBA);</p>
<p align=left>&nbsp;<wbr></p>
<p align=left>}</p>
<p align=left>&nbsp;<wbr></p>
<p align=left>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> OK，问题搞定，打完收工。试试，效果还不错，可以洗洗睡了。特将自己的一点体会写出来，给新手提供个捷径，也希望高手批评指教。</p>
<img src ="http://www.cppblog.com/winmain/aggbug/108576.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/winmain/" target="_blank">Code Knight</a> 2010-02-27 21:38 <a href="http://www.cppblog.com/winmain/archive/2010/02/27/108576.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转]OGRE新插件PagedGeometry(海量场景分页调度)</title><link>http://www.cppblog.com/winmain/archive/2010/02/24/108371.html</link><dc:creator>Code Knight</dc:creator><author>Code Knight</author><pubDate>Wed, 24 Feb 2010 13:31:00 GMT</pubDate><guid>http://www.cppblog.com/winmain/archive/2010/02/24/108371.html</guid><wfw:comment>http://www.cppblog.com/winmain/comments/108371.html</wfw:comment><comments>http://www.cppblog.com/winmain/archive/2010/02/24/108371.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/winmain/comments/commentRss/108371.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/winmain/services/trackbacks/108371.html</trackback:ping><description><![CDATA[<div class=postcontent>
<div><font size=3><strong><span>1,</span></strong><strong><span>介绍：</span></strong></font></div>
<div><span><strong><font size=3>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font></strong>
<p><font size=3><font face="Times New Roman">&nbsp;<span>PagedGeometry</span></font><span>是</span><span><font face="Times New Roman">OGRE</font></span><span>引擎的一个插件，它对（无穷）大区域的海量网格的渲染提供优化策略。它非常适合于稠密的森林和室外场景，那里有海量的树，草，岩石，灌木丛等场景对象。</span></font></p>
<p><span><span><font size=3>&nbsp;</font> </span></span></p>
<p><font size=3><strong><span>2,</span><span> </span></strong><strong><span>PagedGeometry</span></strong><strong><span>管理</span></strong><strong></strong></font></p>
<p><span><font size=3>PagedGeometry class</font></span></p>
<p>&nbsp;</p>
<p><span><font size=3></font></span></p>
<font size=3><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span>该类负责加载那些需要立即（或很快）可见的场景几何，而不加载其他的场景以节约内存空间。</span><span>PagedGeometry</span><span>引擎可以通过诸如静态几何，</span><span>imposters</span><span>等方法去显示实体对象（</span><span>Entities</span><span>）。这些方法是与实体和场景相机的距离，以及你的配置相关的。</span></font>
<p><font size=3><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span>对页面的加载是通过用户定义的</span><span>PageLoader</span><span>来完成的。这样，用户可以编程实现加载页面，无论它是来自硬盘上的文件，程序产生的或是其他地方。</span></font></p>
<p><span><font size=3>&nbsp;</font></span></p>
<p><span><font size=3><span>&nbsp;&nbsp;&nbsp;&nbsp; </span>GeometryPageManager</font></span></p>
<p><font size=3><span><span>&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span>在</span><span>PagedGeometry</span><span>类中使用，用于管理分页页面，在需要的时候做</span><span>cacheing, deleting</span><span>等工作。它通过分析摄像机距离去计算页面</span><span>cathe</span><span>的速度，并</span><span>delete</span><span>那些已经经过了设定时间的不可见页面。</span></font></p>
<p><font size=3><span>调用</span><span>PagedGeometry::addDetailLevel(), </span><span>创建</span><span> GeometryPageManager </span><span>。</span></font></p>
<p><span><font size=3>addDetailLevel() returns a pointer to this page manager, allowing you access to some useful functions, documented below.</font></span></p>
<p><font size=3><span>类成员函数中有些注释了</span><span>DO NOT USE</span><span>的，不能被用户使用，它们是在</span><span>PagedGeometry</span><span>中被使用的。</span></font></p>
<p><span><font size=3>addDetailLevel()</font></span></p>
<p><span><font size=3>Adds a detail level to the PagedGeometry object.</font></span></p>
<p><font size=3><span>PageType&nbsp;</span><span>对该</span><span>detail level</span><span>，用户想使用的页面类型。它不是一个函数参数，而是一个模板参数。</span></font></p>
<p><font size=3><span>&nbsp;maxRange&nbsp;</span><span>这个</span><span>detail level</span><span>使用的最大距离（摄像机的视距）</span></font></p>
<p><font size=3><span>transitionLength&nbsp;</span><span>期望的衰减转变长度</span><span> - </span><span>（可选）</span></font></p>
<p><span><font size=3>示例：</font></span></p>
<p><span><font size=3><span>&nbsp;&nbsp;&nbsp; </span>pagedTrees-&gt;addDetailLevel&lt;BatchPage&gt;(100); //Use batched geometry from 0-100</font></span></p>
<p><span><font size=3><span>&nbsp;&nbsp;&nbsp; </span>pagedTrees-&gt;addDetailLevel&lt;ImpostorPage&gt;(500); //Use impostors from 100-500</font></span></p>
<p><font size=3><span>名叫</span><span>pagedTrees</span><span>的</span><span>PagedGeometry </span><span>的对象会在</span><span>0</span><span>－</span><span>100</span><span>单位摄像机距离的范围内使用</span><span>batched</span><span>（分批几何，静态几何），</span><span>100</span><span>－</span><span>500</span><span>单位距离范围内使用</span><span>imposters</span></font></p>
<p><font size=3><span>如果已有的页面类型不合适，用户可以很轻松的添加自定义的</span><span>GeometryPage</span><span>子类</span></font></p>
<p><font size=3><span>transitionLength&nbsp;</span><span>参数在默认情况下是没有的，但是用户可以自己添加，它的作用是使细节层次转变更平滑。但是注意，使用参数可能会是渲染的效率下降</span><span>10</span><span>％－</span><span>30</span><span>％。</span></font></p>
<span>
<p><font size=3><strong><span><font face="Times New Roman"></font></span></strong></font></p>
<p><font size=3><strong><span><font face="Times New Roman">3,</font></span></strong><strong><span>页面类型</span></strong></font></p>
<span>
<p><span><font size=3 face="Times New Roman">Class GeometryPage</font></span></p>
<p><font size=3><span>如上所说，该类是一个虚基类，用户可以扩展继承该类去实现不同的替代被渲染实体的方式，如</span><span><font face="Times New Roman">batched</font></span><span>，</span><span><font face="Times New Roman">imposters</font></span><span>等。如果你需要其他的页面类型，你可以自己实现一些。</span></font></p>
<p><span><font size=3>以下是用户必须在子类中实现的虚函数：</font></span></p>
<p><span><font size=3 face="Times New Roman">virtual void init(SceneManager *mgr, Camera *cam) = 0;</font></span></p>
<p><span><font size=3 face="Times New Roman">virtual void setRegion(Real left, Real top, Real right, Real bottom) = 0;</font></span></p>
<p><span><font size=3 face="Times New Roman">virtual void addEntity(Entity *ent, const Vector3 &amp;position, const Quaternion &amp;rotation, const Vector3 &amp;scale, const Ogre::ColourValue &amp;color) = 0;</font></span></p>
<p><span><font size=3 face="Times New Roman">virtual void build() {}</font></span></p>
<p><span><font size=3 face="Times New Roman">virtual void removeEntities() = 0;</font></span></p>
<p><span><font size=3 face="Times New Roman">virtual void setVisible(bool visible) = 0;</font></span></p>
<p><span><font size=3 face="Times New Roman">virtual void setFade(bool enabled, Real visibleDist, Real invisibleDist) = 0;</font></span></p>
<p><span><font size=3 face="Times New Roman">virtual void update() {}</font></span></p>
<p><font size=3><span>以下是页面管理器（</span><span><font face="Times New Roman">page manager</font></span><span>）如何去使用上面的函数：</span></font></p>
<p><font size=3><span><font face="Times New Roman">1</font></span><span>，当</span><span><font face="Times New Roman">PagedGeometry</font></span><span>首先</span><span><font face="Times New Roman">create</font></span><span>一个</span><span><font face="Times New Roman">GeometryPage</font></span><span>，马上调用它的</span><span><font face="Times New Roman">init</font></span><span>（），该函数就好像构造函数一样。</span></font></p>
<p><font size=3><span><font face="Times New Roman">2</font></span><span>，准备一个几何页面给待渲染实体，设置页面区域。</span></font></p>
<p><font size=3><span><font face="Times New Roman">3</font></span><span>，添加实体对象到该页面，并初始化位置，方向等。</span></font></p>
<p><font size=3><span><font face="Times New Roman">4</font></span><span>，添加实体到场景中的最后一步。在添加完所有实体对象后自动调用。</span></font></p>
<p><font size=3><span><font face="Times New Roman">5</font></span><span>，从页面完全删除实体对象。</span></font></p>
<p><font size=3><span><font face="Times New Roman">6</font></span><span>，使整个页面变为可见。</span></font></p>
<p><font size=3><span><font face="Times New Roman">7</font></span><span>，设置页面的消减属性。</span></font></p>
<p><font size=3><span><font face="Times New Roman">8</font></span><span>，在帧循环中保证页面几何的更新。</span></font></p>
<p><span><font face="Times New Roman"><font size=3>class BatchPage</font></font></span></p>
<p><font size=3><span><font face="Times New Roman">The BatchPage class</font></span><span>把实体当作静态几何体来渲染。</span></font></p>
<p>&nbsp;</p>
<p><span><font size=3 face="Times New Roman"></font></span></p>
<font size=3><span>静态几何体（</span><span><font face="Times New Roman">StaticGeometry</font></span><span>）：在场景中有许多实体是从它们加入场景开始就不会移动的，如房屋，树等，</span><span><font face="Times New Roman">Ogre</font></span><span>为这种情况提供了</span><span><font face="Times New Roman">StaticGeometry</font></span><span>类</span><span><font face="Times New Roman">,</font></span><span>它允许你<strong>批渲染</strong>很多物体</span><span><font face="Times New Roman">.</font></span><span>这个通常要比手动在</span><span><font face="Times New Roman">SceneNodes</font></span><span>添加要快多了。</span></font>
<p><span><font size=3 face="Times New Roman">&nbsp;</font></span></p>
<p><span><font face="Times New Roman"><font size=3>class ImposterPage</font></font></span></p>
<p><font size=3><span><font face="Times New Roman">the ImpostorPage class.</font></span><span>把实体当作</span><span><font face="Times New Roman">impostors</font></span><span>（一种布告版图像，看起来像真实的实体）来渲染</span></font></p>
<p><font size=3><span>所有</span><span><font face="Times New Roman">page</font></span><span>类型中，这个是最快的，它使用</span><span><font face="Times New Roman">Impostors</font></span><span>去代替要渲染的</span><span><font face="Times New Roman">entities</font></span><span>，这样，显卡只要去渲染一系列的</span><span><font face="Times New Roman">2d image</font></span><span>，而不是</span><span><font face="Times New Roman">3d mesh</font></span></font></p>
<p>&nbsp;</p>
<p><span><font size=3 face="Times New Roman"></font></span></p>
<span><font size=3 face="Times New Roman">&nbsp;</font></span>
<p><span><font face="Times New Roman"><font size=3>class GrassPage</font></font></span></p>
<p><span><font face="Times New Roman"><font size=3>A custom page type designed specifically for use with GrassLoader.</font></font></span></p>
<p><font size=3><span><font face="Times New Roman">GrassPage</font></span><span>页面类型是被设计来配合</span><span><font face="Times New Roman">GrassLoader</font></span><span>使用的</span></font></p>
<p><font size=3><span>这种类型是没有做过优化的，它只是对所给的</span><span><font face="Times New Roman">entity</font></span><span>进行克隆，然后绑定到一个新的场景节点之上。这意味着性能很差。</span></font></p>
<p><font size=3><strong><span><font face="Times New Roman"></font></span></strong></font></p>
<p><font size=3><strong><span><font face="Times New Roman">4</font></span></strong><strong><span>，</span></strong><strong><span><font face="Times New Roman">BatchedGeometry</font></span></strong><strong><span>－一种静态几何的版本</span></strong></font></p>
<span>
<p><span><font face="Times New Roman"><font size=3>class BatchedGeometry</font></font></span></p>
<p><font size=3><span>它是</span><span><font face="Times New Roman">Ogre::StaticGeometry</font></span><span>的一个轻量级版本。</span></font></p>
<p><font size=3><span><font face="Times New Roman">staticGeometry</font></span><span>是</span><span><font face="Times New Roman">ogre</font></span><span>提供给用户的批渲染的类，它可以一次性渲染那些在场景中保持&#8220;静态的&#8221;实体（</span><span><font face="Times New Roman">entities</font></span><span>），如，房屋，树等。</span></font></p>
<p><font size=3><span>它给用户提供多一些的对</span><span><font face="Times New Roman">batch</font></span><span>材质等的控制。</span></font></p>
<p><span><font face="Times New Roman"><font size=3>class SubBatch: public Ogre::Renderable</font></font></span></p>
<p><font size=3><span><font face="Times New Roman">subBatch</font></span><span>继承于</span><span><font face="Times New Roman">Renderable</font></span><span>，是</span><span><font face="Times New Roman">BatchedGeometry</font></span><span>的内部类，它的构造函数中传入</span><span><font face="Times New Roman">BatchedGeometry</font></span><span>指针和</span><span><font face="Times New Roman">submesh</font></span><span>的指针，该类包含在</span><span><font face="Times New Roman">BatchedGeometry</font></span><span>中。</span></font></p>
<p><font size=3><strong><span><font face="Times New Roman"></font></span></strong></font></p>
<p><font size=3><strong><span><font face="Times New Roman">5</font></span></strong><strong><span>，</span></strong><strong><span><font face="Times New Roman">Loading Entities</font></span></strong></font></p>
<p><span><font face="Times New Roman"><font size=3>class PageLoader</font></font></span></p>
<p><font size=3><span>虚基类。用户可以扩展它去提供负责加载页面（</span><span><font face="Times New Roman">Page</font></span><span>）的回调函数。</span></font></p>
<p><font size=3><span><font face="Times New Roman">PagedGeometry</font></span><span>预装了几种不同的</span><span><font face="Times New Roman">Loader</font></span><span>，继承于</span><span><font face="Times New Roman">PageLoader</font></span><span>，跟很多实体管理器不同的是，</span><span><font face="Times New Roman">PagedGeometry</font></span><span>不允许用户一次性向</span><span><font face="Times New Roman">object</font></span><span>添加所有的</span><span><font face="Times New Roman">entities</font></span><span>，由于它是用于大规模的游戏场景，所以它会对世界几何进行分页，然后调度，只加载需要绘制的页面。</span></font></p>
<p><font size=3><span>只要引擎需要确定世界几何的那一块区域需要被加载，就要调用</span><span><font face="Times New Roman">PageLoader</font></span><span>的成员</span><span><font face="Times New Roman">loadPage()</font></span><span>。在函数中的</span><span><font face="Times New Roman">PageInfo</font></span><span>结构体，提供了页面的包围体信息。在函数中，用户通过</span></font></p>
<p><font size=3><span><font face="Times New Roman">addEntity</font></span><span>（）来添加实体到该页面中，还可以定义实体的尺度，位置，旋转等属性。</span></font></p>
<p><font size=3><span>当用户创建了自己的</span><span><font face="Times New Roman">loader</font></span><span>对象后，必须将其</span><span><font face="Times New Roman">attatch</font></span><span>到</span><span><font face="Times New Roman">PagedGeometry</font></span><span>对象上去。如下：</span></font></p>
<p><span><font face="Times New Roman"><font size=3>pagedGeometry-&gt;setPageLoader(yourPageLoader);</font></font></span></p>
<p><span><font size=3 face="Times New Roman">&nbsp;</font></span></p>
<p><font size=3><font face="Times New Roman"><span>PageInfo:</span><span> </span></font><span>结构体。提供给</span><span><font face="Times New Roman">PageLoader</font></span><span>的有用的页面信息。基本的信息是定义被加载的区域，还有一些该区域的其他信息。</span></font></p>
<p><font size=3><span>结构体内包含了一个</span><span><font face="Times New Roman">TBound</font></span><span>（</span><span><font face="Times New Roman">typedef Ogre::TRect&lt;Ogre::Real&gt; TBounds</font></span><span>），所有在该页面内的实体都必须放置在这个矩形包围体之中。</span></font></p>
<p><font size=3></font></p>
<p><font size=3><span>具体的</span><span><font face="Times New Roman">loaders</font></span><span>：</span></font></p>
<p><font size=3><span>（</span><span><font face="Times New Roman">1</font></span><span>）</span><span><font face="Times New Roman">GrassLoader </font></span><span>继承于</span><span><font face="Times New Roman">PageLoader</font></span><span>，用于和</span><span><font face="Times New Roman">PagedGeometry</font></span><span>一起产生真实的草地场景。所谓真实的草地模拟，使用</span><span><font face="Times New Roman">GrassLoader</font></span><span>成员函数</span><span><font face="Times New Roman">addLayer</font></span><span>（）来添加草，使用</span><span><font face="Times New Roman">updateAnimation()</font></span><span>来驱动动画。</span></font></p>
<p><font size=3><span><span><font face="Times New Roman">&nbsp;&nbsp;&nbsp;&nbsp; </font></span></span><span>当用户创建了</span><span><font face="Times New Roman">Grassloader</font></span><span>对象后，必须将其</span><span><font face="Times New Roman">attatch</font></span><span>到</span><span><font face="Times New Roman">PagedGeometry</font></span><span>对象上去。如下：</span></font></p>
<p><span><font face="Times New Roman"><font size=3>pagedGeometry-&gt;setPageLoader(GrassLoader);</font></font></span></p>
<p><font size=3><span><span><font face="Times New Roman">&nbsp;&nbsp;&nbsp;&nbsp; </font></span></span><span>草地</span><span><font face="Times New Roman">loader</font></span><span>在使用几何页面类型的时候，被推荐为使用</span><span><font face="Times New Roman">GrassPage</font></span><span>，这样的渲染效率较高，而采用其他类型则效率很低。</span></font></p>
<p><font size=3><span><span><font face="Times New Roman">&nbsp;&nbsp;&nbsp;&nbsp; </font></span></span><span>同时提供了一个数据结构来完全控制</span><span><font face="Times New Roman">Grass</font></span><span>的属性</span><span><font face="Times New Roman"> class GrassLayer</font></span><span>，它是通过</span><span><font face="Times New Roman">addLayer</font></span><span>（）来添加的，该类提供了一系列的&#8220;</span><span><font face="Times New Roman">set</font></span><span>&#8221;方法，用于用户配置草地的材质，密度，大小等属性信息。</span></font></p>
<p><span><font size=3 face="Times New Roman">&nbsp;</font></span></p>
<p><font size=3><span>（</span><span><font face="Times New Roman">2</font></span><span>）</span><span><font face="Times New Roman">TreeLoader2D</font></span><span>继承于</span><span><font face="Times New Roman">PageLoader</font></span><span>，用于和</span><span><font face="Times New Roman">PagedGeometry</font></span><span>一起轻易的实现在地形上放置树木的功能。</span></font></p>
<p><font size=3><span><span><font face="Times New Roman">&nbsp;&nbsp;&nbsp;&nbsp; </font></span></span><span>使用方法和前述一致，使用时，</span><span><font face="Times New Roman">addTrees</font></span><span>（）方法向场景中添加树木。需要注意的是，</span><span><font face="Times New Roman">loader</font></span><span>加载树木时并不知道该地形的高度，而是假设高度为</span><span><font face="Times New Roman">0</font></span><span>，这就需要设定获得当前（即给定</span><span><font face="Times New Roman">x</font></span><span>，</span><span><font face="Times New Roman">z</font></span><span>值时）的地形高度。</span><span><font face="Times New Roman">Loader</font></span><span>提供了这些方法。</span></font></p>
<p><span><font size=3 face="Times New Roman">&nbsp;</font></span></p>
<p><font size=3><span>（</span><span><font face="Times New Roman">3</font></span><span>）</span><span><font face="Times New Roman">TreeLoader3D</font></span><span>同</span><span><font face="Times New Roman">2D</font></span><span>的情况差不多，只是效率大概低</span><span><font face="Times New Roman">40</font></span><span>％左右。</span><span><font face="Times New Roman">TreeLoader3D</font></span><span>将树在内存中打包的效率很高，大约</span><span><font face="Times New Roman">10Bytes</font></span><span>一棵树，相当于</span><span><font face="Times New Roman">100</font></span><span>万棵树只要</span><st1:chmetcnv unitname="m" sourcevalue="9.53" hasspace="False" negative="False" numbertype="1" tcsc="0" w:st="on"><span><font face="Times New Roman">9.53m</font></span></st1:chmetcnv><span>内存空间。这就很适用于大规模森林的渲染。</span></font></p>
<p><font size=3><span><span><font face="Times New Roman">&nbsp;&nbsp;&nbsp;&nbsp; </font></span></span><span>引擎为</span><span><font face="Times New Roman">2D</font></span><span>，</span><span><font face="Times New Roman">3Dloader</font></span><span>提供了一些公用的工具类，如</span><span><font face="Times New Roman">class TreeRef</font></span><span>，以内联函数的性质为</span><span><font face="Times New Roman">loader</font></span><span>提供了位置，旋转，尺寸，方向等的&#8220;</span><span><font face="Times New Roman">get</font></span><span>&#8221;数学运算。而</span><span>TreeIterator2D</span><span>，<span>TreeIterator3D</span>则为<span>loader</span>提供了树指针的操作。</span></font></p>
</span></span></span></span></div>
</div>
<img src ="http://www.cppblog.com/winmain/aggbug/108371.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/winmain/" target="_blank">Code Knight</a> 2010-02-24 21:31 <a href="http://www.cppblog.com/winmain/archive/2010/02/24/108371.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转]OGRE根据高度图创建Terrain地形流程分析</title><link>http://www.cppblog.com/winmain/archive/2010/02/24/108370.html</link><dc:creator>Code Knight</dc:creator><author>Code Knight</author><pubDate>Wed, 24 Feb 2010 13:30:00 GMT</pubDate><guid>http://www.cppblog.com/winmain/archive/2010/02/24/108370.html</guid><wfw:comment>http://www.cppblog.com/winmain/comments/108370.html</wfw:comment><comments>http://www.cppblog.com/winmain/archive/2010/02/24/108370.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/winmain/comments/commentRss/108370.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/winmain/services/trackbacks/108370.html</trackback:ping><description><![CDATA[<p><span style="FONT-SIZE: small">OGRE可以通过两个接口来生成地形，分别是void TerrainSceneManager::setWorldGeometry( const String&amp; filename )以及void TerrainSceneManager::setWorldGeometry(DataStreamPtr&amp; stream, const String&amp; typeName )，两者的根本区别就是一个是传递地形信息文件名一个是传递地形信息数据流，设计两个接口的目的是可以让用户使用自己的地形信息配置文件，而不必局限于 OGRE定义的地形信息配置文件格式。在分析流程之前，先说明一点，为了提高渲染性能以及地形查找性能，OGRE把整个地形分成若干个地形页，每个地形页又分成了多个地形小块，到最后会把地形页及地形小块tile挂接到场景节点上。以下是生成地形的主要流程：</span></p>
<p><span style="FONT-SIZE: small">一：清除地形分级索引缓冲及地形分页，根据地形信息数据流加载地形信息配置文件，</span></p>
<p><span style="FONT-SIZE: small">void TerrainSceneManager::loadConfig(DataStreamPtr&amp; stream)，其先将地形配置信息从数据流中逐一读出到map中，然后通过void TerrainSceneManager::selectPageSource(const String&amp; typeName,&nbsp; TerrainPageSourceOptionList&amp; optionList)设置地形数据源(目前只有高度图数据源)。在地形信息配置文件中可以配置多个地形数据源，然后根据一种数据源类型生成地形，参数 typeName就用来指定数据源类型，目前就是HeightMap，找到指定的数据源后，对指定的数据源进行初始化，</span></p>
<p><span style="FONT-SIZE: small">&nbsp;void HeightmapTerrainPageSource::initialise(TerrainSceneManager* tsm,&nbsp; ushort tileSize, ushort pageSize, bool asyncLoading,&nbsp;TerrainPageSourceOptionList&amp; optionList)。初始化的过程主要是调用void HeightmapTerrainPageSource::loadHeightmap(void)将高度图灰度图像数据加载到内存中，如果是Raw数据，就加载到mRawData中，否则加载到mImage中。整个加载过程其实完成了两大工作，首先加载地形配置信息，然后加载高度图数据。 <br></span></p>
<p><span style="FONT-SIZE: small">二：初始化分级索引缓冲，void TerrainSceneManager::initLevelIndexes()； <br></span></p>
<p><span style="FONT-SIZE: small">三：void OctreeSceneManager::resize( const AxisAlignedBox &amp;box ) <br></span></p>
<p><span style="FONT-SIZE: small">四：设置地形材质，void TerrainSceneManager::setupTerrainMaterial(void)； <br></span></p>
<p><span style="FONT-SIZE: small">五：设置地形分页， void TerrainSceneManager::setupTerrainPages(void)</span></p>
<p><span style="FONT-SIZE: small">首先创建一个名为Terrain的场景根节点的子节点</span></p>
<p><span style="FONT-SIZE: small">mTerrainRoot = getRootSceneNode() -&gt; createChildSceneNode( "Terrain" );</span></p>
<p><span style="FONT-SIZE: small">然后初始化TerrainPage2D mTerrainPages；</span></p>
<p><span style="FONT-SIZE: small">最后调用 void HeightmapTerrainPageSource::requestPage(ushort x, ushort y)requestPage只支持一个Page，首先将图像数据进行缩放</span></p>
<p><span style="FONT-SIZE: small">然后调用 &#8220;TerrainPageSource::firePageConstructed（）&#8221;通知Listener；然后调用&#8220;TerrainPage* TerrainPageSource::buildPage(Real*heightData, const MaterialPtr&amp; pMaterial)&#8221;创建一个新的TerrainPage对象。</span></p>
<p><span style="FONT-SIZE: small">buildPage()是一个比较核心的函数。它首先构造一个 TerrainPage对象，然后创建一个用于容纳该TerrainPage对象的场景节点：&#8220;page-&gt;pageSceneNode = mSceneManager-&gt;createSceneNode(name);&#8221;，然后根据对地形的分割，循环创建子SceneNode，并且创建子场景节点对应的可渲染体TerrainRenderable，将该可渲染体attach到这个子节点上。通过 &#8220;TerrainRenderable::initialise（）&#8221;来创建顶点数据、渲染方式等。 <br></span></p>
<p><span style="FONT-SIZE: small">然后调用void TerrainSceneManager::attachPage(ushort pageX, ushort pageZ, TerrainPage* page)加入到mTerrainPages中；</span></p>
<p><span style="FONT-SIZE: small">然后在attachPage中调用&#8220;mTerrainRoot-&gt;addChild(page-&gt;pageSceneNode);&#8221;加入到SceneGraph中。 <br></span></p>
<p><span style="FONT-SIZE: small">注：当前只支持一个Page，该分页被挂接到一个称谓Terrain的场景节点上，该场景节点下面又创建了很多子场景节点，每一个子场景节点对应一个tile，也就是一个独立的可渲染体TerrainRenderable</span></p>
<img src ="http://www.cppblog.com/winmain/aggbug/108370.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/winmain/" target="_blank">Code Knight</a> 2010-02-24 21:30 <a href="http://www.cppblog.com/winmain/archive/2010/02/24/108370.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转] OGRE地形配置文件解析</title><link>http://www.cppblog.com/winmain/archive/2010/02/24/108369.html</link><dc:creator>Code Knight</dc:creator><author>Code Knight</author><pubDate>Wed, 24 Feb 2010 13:30:00 GMT</pubDate><guid>http://www.cppblog.com/winmain/archive/2010/02/24/108369.html</guid><wfw:comment>http://www.cppblog.com/winmain/comments/108369.html</wfw:comment><comments>http://www.cppblog.com/winmain/archive/2010/02/24/108369.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/winmain/comments/commentRss/108369.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/winmain/services/trackbacks/108369.html</trackback:ping><description><![CDATA[<p>OGRE通过配置文件生成地形，极大提高了地形生成的灵活性。下面对地形配置文件(terrain.cfg)各配置项的意义进行简要分析。</p>
<p>WorldTexture=terrain_texture.jpg&nbsp; <span style="COLOR: rgb(0,128,0)">//地形纹理<br></span>DetailTexture=terrain_detail.jpg&nbsp; <span style="COLOR: rgb(0,128,0)">//地形细节纹理(相机距离地面很近时采用细节纹理)<br></span>DetailTile=3&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: rgb(0,128,0)"> //细节纹理在一个地形小块中的平铺数<br></span>PageSource=Heightmap&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: rgb(0,128,0)"> //高度图数据源<br></span>Heightmap.image=terrain.png&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: rgb(0,128,0)"> //高度图名称(灰度图文件名),符合2^n+1<br></span>PageSize=513&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: rgb(0,128,0)"> //高度图大小<br></span>TileSize=65&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: rgb(0,128,0)"> //地形小块大小<br></span>MaxPixelError=3&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: rgb(0,128,0)"> //决定使用层次细节时充许误差<br></span>PageWorldX=1500&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="COLOR: rgb(0,128,0)">//地形在世界中的范围x方向<br></span>PageWorldZ=1500&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: rgb(0,128,0)">&nbsp; //z方向<br></span>MaxHeight=100&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: rgb(0,128,0)">&nbsp; //世界中地形最大映射高度<br></span>MaxMipMapLevel=5&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: rgb(0,128,0)">&nbsp; //层次细节上限<br></span>#VertexNormals=yes&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="COLOR: rgb(0,128,0)">//在缓冲中计算顶点法线，计算机光照或GPU程序用到时打开<br></span>#VertexColors=yes　　　　　　　　 <span style="COLOR: rgb(0,128,0)">//在缓冲中设置顶点颜色，假如有GPU程序需要时打开</span><br>#UseTriStrips=yes&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: rgb(0,128,0)"> //对于现在的硬件，建议关掉<br></span>VertexProgramMorph=yes　　　&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: rgb(0,128,0)"> //使用顶点程序进行LOD融合处理<br></span>LODMorphStart=0.2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: rgb(0,128,0)"> //LOD融合开始点：高，低LOD之间距离之比</span></p>
<p>下列参数用于提供自己的着色程序时使用，这会提供自己定义的material，那么先前定义的<br>WorldTexture 与 DetailTexture的设置不再用到。</p>
<p>MorphLODFactorParamName=morphFactor　<br><span style="COLOR: rgb(0,128,0)">//假设VertexProgramMorph被设为yes,定制的material中包括一个高级顶点程序。它指定了一个顶点<br>//程序的参数名，这个参数用于融合LOD,参数值从0－1，0表示不调整，1表示完全调整到下一级LOD</span><br>MorphLODFactorParamIndex&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: rgb(0,128,0)"> //用于materail中包含低级顶点程序的情况，意义同上<br></span>CustomMaterialName&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: rgb(0,128,0)"> //指定的materail名字</span></p>
<p>上述配置文件定义了基于高度图的地形。</p>
<p>这些参数定义可概括为两类：Ogre使用第一类从高度图产生地形<br>mesh与材质。</p>
<p>第二类是定制材质与GPU顶点程序，这可以代替ogre自动产生的着色程序。<br><span style="COLOR: rgb(255,20,147)">另外的说明：</span><br>TerrainScenceManager会把高度图分为多个page,每个page由几个tile组成.它们都定义了在产生的mesh中一组构成正方形的顶点集。<br>WorldTexture定义的纹理不必与目标地形一样大。<br>PageWorldX，PageWorldZ可以缩放世界中的地形。<br>MaxHeight 在Y方向缩放地形。<br>DetailTexture 只使用一个纹理，如使用多层纹理，应该使用自定义materail。<br><br><span style="COLOR: rgb(0,0,255)">从程序加载地形</span><br>setWorldGeometry()有重载形式，一种用于加载配置文件，另一种我们可在程序中使用，以<br>达到手工加载的功能。这里，SceneData被 typedef 为std:map,它存储了如我们在terrain.cfg<br>中看到那些值对。假设我们已经从某个二进制文件读入我们想要的内容到SceneData中。我们要做<br>的就是把读入的内容转换成setWorldGeometry()需要的类型。</p>
<img src ="http://www.cppblog.com/winmain/aggbug/108369.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/winmain/" target="_blank">Code Knight</a> 2010-02-24 21:30 <a href="http://www.cppblog.com/winmain/archive/2010/02/24/108369.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[原]《深度探索C++对象模型》读书笔记</title><link>http://www.cppblog.com/winmain/archive/2010/02/23/108308.html</link><dc:creator>Code Knight</dc:creator><author>Code Knight</author><pubDate>Tue, 23 Feb 2010 13:37:00 GMT</pubDate><guid>http://www.cppblog.com/winmain/archive/2010/02/23/108308.html</guid><wfw:comment>http://www.cppblog.com/winmain/comments/108308.html</wfw:comment><comments>http://www.cppblog.com/winmain/archive/2010/02/23/108308.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/winmain/comments/commentRss/108308.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/winmain/services/trackbacks/108308.html</trackback:ping><description><![CDATA[1，使用初始化列表初始化参数的顺序不是根据参数列表里声明的顺序，而是根据该成员变量在类中声明的顺序决定的。<br>et.<br>class A<br>{<br>public:<br>&nbsp;&nbsp;&nbsp;A();<br>&nbsp;&nbsp; ~A();<br>private:<br>&nbsp;&nbsp; int a;<br>&nbsp;&nbsp; byte b;<br>}<br><br>A::A():b(1),a(b)<br>{<br><br>}<br><br>a的值无法确定，而b是1<br><br>2，在data语义学中<br>找到了一个一年困扰过我的问题，总算得到解答<br>class X;<br>class A:class X;<br>class B:class X;<br>class Y:class A, class B;<br><br>sizeof(X):1<br>sizeof(A):8<br>sizeof(B):8<br>sizeof(Y):12<br><br>编译器对空类会做优化给予一个char的大小<br>至于A,B 由于有继承关系存在虚函数表，size应为5，在4字节对其的编译器下sizeof为8，当然设定字节对齐为1的话应该是5
<img src ="http://www.cppblog.com/winmain/aggbug/108308.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/winmain/" target="_blank">Code Knight</a> 2010-02-23 21:37 <a href="http://www.cppblog.com/winmain/archive/2010/02/23/108308.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Introduction To Octrees</title><link>http://www.cppblog.com/winmain/archive/2010/02/23/108306.html</link><dc:creator>Code Knight</dc:creator><author>Code Knight</author><pubDate>Tue, 23 Feb 2010 13:18:00 GMT</pubDate><guid>http://www.cppblog.com/winmain/archive/2010/02/23/108306.html</guid><wfw:comment>http://www.cppblog.com/winmain/comments/108306.html</wfw:comment><comments>http://www.cppblog.com/winmain/archive/2010/02/23/108306.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/winmain/comments/commentRss/108306.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/winmain/services/trackbacks/108306.html</trackback:ping><description><![CDATA[<center>
<table style="TABLE-LAYOUT: fixed" border=0 cellSpacing=0 cellPadding=0 width="80%">
    <tbody>
        <tr>
            <td style="BACKGROUND-COLOR: #000000; COLOR: #000000" width="100%"><font color=#ffffff size=3 face="Verdana, Helvetica, Arial, Times New Roman"><strong>Introduction <font size=1><br><img src="http://www.flipcode.com/archives/line_grey.png"><br><br></font></strong></font></td>
        </tr>
    </tbody>
</table>
</center>
<center>
<table style="TABLE-LAYOUT: fixed" border=0 cellSpacing=0 cellPadding=0 width="80%">
    <tbody>
        <tr>
            <td style="BACKGROUND-COLOR: #000000; COLOR: #000000" width="100%"><font color=#ffe291 size=2 face="Verdana, Helvetica, Arial, Times New Roman">Hidden surface removal is among the biggest problems when writing a 3D engine.<br><br>I struggled with it since the very beginning of writing 3D engines and still have no satisfactory solution to it. The ideal visibility detection scheme would allow unlimited data, extremely dynamic worlds and would have zero overdraw. The first 3d engine which implements these three demands still has to be written. <br><br>The Z buffer for example allows dynamical worlds and even crossing faces, but it suffers from immense overdraw. The BSP-tree on the other hand, if well implemented, has no overdraw at all but needs that much pre-processing that dynamical worlds are a definite nono. <br><br>It wasn't until recently i first heard of the octree, and I must admit i was struck by it's simplicity. I never actually implemented this structure and therefore I will present no pseudo code at all. This explanation is merely an attempt to make it more clear to people who have never heard of it. Besides, if you really understand the structure, then implementation is a piece of cake.</font></td>
        </tr>
    </tbody>
</table>
</center><br><br>
<center>
<table style="TABLE-LAYOUT: fixed" border=0 cellSpacing=0 cellPadding=0 width="80%">
    <tbody>
        <tr>
            <td style="BACKGROUND-COLOR: #000000; COLOR: #000000" width="100%"><font color=#ffffff size=3 face="Verdana, Helvetica, Arial, Times New Roman"><strong>The Octree Structure <font size=1><br><img src="http://www.flipcode.com/archives/line_grey.png"><br><br></font></strong></font></td>
        </tr>
    </tbody>
</table>
</center>
<center>
<table style="TABLE-LAYOUT: fixed" border=0 cellSpacing=0 cellPadding=0 width="80%">
    <tbody>
        <tr>
            <td style="BACKGROUND-COLOR: #000000; COLOR: #000000" width="100%"><font color=#ffe291 size=2 face="Verdana, Helvetica, Arial, Times New Roman">Our virtual world or level is actually nothing more then a soup of polygons. Some of you people might have thrown in a couple of curves and voxels but most of it will be polygons. Here it is:<br><br>
            <center><img src="http://www.flipcode.com/archives/article_introtooctrees01.jpg" width=340 height=314><br><br>Fig 1. Our little level.</center><br><br>In the picture I just built a simple level containing no more than 250 polys. Now imagine a cube surrounding the world like in the next image:<br><br>
            <center><img src="http://www.flipcode.com/archives/article_introtooctrees02.jpg" width=429 height=434><br><br>Fig. 2. Our little level surrounded by a cube.</center><br><br>Now it isn't hard to see that this cube can be divided into eight smaller cubes, hence the name octree. Take a look at this picture:<br><br>
            <center><img src="http://www.flipcode.com/archives/article_introtooctrees03.jpg" width=429 height=434><br><br>Fig 3. Our little level with the surrounding cube subdivided.</center><br><br>Call the larger cube the parent and the smaller cubes the children. On their turn subdivide each children into eight smaller cubes, and you will notice we are creating a tree where each node has eight children. <br><br>There is still one little problem left. When should we stop dividing cubes into smaller ones? There are two possible solutions. The first one is to stop when a cube has some size smaller then a fixed number. The second one is more common. You might have noticed that every child has less polygons then it's parent. The trick is to stop subdividing when the number of polygons in a cube is smaller then some fixed number. </font></td>
        </tr>
    </tbody>
</table>
</center><br><br>
<center>
<table style="TABLE-LAYOUT: fixed" border=0 cellSpacing=0 cellPadding=0 width="80%">
    <tbody>
        <tr>
            <td style="BACKGROUND-COLOR: #000000; COLOR: #000000" width="100%"><font color=#ffffff size=3 face="Verdana, Helvetica, Arial, Times New Roman"><strong>Creating The Octree <font size=1><br><img src="http://www.flipcode.com/archives/line_grey.png"><br><br></font></strong></font></td>
        </tr>
    </tbody>
</table>
</center>
<center>
<table style="TABLE-LAYOUT: fixed" border=0 cellSpacing=0 cellPadding=0 width="80%">
    <tbody>
        <tr>
            <td style="BACKGROUND-COLOR: #000000; COLOR: #000000" width="100%"><font color=#ffe291 size=2 face="Verdana, Helvetica, Arial, Times New Roman">Trees are recursion, recursion is trees. It is as simple as that. If you have a correct definition of you cubeNode it is very easy to create an octree recursively. First of all you check all polygons against the boundarys of the cube. This is very simple cause these boundaries are all axis aligned. This means that the cube has six plane equations, which are:<br><br>
            <li>1. X = Q.X </li>
            <li>2. Y = Q.Y </li>
            <li>3. Z = Q.Z<br><br></li>
            <li>4. X = Q.X + cubeSize </li>
            <li>5. Y = Q.Y + cubeSize </li>
            <li>6. Z = Q.Z + cubeSize<br><br>Where Q is the position of one corner of the cube. This are very easy equations and the all parent polygons can very easily be checked against them.<br><br>It could occur that a polygon crosses a cube boundary. Again two possible solution are at hand. First of all we could clip the polygon against the cube, which is simple, because of the axis aligned boundarys. On the other hand we could put the polygon in all cubes it is in. This means that some cubes can contain the same polygons. In order to prevent us from drawing one poly more than one time we should have a flag on each polygon which will be set if the poly is drawn for the first time.<br><br>The implementation of an octree is very straight forward. I haven't done it myself yet, but I will soon. It is all matter of recursion. In order to construct a tree, the first thing you should think of is recursion. Whether we are talking about binary trees, quad trees or octrees, it doesnt matter, just build the darn thing recursively. So have a class definition of one cubeNode and put the creation of the tree in it's constructor. In this constructor you will call the constructor itself for smaller cubes.</li>
            </font></td>
        </tr>
    </tbody>
</table>
</center><br><br>
<center>
<table style="TABLE-LAYOUT: fixed" border=0 cellSpacing=0 cellPadding=0 width="80%">
    <tbody>
        <tr>
            <td style="BACKGROUND-COLOR: #000000; COLOR: #000000" width="100%"><font color=#ffffff size=3 face="Verdana, Helvetica, Arial, Times New Roman"><strong>The Purpose Of The Octree <font size=1><br><img src="http://www.flipcode.com/archives/line_grey.png"><br><br></font></strong></font></td>
        </tr>
    </tbody>
</table>
</center>
<center>
<table style="TABLE-LAYOUT: fixed" border=0 cellSpacing=0 cellPadding=0 width="80%">
    <tbody>
        <tr>
            <td style="BACKGROUND-COLOR: #000000; COLOR: #000000" width="100%"><font color=#ffe291 size=2 face="Verdana, Helvetica, Arial, Times New Roman">An octree is actually nothing more then a data structure. It can be used for very different things. It is not only handy for visibility detection but also for collision detection, realtime shadows and many more things. The most important thing to understand about octrees is that if a parent is not important then it's children aren't either. Let's makes this a little bit more clear with an example.<br><br>We will do this in 2d, which therefore resembles a quadtree, but with some imagination it can very easily be extended to 3d. Here we test the cubes (squares) against the viewing frustrum. Take a look at the next picture: <br><br>
            <center><img src="http://www.flipcode.com/archives/article_introtooctrees04.jpg" width=342 height=331><br><br>Fig 4. An octree from the top and a viewing frustrum.</center><br><br>In this picture a colored square that has one color was dumped without checking it�s children. As you can see some squares had to be checked all the way to the final node, but some large squares could be dumped at once. The colored squares are the ones that are outside the viewing frustrum and the greyscale ones are the one inside the viewing frustrum. As you can see this is actually a worst case scenario because the viewing frustrum crosses the middle of the surrounding square and therefore all the four children have to be checked.<br><br>You could also apply the octree to many other things. Collision detection for example. Just check in which cube your bounding sphere or box is and you will only have to check against those faces. There are many more examples.</font></td>
        </tr>
    </tbody>
</table>
</center><br><br>
<center>
<table style="TABLE-LAYOUT: fixed" border=0 cellSpacing=0 cellPadding=0 width="80%">
    <tbody>
        <tr>
            <td style="BACKGROUND-COLOR: #000000; COLOR: #000000" width="100%"><font color=#ffffff size=3 face="Verdana, Helvetica, Arial, Times New Roman"><strong>Conclusion <font size=1><br><img src="http://www.flipcode.com/archives/line_grey.png"><br><br></font></strong></font></td>
        </tr>
    </tbody>
</table>
</center>
<center>
<table style="TABLE-LAYOUT: fixed" border=0 cellSpacing=0 cellPadding=0 width="80%">
    <tbody>
        <tr>
            <td style="BACKGROUND-COLOR: #000000; COLOR: #000000" width="100%"><font color=#ffe291 size=2 face="Verdana, Helvetica, Arial, Times New Roman">There is already a lot written about octrees. I tried to give my view on them in the hope somebody might read this. As you can see octrees are way easier to implement than BSP-trees (although some disagree) while offering a better structure. The main point about an octrees is that when a parent is discarded so are it's children. Actually that is all there is to it.<br><br>Code clean, play Goldeneye and go vegetarian.<br><br>Jaap Suter a.k.a .........</font></td>
        </tr>
    </tbody>
</table>
<br>译文：<br><strong>1、引言</strong>（<span class=English>Introduction</span>）<br>　　隐面移除是写3D引擎时候最大的问题之一。<br>　　<span class=English>Hidden surface removal is among the biggest problems when writing a 3D engine.</span><br><br>　　在我写3D引擎的开始阶段就开始和它斗争并且一直没有满意的解决方法。理想的可见检测方案应当做到允许（使用）无限的数据、大动态的世界和零重画。第一流的3D引擎一直在追求实现这3个要求。<br>　　<span class=English>I struggled with it since the very beginning of writing 3D engines and still have no satisfactory solution to it. The ideal visibility detection scheme would allow unlimited data, extremely dynamic worlds and would have zero overdraw. The first 3d engine which implements these three demands still has to be written.</span><br><br>　　Z buffer允许动态世界以及即使是交叉的面，但是得忍受大量的重画。另一方面，BSP树如果能够被很好的实现，可以避免重画，但是它需要大量的预处理计算而且不适合动态世界。<br>　　<span class=English>The Z buffer for example allows dynamical worlds and even crossing faces, but it suffers from immense overdraw. The BSP-tree on the other hand, if well implemented, has no overdraw at all but needs that much pre-processing that dynamical worlds are a definite nono.</span><br><br>　　直到最近我第一次听说了八叉树（<span class=English>Octree</span>），我必须承认我被它的简易性&#8220;狠狠地打了一下儿&#8221;。我从来没有真正地去实现这个结构，因此我不会去实现一些代码。这个解释只是想让从没有听说过八叉树的人感到更清晰易懂。如果你真的了解了这个结构（<span class=English>Octree</span>），实现它只是一个小意思。<br>　　<span class=English>It wasn't until recently i first heard of the octree, and I must admit i was struck by it's simplicity. I never actually implemented this structure and therefore I will present no pseudo code at all. This explanation is merely an attempt to make it more clear to people who have never heard of it. Besides, if you really understand the structure, then implementation is a piece of cake.</span><br><a name=2.0></a><br><strong>2、八叉树的结构</strong>（<span class=English>The Octree Structure</span>）<br>　　我们的实际&#8216;世界&#8217;或者说是关卡只不过是一些多边形。你们或许在其中加入了一些曲面（<span class=English>Curves</span>）和Voxels（地形实现方法的一种），但是大多数也都是多边形。<br>　　<span class=English>Our virtual world or level is actually nothing more then a soup of polygons. Some of you people might have thrown in a couple of curves and voxels but most of it will be polygons. Here it is:</span><br><br>
<table class=BGRed border=0 cellSpacing=0 cellPadding=2 align=center>
    <tbody>
        <tr align=middle>
            <td height=303 colSpan=3><img src="mhtml:file://G:%5CDocuments%5CMyDocument%5C%E6%8A%80%E6%9C%AF%E6%96%87%E7%AB%A0%5C%E6%94%B6%E8%97%8F%5C%E5%85%AB%E5%8F%89%E6%A0%91%E5%85%A5%E9%97%A8.mht%21http://www.chinagamedev.net/cgd/develop/3D/200306/image/IntroToOct/IntroToOct-1.jpg" width=340 height=314></td>
        </tr>
        <tr align=middle>
            <td colSpan=3><font color=#cccccc><strong>图1</strong></font></td>
        </tr>
    </tbody>
</table>
<br>　　图1：我们设计的小型关卡。<br>　　<span class=English>Fig 1. Our little level.</span><br><br>　　在这张图片中我建立了一个不超过250个多边形的&#8216;关卡&#8217;。现在想象有一个包围了这个世界的立方体，像下一张图片那样。<br>　　<span class=English>In the picture I just built a simple level containing no more than 250 polys. Now imagine a cube surrounding the world like in the next image:</span><br><br>
<table class=BGRed border=0 cellSpacing=0 cellPadding=2 align=center>
    <tbody>
        <tr align=middle>
            <td height=303 colSpan=3><img src="mhtml:file://G:%5CDocuments%5CMyDocument%5C%E6%8A%80%E6%9C%AF%E6%96%87%E7%AB%A0%5C%E6%94%B6%E8%97%8F%5C%E5%85%AB%E5%8F%89%E6%A0%91%E5%85%A5%E9%97%A8.mht%21http://www.chinagamedev.net/cgd/develop/3D/200306/image/IntroToOct/IntroToOct-2.jpg" width=429 height=434></td>
        </tr>
        <tr align=middle>
            <td colSpan=3><font color=#cccccc><strong>图2</strong></font></td>
        </tr>
    </tbody>
</table>
<br>　　图2：我们设计的关卡被一个立方体所包围着。<br>　　<span class=English>Fig. 2. Our little level surrounded by a cube.</span><br><br>　　现在不难看出这个立方体可以被八等分为八个小些的立方体，所以才叫八叉树。看看这张图：<br>　　<span class=English>Now it isn't hard to see that this cube can be divided into eight smaller cubes, hence the name octree. Take a look at this picture:</span><br><br>
<table class=BGRed border=0 cellSpacing=0 cellPadding=2 align=center>
    <tbody>
        <tr align=middle>
            <td height=303 colSpan=3><img src="mhtml:file://G:%5CDocuments%5CMyDocument%5C%E6%8A%80%E6%9C%AF%E6%96%87%E7%AB%A0%5C%E6%94%B6%E8%97%8F%5C%E5%85%AB%E5%8F%89%E6%A0%91%E5%85%A5%E9%97%A8.mht%21http://www.chinagamedev.net/cgd/develop/3D/200306/image/IntroToOct/IntroToOct-3.jpg" width=429 height=434></td>
        </tr>
        <tr align=middle>
            <td colSpan=3><font color=#cccccc><strong>图3</strong></font></td>
        </tr>
    </tbody>
</table>
<br>　　图3：对围绕着关卡的立方体进行细分。<br>　　<span class=English>Fig 3. Our little level with the surrounding cube subdivided.</span><br><br>　　大点儿的这个立方体被叫做&#8216;父亲&#8217;小些的立方体叫做&#8216;孩子&#8217;。处理每个&#8216;孩子&#8217;的时候，再为更小的八个立方体，你会发现我们在创建一个每个节点有八个子节点（孩子）的树。<br>　　<span class=English>Call the larger cube the parent and the smaller cubes the children. On their turn subdivide each children into eight smaller cubes, and you will notice we are creating a tree where each node has eight children.</span><br><br>　　还有一个小问题。什么时候我们该结束细分的过程呢？有两个可行的解决方法。第一个是当一个立方体的尺寸已经比一个预定的固定值小的时候。第二个更普通。你可以注意到每个&#8216;孩子&#8217;都比他的&#8216;父亲&#8217;有更少的多边形。这就是说：当一个立方体包含的多边形数量比一个预定的固定值少的时候停止细分。<br>　　<span class=English>There is still one little problem left. When should we stop dividing cubes into smaller ones? There are two possible solutions. The first one is to stop when a cube has some size smaller then a fixed number. The second one is more common. You might have noticed that every child has less polygons then it's parent. The trick is to stop subdividing when the number of polygons in a cube is smaller then some fixed number.</span><br><a name=3.0></a><br><strong>3、创建八叉树</strong>（<span class=English>Creating The Octree</span>）<br>　　树是递归的，递归的是树。就那么简单。如果你正确的定义了你的立方体节点，那么递归地创建一个八叉树是很容易的。首先，检查所有的多边形（多边形上位置最外面的点作为）立方体的边界。这很简单因为所有边界都是和坐标轴对其的。这意味着立方体有六个平面方程，分别是：<br>　　<span class=English>Trees are recursion, recursion is trees. It is as simple as that. If you have a correct definition of you cubeNode it is very easy to create an octree recursively. First of all you check all polygons against the boundarys of the cube. This is very simple cause these boundaries are all axis aligned. This means that the cube has six plane equations, which are:</span> <br>
<ul><font id=zoom class=f14>
    <li><span class=ColorCode>1. X = Q.X</span> </li>
    <li><span class=ColorCode>2. Y = Q.Y</span> </li>
    <li><span class=ColorCode>3. Z = Q.Z<br><br></span></li>
    <li><span class=ColorCode>4. X = Q.X + cubeSize<br></span></li>
    <li><span class=ColorCode>5. Y = Q.Y + cubeSize<br></span></li>
    <li><span class=ColorCode>6. Z = Q.Z + cubeSize</span> </li>
    </font></ul>
    <font id=zoom class=f14>　　在这里Q是立方体一个顶角的位置。这是个很简单的方程，而且所有的父亲多边形可以容易地用这些方程来检测。<br>　　<span class=English>WhereQ is the position of one corner of the cube. This are very easy equations and the all parent polygons can very easily be checked against them.</span><br><br>　　一个多边形穿过了一个立方体边界这样的事情是会发生的。再一次，有两个解决方案可用。首先我们可以沿着立方体剪切这个多边形，这也是很简单的，因为（立方体的）边界是与坐标轴对齐的。还有，我们可以把一个多边形放在所有它所在的立方体里面。这就意味着一些立方体可能包含着同一个多边形。为了防止重画一个多边形，我们应当在每一个多边形上做一个标记，当多边形第一次被画的时候，设置这个标记（当然画之前也要检查这个标记啦，不过肯定影响效率。<br>　　<span class=English>It could occur that a polygon crosses a cube boundary. Again two possible solution are at hand. First of all we could clip the polygon against the cube, which is simple, because of the axis aligned boundarys. On the other hand we could put the polygon in all cubes it is in. This means that some cubes can contain the same polygons. In order to prevent us from drawing one poly more than one time we should have a flag on each polygon which will be set if the poly is drawn for the first time.</span><br><br>　　实现一个八叉树是很简单明了的事情，我还没有自己做过，但是我不久会做的。只不过是递归而已。为了构造一个树，第一件你该想的事情就是递归。不管我们讨论的是二叉、四叉还是八叉树，都没有区别，都是递归的方法。所以定义一个立方体节点的类，在构造函数里面写上创建树的代码。在这个构造函数里面，你会调用到更小立方体的构造函数。<br>　　<span class=English>The implementation of an octree is very straight forward. I haven't done it myself yet, but I will soon. It is all matter of recursion. In order to construct a tree, the first thing you should think of is recursion. Whether we are talking about binary trees, quad trees or octrees, it doesnt matter, just build the darn thing recursively. So have a class definition of one cubeNode and put the creation of the tree in it's constructor. In this constructor you will call the constructor itself for smaller cubes.</span><br><a name=4.0></a><br><strong>4、八叉树的用途</strong>（<span class=English>The Purpose Of The Octree</span>）<br>　　一个八叉树实际上就是一个数据结构。它可以用做不同的事情。不仅仅对于&#8216;可见检测&#8217;来说很方便，还有实时阴影以及其它方面。理解八叉树过程中最重要的事情是：如果一个&#8216;父亲&#8217;节点是&#8216;没用&#8217;的，那么他的&#8216;孩子&#8217;节点也同样。让我们举个例子让它更清楚。<br>　　<span class=English>An octree is actually nothing more then a data structure. It can be used for very different things. It is not only handy for visibility detection but also for collision detection, realtime shadows and many more things. The most important thing to understand about octrees is that if a parent is not important then it's children aren't either. Let's makes this a little bit more clear with an example.</span><br><br>　　我们用2D来表示它，这样就很像一个四叉树，但是想象一下它也可以很容易的扩展到3D上。在这里我们沿着视锥（<span class=English>viewing frustrum</span>）检测立方体（正方形）。<br>　　<span class=English>We will do this in 2d, which therefore resembles a quadtree, but with some imagination it can very easily be extended to 3d. Here we test the cubes (squares) against the viewing frustrum. Take a look at the next picture:</span><br><br>
    <table class=BGRed border=0 cellSpacing=0 cellPadding=2 align=center>
        <tbody>
            <tr align=middle>
                <td height=303 colSpan=3><img src="mhtml:file://G:%5CDocuments%5CMyDocument%5C%E6%8A%80%E6%9C%AF%E6%96%87%E7%AB%A0%5C%E6%94%B6%E8%97%8F%5C%E5%85%AB%E5%8F%89%E6%A0%91%E5%85%A5%E9%97%A8.mht%21http://www.chinagamedev.net/cgd/develop/3D/200306/image/IntroToOct/IntroToOct-4.jpg" width=342 height=331></td>
            </tr>
            <tr align=middle>
                <td colSpan=3><font color=#cccccc><strong>图4</strong></font></td>
            </tr>
        </tbody>
    </table>
    <br>　　图4：顶部视锥内的八叉树。<br>　　<span class=English>Fig 4. An octree from the top and a viewing frustrum.</span><br><br>　　在这个图片中，彩色的正方形是没有（没必要）检测它的&#8216;孩子&#8217;的。就像你看到的那样一些正方形（灰色的一些）被检测直到最终节点，但是一些大的正方形只被涂了一种颜色。那些彩色的正方形就是超出了视锥范围的，灰色的是在视锥范围内的。就像你看到的那样，这确实是最糟糕的一种情况，因为视锥穿过了包围正方形的中央，所以所有的四个&#8216;孩子&#8217;都得被检测。<br>　　<span class=English>In this picture a colored square that has one color was dumped without checking it抯 children. As you can see some squares had to be checked all the way to the final node, but some large squares could be dumped at once. The colored squares are the ones that are outside the viewing frustrum and the greyscale ones are the one inside the viewing frustrum. As you can see this is actually a worst case scenario because the viewing frustrum crosses the middle of the surrounding square and therefore all the four children have to be checked.</span><br><br>　　你可以应用八叉树到很多别的地方。例如碰撞检测。只检查你的碰撞球或者碰撞盒子所在的立方体，而且只需要检测那些面。还有更多的例子。<br>　　<span class=English>You could also apply the octree to many other things. Collision detection for example. Just check in which cube your bounding sphere or box is and you will only have to check against those faces. There are many more examples.</span><br><a name=5.0></a><br><strong>5、结论</strong>（<span class=English>Conclusion</span>）<br>　　关于八叉树已经写了很多了。我设法表述自己对它的看法，并且希望有人会读到它。就像你看到的那样，当提供好的结构的时候，八叉树比BSP树更容易实现（有人持异议）。主要的一点是：当一个&#8216;父亲&#8217;节点被丢弃的时候，他的&#8216;孩子&#8217;节点也同样被丢弃。实际上这就是全部。<br>　　<span class=English>There is already a lot written about octrees. I tried to give my view on them in the hope somebody might read this. As you can see octrees are way easier to implement than BSP-trees (although some disagree) while offering a better structure. The main point about an octrees is that when a parent is discarded so are it's children. Actually that is all there is to it.<br>　　Code clean, play Goldeneye and go vegetarian. Jaap Suter a.k.a .........</span></font><br></center>
<img src ="http://www.cppblog.com/winmain/aggbug/108306.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/winmain/" target="_blank">Code Knight</a> 2010-02-23 21:18 <a href="http://www.cppblog.com/winmain/archive/2010/02/23/108306.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[原]图形学学习笔记1(光照着色模型)</title><link>http://www.cppblog.com/winmain/archive/2010/02/23/108303.html</link><dc:creator>Code Knight</dc:creator><author>Code Knight</author><pubDate>Tue, 23 Feb 2010 13:13:00 GMT</pubDate><guid>http://www.cppblog.com/winmain/archive/2010/02/23/108303.html</guid><wfw:comment>http://www.cppblog.com/winmain/comments/108303.html</wfw:comment><comments>http://www.cppblog.com/winmain/archive/2010/02/23/108303.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/winmain/comments/commentRss/108303.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/winmain/services/trackbacks/108303.html</trackback:ping><description><![CDATA[&nbsp;
<p><span>一，四种光照着色模型</span></p>
<p><span>1</span><span>，固定着色<span>(constant shading)</span></span></p>
<p><span><span>&nbsp;&nbsp;&nbsp; </span></span><span>固定着色根本不考虑光照模型，只是根据多边形颜色的索引或<span>RGB</span>值绘制它。</span></p>
<p><span>PS:</span><span>基本已经被游戏淘汰，太简单的着色模型</span></p>
<p><span>2</span><span>，恒定着色（<span>flat shding</span>）</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp; </span></span><span>对于每个多边形只需要根据一个顶点执行光照计算，然后根据计算结果对整个多边形进行着色，这就是恒定着色，也称为面片着色<span>(faceted shading)</span>，对于由平面组成的多边形这种方法是可行的（立方体），但对于由曲面组成的多边形这种着色方式会出现非你想要的结果<span>. </span></span></p>
<p><span>3</span><span>，<span>Gougraud</span>着色</span></p>
<p><span>　　对于顶点之间的像素值采用两个顶点之间的插值计算来确定，顶点之间的颜色过渡自然，渲染效果也比较平滑<span>,</span>没有恒定着色那样突兀。</span></p>
<p><span>4</span><span>，<span>Phong</span>着色</span></p>
<p><span>　　与<span>Gougraud</span>着色类似，不过优点在于还对每个像素进行了法线的插值，对于镜面反射效果比较好。</span></p>
<img src ="http://www.cppblog.com/winmain/aggbug/108303.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/winmain/" target="_blank">Code Knight</a> 2010-02-23 21:13 <a href="http://www.cppblog.com/winmain/archive/2010/02/23/108303.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>OCTREE 教程</title><link>http://www.cppblog.com/winmain/archive/2010/02/23/108300.html</link><dc:creator>Code Knight</dc:creator><author>Code Knight</author><pubDate>Tue, 23 Feb 2010 13:08:00 GMT</pubDate><guid>http://www.cppblog.com/winmain/archive/2010/02/23/108300.html</guid><wfw:comment>http://www.cppblog.com/winmain/comments/108300.html</wfw:comment><comments>http://www.cppblog.com/winmain/archive/2010/02/23/108300.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/winmain/comments/commentRss/108300.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/winmain/services/trackbacks/108300.html</trackback:ping><description><![CDATA[&nbsp;
<td bgcolor="#f7ebde"><font class=NewsContent2><br><strong>对OCTREE的描述</strong><br><br>　　OCTREE 是对3D空间进行划分，也可以叫空间分割。他允许你只对你的3D世界中摄象机照射的区域进行作画。他也能用于冲突检测。下面讲一下为什么要进行空间分割。假设你建立了一个游戏世界，这个世界有超过100，000个多边形要画。如果你建立一个循环并传递这些多边形，那速度是很慢的。即使你有一块很好的显示卡，他也会有很大的麻烦。但是玩你游戏的玩家的显示卡不会超过300$。有没有一种方法只渲染摄象机看见的多边形？那就是美丽的OCTREE。他允许你快速的找到你要渲染的多边形。<br><br><br><strong>OCTREE是怎样工作的</strong><br><br>　　OCTREE工作在立方体中。最初，OCTREE从根接点开始，这个根接点对齐于立方体中整个世界，水平或场景的axis中心线。因此，把我们的整个世界想象成一个不可见的立方体。<br>　</font>
<div align=center><font class=NewsContent2>
<table id=table4 border=0 cellSpacing=0 cellPadding=0 width="100%">
    <tbody>
        <tr>
            <td>
            <p align=center><img border=0 src="http://dev.gameres.com/Program/Visual/3D/OCTREETutorial1.jpg" width=320 height=200></p>
            </td>
        </tr>
    </tbody>
</table>
</font></div>
<font class=NewsContent2></font>
<p><font class=NewsContent2><br>　　现在根接点存储了世界中的全部顶点。这是，他还是不能给我们任何好处，因为他还会画所有的东西。我们想把这个接点分成8个部分。一次，我们划分时，有8个立方体包含那最初的根接点的立方体。那意味着有4个立方体在上面，4个立方体在下面。请看下图：</font></p>
<font class=NewsContent2></font>
<div align=center><font class=NewsContent2>
<table id=table5 border=0 cellSpacing=0 cellPadding=0 width="100%">
    <tbody>
        <tr>
            <td>
            <p align=center><img border=0 src="http://dev.gameres.com/Program/Visual/3D/OCTREETutorial2.jpg" width=320 height=200></p>
            </td>
        </tr>
    </tbody>
</table>
</font></div>
<font class=NewsContent2></font>
<p><font class=NewsContent2><br>　　记住图中黄色轮廓线没有。<br>　　我们刚刚把这个世界分成8个部分。想象一下如果我们有2，3，4个部分，我们的世界将是怎样？我们的摄象机在世界的中间，向着后面靠右的角落。如果你看这些线，你将注意到在OCTREE中8个结点中的第4个。这些结点包含2个后面的顶和底结点。这意味着我们只用画存储在这些结点中的顶点。</font></p>
<font class=NewsContent2></font>
<div align=center><font class=NewsContent2>
<table id=table6 border=0 cellSpacing=0 cellPadding=0 width="100%">
    <tbody>
        <tr>
            <td>
            <p align=center><img border=0 src="http://dev.gameres.com/Program/Visual/3D/OCTREETutorial3.jpg" width=320 height=200></p>
            </td>
        </tr>
    </tbody>
</table>
</font></div>
<font class=NewsContent2></font>
<p><font class=NewsContent2><br>　　我们如何检测出我们要画的结点？如果你学过破片拣选（frustum culling),这将是很简单的。你能得到这些破片的大小并检测每个结点，看他是否被截断或在你的视觉破片中。有一个关于破片拣选的教程在<a href="http://www.gametutorials.com/"><u><font color=#0066cc>http://www.gametutorials.com</font></u></a>. 如果一个立方体截断破片，我们就将画这些结点。在这个例子中，我们切的数量是我们需要画的50%。记住，这只是我们世界中的一个部分。部分越多，我们就将越精确。当然，我们不会需要太多的点。下面，我们来看一下下面的图：</font></p>
<font class=NewsContent2></font>
<div align=center><font class=NewsContent2>
<table id=table7 border=0 cellSpacing=0 cellPadding=0 width="100%">
    <tbody>
        <tr>
            <td>
            <p align=center><img border=0 src="http://dev.gameres.com/Program/Visual/3D/OCTREETutorial4.jpg" width=320 height=200></p>
            </td>
        </tr>
    </tbody>
</table>
</font></div>
<font class=NewsContent2></font>
<p><font class=NewsContent2><br>　　在上面这幅图中，你将发现许多的不同。这个例子中，不是在原始的8个立方体的每一个结点中建立8个新的立方体。原始的8个结点的顶和底面没有细分。你总是把一个结点分成8个或更多的结点，但是，如果在这个面没有三角形可以存储，我们将忽视这个结点并不给他分配内存。如果我们进一步的细分，更多的结点将形成原始的世界。如果我们变换到另一个部分，那立方体将相似的变换。为了说明这一点，请看图： </font></p>
<font class=NewsContent2></font>
<div align=center><font class=NewsContent2>
<table id=table8 border=0 cellSpacing=0 cellPadding=0 width="100%">
    <tbody>
        <tr>
            <td align=middle><img border=0 src="http://dev.gameres.com/Program/Visual/3D/OCTREETutorial5.jpg" width=304 height=304></td>
            <td align=middle><img border=0 src="http://dev.gameres.com/Program/Visual/3D/OCTREETutorial6.jpg" width=304 height=304></td>
        </tr>
    </tbody>
</table>
</font></div>
<font class=NewsContent2></font>
<p><font class=NewsContent2><br>　　在图中，有两个球，但是方向相反。注意左边的部分，他将那世界分成2个结点，不是8个。这是因为球只要2个结点。请看右边的球是不是和左边的很相似。这幅图告诉我们：只显示需要的部分结点。如果没有三角形占用空间，结点将不会建立。<br><br><br><strong>何时停止细分</strong><br><br>　　现在，我们明白了如何细分，但是我们也需要知道怎样停止细分。有许多的方法：<br>　　1。如果当时的三角形数量少于我们定义的最大的三角形数量，我们可以停止细分当前的结点。举个例子，我们定义三角形的最大数量为100。这意味着我们在细分结点之前，要检测一下当前三角形的总数量是否小于或等于我们定义的最大数量，然后再做决定。如果数量少于或等于，我们将停止细分并指定这些三角形到那个结点。请注意我们从不指定任何三角形到任何结点，除非他是末结点。如果我们划分一个结点，我们不能存储三角形到那个结点，但是可以存储在他的子结点或他们的子结点中，甚至到他们的子中，等等。当我们复习了怎样画0C树后，将会有更多的了解。<br><br>　　2。另一个方法是在停止细分时，看我们是否细分的数目是否超过了细分的标准。例如，我们可以先建立细分的标准为10，如果细分的数量大于这个标准，我们将停止并指定这些在立方体中这个面的顶点到那个结点。当我们说&#8220;大于这个标准&#8221;就意味着细分的数量有11个。<br><br>　　3。最后的方法是看结点数是否超过结点变量定义时的值。例如，我们设置结点变量的值为500。每次，我们建立一个结点，相应的结点数增加1。然后在我们每次建立另一个结点时，检测一下我们当前的结点数是否超过结点变量。如果结点数为501，我们将不会细分这个结点，但是指定他的当前顶点给他。我自己用 1和3的方法，但是1和2也很好，因为你可以测试不同的细分的标准。<br><br>　<br><strong>怎样画OCTREE</strong><br><br>　　OCTREE建立后，我们就可以画我们需要的结点。那些立方体不是全部包含在我们的视觉中的，只有一部分。这就是我们为什么要计算每个结点的三角形的数量，如果我们只需要一个结点中的一部分，这样我们就不需要画成千上万个三角形。我们从根目录开始画OCTREE。对于每个结点都存储着一个中心点。这是非常好的，比如在下面这个函数中：<br><br>　　//这个函数取走立方体（X，Y，Z）的中心点和他的大小（width/2)<br>　　bool CubeInFrustum(float x,float y,float z,float size);<br><br>　　这个函数返回true or false,是由立方体是否在破片中决定的。如果立方体在破片中，我们将检测所有他的结点，看他们是否在破片中，否则我们将忽约树中的整个分枝。当我们得到了破片中的结点，但是没有任何结点在他下面。我们想画的顶点存储在末结点中。记住，只有末结点有顶点存储。看下面的图：</font></p>
<font class=NewsContent2></font>
<div align=center><font class=NewsContent2>
<table id=table9 border=0 cellSpacing=0 cellPadding=0 width="100%">
    <tbody>
        <tr>
            <td>
            <p align=center><img border=0 src="http://dev.gameres.com/Program/Visual/3D/OCTREETutorial7.jpg" width=320 height=200></p>
            </td>
        </tr>
    </tbody>
</table>
</font></div>
<font class=NewsContent2></font>
<p><font class=NewsContent2><br>　　有阴影的立方体是在破片中。白色的立方体不是在破片中。这里显示了细分的2层。<br><br><br><strong>OCTREE 中的冲突</strong><br><br>　　OCTREE 不是用于渲染，但是用于冲突检测很好。随着游戏的发展，冲突检测也在改变，你将不得不在游戏世界中运用自己的算式检测你的角色或目标是否冲突。下面是一些冲突检测的例子：<br>　　1。你将建立一个函数允许你转递3D空间中的点到你的OCTREE并返回在这个点周围的顶点。你将转递的那个点是你的角色和目标的中心点。这虽然可以工作一端时间，但如果这个点靠近一个立方体的边时呢？你的角色或目标可能和另一个立方体的顶点相冲突。为了解决这个问题，你将做一些事情。你可以转递角色/目标的半径或一定的空间，然后检测半径或一定的空间是否和周围的结点相冲突。这由你的角色/目标的形状决定。下面是一些典型的函数：<br><br>　　//这个函数取走角色/目标（X，Y，Z）的中心点并返回靠近他的顶点<br>　　CVector3 *GetVerticesFromPoint(float x,float y,float z);<br><br>　　//这个函数取走角色/目标（X，Y，Z）的中心点和半径，然后返回和他冲突的结点中的顶点<br>　　CVector3 *GetVerticesFromPointAndRadius(float x,float y,float z,float radius);<br><br>　　//这个函数取走角色/目标（X，Y，Z）的中心点和立方体的大小，然后返回和他冲突的结点中的顶点<br>　　CVector3 *GetVerticesFromPointAndCube(float x,float y,float z,float size);<br><br>　　我相信你有更好的方法快速的检测，在这里只是给你一点基础。<br><br><br><strong>总结</strong><br><br>　　这篇教程只是给你讲截如何建立自己的OCTREE。关于这篇文章中的代码在www.gametutorials.com，我希望这篇文章对你有用。<br><br><br>中文译者：antking<br><a href="http://akinggame.gameres.com/"><u><font color=#0066cc>http://akinggame.gameres.com</font></u></a> <br>这篇文章的英文版在<a href="http://www.gametutorials.com/Tutorials/OpenGL/Octree.htm"><u><font color=#0066cc>http://www.gametutorials.com/Tutorials/OpenGL/Octree.htm</font></u></a> <br><br>Ben Humphrey (DigiBen)<br>Game Programmer<br>DigiBen@GameTutorials.com<br>Co-Web Host of www.GameTutorials.com</font></p>
</td>
<img src ="http://www.cppblog.com/winmain/aggbug/108300.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/winmain/" target="_blank">Code Knight</a> 2010-02-23 21:08 <a href="http://www.cppblog.com/winmain/archive/2010/02/23/108300.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>total commader插件编写</title><link>http://www.cppblog.com/winmain/archive/2010/02/19/108069.html</link><dc:creator>Code Knight</dc:creator><author>Code Knight</author><pubDate>Fri, 19 Feb 2010 06:53:00 GMT</pubDate><guid>http://www.cppblog.com/winmain/archive/2010/02/19/108069.html</guid><wfw:comment>http://www.cppblog.com/winmain/comments/108069.html</wfw:comment><comments>http://www.cppblog.com/winmain/archive/2010/02/19/108069.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/winmain/comments/commentRss/108069.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/winmain/services/trackbacks/108069.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;休息了将近十天左右，代码的东西一点都没摸，完全脱离出代码的世界，有时觉得程序员不应该总沉浸于自己的代码世界，这段时间走走看看，把脑子打开去体会更多的东西，感受到以前自娱自乐的那种渺小，人应该有张有弛的，什么事情都不能过度，该做什么的时候绝对不要想着不该去想的东西，活在当下，才是幸福。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;新的一年，要开始工作了，今天看看自己的电脑，感觉好乱，想把所有的资料全扔进Total commander里，也想写一些插件来做一些额外的工作，比如把电影音乐打上tag或写上评论待以后方便查看等，先存一篇文章，以后有空的时候动手做这些事情的时候也许有用。<br><br>/////////////////////////////////////////////////////////////////////////////////////////////////////////////华丽分割线<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;应nevermind版主之约，写了<strong style="BACKGROUND-COLOR: rgb(153,255,153); COLOR: black">插件</strong>开发的一个Guild，简单介绍了如何为TC开发一个<strong style="BACKGROUND-COLOR: rgb(153,255,153); COLOR: black">插件</strong>以及<strong style="BACKGROUND-COLOR: rgb(153,255,153); COLOR: black">插件</strong>的基本工作过程，仅仅是一个入门介绍，详细的编程细节需要从网上下载帮助，下面文章中都给出了下载地址。<br><br>首先声明，本文撰写背景是TC 6.03a，6.5会加入新的<strong style="BACKGROUND-COLOR: rgb(153,255,153); COLOR: black">插件</strong>内容，但估计向下兼容应该是没有问题的。<br>众所周知，TC的<strong style="BACKGROUND-COLOR: rgb(153,255,153); COLOR: black">插件</strong>现在分为3类，Lister<strong style="BACKGROUND-COLOR: rgb(153,255,153); COLOR: black">插件</strong>（.wlx）、FileSystem<strong style="BACKGROUND-COLOR: rgb(153,255,153); COLOR: black">插件</strong>（.wfx）和Packer<strong style="BACKGROUND-COLOR: rgb(153,255,153); COLOR: black">插件</strong>（.wcx）（另外还有传说中6.5新加的Content<strong style="BACKGROUND-COLOR: rgb(153,255,153); COLOR: black">插件</strong>（.wdx），现在还不见庐山真面目，先按下不表）。尽管扩展名穿上了不同的马甲，但其本质都是一样的，都是Windows的DLL动态链接库，我们需要做的仅仅是按照TC的规范，实现其给定的DLL接口函数，最后把 dll扩展名改成相应扩展名就万事大吉了（使用不同的扩展名，只不过使其容易区分而已）。<br><br>1. 开发方法、环境和工具<br>如前所述，TC<strong style="BACKGROUND-COLOR: rgb(153,255,153); COLOR: black">插件</strong>本质上都是Windows的DLL动态链接库，其开发方法和普通的DLL程序开发并没有什么不同，任何一个可用来开发DLL的环境和工具都可以用来开发TC<strong style="BACKGROUND-COLOR: rgb(153,255,153); COLOR: black">插件</strong>。<br>因此，写TC<strong style="BACKGROUND-COLOR: rgb(153,255,153); COLOR: black">插件</strong>首先得熟悉DLL的<strong style="BACKGROUND-COLOR: rgb(255,153,153); COLOR: black">编写</strong>，更高一点的要求是熟悉一些常用的Windows API，对于一个程序员老手来说应该是很容易的事情，而用什么开发环境和工具都是次要的。但是对于新手，笔者推荐使用VC或者Delphi来<strong style="BACKGROUND-COLOR: rgb(255,153,153); COLOR: black">编写</strong>，一方面的原因是TC作者提供的函数头文件声明只有C/C++和Pascal，可以省却改写成别的语言的麻烦；另一方面原因是TC作者给的帮助、例子，甚至网上公开源码的<strong style="BACKGROUND-COLOR: rgb(153,255,153); COLOR: black">插件</strong>大都是基于此两种环境的，而有一个可参考的源码例子能在很大程度上提供<strong style="BACKGROUND-COLOR: rgb(255,153,153); COLOR: black">编写</strong>帮助。另外由于TC作者提供的例子（VC环境下）已经搭建起了 <strong style="BACKGROUND-COLOR: rgb(153,255,153); COLOR: black">插件</strong>的整个框架，我们甚至可以直接在此例子上修改开发。<br><br>Lister<strong style="BACKGROUND-COLOR: rgb(153,255,153); COLOR: black">插件</strong>的官方源码例子：http://ghisler.fileburst.com/lsplugins/listplugsample.zip。<br>FS<strong style="BACKGROUND-COLOR: rgb(153,255,153); COLOR: black">插件</strong>的官方源码例子：http://ghisler.fileburst.com/fsplugins/sampleplugin.zip。<br>其它第3方<strong style="BACKGROUND-COLOR: rgb(153,255,153); COLOR: black">插件</strong>的源码例子可以从以下各个<strong style="BACKGROUND-COLOR: rgb(153,255,153); COLOR: black">插件</strong>站点找到：<br>http://www.ghisler.com/plugins.htm<br>http://www.<span class=ColorResultsClass alpha-value="20" realoffset="833" highlight="true">total</span>cmd.net<br>http://club<span class=ColorResultsClass alpha-value="20" realoffset="851" highlight="true">total</span>.free.fr<br><br>2. Lister <strong style="BACKGROUND-COLOR: rgb(153,255,153); COLOR: black">插件</strong><br>首先说明一下Lister<strong style="BACKGROUND-COLOR: rgb(153,255,153); COLOR: black">插件</strong>的工作过程：默认快捷键情况下，当在TC中对一个文件按下F3或者Ctrl+Q的时候，TC会检查wincmd.ini中[ListerPlugins]一节，以下是个例子：<br>[ListerPlugins]<br>0=%<span class=ColorResultsClass alpha-value="20" realoffset="1050" highlight="true">COMMANDER</span>_PATH%\plugins\Imagine\Imagine.wlx<br>0_detect="MULTIMEDIA"<br>1=%<span class=ColorResultsClass alpha-value="20" realoffset="1086" highlight="true">COMMANDER</span>_PATH%\plugins\FlashView\FlashView.wlx<br>1_detect="([0]="F" &amp; [1]="W" &amp; [2]="S")|([0]="C" &amp; [1]="W" &amp; [2]="S")"<br><br>TC会顺序检查该节中每个<strong style="BACKGROUND-COLOR: rgb(153,255,153); COLOR: black">插件</strong>对应的x_detect字段，该字段实际上是一个逻辑判断表达式，如果此表达式结果为真，TC就会Load该<strong style="BACKGROUND-COLOR: rgb(153,255,153); COLOR: black">插件</strong>并调用其ListLoad函数，否则检查下一个<strong style="BACKGROUND-COLOR: rgb(153,255,153); COLOR: black">插件</strong>。如果<strong style="BACKGROUND-COLOR: rgb(153,255,153); COLOR: black">插件</strong>对应的x_detect字段根本就不存在，TC会调 用<strong style="BACKGROUND-COLOR: rgb(153,255,153); COLOR: black">插件</strong>的ListGetDetectString函数，如果此函数存在，TC会将函数的返回结果保存在x_detect字段中再检查，如果此函数仍然不存在，则TC就直接调用<strong style="BACKGROUND-COLOR: rgb(153,255,153); COLOR: black">插件</strong>的ListLoad函数。最后，如果调用了ListLoad函数，还要判断该 函数的返回值，如果该值是一个Windows句柄，则<strong style="BACKGROUND-COLOR: rgb(153,255,153); COLOR: black">插件</strong>调用成功；若返回值为0（NULL），则调用失败，继续检查下一个<strong style="BACKGROUND-COLOR: rgb(153,255,153); COLOR: black">插件</strong>。<br><br>Lister<strong style="BACKGROUND-COLOR: rgb(153,255,153); COLOR: black">插件</strong>的详细接口函数介绍可以从网上下到：http://ghisler.fileburst.com/lsplugins/listplughelp1.2.zip。<br><br>实际上，Lister<strong style="BACKGROUND-COLOR: rgb(153,255,153); COLOR: black">插件</strong>必需的函数只有ListLoad一个，它是<strong style="BACKGROUND-COLOR: rgb(153,255,153); COLOR: black">插件</strong>的核心实现函数。<strong style="BACKGROUND-COLOR: rgb(153,255,153); COLOR: black">插件</strong>必须在此函数中读入文件内容，创建一个窗口并显示文件内容，最后返回这个窗口的句柄，Lister会获得并Subclass该句柄，并在Lister内显示。<br><br>其余的接口函数都是可选函数，但其中有两个比较重要的函数：ListGetDetectString和ListCloseWindow，这两个函数与ListLoad一起构成了<strong style="BACKGROUND-COLOR: rgb(153,255,153); COLOR: black">插件</strong>的主干部分。<br><br>ListGetDetectString虽然是可选函数，但是我强烈建议实现这个函数，这对Lister的效率有很大的影响。从Lister工作过程可以看出，这个函数仅仅是在<strong style="BACKGROUND-COLOR: rgb(153,255,153); COLOR: black">插件</strong>第一次被调用时才被调用，功能是返回一个检测字符串以填写x_detec t字段，在此之后，Lister都将只检查此字段以决定是否调用<strong style="BACKGROUND-COLOR: rgb(153,255,153); COLOR: black">插件</strong>。因此，一个好的检测字符串可以让Lister迅速判断<strong style="BACKGROUND-COLOR: rgb(153,255,153); COLOR: black">插件</strong>是否适用于显示文件，如果没有这个，Lister每次显示文件都将不得不把<strong style="BACKGROUND-COLOR: rgb(153,255,153); COLOR: black">插件</strong>一个个都Load进来、分配空间、调用ListL oad，直到找到一个合适的，这个速度可是偏离了Lister快速查看的本意。例如：检测字符串是&#8220;ext="HTM" | ext="HTML"&#8221;，这时TC只需要根据文件扩展名是否是htm或html就可以直接判断该<strong style="BACKGROUND-COLOR: rgb(153,255,153); COLOR: black">插件</strong>是否适合，而无需读入任何文件，这就是为什么在<strong style="BACKGROUND-COLOR: rgb(153,255,153); COLOR: black">插件</strong>众多的时候，Lister仍然能很快显示的原因。当然，在某些情况下，确实难以给出一个合适的检测字符串，这就要求ListL oad函数在文件类型判断上的速度应该尽可能快。<br><br>ListColseWindow是在用户关闭Lister或在Lister中显示另一个文件时被调用，如果此函数不存在，Lister将直接调用DestroyWindow()关闭<strong style="BACKGROUND-COLOR: rgb(153,255,153); COLOR: black">插件</strong>窗口。通常情况下，我们需要在这里做窗口关闭时的善后工作，包括释放 资源等等。<br><br>除以上3个函数外，其它的几个可选函数都涉及一些具体的附加功能，取决于具体需求。<br><br>2. FileSystem<strong style="BACKGROUND-COLOR: rgb(153,255,153); COLOR: black">插件</strong><br>与Lister<strong style="BACKGROUND-COLOR: rgb(153,255,153); COLOR: black">插件</strong>不同，当用户安装一个FS<strong style="BACKGROUND-COLOR: rgb(153,255,153); COLOR: black">插件</strong>时，该<strong style="BACKGROUND-COLOR: rgb(153,255,153); COLOR: black">插件</strong>就会被第一次Load进来，并调用FsGetDefRootName以获得<strong style="BACKGROUND-COLOR: rgb(153,255,153); COLOR: black">插件</strong>名称，也是该FS根目录的名字，如果这个函数不存在，TC会直接使用wfx文件的名字做<strong style="BACKGROUND-COLOR: rgb(153,255,153); COLOR: black">插件</strong>名称（去掉文件扩展名） ，该名称会保存在wincmd.ini文件[FileSystemPlugins]一节，下面是个例子：<br>[FileSystemPlugins]<br>Linux-drives=%<span class=ColorResultsClass alpha-value="20" realoffset="1825" highlight="true">COMMANDER</span>_PATH%\plugins\ex2fs\ex2fs.wfx<br>Calendar=%<span class=ColorResultsClass alpha-value="20" realoffset="1843" highlight="true">COMMANDER</span>_PATH%\plugins\calendar\calendar.wfx<br>Shared files=%<span class=ColorResultsClass alpha-value="20" realoffset="1861" highlight="true">COMMANDER</span>_PATH%\plugins\netmon\NetMon.wfx<br>这样，当用户进入网上邻居时，TC不需要Load<strong style="BACKGROUND-COLOR: rgb(153,255,153); COLOR: black">插件</strong>就可以把所有<strong style="BACKGROUND-COLOR: rgb(153,255,153); COLOR: black">插件</strong>列出来，<strong style="BACKGROUND-COLOR: rgb(153,255,153); COLOR: black">插件</strong>只有在用户试图进入FS<strong style="BACKGROUND-COLOR: rgb(153,255,153); COLOR: black">插件</strong>目录时才真正被Load进来。<br><br>大致结构上，FS<strong style="BACKGROUND-COLOR: rgb(153,255,153); COLOR: black">插件</strong>需要提供的接口函数与一个真正文件系统的基本函数有些类似。其必需的函数有4个：FsInit、FsFindFirst、FsFindNext和 FsFindClose，是不是看了很眼熟，就和平时列举一个目录下所有文件所用的函数 结构一样。顾名思义，FsInit是用于<strong style="BACKGROUND-COLOR: rgb(153,255,153); COLOR: black">插件</strong>初始化的函数，同时TC会传给<strong style="BACKGROUND-COLOR: rgb(153,255,153); COLOR: black">插件</strong>3个TC提供给FS<strong style="BACKGROUND-COLOR: rgb(153,255,153); COLOR: black">插件</strong>调用的callback函数地址（下面会介绍）；FsFindFirst和FsFindNext用于列举一个目录下所有的文件；FsFindClose用 于终止FsFindFirst/FsFindNext的文件列举。有了这4个函数，就构成了最小的FS<strong style="BACKGROUND-COLOR: rgb(153,255,153); COLOR: black">插件</strong>，就可以浏览FS<strong style="BACKGROUND-COLOR: rgb(153,255,153); COLOR: black">插件</strong>的各个目录了。<br><br>有了文件目录结构后，就到了根据需要提供各种文件功能的时候了，包括删除文件FsDeleteFile；删除目录FsRemoveDir；建立目录 FsMkDir；执行文件FsExecuteFile；设置文件属性FsSetAttr；设置文件时间Fs SetTime；拷贝文件FsGetFile/FsPutFile/FsRenMovFile。大致上都和普通文件操作功能差不多，需要说明的是拷贝文件，由于FS<strong style="BACKGROUND-COLOR: rgb(153,255,153); COLOR: black">插件</strong>的特殊性，拷贝文件分成了3种情况：FsGetFile是从FS中往本地硬盘拷贝；FsPutFile是从本地硬盘往FS拷贝；FsRenMovFile是 在FS内部拷贝、移动或重命名文件。<br><br>此外，根据FS<strong style="BACKGROUND-COLOR: rgb(153,255,153); COLOR: black">插件</strong>的需要，TC还提供了3个callback函数以供其调用：<br>1) ProgressProc，用于显示一个进度条，例如拷贝文件时的进度条。 <br>2) LogProc，用于显示FTP工具栏，<strong style="BACKGROUND-COLOR: rgb(153,255,153); COLOR: black">插件</strong>可以在工具栏中显示log信息，并写入log文件。如果显示了FTP工具栏，点击&#8220;断开连接&#8221;按钮时还将调用<strong style="BACKGROUND-COLOR: rgb(153,255,153); COLOR: black">插件</strong>的FsDisconnect函数。<br>3) RequestProc，用于显示一个输入对话框，例如要求用户输入用户名和密码等等。<br><br>最后，FS<strong style="BACKGROUND-COLOR: rgb(153,255,153); COLOR: black">插件</strong>还可以实现一个函数FsStatusInfo，如果这个函数被实现，TC在调用<strong style="BACKGROUND-COLOR: rgb(153,255,153); COLOR: black">插件</strong>的任何函数（除了FsInit和FsDisconnect）之前和之后都将调用此函数，以方便<strong style="BACKGROUND-COLOR: rgb(153,255,153); COLOR: black">插件</strong>释放资源等等操作。<br><br>FS<strong style="BACKGROUND-COLOR: rgb(153,255,153); COLOR: black">插件</strong>的详细接口函数介绍可以从网上下载：http://ghisler.fileburst.com/fsplugins/fspluginhelp1.3.zip。<br><br>2. FileSystem<strong style="BACKGROUND-COLOR: rgb(153,255,153); COLOR: black">插件</strong><br>与Lister<strong style="BACKGROUND-COLOR: rgb(153,255,153); COLOR: black">插件</strong>不同，当用户安装一个FS<strong style="BACKGROUND-COLOR: rgb(153,255,153); COLOR: black">插件</strong>时，该<strong style="BACKGROUND-COLOR: rgb(153,255,153); COLOR: black">插件</strong>就会被第一次Load进来，并调用FsGetDefRootName以获得<strong style="BACKGROUND-COLOR: rgb(153,255,153); COLOR: black">插件</strong>名称，也是该FS根目录的名字，如果这个函数不存在，TC会直接使用wfx文件的名字做<strong style="BACKGROUND-COLOR: rgb(153,255,153); COLOR: black">插件</strong>名称（去掉文件扩展名） ，该名称会保存在wincmd.ini文件[FileSystemPlugins]一节，下面是个例子：<br>[FileSystemPlugins]<br>Linux-drives=%<span class=ColorResultsClass alpha-value="20" realoffset="1825" highlight="true">COMMANDER</span>_PATH%\plugins\ex2fs\ex2fs.wfx<br>Calendar=%<span class=ColorResultsClass alpha-value="20" realoffset="1843" highlight="true">COMMANDER</span>_PATH%\plugins\calendar\calendar.wfx<br>Shared files=%<span class=ColorResultsClass alpha-value="20" realoffset="1861" highlight="true">COMMANDER</span>_PATH%\plugins\netmon\NetMon.wfx<br>这样，当用户进入网上邻居时，TC不需要Load<strong style="BACKGROUND-COLOR: rgb(153,255,153); COLOR: black">插件</strong>就可以把所有<strong style="BACKGROUND-COLOR: rgb(153,255,153); COLOR: black">插件</strong>列出来，<strong style="BACKGROUND-COLOR: rgb(153,255,153); COLOR: black">插件</strong>只有在用户试图进入FS<strong style="BACKGROUND-COLOR: rgb(153,255,153); COLOR: black">插件</strong>目录时才真正被Load进来。<br><br>大致结构上，FS<strong style="BACKGROUND-COLOR: rgb(153,255,153); COLOR: black">插件</strong>需要提供的接口函数与一个真正文件系统的基本函数有些类似。其必需的函数有4个：FsInit、FsFindFirst、FsFindNext和 FsFindClose，是不是看了很眼熟，就和平时列举一个目录下所有文件所用的函数 结构一样。顾名思义，FsInit是用于<strong style="BACKGROUND-COLOR: rgb(153,255,153); COLOR: black">插件</strong>初始化的函数，同时TC会传给<strong style="BACKGROUND-COLOR: rgb(153,255,153); COLOR: black">插件</strong>3个TC提供给FS<strong style="BACKGROUND-COLOR: rgb(153,255,153); COLOR: black">插件</strong>调用的callback函数地址（下面会介绍）；FsFindFirst和FsFindNext用于列举一个目录下所有的文件；FsFindClose用 于终止FsFindFirst/FsFindNext的文件列举。有了这4个函数，就构成了最小的FS<strong style="BACKGROUND-COLOR: rgb(153,255,153); COLOR: black">插件</strong>，就可以浏览FS<strong style="BACKGROUND-COLOR: rgb(153,255,153); COLOR: black">插件</strong>的各个目录了。<br><br>有了文件目录结构后，就到了根据需要提供各种文件功能的时候了，包括删除文件FsDeleteFile；删除目录FsRemoveDir；建立目录 FsMkDir；执行文件FsExecuteFile；设置文件属性FsSetAttr；设置文件时间Fs SetTime；拷贝文件FsGetFile/FsPutFile/FsRenMovFile。大致上都和普通文件操作功能差不多，需要说明的是拷贝文件，由于FS<strong style="BACKGROUND-COLOR: rgb(153,255,153); COLOR: black">插件</strong>的特殊性，拷贝文件分成了3种情况：FsGetFile是从FS中往本地硬盘拷贝；FsPutFile是从本地硬盘往FS拷贝；FsRenMovFile是 在FS内部拷贝、移动或重命名文件。<br><br>此外，根据FS<strong style="BACKGROUND-COLOR: rgb(153,255,153); COLOR: black">插件</strong>的需要，TC还提供了3个callback函数以供其调用：<br>1) ProgressProc，用于显示一个进度条，例如拷贝文件时的进度条。 <br>2) LogProc，用于显示FTP工具栏，<strong style="BACKGROUND-COLOR: rgb(153,255,153); COLOR: black">插件</strong>可以在工具栏中显示log信息，并写入log文件。如果显示了FTP工具栏，点击&#8220;断开连接&#8221;按钮时还将调用<strong style="BACKGROUND-COLOR: rgb(153,255,153); COLOR: black">插件</strong>的FsDisconnect函数。<br>3) RequestProc，用于显示一个输入对话框，例如要求用户输入用户名和密码等等。<br><br>最后，FS<strong style="BACKGROUND-COLOR: rgb(153,255,153); COLOR: black">插件</strong>还可以实现一个函数FsStatusInfo，如果这个函数被实现，TC在调用<strong style="BACKGROUND-COLOR: rgb(153,255,153); COLOR: black">插件</strong>的任何函数（除了FsInit和FsDisconnect）之前和之后都将调用此函数，以方便<strong style="BACKGROUND-COLOR: rgb(153,255,153); COLOR: black">插件</strong>释放资源等等操作。<br><br>FS<strong style="BACKGROUND-COLOR: rgb(153,255,153); COLOR: black">插件</strong>的详细接口函数介绍可以从网上下载：http://ghisler.fileburst.com/fsplugins/fspluginhelp1.3.zip。 
<img src ="http://www.cppblog.com/winmain/aggbug/108069.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/winmain/" target="_blank">Code Knight</a> 2010-02-19 14:53 <a href="http://www.cppblog.com/winmain/archive/2010/02/19/108069.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>地形显示了</title><link>http://www.cppblog.com/winmain/archive/2010/02/05/107307.html</link><dc:creator>Code Knight</dc:creator><author>Code Knight</author><pubDate>Fri, 05 Feb 2010 13:27:00 GMT</pubDate><guid>http://www.cppblog.com/winmain/archive/2010/02/05/107307.html</guid><wfw:comment>http://www.cppblog.com/winmain/comments/107307.html</wfw:comment><comments>http://www.cppblog.com/winmain/archive/2010/02/05/107307.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/winmain/comments/commentRss/107307.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/winmain/services/trackbacks/107307.html</trackback:ping><description><![CDATA[&nbsp; <img border=0 src="http://www.cppblog.com/images/cppblog_com/winmain/tlscene.jpg">
<img src ="http://www.cppblog.com/winmain/aggbug/107307.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/winmain/" target="_blank">Code Knight</a> 2010-02-05 21:27 <a href="http://www.cppblog.com/winmain/archive/2010/02/05/107307.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>QT小记之在VS2005中使用QT</title><link>http://www.cppblog.com/winmain/archive/2010/01/31/106885.html</link><dc:creator>Code Knight</dc:creator><author>Code Knight</author><pubDate>Sun, 31 Jan 2010 06:44:00 GMT</pubDate><guid>http://www.cppblog.com/winmain/archive/2010/01/31/106885.html</guid><wfw:comment>http://www.cppblog.com/winmain/comments/106885.html</wfw:comment><comments>http://www.cppblog.com/winmain/archive/2010/01/31/106885.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/winmain/comments/commentRss/106885.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/winmain/services/trackbacks/106885.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp; QT的结构很清晰明了，看过第一个HELLO WORLD便爱上了它，感觉CEGUI有借鉴过QT的设计。<br>&nbsp;&nbsp;&nbsp; 如何在Windows平台下使用QT开发？<br>&nbsp;&nbsp;&nbsp; 一，下载SDK包<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 请去官网(QT被NOKIA收购，貌似使用协议更宽松了）下载win版本的QTSDK包。（地址如不知请百度GOOGLE之）<br>&nbsp;&nbsp;&nbsp; 二，设置开发环境相关变量<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 系统环变：PATH下加入：(<span class=ColorResultsClass highlight="true" realoffset="1153" alpha-value="20"></span>yourqtinstallpath)\bin<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 添加新的环境变量,名字为"QMAKESPEC",值为"win32-msvc<span class=ColorResultsClass highlight="true" realoffset="1174" alpha-value="20">2005</span>".<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; VS2005环境：include和lib分别包含qt的include目录和qt的lib目录<br>&nbsp;&nbsp;&nbsp; 三, 编译你所需要的QT Lib<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 通过"开始"菜单 -&gt; "Microsoft Visual Studio <span class=ColorResultsClass highlight="true" realoffset="561" alpha-value="20">2005</span>" -&gt; "Visual Studio Tools", 运行命令行（勿使用cmd，找不到nmake)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (<span class=ColorResultsClass highlight="true" realoffset="1153" alpha-value="20"></span>yourqtinstallpath)&gt;configure -no-stl -no-dsp -vcproj <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 待QMake完成 继续简单的敲入nmake即可（等待编译吧）<br>&nbsp;&nbsp;&nbsp; 四,创建QT工程 helloworld<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 有三种办法把QT代码生成为VS工程<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1，使用qmake,如代码在C盘下<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; C:\&gt; qmake -project -t vcapp -o projectname.pro<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; C:\&gt; qmake<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2，编写pro工程文件。如果是商业版的就不用了。具体可以参考帮助文档qmake。新建记事本文件，文件名修改为hello.pro，文件名没有 特殊要求哈；输入
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SOURCES +=main.cpp<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CONFIG +=<span class=ColorResultsClass highlight="true" realoffset="1714" alpha-value="20">qt</span></p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ok 保存。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 打开命令行，切换目录到hello.cpp所在目录。生成Makefile文件；输入：</p>
<p style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp; qmake -o Makefile hello.pro&nbsp;； </p>
<p style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp; 接下来生成项目文件.vcproj文件。 </p>
<p style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp; qmake -tp vc -o hello.vcproj hello.pro <br></p>
<p style="TEXT-INDENT: 2em">&nbsp;&nbsp; 3，直接使用<span class=ColorResultsClass highlight="true" realoffset="1237" alpha-value="20">Qt</span> Visual Studio Integration v1.2.2 for.<span class=ColorResultsClass highlight="true" realoffset="1237" alpha-value="20">VS</span>.2003.<span class=ColorResultsClass highlight="true" realoffset="1237" alpha-value="20">2005插件(详见http://blog.csdn.net/znf19850924/archive/2008/01/16/2047373.aspx)</span></p>
<p style="TEXT-INDENT: 2em"><strong>&nbsp;&nbsp;&nbsp; 需要配置<span class=ColorResultsClass highlight="true" realoffset="1384" alpha-value="20"></span>如下：</strong><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "Tools" -&gt; "Options" -&gt; "<span class=ColorResultsClass highlight="true" realoffset="1405" alpha-value="20">Qt</span>" -&gt; "Builds", 添加我们刚才编译的<span class=ColorResultsClass highlight="true" realoffset="1405" alpha-value="20">Qt</span>代码,名字为"<span class=ColorResultsClass highlight="true" realoffset="1405" alpha-value="20">Qt</span> 4.3.2", 路径为(<span class=ColorResultsClass highlight="true" realoffset="1153" alpha-value="20"></span>yourqtinstallpath)</p>
<p style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp;&nbsp; 启动一个新的工程.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; 选择"<span class=ColorResultsClass highlight="true" realoffset="1927" alpha-value="20">Qt</span> projects" -&gt; "<span class=ColorResultsClass highlight="true" realoffset="1927" alpha-value="20">Qt</span> Application"类型,输入工程名字,单击OK.</p>
<p style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp;&nbsp; 双击工程文件里面的"test.ui",马上出现了所见及所得的窗体编辑器,在上面添加一个按钮.</p>
<p style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp;&nbsp; 双击按钮,产生相应的消息响应函数.<br></p>
<p style="TEXT-INDENT: 2em">&nbsp; &nbsp;&nbsp; 添加头文件:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #include &lt;QMessageBox&gt;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; 在函数void Test::on_pushButton_clicked()体内添加如下代码:<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; QMessageBox box(this);<br>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; box.setText("Haha, hit me.");<br>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; box.exec();</p>
&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; PS:另外可以直接使用QTSDK自带安装的QTCreate来进行QT工程，在安装好SDK后不需要进行任何配置就能够运行DEMO并看到效果，可能自身已经配置好，但是如何引入到VS中，暂时还不知道，没有研究。<br>
<img src ="http://www.cppblog.com/winmain/aggbug/106885.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/winmain/" target="_blank">Code Knight</a> 2010-01-31 14:44 <a href="http://www.cppblog.com/winmain/archive/2010/01/31/106885.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>第一个场景</title><link>http://www.cppblog.com/winmain/archive/2010/01/15/105785.html</link><dc:creator>Code Knight</dc:creator><author>Code Knight</author><pubDate>Fri, 15 Jan 2010 15:51:00 GMT</pubDate><guid>http://www.cppblog.com/winmain/archive/2010/01/15/105785.html</guid><wfw:comment>http://www.cppblog.com/winmain/comments/105785.html</wfw:comment><comments>http://www.cppblog.com/winmain/archive/2010/01/15/105785.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/winmain/comments/commentRss/105785.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/winmain/services/trackbacks/105785.html</trackback:ping><description><![CDATA[<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 干，整了半个月总算出了天龙的第一个场景：少林。天下武功出少林...&nbsp;<br></p>
<p><img src="http://www.cppblog.com/images/cppblog_com/winmain/tianlong1.JPG" border=0><br></p>
<p><img src="http://www.cppblog.com/images/cppblog_com/winmain/tianlong2.JPG" border=0><br></p>
<p><br>纹理好像还有些问题....<br><br></p>
<img src ="http://www.cppblog.com/winmain/aggbug/105785.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/winmain/" target="_blank">Code Knight</a> 2010-01-15 23:51 <a href="http://www.cppblog.com/winmain/archive/2010/01/15/105785.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>OGRE贴花分类</title><link>http://www.cppblog.com/winmain/archive/2010/01/14/105618.html</link><dc:creator>Code Knight</dc:creator><author>Code Knight</author><pubDate>Wed, 13 Jan 2010 16:03:00 GMT</pubDate><guid>http://www.cppblog.com/winmain/archive/2010/01/14/105618.html</guid><wfw:comment>http://www.cppblog.com/winmain/comments/105618.html</wfw:comment><comments>http://www.cppblog.com/winmain/archive/2010/01/14/105618.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/winmain/comments/commentRss/105618.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/winmain/services/trackbacks/105618.html</trackback:ping><description><![CDATA[<p>法线贴花，根据所在位置的法线自动调整贴花朝向（不要求紧贴）</p>
<p>模型贴花，根据贴花所在的网格自动生成模型（一般贴图）</p>
<p>投影贴花，利用投影纹理的方式实现的贴花（frustum）</p>
<p>网格贴花，创建指定大小的网格贴花，然后自动调整网格的位置（mesh，贴图）</p>
<br><img src ="http://www.cppblog.com/winmain/aggbug/105618.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/winmain/" target="_blank">Code Knight</a> 2010-01-14 00:03 <a href="http://www.cppblog.com/winmain/archive/2010/01/14/105618.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>贴</title><link>http://www.cppblog.com/winmain/archive/2009/12/29/104407.html</link><dc:creator>Code Knight</dc:creator><author>Code Knight</author><pubDate>Tue, 29 Dec 2009 13:54:00 GMT</pubDate><guid>http://www.cppblog.com/winmain/archive/2009/12/29/104407.html</guid><wfw:comment>http://www.cppblog.com/winmain/comments/104407.html</wfw:comment><comments>http://www.cppblog.com/winmain/archive/2009/12/29/104407.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.cppblog.com/winmain/comments/commentRss/104407.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/winmain/services/trackbacks/104407.html</trackback:ping><description><![CDATA[<img  src="http://www.cppblog.com/images/cppblog_com/winmain/screenshot_2.png" border="0"><img src="http://www.cppblog.com/images/cppblog_com/winmain/screenshot_1.png" border="0"><br> <img src ="http://www.cppblog.com/winmain/aggbug/104407.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/winmain/" target="_blank">Code Knight</a> 2009-12-29 21:54 <a href="http://www.cppblog.com/winmain/archive/2009/12/29/104407.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>OGRE小记</title><link>http://www.cppblog.com/winmain/archive/2009/12/28/104319.html</link><dc:creator>Code Knight</dc:creator><author>Code Knight</author><pubDate>Mon, 28 Dec 2009 15:15:00 GMT</pubDate><guid>http://www.cppblog.com/winmain/archive/2009/12/28/104319.html</guid><wfw:comment>http://www.cppblog.com/winmain/comments/104319.html</wfw:comment><comments>http://www.cppblog.com/winmain/archive/2009/12/28/104319.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/winmain/comments/commentRss/104319.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/winmain/services/trackbacks/104319.html</trackback:ping><description><![CDATA[1,entity是没有getPosition的<br>2,node的默认position是原点<br>3,材质脚本中定义的程序段中的source文件名后缀必须与定义的shader文件类型匹配。<br>如：<br>vertex_program Ogre/CelShadingVP1 <span style="color: red;">hlsl</span><br>{<br>&nbsp;&nbsp; &nbsp;source Example_CelShading1.<span style="color: red;">hlsl</span><br>&nbsp;&nbsp; &nbsp;entry_point main_vp<br>&nbsp;&nbsp; &nbsp;<span style="color: red;">target</span> vs_2_0<br>}
<br>注意target是hlsl中独占,cg中是profile,且参数不同<br>4，Plugin_CgProgramManager_d.dll 插件一定要有cg.dll配合<br>5，OGRE不支持的中文路径用下面解决：<br>setlocale(LC_ALL, "chinese-simplified");
<br>记得读取完资源要还原<br>6，&nbsp;&nbsp;&nbsp; Ogre::ResourceGroupManager::getSingleton().initialiseAllResourceGroups()一定要在rendersystem初始化完毕才能调用。也就是在root的createRenderWindow 之后<br>7，想要你的OIS中的mouse何keboard响应你得记得在frameStarted
中每次去capture;<br>记得在&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; <br>mKeyboard = static_cast&lt;OIS::Keyboard*&gt;(mInputManager-&gt;createInputObject(OIS::OISKeyboard, true));<br>mMouse = static_cast&lt;OIS::Mouse*&gt;(mInputManager-&gt;createInputObject(OIS::OISMouse, true));<br>之后<br>mMouse-&gt;setEventCallback(this);<br>mKeyboard-&gt;setEventCallback(this);
<br>
<br><br><br>
<br>      <img src ="http://www.cppblog.com/winmain/aggbug/104319.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/winmain/" target="_blank">Code Knight</a> 2009-12-28 23:15 <a href="http://www.cppblog.com/winmain/archive/2009/12/28/104319.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>