﻿<?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++博客-Render Donkey-随笔分类-Irrlicht</title><link>http://www.cppblog.com/Leaf/category/20462.html</link><description>~~</description><language>zh-cn</language><lastBuildDate>Sun, 28 Apr 2013 04:33:24 GMT</lastBuildDate><pubDate>Sun, 28 Apr 2013 04:33:24 GMT</pubDate><ttl>60</ttl><item><title>irrlicht引擎：为什么我会想着捣鼓这货</title><link>http://www.cppblog.com/Leaf/archive/2013/04/11/199331.html</link><dc:creator>Render Donkey</dc:creator><author>Render Donkey</author><pubDate>Wed, 10 Apr 2013 17:30:00 GMT</pubDate><guid>http://www.cppblog.com/Leaf/archive/2013/04/11/199331.html</guid><wfw:comment>http://www.cppblog.com/Leaf/comments/199331.html</wfw:comment><comments>http://www.cppblog.com/Leaf/archive/2013/04/11/199331.html#Feedback</comments><slash:comments>4</slash:comments><wfw:commentRss>http://www.cppblog.com/Leaf/comments/commentRss/199331.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Leaf/services/trackbacks/199331.html</trackback:ping><description><![CDATA[<p>其实我也在问自己，为什么整来整去，又捣鼓起这个东西了。</p> <p>首先，irrlicht的商业性是很浅的，如果要想应用于商业化，不下一翻功夫是不行的。 比起现在满天飞舞的UINTY3D，就更不用说了。就算和OGRE比，也因为IRRLICHT没有提供太多花哨的特性，而导致这么多年来ARPU值一直没有OGRE高，玩家流失率是巨大的。</p> <p>Niko自己整的SupperCuber.就更不用说了，我自己下载来弄了一下，也没见得有多好使，反正没有官方介绍得那么牛B。</p> <p>&nbsp;</p> <p>在重新定位自己要深入挖掘的引擎之前，也曾再一次被OGRE吸引过。 原因有很多种，</p> <p>一是天龙代码的泄漏，里面有很多OGRE模型，可以直接加载，构建场景。很快速地获得像模像样的成就感。</p> <p>二是，OGRE本身的DEMO就提供了大量的SHADER，不用自己再辛辛苦苦地去东拼西找了。</p> <p>三是，本来与一个朋友相约用OGRE整RTS的， 因为目前公司的项目是RTS，所以一时间，对RTS兴趣大增， 看了0 A.D. GLEST等代码。 也明白了RTS中，工具与AI，远远大过于画面显示。 所以，使用OGRE，有现成的OgreCrowd等可以使用。 不用再为动态寻路找麻烦。</p> <p>四是，OGRE的招聘和成熟的案例远远大于irrlicht. 光是我知道的 天龙八部，成吉思汗，独孤求败，极光世界，火炬之光等，就足够说明它的威力。</p> <p>五是，OGRE官方支持WIN8,ADDROID,IOS。。</p> <p>原因太多了，这是一篇讲irrlicht的文章，老是夸OGRE是不道德的。</p> <p>&nbsp;</p> <p>下面，我来说说我的原因，也供和我一样纠结的朋友作一个参考。</p> <p>一、我时间有限，虽然之前看过OGRE的代码，但是对OGRE还是不敢说有掌握， 如果要用OGRE，其实还是得重头再来。</p> <p>二、IRRLICHT因为东西不多，所以以前在大学的时候，就对其很熟悉了，回过头来上手，也更容易。</p> <p>三、有一点点控制欲在里面，想看看IRRLICHT经过改造后，是不是真的比不上OGRE。</p> <p>四、蜀门的成功，足够说明一个游戏的画面，不是全部，只要不影响大局， 有一个比较亮点的技术或者效果，就可以留住玩家。 我想，蜀门里装备的流光效果，虽然就是经过美术精心设计后的纹理动画， 但已经足够体现高级装备和低级装备的差距。 玩家也能感受到自己高级装备的华丽， 所以，我更喜欢蜀门的小巧。</p> <p>五、犯贱，越是多的人喜欢的东西，越是不想整。</p> <p>六、想慢慢过渡，先使用IRRLICHT，直到IRRLICHT不够用，就改，改完了，就把IRR所有的东西删除了，名字换了。 就是自己的了。</p> <p>七、GAMELOFT的刺客信条用的是IRRLICHT，所以，我觉得还是可以的。 （PS:下载来玩了一下，在IPAD上，主角站立不动的时候，会来回抖动， 摄相机移动的时候，也会抖动，很费解， 难道是浮点精度问题？ 但UNITY3D和COCOS2D-X等是没有这问题的呀）。</p> <p>&nbsp;</p> <p>其实，列了很多条，最后也发现，IRRLICHT除了要简单点以外，是没有OGRE那么强大的。 不过，我还是选择了从简，毕竟精力有限。 如果要把OGRE整套东西理解了，再逐步重写，我估计会疯掉。 毕竟大而全的东西，具体在用的时候，是要抛掉很多东西来换取效率的。</p> <p>&nbsp;</p> <p>既然到这个点了，不得不说点别的。</p> <p>11年的时候，公司研发的引擎在演示完DEMO后，就叫停了。 项目进行了两年半，最后只有一堆代码和演示程序。 对公司来说，其实是一定的损失。 后来项目组成员转战WEB。&nbsp; 走到这一步，其实原来的成员只剩和我另一个搭档了。</p> <p>没想到，进入了WEB，就一去不复返了。 并且，公司的WEB项目进展也不是很顺利。&nbsp; 都说毕业后两年是一个分水岭， 当时正好毕业两年。 于是决定换一个环境挑战。 就来到了目前的公司，做RTS游戏服务器。&nbsp; 面对未知的东西，貌似更能激发我的兴趣，如今马上又是一年了。渐渐地，开始怀念引擎，怀念图形。 可以说IRRLICHT目前就是被我用来表达我对图形的思念。 虽然我图形方面的技术很陈旧，老土， 但并不影响我说我喜欢搞图形。</p> <p>文章就到此吧。也不知道再要说些什么了。</p> <img src ="http://www.cppblog.com/Leaf/aggbug/199331.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Leaf/" target="_blank">Render Donkey</a> 2013-04-11 01:30 <a href="http://www.cppblog.com/Leaf/archive/2013/04/11/199331.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>irrlicht引擎:中文支持</title><link>http://www.cppblog.com/Leaf/archive/2013/04/11/199329.html</link><dc:creator>Render Donkey</dc:creator><author>Render Donkey</author><pubDate>Wed, 10 Apr 2013 17:01:00 GMT</pubDate><guid>http://www.cppblog.com/Leaf/archive/2013/04/11/199329.html</guid><wfw:comment>http://www.cppblog.com/Leaf/comments/199329.html</wfw:comment><comments>http://www.cppblog.com/Leaf/archive/2013/04/11/199329.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/Leaf/comments/commentRss/199329.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Leaf/services/trackbacks/199329.html</trackback:ping><description><![CDATA[<p>还是先上图吧</p> <p><img src="http://t1.qpic.cn/mblogpic/19a1da54dec018ffffa6/460" width="555" height="392"></p> <p>这是使用freetype进行中文显示的效果。</p> <p>irrlicht由于是使用位图字体的方式，是很容易替换掉字体的。 同时，其本身也提供了Font接口替换的功能。</p> <p>具体做法和网上大多数人是一样的。</p> <p>&nbsp;</p> <p>在做这个的时候，又引入了另一个话题， gameswf和kfont(KlayGE Font)</p> <p>gameswf是一个开源的C++ FLASH PLAYER。</p> <p>gameloft以及很多移动应用或者游戏都在使用它。</p> <p>当然，也包括ScaleForm. 因为ScaleForm是商业的，所以比gameswf更加完善，虽然说，gameswf是ScaleForm的原型。</p> <p>&nbsp;</p> <p>kfont一直是自己喜欢的一种字体解决方案，其无比拉伸的能力非常讨人喜欢。加上现在又单独成库了，如果不用gameswf的话，我想把它整合进irrlicht中。 两年前公司（先前的公司）的引擎就用上了这个，遗憾字体库不是我弄进去的，一直对kfont没有近距离接触。</p> <p></p> <p>&nbsp;</p> <p>网上下载下来的代码 下面地址可供参考，这是我觉得众多文章中，讲得比较细的一个。</p> <p><a title="http://blog.csdn.net/lee353086/article/details/5260101" href="http://blog.csdn.net/lee353086/article/details/5260101">http://blog.csdn.net/lee353086/article/details/5260101</a></p> <p>&nbsp;</p> <p>至于FreeType,大家去官方下载来编译就可以了。</p> <img src ="http://www.cppblog.com/Leaf/aggbug/199329.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Leaf/" target="_blank">Render Donkey</a> 2013-04-11 01:01 <a href="http://www.cppblog.com/Leaf/archive/2013/04/11/199329.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>irrlicht引擎:Bloom效果</title><link>http://www.cppblog.com/Leaf/archive/2013/04/11/199328.html</link><dc:creator>Render Donkey</dc:creator><author>Render Donkey</author><pubDate>Wed, 10 Apr 2013 16:49:00 GMT</pubDate><guid>http://www.cppblog.com/Leaf/archive/2013/04/11/199328.html</guid><wfw:comment>http://www.cppblog.com/Leaf/comments/199328.html</wfw:comment><comments>http://www.cppblog.com/Leaf/archive/2013/04/11/199328.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/Leaf/comments/commentRss/199328.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Leaf/services/trackbacks/199328.html</trackback:ping><description><![CDATA[<p>先上图，再说点别的。</p> <p>&nbsp;</p> <p><a href="http://www.cppblog.com/images/cppblog_com/Leaf/WindowsLiveWriter/irrlichtBloom_AA4/image_4.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://www.cppblog.com/images/cppblog_com/Leaf/WindowsLiveWriter/irrlichtBloom_AA4/image_thumb_1.png" width="532" height="400"></a> </p> <p>BLOOM开</p> <p>&nbsp;</p> <p><a href="http://www.cppblog.com/images/cppblog_com/Leaf/WindowsLiveWriter/irrlichtBloom_AA4/2000_2.jpg"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="2000" border="0" alt="2000" src="http://www.cppblog.com/images/cppblog_com/Leaf/WindowsLiveWriter/irrlichtBloom_AA4/2000_thumb.jpg" width="538" height="404"></a> </p> <p></p> <p>BLOOM关</p> <p>&nbsp;</p> <p>在IRRLICHT中实现BLOOM，和其它引擎中没有太多的不同。 SHADER还是那个SHADER。</p> <p>关于BLOOM的算法，也就那样了，没有特别之处，况且，我这BLOOM很暴力</p> <p>render scene to texture.</p> <p>1/4 downsample 选择暴光像素</p> <p>h_blur&nbsp; 7次采样 和权重混合 </p> <p>v_blur&nbsp; 7次采样 和权重混合</p> <p>compose 两图叠加</p> <p>&nbsp;</p> <p>下面说说我在irrlicht中实现post processing的方案。</p> <p>在irrlicht中是没有屏幕对齐四边形节点的，如果要特殊扩展，就只能修改代码了。我是尽量保证自己不修改IRR一行代码， 除非是真正使用时，要对效率进行优化。前现实现的GPU蒙皮，水面，镜面等，都没有修改过一行代码， 因为我不想因为自己的一时需求，而改动了那一堆。 当我真的需要改动irrlicht才能达到目标的时候，表示irrlicht中我使用的部分，可以退休了。</p> <p>&nbsp;</p> <p>渲染场景的时候，我们通常在使用addXXXXSceneNode的时候，都默认不传父节点。这样就是默认的场景根节点。但是，当我们要做post process的时候，就需要对场景中的物体进行显示的开和关， 于是，我们为了很快速地控制， 于是将普通场景节点多加了一个父节点， 而post processing作为场景的兄弟节点， 这样在渲染的时候，就可以方便地进行相关控制了。</p> <p>大概是这样的</p> <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; RootSceneNode</p> <p>&nbsp;&nbsp;&nbsp;&nbsp; PostProcessingNode&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SceneOjbectsNode</p> <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Obj1… Obj2….Obj3…</p> <p>&nbsp;</p> <p>流程：</p> <p>关闭&nbsp;&nbsp;&nbsp; PostProcessingNode ， 渲染&nbsp; SceneOjbectsNode 下所有的物体到RT上。</p> <p>关闭&nbsp;&nbsp;&nbsp; SceneOjbectsNode， 打开PostProcessingNode， 进行一系列的后期效果处理。</p> <p>&nbsp;</p> <p>在irrlicht中是没有提供屏幕对齐四边形绘制的， 如果手工构建，就很麻烦。 所以，我采用的是一种很常见的手法， 即通过UV坐标来计算最最终的顶点坐标值。</p> <p>VS的输出，是规一化坐标系， 即X,Y是处于 （－1，1）之间的， 于是。 我们只需要 pos = (uv-0.5)*2;&nbsp; pos.y = –pos.y;就可以了。</p> <p>最近一直在加班，没时间整理出代码。 有兴趣的朋友可以加下面的群</p> <p>Irrlicht Engine-China</p> <p>254431855</p><img src ="http://www.cppblog.com/Leaf/aggbug/199328.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Leaf/" target="_blank">Render Donkey</a> 2013-04-11 00:49 <a href="http://www.cppblog.com/Leaf/archive/2013/04/11/199328.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Programming 3D games on Android with Irrlicht and Bullet</title><link>http://www.cppblog.com/Leaf/archive/2013/04/06/199161.html</link><dc:creator>Render Donkey</dc:creator><author>Render Donkey</author><pubDate>Sat, 06 Apr 2013 13:19:00 GMT</pubDate><guid>http://www.cppblog.com/Leaf/archive/2013/04/06/199161.html</guid><wfw:comment>http://www.cppblog.com/Leaf/comments/199161.html</wfw:comment><comments>http://www.cppblog.com/Leaf/archive/2013/04/06/199161.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/Leaf/comments/commentRss/199161.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Leaf/services/trackbacks/199161.html</trackback:ping><description><![CDATA[<p>Programming 3D games on Android with Irrlicht and Bullet (Part 1) <p>Posted on May 19, 2011, 11:00 pm, by xp, under <a href="http://renzhi.ca/category/programming/">Programming</a>. <p>Just got a new Android phone (a Samsung Vibrant) a month ago, so after flashing a new ROM and installing a bunch of applications, what would I want to do with the new phone? Well, I’d like to know if the phone is fast enough to play 3D games. From the hardware configuration point of view, it is better equipped than my desktop computer in the 1990s, and since my desktop computer at the time had no problem with 3D games, I would expect it to be fast enough to do the same. <p>At first, I was considering downloading a 3D game from the market, but 3D games for Android are still rare, then why don’t I just create a 3D demo game myself? <p>After looking around which 3D game engines are available for the Android platform, I just settled down with <a href="http://irrlicht.sourceforge.net/">Irrlicht</a>. This is an open source C++ graphic engine, and not really a game engine per se, but it should have enough features to create my demo 3D application. And I like to have realistic physics in my game, so what could be better than the <a href="http://bulletphysics.org/wordpress/">Bullet Physics</a> library? This is the best known open source physics library, also developed in C++. The two libraries together would be an interesting combination. <p>Although Irrlicht was developed for desktop computers, but luckily enough, someone has already <a href="http://gitorious.org/irrlichtandroid/">ported Irrlicht to the Android platform</a>, which requires a special device driver for the graphic engine. And guess what? Someone has also created a <a href="http://sourceforge.net/projects/irrbullet/">Bullet wrapper for the Irrlicht engine</a>. All of them in C++, and open source. All we need to do now to pull all these codes together to build a shared library for Android. <p>In this part, I’ll just describe what needs to compile all the codes for Android. Since we will compile C/C++ codes, you’ll need to download the <a href="http://developer.android.com/sdk/ndk/">Android native development kit</a>. Please refer to the documentation on how to install. <p>We create an Android project, and add a <em>jni</em> folder. Then we put all the C/C++ source codes under the <em>jni</em> folder. I created three sub-folders: <ol> <li><em>Bullet</em>: All the Bullet Physics source codes. Actually, we only need the Collision, Dynamics, Soft Body and Linear Math libraries.  <li><em>Irrlicht</em>: The Irrlicht 3D graphic engine source codes. This is the Android port of the engine.  <li><em>irrBullet</em>: This is the Bullet wrapper for Irrlicht engine, which makes it easier to write your programs. </li></ol> <p>After, all we need to do is to create an <em>Android.mk</em> file, which is quite simple, really. You can read the makefile to see how it is structured. Basically, we just tell the Android NDK build tools that we want to build all the source codes for the Arm platform, and we want to link with the OpenGL ES library, to create a shared library called <em>libirrlichtbullet.so</em>. That’s about it. <p>However, there’s one minor thing to note though. Android does not really support C++ standard template library, but the <em>irrBullet</em> library made use of it. Therefore, in the <em>jni</em> folder, we need to add an <em>Application.mk</em> file, which contains the following line:<pre>APP_STL  := stlport_static</pre>
<p>And that’s it. Now, you can run <em>ndk-build</em> to build the shared library. If you have a slow computer, it would take a while. If everything is alright, you should have a shared library in the folder <em>libs/armeabi/</em>. That shared library contains the Bullet Physics, Irrlicht and the irrBullet wrapper libraries. You can now create your 3D games for Android with it. In the next part, we will write a small demo program using this library.
<p>You can download all the source codes and pre-built library <a href="http://renzhi.ca/BulletAndroid.tar.gz">here</a>.
<p>&nbsp;</p>
<p>&nbsp;</p>
<h4>Programming 3D games on Android with Irrlicht and Bullet (Part 2)</h4>
<p>Posted on May 20, 2011, 11:30 am, by xp, under <a href="http://renzhi.ca/category/programming/">Programming</a>.
<p>In the last post, we have built the Bullet Physics, Irrlicht and irrBullet libraries together to create a shared library for the Android platform. In this post, we are going to create a small demo 3D game for Android, using the libraries that we have built earlier.
<p>This demo is not really anything new, I am going to just convert an Irrlicht example to run on Android. In this simple game, we are going to stack up a bunch of crates, and then we will shoot a sphere or a cube, from a distance, to topple the crates. The Irrlicht engine will handle all the 3D graphics, and the Bullet Physics library will take care of rigid body collision detection and all realistic physical kinetics. For example, when we shoot a sphere from the distance, how the sphere follows a curve line when flying over the air, how far it will fly, where it is going to fall on to the ground, how it reacts when it hits the ground, how it reacts when it hits the crates, and how the crates will react when being hit, etc, all these will be taken care of by Bullet Physics, and Irrlicht will render the game world accordingly.
<p>Since it is easier to create Android project in Eclipse, we are going to work with Eclipse here. You will need to following tools to work with:
<ol>
<li>Android SDK 
<li>Android NDK 
<li>Eclipse IDE 
<li>Eclipse plugin for Android development. </li></ol>
<p>I’m assuming you have all these tools installed and configured correctly. And I’m assuming you have basic knowledge on Android programming too, so I won’t get into the basic details here.
<p>Let’s create a project called <em>ca.renzhi.bullet</em>, with an Activity called <em>BulletActivity</em>. The <em>onCreate()</em> method will look something like this:
<ol>
<li>
<li>
<p>@Override</p>
<li>
<p>public void onCreate(Bundle savedInstanceState) {</p>
<li>
<p>super.onCreate(savedInstanceState);</p>
<li>
<p>// Lock screen to landscape mode.</p>
<li>
<p>this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);</p>
<li>
<li>
<p>mGLView = new GLSurfaceView(getApplication());</p>
<li>
<p>renderer = new BulletRenderer(this);</p>
<li>
<p>mGLView.setRenderer(renderer);</p>
<li>
<li>
<p>DisplayMetrics displayMetrics = getResources().getDisplayMetrics();</p>
<li>
<p>width = displayMetrics.widthPixels;</p>
<li>
<p>height = displayMetrics.heightPixels;</p>
<li>
<li>
<p>setContentView(mGLView);</p>
<li>
<p>}</p></li></ol>
<p>This just tells Android that we want an OpenGL surface view. We will create a Renderer class for this, something very simple like the following:
<ol>
<li>
<p>public class BulletRenderer implements <a href="http://www.google.com/search?hl=en&amp;q=allinurl:Renderer+java.sun.com&amp;btnI=I'm%20Feeling%20Lucky">Renderer</a></p>
<li>
<p>{</p>
<li>
<p>BulletActivity activity;</p>
<li>
<li>
<p>public BulletRenderer(BulletActivity activity)</p>
<li>
<p>{</p>
<li>
<p>this.activity = activity;</p>
<li>
<p>}</p>
<li>
<li>
<p>public void onDrawFrame(GL10 arg0)</p>
<li>
<p>{</p>
<li>
<p>activity.drawIteration();</p>
<li>
<p>}</p>
<li>
<li>
<p>public void onSurfaceChanged(GL10 gl, int width, int height)</p>
<li>
<p>{</p>
<li>
<p>activity.nativeResize(width, height);</p>
<li>
<p>}</p>
<li>
<li>
<p>public void onSurfaceCreated(GL10 gl, EGLConfig config)</p>
<li>
<p>{</p>
<li>
<p>activity.nativeInitGL(activity.width, activity.height);</p>
<li>
<p>}</p>
<li>
<p>}</p></li></ol>
<p>The renderer class’s method will be invoked every time a frame needs to be rendered. There’s nothing special here. When the methods are invoked, we just invoke the native methods in the activity class, which will then call the C native functions through JNI. Since Irrlicht and Bullet are C++ libraries, we will have to write the main part of the game in C/C++. We keep very little logic in Java code.
<p>When the surface is first created, the <em>onSurfaceCreated()</em> method is invoked, and here, we just call <em>nativeInitGL()</em>, which will initialize our game world in Irrlicht. This will initialize the device, the scene manager, create a physical world to manage the rigid bodies and their collision, create a ground floor, and put a stack of crates in the middle point. Then, we create a first-person-shooter (FPS) camera to look at the stack of crates. The player will look at this game world through the FPS camera.
<p>I’m not going to describe the codes line by line, since you can download the codes to play with it. But when you create the Irrlicht device with the following line of code:
<ol>
<li>
<p>device = createDevice( video::EDT_OGLES1, dimension2d(gWindowWidth, gWindowHeight), 16, false, false, false, 0);</p></li></ol>
<p>Make sure you select the correct version of OpenGL ES library on your Android device. I have version 1.x on mine. But if you have version 2.x, change to <em>video::EDT_OGLES2</em> instead.
<p>After the initialization, we would have a scene that looks like this:
<p><a href="http://renzhi.ca/wp-content/uploads/2011/05/snap20110520_092510.png"><img title="snap20110520_092510" alt="" src="http://renzhi.ca/wp-content/uploads/2011/05/snap20110520_092510-300x180.png" width="300" height="180"></a>
<p>When a frame is changed and needs to render, the <em>onDrawFrame()</em> method of the renderer is invoked. And here, we just call the <em>nativeDrawIteration()</em> function and will handle the game logic in C/C++ codes. The code looks like this:
<ol>
<li>
<p>void Java_ca_renzhi_bullet_BulletActivity_nativeDrawIteration(</p>
<li>
<p>JNIEnv* env,</p>
<li>
<p>jobject thiz,</p>
<li>
<p>jint direction,</p>
<li>
<p>jfloat markX, jfloat markY)</p>
<li>
<p>{</p>
<li>
<p>deltaTime = device-&gt;getTimer()-&gt;getTime() – timeStamp;</p>
<li>
<p>timeStamp = device-&gt;getTimer()-&gt;getTime();</p>
<li>
<li>
<p>device-&gt;run();</p>
<li>
<li>
<p>// Step the simulation</p>
<li>
<p>world-&gt;stepSimulation(deltaTime * 0.001f, 120);</p>
<li>
<li>
<p>if ((direction != -1) || (markX != -1) || (markY != -1))</p>
<li>
<p>handleUserInput(direction, markX, markY);</p>
<li>
<li>
<p>driver-&gt;beginScene(true, true, SColor(0, 200, 200, 200));</p>
<li>
<p>smgr-&gt;drawAll();</p>
<li>
<p>guienv-&gt;drawAll();</p>
<li>
<p>driver-&gt;endScene();</p>
<li>
<p>}</p></li></ol>
<p>As you can see, this is very standard Irrlicht game loop, the only thing added here is a function to handle user input.
<p>User input includes moving left and right, forward and backward, shooting sphere and cube. Irrlicht engine depends on keyboard and mouse for user interaction, which are not available on Android devices. So, we will create a very basic kludge to allow users to move around and shoot. We will use touch and tap to handle user input. Users will move their finger left and right, on the left part of the screen, to move left and right in the game world. Users will move their finger up and down, on the right part of screen, to move forward and backward in the game world. And tap on the screen to shoot. Therefore, the movement direction is translated into a parameter, called <em>direction</em>, and passed to the native code to be handled. We also grab the X and Y coordinates of the shooting mark, and pass them as parameters to native codes as well.
<p>That’s it. You can now build it, package into an apk, install it on your Android device, and play with it. When you shoot on the stack of crates, you would have a scene that looks like this:
<p><a href="http://renzhi.ca/wp-content/uploads/2011/05/snap20110520_092531.png"><img title="snap20110520_092531" alt="" src="http://renzhi.ca/wp-content/uploads/2011/05/snap20110520_092531-300x180.png" width="300" height="180"></a>
<p>The performance on my Samsung Vibrant is ok, I get about 56 or 57 FPS, which is quite smooth. But if there are too many objects to animate, especially after we have shot many spheres and cubes, we will have a screen that hangs and jumps a bit, or sometimes, it stops to react to user input for a fraction of second. In a real game, we might want to remove objects that have done their work, so that the number of objects to animate is significantly reduced to maintain an acceptable performance.
<p>The other important thing that we want to improve is user interaction and control. The Irrlicht engine is developed for desktop computers, it relies mainly on keyboard and mouse for user interaction. These are not available on mobile devices. The current demo attempted to use touch and tap on screen as user control, but it does not work very well. In a next post, we will try to create virtual controls on screen (e.g. buttons, dials, etc), and we might want to take advantage of the sensor as well, which is a standard feature on mobile devices now.
<p>You can download the source codes of the demo <a href="http://renzhi.ca/ca.renzhi.bullet.tar.gz">here</a>.
<p></p>
<p>&nbsp;</p>
<h4>Programming 3D games on Android with Irrlicht and Bullet (Part 3)</h4>
<p>Posted on May 23, 2011, 6:25 pm, by xp, under <a href="http://renzhi.ca/category/programming/">Programming</a>.
<p>In the last post, we have created a basic 3D demo application with Irrlicht, in which we put a stack of crates, and we topple them by shooting a cube or a sphere.
<p>In this post, we will try to create an on-screen control so that you can move around with it, like using a hardware control. What we want to have is something like this, in the following screenshot:
<p><a href="http://renzhi.ca/wp-content/uploads/2011/05/snap20110523_161458.png"><img title="snap20110523_161458" alt="" src="http://renzhi.ca/wp-content/uploads/2011/05/snap20110523_161458-300x180.png" width="300" height="180"></a>
<p>What we have here is a control knob, sitting on a base. The knob is in the centre of the base. The on-screen control always stays on top of the game scene, and the position should stay still regardless of how you move the camera. However, users can press on the knob, and drag it left and right, and this, in turn, moves the camera left and right accordingly.
<p>Obviously, you can implement movement direction along more than one axis too. And you can also have more than one on-screen control if you want, since it is a device with multi-touch screen. But that’s left to you as an exercise.
<p>Placing an on-screen control is actually quite easy. All you have to do is to load a picture as texture, then draw it as 2D image on the screen, at the location you want to put the control. But since we want the on-screen control to be always on top, we have to draw the 2D image after the game scene (and all the scene objects) are drawn. If we draw the 2D image first, it will hidden by the game scene. There, in your loop, you would have something like this:
<ol>
<li>
<p>driver-&gt;beginScene(true, true, SColor(0, 200, 200, 200));</p>
<li>
<p>smgr-&gt;drawAll();</p>
<li>
<p>guienv-&gt;drawAll();</p>
<li>
<p>// Draw the on-screen control now</p>
<li>
<p>onScreenControl-&gt;draw(driver);</p>
<li>
<p>driver-&gt;endScene();</p></li></ol>
<p>That’s the basic idea. Here, we have created an <em>OnScreenControl</em> class, which encloses two objects, one of <em>VirtualControlBase</em> class and the other, of <em>VirtualControlKnob</em> class. The <em>draw()</em> method of the <em>OnScreenControl</em> class looks like this:
<ol>
<li>
<p>void OnScreenControl::draw(IVideoDriver* driver)</p>
<li>
<p>{</p>
<li>
<p>base-&gt;draw(driver);</p>
<li>
<p>knob-&gt;draw(driver);</p>
<li>
<p>}</p></li></ol>
<p>It just relegates the drawing works to its sub-objects, the control base and the control knob. Note that the knob has to be drawn after the base, otherwise, it will be hidden behind the base, instead of sitting on top of it. The <em>draw()</em> method of the base looks like:
<ol>
<li>
<p>void VirtualControlBase::draw(IVideoDriver* driver)</p>
<li>
<p>{</p>
<li>
<p>driver-&gt;draw2DImage(_texture,</p>
<li>
<p>position2d(pos_x, pos_y),</p>
<li>
<p>rect(0, 0, width, height),</p>
<li>
<p>0,</p>
<li>
<p>SColor(255,255,255,255),</p>
<li>
<p>true);</p>
<li>
<p>}</p></li></ol>
<p>As you see, it just draws a 2D image with the texture, at the location specified. That’s it.
<p>After putting the on-screen control in place, we have to handle user touch events on the screen. If users press on the knob (i.e. pressing within the square boundary of the knob image), and move the finger around, we update the position of the knob according to the movement direction. Here, we want to make sure that users can not drag the knob out of the control base boundary (or too far out of the boundary anyway), to make it look and behave like a real control. As users move the knob around, you want to update your camera’s position accordingly. And when the knob is released, you want to reset its position back to the centre of the control base.
<p>That’s basically the idea. You can grab the source code <a href="http://renzhi.ca/ca.renzhi.bullet-2.tar.gz">here</a>. Ugly codes, I warn you.
<p>The major problem of programming Irrlicht on Android is the separation of Java codes and the C/C++ codes. If you want to limit your program to only Android 2.3 or later, you can probably write the whole program in C/C++, using the native activity class. That way, you don’t have to move back and forth between Java and C++. But if you want to run your program on older versions of Android, your Activity must be written in Java, and the main game logic written in C/C++. You then have to catch user interaction events in your Java code, pass them through JNI to your C/C++ code. There will be loss of information as you move back and forth, not to mention that there will be quite a bit of code duplication. You can certainly create a full wrapper for the Irrlicht and Bullet libraries, but that will be taxing your mobile device heavily, and will certainly have a negative impact on performance. And creating a full wrapper for these two libraries would be a heck of a job.
<p>The other problem is that, Irrlicht is an engine developed for the desktop, where keyboard and mouse are the main input devices. The Irrlicht port to Android mainly concerns with a display driver for Android, but the port has not really gone deep into this area of user interaction. Therefore, as you write your Irrlicht-based Android program, you would have to hack together user input handling model, event model, etc. In my demo, I haven’t even touched that, I have just kludged together some primitive event handling codes. In order to have our program fit in those multi-touch based devices, we would have to dig into the Irrlicht scene node animator and event handling mechanisms, and work it out from there. For example, we will have to define our own scene node animator which would be based on touch events instead of keyboard and mouse events, and add it to the scene node that we want to animate. This is something that we are going to look into in our future posts.
<img src ="http://www.cppblog.com/Leaf/aggbug/199161.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Leaf/" target="_blank">Render Donkey</a> 2013-04-06 21:19 <a href="http://www.cppblog.com/Leaf/archive/2013/04/06/199161.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>irrlicht引擎：镜子效果</title><link>http://www.cppblog.com/Leaf/archive/2013/04/05/199111.html</link><dc:creator>Render Donkey</dc:creator><author>Render Donkey</author><pubDate>Thu, 04 Apr 2013 16:53:00 GMT</pubDate><guid>http://www.cppblog.com/Leaf/archive/2013/04/05/199111.html</guid><wfw:comment>http://www.cppblog.com/Leaf/comments/199111.html</wfw:comment><comments>http://www.cppblog.com/Leaf/archive/2013/04/05/199111.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/Leaf/comments/commentRss/199111.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Leaf/services/trackbacks/199111.html</trackback:ping><description><![CDATA[<p>&nbsp;</p> <p>最近在用irrlicht做一个3D试衣间的小项目，为了给项目增添点花样，于是想实现一面镜子。</p> <p>我记得D3D龙书上有一个使用模板缓冲区实现的例子。网上也有OPENGL实现的例子。 但这一次，我想用irrlicht的RTT实现一面镜子效果。</p> <p>其实原理和水面反射原理是一样的， 只是没有加扰动而已</p> <p>&nbsp;</p> <p>第一步：渲染反射贴图</p> <blockquote> <p>反射贴图的渲染，其实就是将摄相机通过镜面镜像即可，irrlicht中我找了半天，没有发现镜像矩阵的算法，倒是在网上搜到了一个。 很是不错。</p></blockquote> <p>同时，也翻阅了一下先前公司引擎项目的代码，发现其实就是那个公式。 有兴趣的朋友可以参看这里</p> <p>&nbsp;</p> <p><a title="http://www.cnblogs.com/glshader/archive/2010/11/02/1866971.html" href="http://www.cnblogs.com/glshader/archive/2010/11/02/1866971.html">http://www.cnblogs.com/glshader/archive/2010/11/02/1866971.html</a></p> <p>&nbsp;</p> <p>通过这个镜面反射矩阵，我们可以将摄相机镜像， 相当于是从镜子里向外看，渲染出一个世界。 在渲染的时候，要记得设置裁剪面。 在我的测试中我没有设置。</p> <p>第二步：重新渲染世界</p> <blockquote> <p>重新渲染世界的时候，镜子需要一个特殊的纹理来进行反射贴图。（镜像摄相机空间的投影纹理映射）。 这个贴图方式，就是指忽略镜子的纹理坐标，而通过</p></blockquote> <p>镜像摄相机来计算出投影坐标，然后贴在镜子上。在我的测试中，是用SHADER来实现的。 为镜子做了一个特殊的纹理。</p> <p>&nbsp;</p> <p>下面，我贴一下SHADER，很简单，如果实在不清楚的，可以参考一些投影纹理相关的资料。</p> <p>&nbsp;</p> <p>顶点着色器代码 HLSL</p> <p>float4x4&nbsp;&nbsp;&nbsp; WorldViewProj;<br>float4x4&nbsp;&nbsp;&nbsp; MirrorWorldViewProj;<br>struct VS_OUTPUT<br>{<br>&nbsp;&nbsp;&nbsp; float4 position&nbsp;&nbsp;&nbsp; :POSITION; </p> <p>&nbsp;&nbsp;&nbsp; float3 uv: TEXCOORD0;<br>}; </p> <p>struct VS_INPUT<br>{<br>&nbsp;&nbsp;&nbsp; float4 position&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : POSITION;<br>&nbsp;&nbsp;&nbsp; float4 color&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : COLOR0;<br>&nbsp;&nbsp;&nbsp; float2 texCoord0&nbsp;&nbsp;&nbsp; : TEXCOORD0;<br>};  <p>VS_OUTPUT main(VS_INPUT input)<br>{<br>&nbsp;&nbsp;&nbsp; VS_OUTPUT output; <br>&nbsp;&nbsp;&nbsp; float4 pos = mul(input.position, WorldViewProj);<br>&nbsp;&nbsp;&nbsp; output.position = pos;</p> <p>&nbsp;&nbsp;&nbsp; //计算反射纹理的坐标 </p> <p>&nbsp;&nbsp;&nbsp; pos = mul(input.position,MirrorWorldViewProj);<br>&nbsp;&nbsp;&nbsp; output.uv.x = 0.5 * (pos.w + pos.x);<br>&nbsp;&nbsp;&nbsp; output.uv.y = 0.5 * (pos.w - pos.y);<br>&nbsp;&nbsp;&nbsp; output.uv.z = pos.w;<br>&nbsp;&nbsp;&nbsp; return output;<br>}  <p>&nbsp; <p>像素着色器代码 HLSL  <p>sampler2D colorMap;<br>struct PS_OUTPUT<br>{<br>&nbsp;&nbsp;&nbsp; float4 color : COLOR0;&nbsp;&nbsp; <br>};  <p>struct PS_INPUT<br>{<br>&nbsp;&nbsp;&nbsp; float4 position&nbsp;&nbsp;&nbsp; : POSITION;<br>&nbsp;&nbsp;&nbsp; float3 uv: TEXCOORD0;<br>};<br>PS_OUTPUT main( PS_INPUT input )<br>{ <br>&nbsp;&nbsp;&nbsp; PS_OUTPUT output;<br>&nbsp;&nbsp;&nbsp; float2 uv = saturate(input.uv.xy / input.uv.z);<br>&nbsp;&nbsp;&nbsp; output.color = tex2D(colorMap,uv);<br>&nbsp;&nbsp;&nbsp; return output;<br>}  <p>&nbsp;</p> <p>&nbsp;</p> <p>RTT相关的操作，irrlicht的RenderToTexture已经很明白了，再此不在敷述。</p> <p>&nbsp;</p> <p>上图，收工</p> <p>&nbsp;</p> <p><a href="http://www.cppblog.com/images/cppblog_com/Leaf/WindowsLiveWriter/irrlicht_C6B/2000_2.jpg"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="2000" border="0" alt="2000" src="http://www.cppblog.com/images/cppblog_com/Leaf/WindowsLiveWriter/irrlicht_C6B/2000_thumb.jpg" width="539" height="405"></a></p><img src ="http://www.cppblog.com/Leaf/aggbug/199111.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Leaf/" target="_blank">Render Donkey</a> 2013-04-05 00:53 <a href="http://www.cppblog.com/Leaf/archive/2013/04/05/199111.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>irrlicht引擎：真实的水面渲染</title><link>http://www.cppblog.com/Leaf/archive/2013/04/04/199101.html</link><dc:creator>Render Donkey</dc:creator><author>Render Donkey</author><pubDate>Thu, 04 Apr 2013 10:16:00 GMT</pubDate><guid>http://www.cppblog.com/Leaf/archive/2013/04/04/199101.html</guid><wfw:comment>http://www.cppblog.com/Leaf/comments/199101.html</wfw:comment><comments>http://www.cppblog.com/Leaf/archive/2013/04/04/199101.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/Leaf/comments/commentRss/199101.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Leaf/services/trackbacks/199101.html</trackback:ping><description><![CDATA[<p>先上图</p> <p><a href="http://www.cppblog.com/images/cppblog_com/Leaf/WindowsLiveWriter/irrlicht_10026/image_2.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://www.cppblog.com/images/cppblog_com/Leaf/WindowsLiveWriter/irrlicht_10026/image_thumb.png" width="609" height="473"></a> </p> <p>&nbsp;</p> <p><a href="http://www.cppblog.com/images/cppblog_com/Leaf/WindowsLiveWriter/irrlicht_10026/image_4.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://www.cppblog.com/images/cppblog_com/Leaf/WindowsLiveWriter/irrlicht_10026/image_thumb_1.png" width="609" height="483"></a> </p> <p></p> <p>本来说是做镜子效果的，结果手工计算的镜面反射矩阵应用在irrlicht相机上的时候，始终无法出现效果，只能去网上搜索</p> <p>在irrlicht official wiki上发现了这个扩展的WaterNode，下载下来，改了点BUG，整合进了Terrain Demo里， 就是上图的效果。</p> <p>在我的机器上,HLSL版本是没有问题的，GL版本貌似RTT有点问题。</p> <p>&nbsp;</p> <p><a href="http://files.cppblog.com/Leaf/RealisticWaterSceneNode020.zip">点击此处下载源代码</a></p>  <img src ="http://www.cppblog.com/Leaf/aggbug/199101.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Leaf/" target="_blank">Render Donkey</a> 2013-04-04 18:16 <a href="http://www.cppblog.com/Leaf/archive/2013/04/04/199101.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>irrlicht引擎：硬件蒙皮骨骼动画</title><link>http://www.cppblog.com/Leaf/archive/2013/03/26/198823.html</link><dc:creator>Render Donkey</dc:creator><author>Render Donkey</author><pubDate>Mon, 25 Mar 2013 16:08:00 GMT</pubDate><guid>http://www.cppblog.com/Leaf/archive/2013/03/26/198823.html</guid><wfw:comment>http://www.cppblog.com/Leaf/comments/198823.html</wfw:comment><comments>http://www.cppblog.com/Leaf/archive/2013/03/26/198823.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/Leaf/comments/commentRss/198823.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Leaf/services/trackbacks/198823.html</trackback:ping><description><![CDATA[<p>这个东西很顺利，仅用了半小时就找到了方法，最应该感谢的还是Super TuxKart(简称STK，下面就都用这三字母了). 如果不明白STK，同时又对它感兴趣的童鞋，可以访问这里</p> <p><a title="http://supertuxkart.sourceforge.net/" href="http://supertuxkart.sourceforge.net/">http://supertuxkart.sourceforge.net/</a></p> <p>由于墙的原因，需要各位搭梯子。</p> <p>&nbsp;</p> <p>上周末，在弄换装的时候，发现irrlicht引擎本身是不支持硬件蒙皮的，多少令人有些失望。 心里就一直寻思着怎么扩展一下，将它弄出来。</p> <p>值得说明的是STK对irrlicht引擎的用法是很简单的，基本上可以说是裸用，并未在irrlicht接口上做修改。 而是对外进行了一些必要的扩展。</p> <p>当然，STK也对外开放了一个irrlicht.dll，说是修改了其中的BUG。 但直接使用irrlicht是可以的。</p> <p>&nbsp;</p> <p>废话不多说，来说说如何不修改irrlicht一行代码，通过外部扩展来实现硬件骨骼动画吧</p> <p>&nbsp;</p> <p>首先，能够使我们不修改irrlicht代码的原因，是因为ISkinnedMesh提供了一个setHardwareSkinning接口，默认为false.</p> <p>虽然这个接口的说明是"(This feature is not implemented in irrlicht yet)&#8221;，但并不代表，设置与不设置无差别。 </p> <p>查看代码可以发现，当你设置了这个为true以后，irrlicht就完全不管你的动画了。 意思就是，要是你非要让我干我不干不了的事，那就只有您另请高明了。</p> <p>irrlicht连CPU计算都不会参与。 这正好让我们有机可乘，完全用GPU接管。</p> <p>&nbsp;</p> <p>而要让一个顶点参与骨骼计算，那骨骼索引则是少不了的。所以，我们需要想办法让顶点数据能够将骨骼索引代入SHADER中。</p> <p>在STK中用了一种巧妙的方法， 就是使用了顶点的颜色数据， 虽然这样一来，顶点颜色就用不了了。 但在模型渲染时，顶点颜色很少被使用到的。 也就是说，顶点颜色在STK的动画模型中，被用作了骨骼索引。</p> <p>初始化骨骼索引的方法很简单，用下面的代码遍历即可。</p> <p>设：我们有一个骨骼动画模型是 ISkinnedMesh* pSkinnedMesh = &#8230;</p> <p>那么：初始化代码如下</p> <p>for(u32 i = 0;i &lt; pSkinnedMesh -&gt;getMeshBuffers().size();++i)<br>{<br>&nbsp;&nbsp;&nbsp; for(u32 g = 0;g &lt; pSkinnedMesh -&gt;getMeshBuffers()[i]-&gt;getVertexCount();++g)<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pSkinnedMesh -&gt;getMeshBuffers()[i]-&gt;getVertex(g)-&gt;Color = video::SColor(0,0,0,0);<br>&nbsp;&nbsp;&nbsp; }<br>}</p> <p>//初始化完毕以后，就是需要真正的索引赋值了，通过以下代码可以完成</p> <p>const core::array&lt;scene::ISkinnedMesh::SJoint*&gt;&amp; joints = pSkinnedMesh -&gt;getAllJoints();<br>for(u32 i = 0;i &lt; joints.size();++i)<br>{<br>&nbsp;&nbsp;&nbsp; const core::array&lt;scene::ISkinnedMesh::SWeight&gt;&amp;&nbsp;&nbsp;&nbsp; weights = joints[i]-&gt;Weights;<br>&nbsp;&nbsp;&nbsp; for(u32 j = 0;j &lt; weights.size();++j)<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int buffId = weights[j].buffer_id;  <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int vertexId = pSkinedMesh-&gt;getAllJoints()[i]-&gt;Weights[j].vertex_id;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; video::SColor* vColor = &amp;pSkinedMesh-&gt;getMeshBuffers()[buffId]-&gt;getVertex(vertexId)-&gt;Color;  <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(vColor-&gt;getRed() == 0)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; vColor-&gt;setRed(i + 1);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else if(vColor-&gt;getGreen() == 0)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; vColor-&gt;setGreen(i + 1);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else if(vColor-&gt;getBlue() == 0)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; vColor-&gt;setBlue(i + 1);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else if(vColor-&gt;getAlpha() == 0)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; vColor-&gt;setAlpha(i + 1);<br>&nbsp;&nbsp;&nbsp; }<br>} <p>&nbsp;</p> <p>//经过以上两个步骤，顶点数据改造完成。 值得注意的是， 在这里， 索引 0 是被认为是无效的</p> <p>&nbsp;</p> <p>然后，我们来创建一个SHADER作为渲染。</p> <p>假设 我们将这个pSkinnedMesh绑定了到了一个IAnimatedSceneNode* node 上。</p> <p>那，我们为这个结点创建一个材质 在创建材质前，我们需要准备一个SHADER回调。 SHADER回调就像下面一样就可以了。</p> <p>class HWSkinCallBack:public video::IShaderConstantSetCallBack<br>{<br>&nbsp;&nbsp;&nbsp; scene::IAnimatedMeshSceneNode* m_pNode;<br>public:<br>&nbsp;&nbsp;&nbsp; HWSkinCallBack(scene::IAnimatedMeshSceneNode* node):m_pNode(node)<br>&nbsp;&nbsp;&nbsp; {  <p>&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; virtual void OnSetConstants(video::IMaterialRendererServices* services,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; s32 userData)<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; scene::ISkinnedMesh* mesh = (scene::ISkinnedMesh*)m_pNode-&gt;getMesh();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; f32 joints_data[55 * 16];<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int copyIncrement = 0;  <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; const core::array&lt;scene::ISkinnedMesh::SJoint*&gt; joints = mesh-&gt;getAllJoints();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for(u32 i = 0;i &lt; joints.size();++i)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; core::matrix4 joint_vertex_pull(core::matrix4::EM4CONST_NOTHING);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; joint_vertex_pull.setbyproduct(joints[i]-&gt;GlobalAnimatedMatrix, joints[i]-&gt;GlobalInversedMatrix);  <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; f32* pointer = joints_data + copyIncrement;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for(int i = 0;i &lt; 16;++i)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *pointer++ = joint_vertex_pull[i];  <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; copyIncrement += 16;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }  <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; services-&gt;setVertexShaderConstant("JointTransform", joints_data, mesh-&gt;getAllJoints().size() * 16);<br>&nbsp;&nbsp;&nbsp; }<br>}; <p>&nbsp;</p> <p>好了，现在我们来创建一个材质</p> <p>s32 hwskm = gpu-&gt;addHighLevelShaderMaterialFromFiles(<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "../../skinning.vert","main",video::EVST_VS_2_0,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "","main",video::EPST_PS_2_0,&amp;hwc,video::EMT_SOLID);</p> <p>//用新创建出来的材质赋值给这个结点</p> <p>node-&gt;setMaterialType((video::E_MATERIAL_TYPE)hwskm );</p> <p>&nbsp;</p> <p>//到此，设置完毕。</p> <p> //最后，就是skinning.vert本身的内容了。 贴出来即可，没有太多技巧，就是一个普通的蒙皮。</p> <p>// skinning.vert  <p>#define MAX_JOINT_NUM 36<br>#define MAX_LIGHT_NUM 8  <p>uniform mat4 JointTransform[MAX_JOINT_NUM];  <p>void main() <br>{<br>&nbsp;&nbsp;&nbsp; int index;<br>&nbsp;&nbsp;&nbsp; vec4 ecPos;<br>&nbsp;&nbsp;&nbsp; vec3 normal;<br>&nbsp;&nbsp;&nbsp; vec3 light_dir;<br>&nbsp;&nbsp;&nbsp; float n_dot_l;<br>&nbsp;&nbsp;&nbsp; float dist;  <p>&nbsp;&nbsp;&nbsp; mat4 ModelTransform = gl_ModelViewProjectionMatrix;<br>&nbsp;&nbsp;&nbsp; index = int(gl_Color.r * 255.99);<br>&nbsp;&nbsp;&nbsp; mat4 vertTran = JointTransform[index - 1];<br>&nbsp;&nbsp;&nbsp; index = int(gl_Color.g * 255.99);<br>&nbsp;&nbsp;&nbsp; if(index &gt; 0)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; vertTran += JointTransform[index - 1];  <p>&nbsp;&nbsp;&nbsp; index = int(gl_Color.b * 255.99);<br>&nbsp;&nbsp;&nbsp; if(index &gt; 0)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; vertTran += JointTransform[index - 1];<br>&nbsp;&nbsp;&nbsp; index = int(gl_Color.a * 255.99);<br>&nbsp;&nbsp;&nbsp; if(index &gt; 0)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; vertTran += JointTransform[index - 1];<br>&nbsp;&nbsp;&nbsp; ecPos = gl_ModelViewMatrix * vertTran * gl_Vertex;<br>&nbsp;&nbsp;&nbsp; normal = normalize(gl_NormalMatrix * mat3(vertTran) * gl_Normal);<br>&nbsp;&nbsp;&nbsp; gl_FrontColor = vec4(0,0,0,0);<br>&nbsp;&nbsp;&nbsp; for(int i = 0;i &lt; MAX_LIGHT_NUM;i++)<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; light_dir = vec3(gl_LightSource[i].position-ecPos);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; n_dot_l = max(dot(normal, normalize(light_dir)), 0.0);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dist = length(light_dir);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; n_dot_l *= 1.0 / (gl_LightSource[0].constantAttenuation + gl_LightSource[0].linearAttenuation * dist);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; gl_FrontColor += gl_LightSource[i].diffuse * n_dot_l;<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; gl_FrontColor = clamp(gl_FrontColor,0.3,1.0); <p>&nbsp;&nbsp;&nbsp; ModelTransform *= vertTran;<br>&nbsp;&nbsp;&nbsp; gl_Position = ModelTransform * gl_Vertex;<br>&nbsp;&nbsp;&nbsp; gl_TexCoord[0] = gl_MultiTexCoord0;<br>&nbsp;&nbsp;&nbsp; gl_TexCoord[1] = gl_MultiTexCoord1;<br>&nbsp;&nbsp;&nbsp; /* <br>&nbsp;&nbsp;&nbsp; // Reflections.<br>&nbsp;&nbsp;&nbsp; vec3 r = reflect( ecPos.xyz , normal );<br>&nbsp;&nbsp;&nbsp; float m = 2.0 * sqrt( r.x*r.x + r.y*r.y + (r.z+1.0)*(r.z+1.0) );<br>&nbsp;&nbsp;&nbsp; gl_TexCoord[1].s = r.x/m + 0.5;<br>&nbsp;&nbsp;&nbsp; gl_TexCoord[1].t = r.y/m + 0.5;<br>&nbsp;&nbsp;&nbsp; */<br>} <p>&nbsp;</p> <p>&nbsp;</p> <p>//注：这是GLSL 2.0， 在用IRR做测试的时候，要选GL驱动方式。</p> <p>&nbsp;</p> <p>还是上个图吧，不上图感觉没有真像。 虽然图看不出来什么动作</p> <p><a href="http://www.cppblog.com/images/cppblog_com/Leaf/WindowsLiveWriter/irrlicht_14DD5/image_2.png"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://www.cppblog.com/images/cppblog_com/Leaf/WindowsLiveWriter/irrlicht_14DD5/image_thumb.png" width="526" height="410"></a> </p> <p>为了说明它真的在动，不得不上第二张。 </p> <p>&nbsp;</p> <p><a href="http://www.cppblog.com/images/cppblog_com/Leaf/WindowsLiveWriter/irrlicht_14DD5/image_4.png"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://www.cppblog.com/images/cppblog_com/Leaf/WindowsLiveWriter/irrlicht_14DD5/image_thumb_1.png" width="523" height="417"></a>&nbsp;</p> <p>&nbsp;</p> <p>在此，十分感谢Super Tux Kart. 提供了一个学习和扩展irrlicht的榜样.</p>  <img src ="http://www.cppblog.com/Leaf/aggbug/198823.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Leaf/" target="_blank">Render Donkey</a> 2013-03-26 00:08 <a href="http://www.cppblog.com/Leaf/archive/2013/03/26/198823.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>irrlicht引擎：实现天龙八部的RPG角色换装</title><link>http://www.cppblog.com/Leaf/archive/2013/03/24/198762.html</link><dc:creator>Render Donkey</dc:creator><author>Render Donkey</author><pubDate>Sat, 23 Mar 2013 20:08:00 GMT</pubDate><guid>http://www.cppblog.com/Leaf/archive/2013/03/24/198762.html</guid><wfw:comment>http://www.cppblog.com/Leaf/comments/198762.html</wfw:comment><comments>http://www.cppblog.com/Leaf/archive/2013/03/24/198762.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/Leaf/comments/commentRss/198762.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Leaf/services/trackbacks/198762.html</trackback:ping><description><![CDATA[<p>看了看时间，已经3点过了，突然想写点什么，却又不知从何说起。</p> <p>那就从今天这个用irrlicht做天龙八部的模型换装说起吧。</p> <p>&nbsp;</p> <p>也不知道是为什么，最近又捣鼓起了OGRE和irrlicht. 并且，总想用irrlicht实现一些OGRE中的东西。</p> <p>当然，这不是商业项目，也没有商业目的，纯属蛋疼而已。</p> <p>&nbsp;</p> <p>一切行动的由来，都来自于vczh那天晚上的举动。</p> <p>记得有一天晚上在群里聊天，大伙就称赞各位菊苣是多么的厉害。</p> <p>最后vc发了一个自己的桌面截图说：让你们看看菊苣是如何练成的（这不是原话，和话的字眼有出入，在此不想负任何责任，如果真有想看的，去翻群的聊天记录）</p> <p>那天晚上，我想了很久。想想自己自从转做页游以后，是如何虚渡光阴的。</p> <p>终于忍不住了，翻开了自己的移动硬盘，看看自己曾经做过的小东西。90%是建好工程就没理了。</p> <p>这才明白，我花在思考上的时间远远大于了行动。 于是，我决定改变自己，找回那个真的我。</p> <p>&nbsp;</p> <p>3D游戏是我的真爱， 真爱到就算画面差一点，只要是3D，我也会很喜欢。</p> <p>于是，我觉得自己还是应该接着先前的路走下去。 什么服务器，什么 AS3. 都是浮云， 不喜欢就是不喜欢。</p> <p>私下又开始研究irrlicht了。</p> <p>猛地一发现，自己是多么的搞笑， 从09年到11年，一直在做引擎开发， 也翻过irrlicht和ogre无数遍。 却从来就没有写完过一个完整的DEMO。</p> <p>连功能测试用例都没有写过。突然觉得之前的一些设计似乎有些脱离了实际。没有真正使用过，又怎知如何是好，如何是坏呢？</p> <p>&nbsp;</p> <p>这一次是真的玩irrlicht了， 中间也纠结过是不是OGRE更适合。 但在目前这个时间有限的空间下，我更愿意玩irrlicht.小巧，轻便。 当然，意味着更多东西要自己实现。 不过对于一个代码控来说，也反而更自得其乐。 正好可以在短路的时候，去参考一下其它引擎，用来扩充irrlicht.</p> <p>我要做的不是把irrlicht整得牛B，而是想自己弄弄，加上移动平台的崛起，我觉得irrlicht更加适合吧。 据说gameloft也有使用（仅是据说）。</p> <p>&nbsp;</p> <p>可能很多兄弟会说我这讲的东西，其实就是一坨屎了。 不过，我觉得再坏的评论，也表示一种关注。 批评好过于无视啊~~~~</p> <p>----------------------------------------------------------下面说说我遇上的纠结------------------------------------------------</p> <p><strong>纠结1:换装需要场景节点配合</strong></p> <p>&nbsp; 在irrlicht中，并没有提供普通引擎中的submesh或者bodypart这种东西，用于直接支持换装。 在irrlicht中，如果想要换装，最直接的方法就是依赖于场景结点</p> <p>比如,在我的示例中，可以更换头发，帽子，衣服，护腕，靴子，面容。 那就需要7个场景节点，1个作为根节点，用于控制整个角色的世界坐标，平移，缩放，旋转等属性。另外6个场景节点则分别绑有各个部件的模型</p> <p>贴一下我的角色类的代码，行数不多</p> <p>class CCharactor<br>{<br>&nbsp;&nbsp;&nbsp; IrrlichtDevice* m_pDevice;<br>&nbsp;&nbsp;&nbsp; IAnimatedMeshSceneNode* m_pBodyParts[eCBPT_Num];<br>&nbsp;&nbsp;&nbsp; ISceneNode* m_pRoot;<br>public:<br>&nbsp;&nbsp;&nbsp; CCharactor(IrrlichtDevice* pDevice)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; :m_pDevice(pDevice)<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; memset(m_pBodyParts,0,sizeof(m_pBodyParts));<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; m_pRoot = pDevice-&gt;getSceneManager()-&gt;addEmptySceneNode(NULL,12345);<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; void changeBodyPart(ECharactorBodyPartType ePartType,stringw&amp; meshPath,stringw&amp; metrialPath)<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ISceneManager* smgr = m_pDevice-&gt;getSceneManager();  <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; IAnimatedMeshSceneNode* pBpNode = m_pBodyParts[ePartType];<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; IAnimatedMesh* pMesh = smgr-&gt;getMesh(meshPath.c_str());<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(pMesh==NULL)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return;  <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(pBpNode==NULL)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pBpNode = smgr-&gt;addAnimatedMeshSceneNode(pMesh,m_pRoot);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; m_pBodyParts[ePartType] = pBpNode;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pBpNode-&gt;setMesh(pMesh);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ITexture* pTexture = m_pDevice-&gt;getVideoDriver()-&gt;getTexture(metrialPath.c_str());<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(pTexture)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pBpNode-&gt;setMaterialTexture(0,pTexture);<br>&nbsp;&nbsp;&nbsp; }<br>};  <p>&nbsp;</p> <p>//然后，我用了一个结构体来构建部件信息</p> <p>struct SBodyPartInfo<br>{<br>&nbsp;&nbsp;&nbsp; stringw Desc;<br>&nbsp;&nbsp;&nbsp; ECharactorBodyPartType Type;<br>&nbsp;&nbsp;&nbsp; stringw MeshPath;<br>&nbsp;&nbsp;&nbsp; stringw MeterialPath;<br>};  <p>&nbsp;</p> <p><strong>纠结2：共享骨骼</strong></p> <p>首先，irrlicht 1.8中对OGRE模型的格式支持在代码中，最高只看到了1.40版本的解析，更高的就会被无视。 天龙八部的模型有几个是1.30的，而用于换装和主角的，都是1.40的。 可能是解析不全的原因，导致1.40的骨骼动画无法正常播放。 这个问题整了几个小时，没有解决，明天继续</p> <p>其次，多个模型共享骨骼只能通过场景节点的useAnimationFrom来完成，并且传入的是一个Mesh参数。这点让人蛋疼， 天龙八部的角色动作是分开了的，不同的攻击动作是一个skeleton文件。 想要实现共享，有点麻烦。</p> <p>&nbsp;</p> <p><strong>纠结3：模型文件格式</strong></p> <p>irrlicht不像OGRE那样有一个强大且成熟的模型文件格式,虽然提供了.irr格式，但仅是用于irrEdit的场景信息输出。先看一张图</p> <p><a href="http://www.cppblog.com/images/cppblog_com/Leaf/WindowsLiveWriter/irrlicht_354D/image_8.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://www.cppblog.com/images/cppblog_com/Leaf/WindowsLiveWriter/irrlicht_354D/image_thumb_3.png" width="677" height="582"></a> </p> <p>这张图是irrlicht samples中的MeshViewer的提示框内容。 上面列出了可以支持的模型文件类型。 大家可以看看，又有多少模型格式是可以直接拿来放到项目上用的呢？ mdl和ms3d可以考虑，dae的话，我在开源游戏0 A.D. 中见到使用过。 其它的话，就完全不熟悉了。 OGRE的 .mesh支持也不完全。 难道真要自己整一个。 </p> <p>我能想到的，就是选一个插件完整和模型和动画格式都比较好的作为与美术工具交互的格式。 自己再写一个工具，转换成自己的格式。</p> <p>&nbsp;</p> <p><strong>纠结4：硬件蒙皮</strong></p> <p>我以为像NIKO那样的技术狂，怎么会放掉这一个特性。 很高兴地在场景节点上发现了硬件蒙皮的函数接口。但一看注释，把我咽着了。</p> <p>//! (This feature is not implemented in irrlicht yet)<br>virtual bool setHardwareSkinning(bool on);  <p>&nbsp; <p>其它地方，还没有去整，就先不发表言论了。 继续着这个很傻B,很天真的捣鼓之路。  <p>上个图，纪念一下我的irrlicht产物。</p> <p>&nbsp;</p> <p>布衣</p> <p><a href="http://www.cppblog.com/images/cppblog_com/Leaf/WindowsLiveWriter/irrlicht_354D/image_2.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://www.cppblog.com/images/cppblog_com/Leaf/WindowsLiveWriter/irrlicht_354D/image_thumb.png" width="586" height="450"></a> </p> <p>&nbsp;</p> <p>换了身盔甲</p> <p><a href="http://www.cppblog.com/images/cppblog_com/Leaf/WindowsLiveWriter/irrlicht_354D/image_4.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://www.cppblog.com/images/cppblog_com/Leaf/WindowsLiveWriter/irrlicht_354D/image_thumb_1.png" width="588" height="461"></a> </p> <p>&nbsp;</p> <p>换了帽子和靴子</p> <p><a href="http://www.cppblog.com/images/cppblog_com/Leaf/WindowsLiveWriter/irrlicht_354D/image_6.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://www.cppblog.com/images/cppblog_com/Leaf/WindowsLiveWriter/irrlicht_354D/image_thumb_2.png" width="590" height="461"></a> </p> <p>&nbsp;</p> <p>PS:头发没有纹理，所以是白的。</p>  <img src ="http://www.cppblog.com/Leaf/aggbug/198762.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Leaf/" target="_blank">Render Donkey</a> 2013-03-24 04:08 <a href="http://www.cppblog.com/Leaf/archive/2013/03/24/198762.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[原]irrlicht v1.6 中文例程18 Splitscreen</title><link>http://www.cppblog.com/Leaf/archive/2010/04/26/113563.html</link><dc:creator>Render Donkey</dc:creator><author>Render Donkey</author><pubDate>Mon, 26 Apr 2010 01:50:00 GMT</pubDate><guid>http://www.cppblog.com/Leaf/archive/2010/04/26/113563.html</guid><wfw:comment>http://www.cppblog.com/Leaf/comments/113563.html</wfw:comment><comments>http://www.cppblog.com/Leaf/archive/2010/04/26/113563.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/Leaf/comments/commentRss/113563.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Leaf/services/trackbacks/113563.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 这个例程中我们将学习怎么使用irrlicht中的分屏(比如在赛车类游戏中）{<br>我们将创建一个被分为4个部分的视口，有3个固定摄相机和一个用户可以控制的摄相机好，让们从头文件开始吧（我想没有再多说的必要了）&nbsp;&nbsp;<a href='http://www.cppblog.com/Leaf/archive/2010/04/26/113563.html'>阅读全文</a><img src ="http://www.cppblog.com/Leaf/aggbug/113563.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Leaf/" target="_blank">Render Donkey</a> 2010-04-26 09:50 <a href="http://www.cppblog.com/Leaf/archive/2010/04/26/113563.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[原]Irrlicht(鬼火引擎）中多设备的支持</title><link>http://www.cppblog.com/Leaf/archive/2010/04/26/113558.html</link><dc:creator>Render Donkey</dc:creator><author>Render Donkey</author><pubDate>Mon, 26 Apr 2010 01:10:00 GMT</pubDate><guid>http://www.cppblog.com/Leaf/archive/2010/04/26/113558.html</guid><wfw:comment>http://www.cppblog.com/Leaf/comments/113558.html</wfw:comment><comments>http://www.cppblog.com/Leaf/archive/2010/04/26/113558.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/Leaf/comments/commentRss/113558.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Leaf/services/trackbacks/113558.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 理清一个引擎，不得不先理清它的层次结构，进而理清渲染流程。 本文给出了鬼火引擎中的设备抽象层，有助于对鬼火引擎源码的快速阅读&nbsp;&nbsp;<a href='http://www.cppblog.com/Leaf/archive/2010/04/26/113558.html'>阅读全文</a><img src ="http://www.cppblog.com/Leaf/aggbug/113558.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Leaf/" target="_blank">Render Donkey</a> 2010-04-26 09:10 <a href="http://www.cppblog.com/Leaf/archive/2010/04/26/113558.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>