??xml version="1.0" encoding="utf-8" standalone="yes"?>热久久最新网站获取,久久这里有精品,四虎国产精品成人免费久久 http://www.shnenglu.com/yuanyajie/category/3706.html记录所思所惻I收藏所见所闻�? zh-cnMon, 19 May 2008 13:01:23 GMTMon, 19 May 2008 13:01:23 GMT60Ogre3D嵌入Qt框架 之 结http://www.shnenglu.com/yuanyajie/archive/2007/05/21/24528.html清源游民清源游民Mon, 21 May 2007 03:57:00 GMThttp://www.shnenglu.com/yuanyajie/archive/2007/05/21/24528.htmlhttp://www.shnenglu.com/yuanyajie/comments/24528.htmlhttp://www.shnenglu.com/yuanyajie/archive/2007/05/21/24528.html#Feedback10http://www.shnenglu.com/yuanyajie/comments/commentRss/24528.htmlhttp://www.shnenglu.com/yuanyajie/services/trackbacks/24528.html阅读全文

清源游民 2007-05-21 11:57 发表评论
]]>
Ogre3D嵌入Qt框架 之 U?/title><link>http://www.shnenglu.com/yuanyajie/archive/2007/05/21/24506.html</link><dc:creator>清源游民</dc:creator><author>清源游民</author><pubDate>Sun, 20 May 2007 17:26:00 GMT</pubDate><guid>http://www.shnenglu.com/yuanyajie/archive/2007/05/21/24506.html</guid><wfw:comment>http://www.shnenglu.com/yuanyajie/comments/24506.html</wfw:comment><comments>http://www.shnenglu.com/yuanyajie/archive/2007/05/21/24506.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://www.shnenglu.com/yuanyajie/comments/commentRss/24506.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/yuanyajie/services/trackbacks/24506.html</trackback:ping><description><![CDATA[<p>环境QWindowsXp Pro SP2, VS2003.NET, Ogre1.4.1(Eihort), Qt 4.2.2 开源版<br>参考:(x)ShowMesh,MAGE,两款工具源码<br>先把囄出来Q有旉文字ȝ一下,隑ֺ虽然不高Q但也折腾不时?也算q来学习(fn)Qt与Ogre的一个小l?br><br><img height=480 alt="" src="http://www.shnenglu.com/images/cppblog_com/yuanyajie/2865/r_ShowOgreEmbedInQt.jpg" width=612 border=0><br></p> <img src ="http://www.shnenglu.com/yuanyajie/aggbug/24506.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/yuanyajie/" target="_blank">清源游民</a> 2007-05-21 01:26 <a href="http://www.shnenglu.com/yuanyajie/archive/2007/05/21/24506.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>《Pro Ogre 3D Programming》读书笔??W十一?动态阴?/title><link>http://www.shnenglu.com/yuanyajie/archive/2007/03/21/20302.html</link><dc:creator>清源游民</dc:creator><author>清源游民</author><pubDate>Wed, 21 Mar 2007 09:07:00 GMT</pubDate><guid>http://www.shnenglu.com/yuanyajie/archive/2007/03/21/20302.html</guid><wfw:comment>http://www.shnenglu.com/yuanyajie/comments/20302.html</wfw:comment><comments>http://www.shnenglu.com/yuanyajie/archive/2007/03/21/20302.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/yuanyajie/comments/commentRss/20302.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/yuanyajie/services/trackbacks/20302.html</trackback:ping><description><![CDATA[ <p>清源游民  gameogre@gmail.com<br /><br /><font color="#0000ff">阴媄(jing)技?/font><br />Ogre支持两种L的动态阴影技术,模板(stencil)阴媄(jing)与纹?texture)阴媄(jing),每一U都有两个变体:(x)modulative 与additive。这四种技术完全兼容固定函数图形流水线Q因此不需要可~程GPU支持。然而,可利用GPUE序q行加速。在场景中只有用一U阴影技术,应该在场景渲染这前进行阴影技术相兌|(最好是在创建场景管理器之间Q。通过调用SceneManager::setShadowTechnique()来设|技术,参数指定技术的具体cd。阴影技术缺省情况下被关闭。对于物体,投射与接攉影可以在材质中控Ӟ也可以控制物体自己对自己投射。由于模杉Kq法的本质特征Q透明半透明的物体要么全部投实?j)阴p么根本不投媄(jing)影,不可能得到半透明的阴影。而用纹理阴影技术则可以。灯不能用来投射阴媄(jing)?br /><font color="#0000ff">模板阴媄(jing)法<br /></font>模板阴媄(jing)法原理上来讲比较简单:(x)从光源的角度看一个可以投阴q物体Q可以看到物体最外轮廓的<br />形状Q把q个轮廓沿光的方向g伸,形成一个空间体Q就是所谓的阴媄(jing)?shadow volume),很显?dng)如果一<br />个物体被q个阴媄(jing)锥包_(d)那么q个物体处于前面那个物体所投射的阴׃?jin)。既焉影锥是通过延的方式来增长的,那么可以在g伸方向对锥体的g伸范围作出控制。在延方向上,有一端不能g伸,另外一端的延范围控制按照下面两个规则。第一Q如果用可~程囑ŞgQ顶点程序可以对点q行无限延。第二,如果使用固定函数囑Ş水U,延的范围由光线衰减讄(点光源和聚光灯)(j)或?br />SceneManager::setShadowDirectionalLightExtrusionDistance()来控制。在不用加速图形硬件的情况下,应该量避免物体d源过q,q样?x)生过于宽的阴影锥Q导致不正确的阴影效果。根据算法原理,产生的阴p界非常明显:(x)一个像素要么在阴媄(jing)中,要么不在。这带来的好处是Q即佉K影锥的g伸距d大,也不?x)?jing)响精度。可以讲q种技术生的阴媄(jing)是一U“硬阴媄(jing)"。纹理阴影技术可以”Y化“阴影。用模杉K影技术需要边列表(edge lists),标准的{换工具在产生二进制mesh文g时会(x)创徏边列表,如果没有Q在E序中也可以用Mesh::buildEdgeList()来生。因为有时候,我们?x)代码的方式来生成mesh,如果q时我们想用模杉K影技术,那么p保产生?gu)列表数据。如果边列表数据不存在,那么ogre?x)认Z不希望这个物体投阴影?br /><font color="#0000ff">模板阴媄(jing)优化<br /></font>Ogre能进行一些一般的优化。例如可使用g加速,可能通过光的方向与范围来(g)它是否?x)对qx头体<br />(frustum)产生影响Q从面避免了(jin)计算那些不必要的阴媄(jing)几何体。ogre支持双面模板Qstencil-wrapping扩展Q?br />q些都能L不必要的原型安装(primitive setup)与驱动过?driver overhead)。ogre使用相对廉h(hun)的Z-pass法代替Z-Fail法Q当ZQFail法不必要时Q假如相机处于一个阴影锥中,使用Z-pass法?x)有问题Q这U情况下应该使用Z-fail法Q?br />阴媄(jing)锥不受封闭几何的影响。在下图中,<br /><img src="http://www.shnenglu.com/images/cppblog_com/yuanyajie/2865/r_shadowVolumeJPG.JPG" /><br />卫兵投射到地板上Q投的范围内有个封闭的子Q此例中讑֮子不投阴影)(j)。根据现实世界的l验Q箱子上?x)有卫兵投射的阴影,如图中所C。但光线l过子L后应该不再前q,也就是说阴媄(jing)锥经q箱子阻挡后不应该g怺(jin)Q于是箱子后面的地板上不应该再出现卫늚阴媄(jing)Q真实世界中出现子的阴影,但是此例讑֮子不生阴?。图中的地板上出C(jin)卫兵投射的阴影,q说明了(jin)阴媄(jing)不会(x)受到延方向上物体的影响?br />在屏q上看不到的物体也可以把阴媄(jing)投媄(jing)到可视的qx头体(view frustum)中。虽然看不到Q但是这些物?br />也必d被渲染,渲染他们Ua(b)是ؓ(f)?jin)得C生阴q相关数据。在不用硬件加速的情况下,量避免物体d源过q?br /><font color="#0000ff">U理阴媄(jing)</font><br />U理阴媄(jing)法的基本原理是Q首先从光源的角度观察场景,把观察到l果渲染C个纹理,U理中只保存<br />深度|深度~冲中的|(j)。这样做的意义是Q在U理中保存了(jin)场景中的物体与光源之间的最短距R然后从相机的角度进行正常渲染场景,计算每个像素与光源的距离,q与U理对应的D行比较,如果大于Q那么说明它不是光线方向上离光源的最q的Q会(x)有阴׃?font color="#008000">?*可以有点疑惑Q每个需要测试的像素如何与纹理中的像素一一对应呢?q是按照生成U理囄原理Q需要把试点的位|坐标,转换到光源ؓ(f)视点的空_(d)也就是说从光源的角度Q看看顶点应该在哪里。这样就可以一一对应比较?jin)。当然这仅仅是ؓ(f)?jin)比较的目的Q真正渲染时点q是要先转换到视I间?从相度看)*/</font>?br />U理阴媄(jing)速度上要比模杉Kq法快Q但因ؓ(f)阴媄(jing)被渲染到U理中,而纹理具有确定的解析度,因此当阴p扩展Q拉伸时Q效果会(x)较差Q如产生锯边等?br />因ؓ(f)使用?jin)纹理内存,因此它的寸军_?jin)纹理阴影数的上限。ogre中可以管理一帧中可以使用的阴q理数QSceneManager::setShadowTextureCount()。每个光源都需要一个纹理。假如指定的U理数少于光源数Qogre采用”先来先服务“的原则分配U理。假如不能增加纹理尺寸来提高视觉效果Q最好减投阴q距离。阴׃?x)突然终l,ogre?x)E化纹理阴q边缘L有阴׃无阴׃间剧烈过渡。可以控制E化半径?br /><font color="#0000ff">Modulative阴媄(jing)混合<br /></font>正常场景渲染的颜色与阴媄(jing)的颜色相乘来创徏暗的、表C阴q颜色。这U方法有从已l渲染的场景中”减厠Z光照媄(jing)响的效果。阴影区域一律变暗,与进入阴影区的光U数无关。当有多个光源生的阴媄(jing)?br />重叠Ӟ阴媄(jing)?x)非常暗Q视觉效果很差?br /><font color="#0000ff">Additive Shadow Masking<br /></font>Modulative的方法是通过影响阴媄(jing)区实现的。而AdditiveҎ(gu)是只对处于光照中的区域有影响Q对阴媄(jing)区没<br />有媄(jing)响。这样阴影区?x)受到别的光源的影响而变得稍亮,而相互重叠的阴媄(jing)Z不会(x)更暗?br />ogre?x)把一个通道分ؓ(f)三个通道.<br />Ambietn,应用环境光到场景中,在这个通道没有U理被渲染?br /> Diffuse and specular, q个通道Ҏ(gu)个灯都渲染一ơ,当前灯生的阴媄(jing)区域不受影响。其余的区域与场景进行؜合。同样也不用Q何脓(chung)q理?br />Decal。纹理被应用到前面篏U的颜色上?/p> <p> <br /> </p> <img src ="http://www.shnenglu.com/yuanyajie/aggbug/20302.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/yuanyajie/" target="_blank">清源游民</a> 2007-03-21 17:07 <a href="http://www.shnenglu.com/yuanyajie/archive/2007/03/21/20302.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>《Pro Ogre 3D Programming》读书笔??W十?布告板与_子 W二部分 http://www.shnenglu.com/yuanyajie/archive/2007/03/20/20227.html清源游民清源游民Tue, 20 Mar 2007 10:04:00 GMThttp://www.shnenglu.com/yuanyajie/archive/2007/03/20/20227.htmlhttp://www.shnenglu.com/yuanyajie/comments/20227.htmlhttp://www.shnenglu.com/yuanyajie/archive/2007/03/20/20227.html#Feedback0http://www.shnenglu.com/yuanyajie/comments/commentRss/20227.htmlhttp://www.shnenglu.com/yuanyajie/services/trackbacks/20227.htmlgameogre@gmail.com

_子pȝ
ogre中的_子pȝ既可用脚本描qͼ也可用代码完成。用_子脚本定义的粒子系l实际上是个模板Q因此它定义的粒子系l可在程序中方便地重用?br />_子pȝ与场?/font>
_子pȝ?x)被挂到场景l点上,因此Q结点的q移Q羃放,旋{?x)关联到_子pȝQ媄(jing)响粒子反的向?br />_子?x)被发射C界空间中Q这意味着当场景移动时Q它?x)牵q到发射器,但已l发出ȝ_子不受影响。假如需要这些粒子受l点的媄(jing)响,可以把粒子发到本地I间(local space)中。粒子系l不能无限制的发粒子,它有一个限额(quota)。一旦到N额,_子pȝ不会(x)再发粒子,直到已经存在的粒子消亡。缺省的限额?0?br />_子pȝU束(Bounds)
_子pȝ的动态特征意味着它们的绑定盒必须规律地被重新计算。缺省情况下Qogre?x)?0U之后,停止
更新l定盒。可以用ParticleSystem::setBoundsAutoUpdated(  bool  autoUpdate,  Real  stopIn = 0.0f )来改变缺省行为。stopInq个参数告诉ogre多长旉后停止更新。假如有个粒子系l,可以知道它的增长不会(x)过某个范围Q可以事先用ParticleSystem::setBounds()讄l定盒尺寸。这样做效率很高Q如果无法事先确定粒子系l的增长情况Q可先用setBounds()讑֮一个初始尺寸,而用setBoundsAutoUpdated()让它在一D|间之后更新?br />_子pȝ更新
对于_子pȝ的更斎ͼogre采用适度启发式的{略。D例来_(d)当粒子系l不在视锥体之内Qogre仍会(x)对粒子系l进行更斎ͼq是考虑C久之后,_子pȝ有可能会(x)重新q入视锥体之内。这避免了(jin)q种情况下的视觉上的不和谐。但是出于性能上的考虑Q当_子pȝ退?gu)锥体一D|间之后,_子实?x)停止更新。这又会(x)到上面的问题:(x)被冻l的_子pȝH然重新q入视锥体的情况。ogre提供?jin)一个所谓的
"fast-forward"机制Q允许粒子系l在被冻l之后,快速超当前状态。这U特性也可以用在刚创建的_子pȝQ它们状态提前一D|_(d)使用的方法是ParticleSystem::fastForward ();
_子pȝ排序
可以指示ogreҎ(gu)与相Z间的距离Q对_子q行排序。虽然这?x)?jing)响性能Q但有时不得不用。在烟的
例子中,不用排序的l果是,从烟的顶部依然清晰地看到火苗Q而用了(jin)排序之后火苗被烟雾模p掉?jin)。显然后者更加真实?br />发射?br />点发器从空间中单一点发粒子。box发射器可以从规则四方体的M位置发射_子。cylinder定义?jin)一个圆׃。ellipsoid定义?jin)一个椭球体。hollow elipsoid只是椭球体的外壳。ring只出q面圆环的边发射。被发射_子的速度Q方向也可以配置。粒子系l会(x)被挂到场景结点上Q因此发器与父l点有一个相对的位置。粒子通常不会(x)沿直U发,它们在发器方向的一个锥内发,有一个angle参数来定义。假如希望沿直线发射Qangle应该设ؓ(f)0,假如希望全方向发,angle设ؓ(f)180, 90表示?x)在方向向量的半球内随机发射?br />发射率用 _子?U 表示。发器可以按某个发率发射Q也可以使用一个范围内的随机倹{粒子可
以有固定的生命期Q也可以从一个范围随机指定。颜色也一P固定|随机值都可以。也可以在运动时Q以插g的Ş式提供定制发器Q这是扩展ogre_子pȝ最单的Ҏ(gu)?br />影响?br />_子一旦被发射C界中Q媄(jing)响器可被用来影响_子的运动\径与生命期?br />LinearForce:加一个力到粒子上Q力是一个向量,有方向与大小Q模Q?br />ColourFader:用于改变_子颜色。表C每U减的|是一个绝对倹{?br />ColorFader2:与ColourFader怼Q但是粒子生命到到达其生命期的某个阶D|Q可以{换到另一个褪色函数?br />ColourInterpolator:与上面两个相|但是它最多可以有6个阶D,分别Ҏ(gu)个阶D늚旉与颜色进行定义,然后不同阶段之间q行插|q与关键帧动ȝ思想有点像?br />Scaler:用来~放_子寸Q以旉为函数来定义一个羃攑֛子?br />Rotator:通过一l随机数量,或是随机速率来旋转粒子的U理Q这些被定义在某个范围之内?br />colourImage:从图像中d颜色,方向从左到右Q适合一l纹??br />

清源游民 2007-03-20 18:04 发表评论
]]>
《Pro Ogre 3D Programming》读书笔??W十?布告板与_子 W一部分 http://www.shnenglu.com/yuanyajie/archive/2007/03/20/20216.html清源游民清源游民Tue, 20 Mar 2007 07:31:00 GMThttp://www.shnenglu.com/yuanyajie/archive/2007/03/20/20216.htmlhttp://www.shnenglu.com/yuanyajie/comments/20216.htmlhttp://www.shnenglu.com/yuanyajie/archive/2007/03/20/20216.html#Feedback0http://www.shnenglu.com/yuanyajie/comments/commentRss/20216.htmlhttp://www.shnenglu.com/yuanyajie/services/trackbacks/20216.html清源游民 gameogre@gmail.com

布告?Billboard)
Ogre中的布告板简单的来讲是场景中的一个四边ŞQ但它的朝向与相机有兟뀂通常布告杉K着相机的视方向旋{以便与相机的视线方向寚w。把布告板放在场景的M地方Q它?yu)?x)朝向相机。ؓ(f)?jin)效率考虑Q布告板与相机的视线方向寚wQ而不是与从布告板到相机的向量寚w。大部分情况下两者没有明昄区别。如果想使用后一U的寚w形式Q也可以办到Q但在性能?x)有所降低?br />布告杉K(Billboard Sets)
布告板不能独立存在,他们也不能自我渲染。他们必d于某个布告板集。布告板集可认ؓ(f)是一l布告板
的管理器Q布告板集内的所有布告板有相同的寸Q用相同的材质。相同的寸Q相同的U理?x)带来计与渲染效率的提升。可以在一个布告板集内单独改变某个公告板的寸Q但q样做会(x)D性能下降ogre
认ؓ(f)一个布告板集是一个操作的单位Q它们要么都不渲染,要么全部q行渲染Q换句话_(d)它们以同L(fng)
方式q行剔除处理Q也可以寚w合的个体q行单独剔除Q但最好不要这么做Q同栯也是Z效率的虑。在大范围的应用布告杉K来模拟草的例子中Q就有可能出现在布告杉K内的许多布告板落在视角之外的情况Q在q种情况下也怼(x)惛_用单独剔除的方式Q但q样做同样不可避免地?x)?jing)响性能。更好的做法是用多个布告板集而不是在一个巨大的布告杉Kq行单独剔除。布告板集内的布告板是相对于布告杉Kattached到的场景l点q行定位的。既?dng)布告杉K内的布告板用相同的材质Q那么它们会(x)在同一batchq行渲染?br />布告板创?br />布告板可以用与本布告杉K的中?j)的偏移与尺寸(宽,高?j)来描q。它的方向是它到相机向量的函数。缺省,创徏的布告板是所谓的point布告ѝ这U布告板L完全地面对相且垂直。布告板的原点缺省位|是它的中心(j)Q可以在?ji)个规范的位|范围内改变原点位置。第二种cd的布告板是oriented布告板,它即可以沿各自的Y轴旋转,也可沿共同的_(d)通常是Y_(d)(j)旋{。第三种是perpendicular布告板,它与方向向量Q布告板与相Z间的向量Q垂直。这个方向向量可以是׃n的向量(通常是Z_(d)(j)Q也可以是各自的Z轴。这U类型的布告板也需要一个上方向辅助定位?br />point布告板相对于其他cd的布告板有一些优炏V一般,ogre为每个布告板产生一个quad(四个点Q每?br />点都有位置Q纹理坐标)(j)Qƈ把生成的几何体送入GPUq行渲染。对于point 布告板,可以废除其中的三个,让GPU挑选,以及(qing)军_如何q行Z点绘制纹理属性的渲染。进行硬件点渲染有一些限Ӟ(x)只支?br />point布告板,其中只限于以中心(j)为原点的那一cR尺怸外观在材质中定义Q不在布告板集,寸是有?br />的,不可能与软g创徏的一样大。不支持单独的布告板旋{与改变大,但可以对U理单元旋{?br />布告板池
创徏布告板时需要告诉布告板集中布告板的数量。布告板被分别放在active与free列表中,q得定位非常快。当创徏的布告板的数量超q了(jin)布告板池的尺寸,池的寸?x)增加一倍。最好事先确定池的大,避免在用中使池的大不合理地增ѝ?br />布告板纹理坐?/font>
支持非全范围的纹理坐标分配。D个例子,假如你有个纹理,它包含几个子U理。每个纹理都包含一?br />英文字母。这Ӟ你想创徏几个公告板,每个公告板上昄不同的字母,当然它们都来自同一个纹理?br />可以先创Z个包含纹理坐标的数组Q然后把q个数组提供l布告板集。当利用布告杉K创徏布告板时Q?br />可以l这个布告板一个存攄理坐标的数组的烦(ch)引。图片与代码如下Q?br />
// create a new billboard set with a pool of 4 billboards
BillboardSet* bbset = sceneMgr->createBillboardSet("BBSet", 4);
// create a texture coordinate array to address the texture
FloatRect texCoordArray[] = {
FloatRect(0.0, 0.0, 0.5, 0.5), // address the "A"
FloatRect(0.5, 0.0, 1.0, 0.5), // address the "B"
FloatRect(0.0, 0.5, 0.5, 1.0), // address the "C"
FloatRect(0.5, 0.5, 1.0, 1.0), // address the "D"
};
// provide this array to the billboard set
bbset->setTextureCoords(texCoordArray, 4);
// now create a billboard to display the "D"; this
// is the fourth entry in the array, index=3
Billboard* bb = bbset->createBillboard(Vector3(0, 0, 0));
bb->setTexcoordIndex(3);
也可以直接对U理坐标q行赋?br />FloatRect coords(0.5, 0.5, 1.0, 1.0);
bb->setTexcoordRect(coords);
布告板用的材质脚本与可以包括正常材质脚本中的所有东西,而且可以使用布告板与点纹理特有的一?br />指o(h)与参数?br />布告杉K与丝带跟t(Ribbon TrailsQ?br />布告杉K一l前后相联结的一l布告板Q可以联想“老鹰抓小鸡”的游戏中小鸡们的组l结构)(j)。ogre
提供?jin)一个ribbon-trail引用c,它用了(jin)布告杉KQ可以追逐场景中的结点,q留下一条尾巴。布告板铑֏以分多个节,因此可以很好来模拟灯的效果 。布告板铄~点是必L动更新。可以ؓ(f)布告杉K的每个节的尾部添加项Q每个节有最大的长度Q假如超q了(jin)那个长度Q尾部项被移除,重新做ؓ(f)节的头?br />ribbon trail有类似的行ؓ(f)Q从NU除作为头来增长,从头到尾颜色逐渐褪化。图片与代码如下Q?br />

void setupTrailLights(void)
{
NameValuePairList pairList;
pairList["numberOfChains"] = "2";
pairList["maxElements"] = "80";
RibbonTrail* trail = static_cast<RibbonTrail*>(
mSceneMgr->createMovableObject("1", "RibbonTrail", &pairList));
trail->setMaterialName("Examples/LightRibbonTrail");
trail->setTrailLength(400);
mSceneMgr->getRootSceneNode()->
createChildSceneNode()->attachObject(trail);
// Create nodes for trail to follow
SceneNode* animNode = mSceneMgr->getRootSceneNode()->
createChildSceneNode();
animNode->setPosition(50,30,0);
Animation* anim = mSceneMgr->createAnimation("an1", 14);
anim->setInterpolationMode(Animation::IM_SPLINE);
NodeAnimationTrack* track = anim->createNodeTrack(1, animNode);
TransformKeyFrame* kf = track->createNodeKeyFrame(0);
kf->setTranslate(Vector3(50,30,0));
kf = track->createNodeKeyFrame(2);
kf->setTranslate(Vector3(100, -30, 0));
kf = track->createNodeKeyFrame(4);
kf->setTranslate(Vector3(120, -100, 150));
kf = track->createNodeKeyFrame(6);
kf->setTranslate(Vector3(30, -100, 50));
kf = track->createNodeKeyFrame(8);
kf->setTranslate(Vector3(-50, 30, -50));
kf = track->createNodeKeyFrame(10);
kf->setTranslate(Vector3(-150, -20, -100));
kf = track->createNodeKeyFrame(12);
kf->setTranslate(Vector3(-50, -30, 0));
kf = track->createNodeKeyFrame(14);
kf->setTranslate(Vector3(50,30,0));
AnimationState* animState = mSceneMgr->createAnimationState("an1");
animState->setEnabled(true);
mAnimStateList.push_back(animState);
trail->setInitialColour(0, 1.0, 0.8, 0);
trail->setColourChange(0, 0.5, 0.5, 0.5, 0.5);
trail->setInitialWidth(0, 5);
trail->addNode(animNode);
// Add light
Light* l2 = mSceneMgr->createLight("l2");
l2->setDiffuseColour(trail->getInitialColour(0));
animNode->attachObject(l2);
// Add billboard
BillboardSet* bbs = mSceneMgr->createBillboardSet("bb", 1);
bbs->createBillboard(Vector3::ZERO, trail->getInitialColour(0));
bbs->setMaterialName("Examples/Flare");
animNode->attachObject(bbs);

}
首先QRibbonTrail创徏?jin)两个链Q每个最多包?0个元素,ַ?00个世界单位。创Z(jin)一个结点animNoade。ؓ(f)q个l点创徏?jin)一个动?使得q个l点可以Ҏ(gu)关键帧的设计在场景中不断变化位置。ƈ把一个RibbonTrail与这个结点联lv来,于是RibbonTrail可与animNode一赯动。又创徏?jin)一个灯Qƈ联结到这个结点,灯随l点也一赯动,于是怪物头会(x)有明暗变化。最后用一个布告板来Ş象表C刚创徏的灯Q因为灯在场景中是不可见的。因为灯被挂到animNodel点上,所以布告板bbs也挂到同L(fng)l点上。当然别忘了(jin)使用?jin)动ȝ态来推进动画?/p>

清源游民 2007-03-20 15:31 发表评论
]]>
《Pro Ogre 3D Programming?MW记 ?W九(ji)?动画 W一部分 http://www.shnenglu.com/yuanyajie/archive/2007/03/16/19974.html清源游民清源游民Fri, 16 Mar 2007 09:33:00 GMThttp://www.shnenglu.com/yuanyajie/archive/2007/03/16/19974.htmlhttp://www.shnenglu.com/yuanyajie/comments/19974.htmlhttp://www.shnenglu.com/yuanyajie/archive/2007/03/16/19974.html#Feedback0http://www.shnenglu.com/yuanyajie/comments/commentRss/19974.htmlhttp://www.shnenglu.com/yuanyajie/services/trackbacks/19974.htmlgameogre@gmail.com
概述
动画Qȝ来讲Q在计算机发展的各个阶段Q与艺术家们快速浏览一pd彼此E微不同的图片从而生运动的q觉的行为没有什么不同?872q_(d)Eadweard Muybridgel奔跑的马拍?jin)一l连l的照片Q从而证明了(jin)马在奔跑时会(x)四脚同时d。这是一pd的图片流可以产生q动q觉的最早的文档化的记录?br />现在在Ogre中,不必题大作地装配一些设备来创造这U运动觉了(jin)。只需要每帧少量地Ud或变形场景中的数据,q觉׃生了(jin)。它实只是q觉。ogre不跟t对象的速度Q加速度Q或是角色的背是在抬v
或是叉着腰。ogre逐来处理位|与朝向。ogre能ؓ(f)你做的是帮你重新播放q些动画。这些动d以是用离U工具制作的Q或是运行时产生的,或仅是ؓ(f)?jin)实现相机O游而填充了(jin)一pd位置的曲Uѝ?br />场景的每帧都?x)被重画Q两帧之间没有什么会(x)被保存下来。ogre中的动画仅仅是根据关于Q意变量(通常
是时_(d)(j)的函敎ͼ来定位与定向角色。每一帧,在ogre动画pȝ的控制之下,场景中的实体与动画被E稍
Ud或生变形,然后场景被重甅R这U生动ȝ方式Q与华纳兄弟的动d队做卡通动L什么同?br />一行画24个卡通兔Q彼此稍微不同,然后?U钟的时间连l播放?br />Ogre中的动画cd
Ҏ(gu)控制物体的不同方式分ZU:(x)Z关键帧的动画Q控制器?br />抽象地来看,ogre中的动画是相关tracks的集合。track是作为时间函数存储的一l数据倹{一对“track值”与"旉点“,构成?jin)关键?keyframe)Q更好的一U说法是Q在旉轴线上对对象全部或部分的位置Q朝向,~放Q进行采栗根据动ȝcdQogre支持好几U关键?关键帧”这个名U来源于手工制作动画的时代(像上面提到的制作卡通兔动画Q,首席艺术家会(x)l他的下U提供一l关键的帧。这些l出?jin)场景中角色的位|,然后下艺术家们Ҏ(gu)q些d帧之间角色的位置。在ogre中,你就是首席艺术家Q需要提供这些关键Qogre是你的下U,它帮你完成之间的过渡?br />ogre中支持的track有下面这几种cdQ一个track中的所有关键必须有一致的cdQ?
NumericAnimaitonTrack(NumericKeyFrame):
关键帧包含一个AnyNumericcd的标量倹{Any是ogre中定义的l构Q和COM中的variant cd一P允许数据cd的多态化。AnyNumeric限定?jin)可能的数据cd只能是数字的(实数Q整??br />NodeAnimationTrack(TransformKeyFrame):
关键帧包含两?l向量,一个四元数Q分别表C结点的位置Q羃放与朝向?br />VertexAnimationTrack(VertexMorphKeyFrame,VertexPoseKeyFrame):
关键帧包含或是引用在一个特定时间点上(在pose 动画中)(j)点位置和؜合权?VertexPoseKeyFrame)?br />动画状?br />E序与ogre中的动画主要的交互是通过动画状态来完成?animation state)。在建模工具中,可以为骨骼或点|格沿时间uU定义多个动画,导出时每个动画都可以定义一个名字,通过q个名字来定位Entity中同的动甅R通过动画状态可以访问动ȝ许多属性:(x)长度Q当前位|?动画名,是否循环Q有否有效,权重Q用于؜合动画)(j)。权重根据؜合动ȝcdq行不同的处理?br />混合权^均:(x)
告诉ogre做这U؜合时Q所有权重之和ؓ(f)1。如果不?Qogre?x)进行正规化处理Q得它们的d?。这U方式只寚w骼动L效,它也是默认的混合方式?br />混合权篏U:(x)
ogre只是单地把所有引用权重的效果q行累加Q不?x)再q。这U方式只寚w点动L效(pose, morph),用到骨骼动画时也可以?br />动画状态也是也l动甠Z加旉”推动它向前变化的地斏V基本上Ll一个时间增量,意味着从上ơ调用到现在增长?jin)的旉。本质上Q加一个时间增量与直接讑֮旉位置没有什么不同?br />骨骼动画
骨骼动画是最常用的动ȝ型。网?mesh)中的点被绑定到骨骼上,如同我们w体的肌肉绑定到骨上?br />不同的是Q计机动画中的“骨头”不是真实存在的。它们用一些(无对应实体)(j)变换来表C骨头的位置Q朝向与~放Q经常是用矩阉|表示。骨骼动ȝ关键帧,仅是相对于骨骼恢复位|的偏移。它们被l合h形成?jin)沿着旉轴线上某一l定点的骨骼?br />Ogre中的骨骼是有层次关系的,如脚骨与胫骨相连Q胫骨又与膝盖骨相连。在q种层次关系下,除了(jin)root外,每个骨头都有父亲。但q不限于只有一个root,q种层次关系仅仅是用来传递{?自上而下)。改变一栚w头会(x)影响它所有孩子的位置。反向的q动ogre不支持:(x)当一个骨头运动时Q它不会(x)影响父辈?br />点l定
点被绑定到骨骼时会(x)指定一个权重,权重说明?jin)骨头运动对点的?jing)响效果。典型的是把一个顶点绑
定到多个骨头Q赋于不同的权重。ogre仅支持每点四个骨头Q但每个骨头可以与Q意多个顶点关联?br />点动画
与通过计算动画骨骼Q再Ҏ(gu)骨骼位置计算点位置的动L式不同。顶点动ȝ接对点q行动画操作。它是资源密集型的解x案,对于每个动画位置都要转送完整的点数据的拷贝。有时这U方式是l一的办法,例如实现逼真的面部表情动甅R?br />点动画在动画trackq个层次上被理、操Uc(din)这意味着我们可以对角色的_(d)脔R分用复杂的pose动画Q而角色的剩余部分使用相对单的morph动画。但是不能对相同的顶点用不同的动画cd。顶点动d引用一l顶炚wӞ要么全部引用Q要么一个也不引用。这意味着Q在|格U别上来看,所有的׃n几何(shared geometry)构成?jin)顶点动ȝ点数据。在子网格别上来看Q所有子|格的顶Ҏ(gu)成了(jin)点动画的顶Ҏ(gu)据。D例来Ԍ一个子|格的某些顶点参与morph动画Q而剩余顶点参与pose动画Q这U情冉|不允许的?br />变Ş动画(Morph Animation)
变Ş动画是两U顶点动L术中最单最直观的一U。实际的点位置做ؓ(f)"快照"被保存。这与前面说?br />的卡通兔动画的过E是一L(fng)。这U方法比较消耗资源,但是计算效率最高。关键之间数据通过插值得?br />主要的缺Ҏ(gu)不能混合多个变Ş动画Q因Z们保存的是顶点的l对位置。当?dng)如果有两个动画,它?br />影响的顶Ҏ(gu)有交集,那么实可以对这两个动画q行混合?br />姿势动画(Pose Animation)
模型的各U姿势被保存在动画tracks中。这些姿势可以被混合来创建更复杂的动甅R顶点的位置是相对于
复原位置的偏U量Q而不是顶点的l对位置。而且只有变化的数据才被保存。因此,它不仅更灉|Q而且
对资源用也更高效?br />pose动画的关键引用一个或多个pose tracksQ每个引用对姿势有一个媄(jing)响权重。权重决定了(jin)当pose被؜合时每个点偏移Ҏ(gu)l的点位置产生多大的媄(jing)响。不必在每一帧都引用一个pose。在实践中,pose混合?x)碰C些限Ӟ(x)每个附加的pose需要更多的处理旉?br />混合动画
不能混合pose与morph动画CP也不能؜合多个morph动画?br />当؜合骨骼动M点动画Ӟogre首先计?混合点动画Q然后应用骨骼变形到混合点上?br />规范的pose与骨骼动L؜合的E序,?x)؜合全w体的骨骼动M复杂的面部表情。例如,可以对角色的面部点使用pose动画Q而角色的剩余部分(包括?使用相对单的骨骼动画?br />混合两个骨骼动画对于动画之间的切换是最有用的。例如角色可能在循环地执?跑步"q个动画Q一?x)?br />他可能要停下来(执行"idle"动画Q,那么q时需要对两个动画q行混合?br />Morph与骨骼动ȝ混合Q对于给骨骼动画的角色增?外皮"|格变Ş是很合适的。例?一个衣服动M角色实际的骨D动动L؜合,q样避免了(jin)对衣服进行实时模拟的高额代h(hun)?br />gvs软g
应用g加速时最应该C的是Q硬件动ȝ格数据不能被CPU使用。这相当重要Q假如你依赖|格数据
q行别的计算(体积阴媄(jing)计算Q物理模拟)(j)Q一旦顶点变形计被UdGPU中,点永q消׃(jin)Q不在代码中使用?jin),假如需要变形之后的点数据Q那么你q得用CPUq行与GPU同样的计!q确实也可以做到,告诉ogre做吧Q Entity::addSoftwareAnimationRequest()?br />g加速的骨骼动画与顶点动L؜合,?x)在点E序中执行؜合。假如你刚才q没有注意到上面曄提到
q的执行序的话Q现在又有机?x)让你意识到q点Q先点Q然后骨骹{这同样也意味着Q所有的动画技术都应该是基于硬件加速的Q不能让g加速的骨骼动画与基于Y件的点动画混合?br />使用GPU加?font color="#ff1493">骨骼动画
Ӟ应该考虑刎ͼ(x)骨骼动画法的本质上要求Q在计算每个点Ӟ骨架中所有骨头的数据必须都被提供。老旧的硬件仅仅支?4 bones或更的skinning通道。这时应把mesh分ؓ(f)几段Q在多个通道中skin它们。ogre只会(x)把submesh引用到的bones发送到skinning shader,而不是骨g所有的bones,q得多个skinnig pass成ؓ(f)可能?br />在CPU中对morph动画点q行插值的主要优点是利用了(jin)GPUq行计算的本质。morph计算h也不复杂Q?br />主要的输入是两个点位置与一个插值因子,点E序产生插值后的顶点位|做出?br />pose动画与morphcMQ而且有与骨骼动画cM的限Ӟ(x)它提供给E序的pose数目如何q行传递?br />标签?br />标签本n不是动画的一部分Q但它们常被用于联结L对象Q例如武器)(j)到存在的动画模型上。标{
的概忉|较简单:(x)它是骨架中一块特D的骨头Q它能在q行Ӟ控制l定对象的位|与朝向。不必事?br />创徏标签点,可以在运动期attched一个可Ud对象到骨架中一个命名的骨头上。Entity有这样一个方法:(x)
attachObjectToBone();一旦物体被l到骨头上,它就?x)随着标签点移动。需要知道的是,对象q不是真?br />地被attched到标{上。它被attched到用那个骨骼的Entity上?br />动画与控制器
两者都是基于一个一l的变量来控制对象的状态,把变量输入一个函C生输出。对于动L_(d)输入变量是时_(d)而对于控制器来说Q输入变量是M你想要的东西?br />动画的特点:(x)
通过插值函数计给定时间点上track值来产生输出Q从而改变顶点位|?br />动画被认为是个封闭的pȝQ你讄输入|ogre 使用它来更新相关对象的属性?br />插值函数较为固定:(x)要么U|要么三次h插倹{?br />动画有ogre提供的许多工L(fng)支持?br />控制器的特点Q?br />对于输出的计更为灵z,工作函数需要提供,因此有更多选择?br />控制器可以Ş成一个链Q一个输出可作ؓ(f)另一个输入?br />控制器自׃UdM东西Q对于输出可以不做Q何事情。ogre用控制器来驱动纹理动甅R?br />控制器自动逐更新Q然而必L工添加代码每的动d前变化?img src ="http://www.shnenglu.com/yuanyajie/aggbug/19974.html" width = "1" height = "1" />

清源游民 2007-03-16 17:33 发表评论
]]>《Pro Ogre 3D Programming?MW记 ?W八?渲染对象http://www.shnenglu.com/yuanyajie/archive/2007/03/15/19910.html清源游民清源游民Thu, 15 Mar 2007 09:25:00 GMThttp://www.shnenglu.com/yuanyajie/archive/2007/03/15/19910.htmlhttp://www.shnenglu.com/yuanyajie/comments/19910.htmlhttp://www.shnenglu.com/yuanyajie/archive/2007/03/15/19910.html#Feedback0http://www.shnenglu.com/yuanyajie/comments/commentRss/19910.htmlhttp://www.shnenglu.com/yuanyajie/services/trackbacks/19910.html清源游民 gameogre@gmail.com

OGRE渲染对象
Ogre中的render target 只是׃nAGP内存或显存的某个区域的抽象,q个区域中保存着全部或部分场?D渲染l果。最普通的render target是主渲染H口Q这是应用程序的ȝ口。用这个render target不需要做太多另外的努力,ogre可以帮我们创建它。还可以把场景中的全部或部分Q甚x场景中不可见的部分)(j)渲染C个纹理,q个U理可以被场景中的其他多边Ş使用。目标硬件缓冲在ogre中抽象ؓ(f)render target,它的物理昄可以Z渲染H口Q也可以是副H口Q也可以是非可视的:(x)U理?br />渲染对象也是事g源,假如E序注册?jin)这事gQogre?x)在pre- ?postrender旉知E序Q这l程序改变设|,做出响应的机?x)。甚臛_视口(viewport)U别上pre-,post- 渲染时也有上q通知机制。ogre提供?jin)计渲染状态信息的功能,如多长时间渲染一帧,渲染对象上有多少三角形等?br />渲染H口
H口是由渲染pȝ的具体实现创Zl护的(D3D9下是个标准的Win32 Window)。Ogre允许Ҏ(gu)染窗口进行很的配置Q限于尺寸,标题栏文字等。假如希望开发的E序有菜单,工具栏等Q把ogre的渲染输出到
H口的客户区Q这是可能的。ogre可以提供你系l相关的H口句柄l渲染窗口,也允怽提供句柄l父H口。第一个创建的ogre渲染H口UCؓ(f)ȝ口。另外创建的是副H口。窗口不像主H口那么重要。假如在E序中有三个H口Q那么ؓ(f)?jin)正的q行资源清理Q必d销毁主H口前把另外两个副窗口销毁?br />视口
渲染H口包含一个或多个视口。视口是一个长方Ş区域Q场景管理器把从一个相Z看到的场景可见内?br />的透视图渲染到q个区域中。视口创建时?x)引用一个相机,但这不是视口的静(rn)态属性,可以随时改变用于
渲染视口的相机。每个视口拥有一个z序数Qz序高的位于Z序低之上。z?QL被一个能覆盖整个渲染对象的视口所拥有。缺省,ogre?x)清理视口的颜色与深度缓册Ӏ然而,可以关闭q些~冲清理。视口是渲染对象Q也是特定的渲染系l,如OpenGL)与相机(也就是特定场景管理器与它的内容)(j)之间的唯一交互炏V视口不必占用整个渲染对象的表面?D渲染相机不是真正的相机,所有的几何LoD计算是以相机的位|算的,因此不能单的改变相机的焦点属性来辑ֈ“更q”的渲染效果?br />渲染到纹?br />使用步骤是:(x)创徏一个纹理渲染对象,配置它的渲染属性,加纹理到渲染对象列表Q设|纹理到被用的材质。纹理对象先于其他渲染对象类型更斎ͼq就保证?jin)用?jin)渲染U理的对象正地被渲染。渲染纹理可以像其他普通纹理一栯处理。对于那些不需要每帧都更新的渲染纹理,可以关闭自动逐更新而采用手动更新。从底层看,U理对象是一块硬件缓册Ӏؓ(f)?jin)性能考虑Q认为它们是只写与静(rn)态的。渲染到U理?x)渲染场景中的几何,需要一些时间执行,?x)降低应用程序率。但是很多有用的技术现在离不开渲染到纹理的使用。实旉影,实时反射{。ogre支持渲染到多个纹理,唯一的限制是它们具有相同的寸?br />渲染对象c?br />RenderTarget是RenderWindow,MultiRenderTarget,与RenderTexture的基cR?br />RenderWindow通过子类化来实现QD3D9RenderWindow,GLXWindow{。在windows操作pȝ中,׃可以使用Direct3D 9或是OpenGL,于是可以分别使用D3D9RenderWindowQW(xu)in32Window?br />RenderSystem::createRenderWindow()来创建窗口?br />virtual RenderWindow* Ogre::RenderSystem::createRenderWindow  (  const String &  name, 
  unsigned int  width, 
  unsigned int  height, 
  bool  fullScreen, 
  const NameValuePairList *  miscParams = 0
 ) 
通过最后一个参敎ͼ可以讄H口的一些属性?br />渲染窗口嵌入外部窗口的代码
NameValuePairList params; // is just a typedef std::map<std::string, std::string>
// set external window handle -- assume that you have
// already created a window to embed the Ogre render window, and its handle is
// stored in an integer variable called "mParent"
params["externalWindowHandle"] = StringConverter::toString(mParent);
// window can be resized later to fit within parent client area if needed
RenderWindow* window = createRenderWindow("MyWindow", 800, 600, false, &params);
渲染到纹理Demo
demo在原点创Z(jin)一个倾斜的^面,讄相机Q把场景Q场景由一个魔D袋与几个环面U结l成Q?br />相对于^面的倒媄(jing)渲染到纹理中。渲染纹理与q面已经应用的静(rn)态纹理؜合,q样实C(jin)反射效果?br />创徏渲染U理:
TexturePtr texture = TextureManager::getSingleton().createManual( "RttTex",
                               ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, TEX_TYPE_2D,
                              512, 512, 0, PF_R8G8B8, TU_RENDERTARGET );
创徏相机与视口用于渲染到U理:
             mReflectCam = mSceneMgr->createCamera("ReflectCam");
            mReflectCam->setNearClipDistance(mCamera->getNearClipDistance());
            mReflectCam->setFarClipDistance(mCamera->getFarClipDistance());
            mReflectCam->setAspectRatio(
                (Real)mWindow->getViewport(0)->getActualWidth() /
                (Real)mWindow->getViewport(0)->getActualHeight());
            Viewport *v = rttTex->addViewport( mReflectCam );
            v->setClearEveryFrame( true );
            v->setBackgroundColour( ColourValue::Black );
创徏使用渲染U理的材?/font>Q?/font>
MaterialPtr mat = MaterialManager::getSingleton().create("RttMat",
                ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
            TextureUnitState* t = mat->getTechnique(0)->getPass(0)->createTextureUnitState("RustedMetal.jpg");
            t = mat->getTechnique(0)->getPass(0)->createTextureUnitState("RttTex");
            // Blend with base texture
            t->setColourOperationEx(LBX_BLEND_MANUAL, LBS_TEXTURE, LBS_CURRENT, ColourValue::White,
                ColourValue::White, 0.25);
            t->setTextureAddressingMode(TextureUnitState::TAM_CLAMP);
            t->setProjectiveTexturing(true, mReflectCam);
            rttTex->addListener(this);
材质名ؓ(f)RttMat,包含一个技术,后者有一个通道。通道有两个纹理单?一个ؓ(f)?rn)态纹?RustedMetal.jpg)
,另一个纹理单元ؓ(f)渲染U理,两个U理按比例؜合。设|了(jin)合适的U理d模式Q开启了(jin)透视U理支持?br />qؓ(f)渲染U理Q它是渲染对象)(j)注册?jin)侦听器?br />相机倒置使用材质:
            // set up linked reflection
            mReflectCam->enableReflection(mPlane);
            // Also clip
            mReflectCam->enableCustomNearClipPlane(mPlane);
        }
           // Give the plane a texture
           mPlaneEnt->setMaterialName("RttMat");
相机q样讄后,渲染出的是场景的倒媄(jing)Q这是以指定q面为参照的。定制最q裁剪^面的作用是:(x)
那些低于反射面的对象不?x)再被渲染。渲染纹理时Qƈ不想把^面也渲染q去Q可以在上边已经注册
侦听器做Ҏ(gu)?/font>Q?br />void preRenderTargetUpdate(const RenderTargetEvent& evt)
    {
        // Hide plane
        mPlaneEnt->setVisible(false);

    }
    void postRenderTargetUpdate(const RenderTargetEvent& evt)
    {
        // Show plane
        mPlaneEnt->setVisible(true);
    }
最后要提的是,在每一帧,都要使两个相机的位置Q朝向保持一?
frameStarted:
 mReflectCam->setOrientation(mCamera->getOrientation());
  mReflectCam->setPosition(mCamera->getPosition());



清源游民 2007-03-15 17:25 发表评论
]]>
《Pro Ogre 3D Programming?MW记 ?W七?资源理 W一部分http://www.shnenglu.com/yuanyajie/archive/2007/03/14/19827.html清源游民清源游民Wed, 14 Mar 2007 09:09:00 GMThttp://www.shnenglu.com/yuanyajie/archive/2007/03/14/19827.htmlhttp://www.shnenglu.com/yuanyajie/comments/19827.htmlhttp://www.shnenglu.com/yuanyajie/archive/2007/03/14/19827.html#Feedback2http://www.shnenglu.com/yuanyajie/comments/commentRss/19827.htmlhttp://www.shnenglu.com/yuanyajie/services/trackbacks/19827.html清源游民  gameogre@gmail.com

资源l?/font>
命名l可以作Z个整体加载与卸蝲。在加蝲Q卸载,初始化时把把l中的所有资源作Z个执行单位来
看待Q而不是逐个q行处理。资源组理Ua(b)是了(jin)Z(jin)理上的方便Q是否用组的方式与性能无关。假
如向资源l管理器中加入了(jin)资源位置而没有指定组名,那么q些资源位置被放?General"l中?br />资源l与世界几何
~省情况下,ogre把加载的世界几何攑օ"General"l。也可以覆盖(override)q种方式Q得对世界几何的管理像其他资源的管理方式一栗统一的场景管理器可以提供关于装蝲世界L骤的U烦(ch)Q这样就可以在关卡加载时Q提供精的以进度条昄的反馈信息?br />资源位置(location)
资源位置是ogreL找资源进行烦(ch)引的地方。烦(ch)引指的是在某个位|的所有资源通过它们的名字被映射Q这样可以方便进行更快的查找资源。可以在E序的Q何时候添加或删除资源位置,不必事先Ҏ(gu)以可能用到的q行定义。资源位|在ogre中实际上是个archive,它的意思就是“文件的集合”。磁盘上的文件系l是
archive的一U类型。另外一U是zip archive。可以自定义archive格式。这通过改写archivecd现来完成,必须支持对命名的leaf文gq行枚D操作Q必L持通配W,支持l点递归Q给ogre提供一个流讉Ka(chn)rchive中文件的数据。ogre中的archive是只ȝ。ogre资源理器利用archive枚DҎ(gu)来索引archive的内容,当ogre对archiveq行索引Ӟ不会(x)实际加蝲M资源?br />资源生命周期
资源有四U状?各状态之间的转换关系如下图:(x)

Undefined:q是E序开始时Q所有资源的~省状态。除非它们被声明Qogre对程序用到的资源一无所知,手工调用代码 ResourceGroupManager::declareResource()或在脚本中被解析之后Q资源的状态变为Declared
Declared:声明是告诉ogre惌加蝲某些资源。ResourceGroupManager::declareResource()L有效的,包括在渲染系l初始之前,q与ResourceManager::create()不同Q因为后者依赖于渲染pȝ?br />Unloaded:通过调用ResourceGroupManager::initialiseAllResourceGroup(), ResourceGroupManager::
initialiseResourceGroup(),或Root::initialise()(它会(x)初始化在此调用之前所有声明的资源)Q资源状态进入到Unloaded,资源?x)占用一点内存来保存它的定义的实例,但是资源本nq没有加载到内存。从另一角度?从Loaded到Unloaded),引v状态变化的调用有:(x)ResourceManager::unload(),ResourceManager::unloadAll(), ResourceManager::unloadAllUnreferencedResources(),ResourceGroupManager::unloadResourceGroup(), or Resource::unload().所有这些调用仍?x)保存资源实例,但真正的资源数据会(x)从内存中卸载?br />Loaded: q种状态下Q所有数据都变得有效。与此状态有关的调用有Resource::load(), Resource::reload(),
ResourceManager::load(), ResourceManager::reload(), ResourceManager::reloadAll(),
ResourceManager::reloadAllUnreferencedResources(), and ResourceGroupManager::
loadResourceGroup().
逻辑资源理
资源以命名组的Ş式组l,每组可以包括Mcd的资源,每种资源都有自己的资源管理器Q后者负责加载与卸蝲特定cd的资源。ogre对它的资源没有实现特定的内存理Ҏ(gu)Q如果你需要对某种资源实“最q最用算法”方案来q行理Q那么需要自q代码来实现。值的一提的是,现在的大多数昑֍驱动Q对于大多数重要的资源已l实C(jin)q种LRU法理?br />资源加蝲
假如没有预加载,当资源被讉K时会(x)q行加蝲。实际的加蝲Q卸载是资源自己的责仅R?br />手动加蝲资源
资源理层不负责实际的加载与卸蝲。通常Q不必担?j)资源是否存在于易失性媒介。然而,手工方式旉要考虑。手工资源加载器必须在Q何时候准备好重新加蝲资源。假如某个资源是通过E序生成的,那么手工资源加蝲器必d存中~冲q些资源Q或者是当资源管理加载时重新创徏它。ogre认ؓ(f)手工加蝲与自动加载没有区别?br />后台资源理
~省Qogre不是U程安全的。假如在OgreConfig.h?#define OGRE_THREAD_SUPPORT 1 ,那么资源理
代码的线E同步功能变得有效,我们可以在包含Root实例的线E之外,开启新的线E对资源理cMҎ(gu)q行操作,从而实现灵zȝ资源加蝲Ҏ(gu)。 
非后台资源管?br />Ogre中大量用了(jin)Observer模式,资源理pȝ也不例外。ResourceGroupListene 回调接口包含?jin)几个方?br />允许对资源加载过E进行细_度的监听?br />资源卸蝲
资源被加载后d在于内存中,直到被应用程序强行卸?通过资源l管理器或是被资源直接释?。资源管理组理?x)把l中所有的资源都卸载掉。在资源被引用时不能卸蝲?br />Resource Locations
// 配置文g方式
ConfigFile cf;
cf.load("resources.cfg");
// Go through all sections & settings in the file
ConfigFile::SectionIterator seci = cf.getSectionIterator();
String secName, typeName, archName;
while (seci.hasMoreElements())
{
secName = seci.peekNextKey();
ConfigFile::SettingsMultiMap *settings = seci.getNext();
ConfigFile::SettingsMultiMap::iterator i;
for (i = settings->begin(); i != settings->end(); ++i)
{
typeName = i->first;
archName = i->second;
ResourceGroupManager::getSingleton().addResourceLocation(
archName, typeName, secName);
}
}
//编码方?br />ResourceGroupManager *rgm = ResourceGroupManager::getSingletonPtr();
rgm->addResourceLocation("../../media/packs/OgreCore.zip", "Zip", "Bootstrap");
rgm->addResourceLocation("../../media", "FileSystem", "General");
rgm->addResourceLocation("../../media/fonts", "FileSystem", "General");

初始?/font>
在初始化之前Q必d一个渲染窗口。因为在分析脚本时可能会(x)创徏GPU资源Q而后者需要渲?br />上下文?br />// initialize all of the previously defined resource groups
ResourceGroupManager::getSingleton().initialiseAllResourceGroups();
// or, alternately, initialize the defined resource groups one at a time
ResourceGroupManager::getSingleton().initialiseResourceGroup("General");
ResourceGroupManager::getSingleton().initialiseResourceGroup("Bootstrap");
卸蝲
可以在Q何时候卸载资源(以组或单个的方式Q?正在使用的资源不?x)被卸蝲?br />以组的方式卸?/font>
ResourceGroupManager::getSingleton().unloadResourceGroup("Bootstrap", true);
ResourceGroupManager::getSingleton().
unloadUnreferencedResourcesInGroup("Bootstrap", true);
true表示只卸载资源数据,不删除资源实例,它可以被reloaded。有些资源在创徏时被标ؓ(f)
"nonreloadable",q种cd的资源不能用上q方法卸载?br />清理或销毁资源组
清理仅是卸蝲资源与分资源烦(ch)引,销毁不仅做清理的工作,q包括从资源l中把自q除?br />ResourceGroupManager::geSingleton().clearResourceGroup("Bootstrap");
ResourceGroupManager::geSingleton().destroyResourceGroup("Bootstrap");
以个体方式卸?/font>
// assume that pEntity is a valid pointer to an instance of Entity
MeshPtr meshPtr = pEntity->getMesh();
meshPtr->unload();
加蝲/重蝲资源l?/font>
ResourceGroupManager::getSingleton().loadResourceGroup("Bootstrap", false, true)
二个布尔变量不同资源cd资源加蝲开养I一针对"Normal"资源Q二针对"World geometry"
资源l加载通知
class LoadingProgressListener : public ResourceGroupListener
{
   public: 
       
 // fired when a group begins parsing scripts
                void resourceGroupScriptingStarted(const String& groupName,
                                                                        size_t scriptCount) {}
       // fired when a script is about to be parsed
               void scriptParseStarted(const String& scriptName) {}
       // fired when the script has been parsed
               void scriptParseEnded() {}
       // fired when all scripts in the group have been parsed
              void resourceGroupScriptingEnded(const String& groupName) {}
      //q有一些接?br />}
//实现之后Q进行注?br />LoadingProgressListener listener(m_progressMeter);
ResourceGroupManager::getSingleton().addResourceGroupListener(&listener);



清源游民 2007-03-14 17:09 发表评论
]]>
《Pro Ogre 3D Programming?MW记 ?W六?材质 材质复制 http://www.shnenglu.com/yuanyajie/archive/2007/03/13/19754.html清源游民清源游民Tue, 13 Mar 2007 07:57:00 GMThttp://www.shnenglu.com/yuanyajie/archive/2007/03/13/19754.htmlhttp://www.shnenglu.com/yuanyajie/comments/19754.htmlhttp://www.shnenglu.com/yuanyajie/archive/2007/03/13/19754.html#Feedback0http://www.shnenglu.com/yuanyajie/comments/commentRss/19754.htmlhttp://www.shnenglu.com/yuanyajie/services/trackbacks/19754.html清源游民 gameogre@gmail.com

材质复制
如果新的脚本只是Ҏ(gu)个已l存在的脚本q行部分的变化Q那么可q行从旧脚本复制Q而不是CQP。新材质可以修改特定technique,pass,texture,或是d新项?br />格式: material <NewUniqueChildName> : <ReferanceParentMaterial>
当材质脚本被加蝲到ogre中,q种l承关系不再l系Q假如父材质在运行时被修改,不会(x)影响到子材质。如果在一个technique中有5个pass,而我们只想修改第5个pass,我们可以用pass指定或是它的索引(?计)(j)
meterial test2: test1
{
  technique 0
    {
      pass 4
        {
          ambient 0.5 0.7 0.3 1.0
        }
    }
}
加入一个新的technique或pass到material中,可以通过赋于它们新的名称来实玎ͼ新名U必d父材质中没有出现q。指定新索引也一栗新technique或pass?x)被加蝲到父材质相应technique或pass末尾.
material BumpMap2 : BumpMap1
{
  technique ati8500
  {
    pass 0
    {
      texture_unit NormalMap
      {
        texture BumpyMetalNM.png
      }
    }
  }
}
在上面的例子中,如果texture_unit的名UNormalMap在父材质中指定过Q那么现在的行ؓ(f)表示override,如果它是一个新的名字,那么表示在pass的最后新加一个texture unit。 

U理别名

在源材质被cloneӞ每个texture unit可以被赋于一个Texture alias(别名Q。可以用q个别名来指定用什么纹理。格式:(x) texture_alias <name> ~省Q?texutre_unit <name>( U理单元的名?
texture_unit DiffuseTex
{
  texture diffuse.jpg
}
在这U情况下Qtexture_alias为DiffuseTex.
material TSNormalSpecMapping
{
  technique GLSL
  {
    pass
    { 
      texture_unit NormalMap
      {
        texture defaultNM.png
        tex_coord_set 0
        filtering trilinear
      }

       texture_unit DiffuseMap
      {
        texture defaultDiff.png
        filtering trilinear
        tex_coord_set 1
      }

        texture_unit SpecMap
      {
        texture defaultSpec.png
        filtering trilinear
        tex_coord_set 2
      }
    } 
  }

  technique HLSL_DX9
  {
    pass
    { 
        texture_unit
      {
        texture_alias NormalMap
        texture defaultNM.png
        tex_coord_set 0
        filtering trilinear
      }

      texture_unit
      {
        texture_alias DiffuseMap
        texture defaultDiff.png
        filtering trilinear
        tex_coord_set 1
      }

      texture_unit
      {
        texture_alias SpecMap
        texture defaultSpec.png
        filtering trilinear
        tex_coord_set 2
      }
    } 
  }
}
例子中有两个技术,都用相同的U理,W一个技术用缺省的方式定义?jin)纹理别名,W二个技术显式地指定U理别名。两者都有相对应的同L(fng)U理别名。如果想定义一个材质只是想使用不同的纹?那么copy父材质时可以使用set_texture_alias来重新指定新U理?br />material fxTest : TSNormalSpecMapping
{
  set_texture_alias NormalMap fxTestNMap.png
  set_texture_alias DiffuseMap fxTestDiff.png
  set_texture_alias SpecMap fxTestMap.png
}
上面代码对拥有指定别名的texture unit所使用的纹理图片进行了(jin)重新指定?br />



清源游民 2007-03-13 15:57 发表评论
]]>
《Pro Ogre 3D Programming?MW记 ?W六?材质 概念http://www.shnenglu.com/yuanyajie/archive/2007/03/13/19703.html清源游民清源游民Tue, 13 Mar 2007 03:31:00 GMThttp://www.shnenglu.com/yuanyajie/archive/2007/03/13/19703.htmlhttp://www.shnenglu.com/yuanyajie/comments/19703.htmlhttp://www.shnenglu.com/yuanyajie/archive/2007/03/13/19703.html#Feedback1http://www.shnenglu.com/yuanyajie/comments/commentRss/19703.htmlhttp://www.shnenglu.com/yuanyajie/services/trackbacks/19703.html基本对象着?br />
材质Q简单的来讲是定义?jin)被赋于此材质的对象如何反射光。ogre中的光照采用局部光照模型,q意味着Q对计算有媄(jing)响的因素有:(x)光照的角度与光的颜色Q相机的视角Q对象的材质。ogre支持四种cd用来描述材质的颜?表述?jin)光照对它的影响Q环境光QO反射Q发散,镜面反射。环境光是对全局光照的近|漫反是指当物体被光照射后在物体各方向上反射的光的颜艌Ӏ发散指物体本n自发光的颜色。镜面反,指的是在某个视角看到的被光反出的“高光”。镜面高光有两个参数可以控power,shininess.power用来控制“加亮点”的寸(影响的范围越?。而shininessD大的表面Q高光越Ҏ(gu)聚集?br />U理映射
通过U理坐标Q用一?D囄l?D对象着色的技术?br />可编E着?/font>
通过写高U或低的顶点程序,片段E序代替固定线的功能。支持可~程囑Şg也可以当做固定函数流水线g来用。可~程g允许更灵zȝ计算点的的颜色Q位|等。纹理也可用于可~程g。纹理中包含的数据,不仅仅可以表C颜Ԍ也可以表CZQ何其他程序员知道如何处理的数据?br />Batching
材质与mesh之间的关pL带来的最大媄(jing)响是渲染状态的改变。ogre中的渲染单元大多数情况下指的是renderable,它是SubEntity的父cR渲染单元这个概늚重要性在于,正是在这里,ogre调用显卡驱动开始ƈ且会(x)l束“画操作”。一ơ画操作Qbatch),指的是清除颜料(color,texture,etc)与材料(vertexof display lists)Q从头开始一l新的操作的q程。就像一个画家每ơ在L上做L?x)洗净他的调色板一栗对?Dg来讲Q这个过E包括发送新的顶点列表与数据索引到GPU(或者引用还存在的)(j)Q用U理Q颜Ԍ以及(qing)光栅化这些顶点组成的面需要的一些元数据来设|GPU。因此,最有效率的做法是一ơ尽可能多的?br />使用同样渲染数据的顶点发送到GPUq行处理。ogre?x)尽量减状态改变带来的影响Q但它遵重你如何构成一个renderable的决定。假如你有一个模型它?0个块l成Q它们都使用相同的材质,q时应该把他们整合到相同的renderable中去Q而不是分20ơbatch发送到昑֍。每帧的batchC(x)有个上限?br />材质克隆
ogre中的材质是共享的。当你从材质理器获得一个指针,它与从用这U材质的其他对象所拥有的材?br />指针是相同的。因此改变一处会(x)影响其他Qؓ(f)?jin)避免?jing)响其他应该克隆材质?br />Technique & Scheme
Technique允许针对不同的硬件^台定制不同的材质。Scheme允许对特定一l技术进行更一般化的描q。Ogre选择技术时有明的序。首先,它寻扑ֱ于某个命名Scheme中的技术。然后在选好的scheme中查N些应用了(jin)特定材质lod的技术。最后在q些技术列表中Q选择最能适应当前g讄的技术。缺省,所有的技术属于细节?,它对应最高细节别?br />Material LoD
层次l节q个术语常用来讨论随场景中的物体的几何复杂性是相机与物体之间距ȝ函数。类似的概念被应用到材质定义上。ogre提供?jin)在哪个层次l节上用特定技术的手段。可以在材质中定义层ơ细节发生变化时的距,赋于材质中的每个技术一个细节烦(ch)引。每个细节烦(ch)引也可以有多个技术,用来支持scheme或是g能力fallback?br />材质l成
一个materail׃个或多个techniquel成Q后者又׃个或多个passl成Q一个时d有一个technique是活动的。pass对于在GPU上执行画操作的renderable来讲Q是完整的原子渲染状态。假如选择的技术有三passQ那么每帧会(x)对renderableq行三次L作。pass可以引用U理单元定义Q而不必包含Q何纹理单元定义?br />U理单元
ogre materail中的U理单元实际引用GPU上的texture sampler.多数C囑Şg有多个texture sampler,
ogre支持的硬件至有一个有效的texture sampler。纹理单元包括一个纹理的引用Q可以来自一个磁盘文Ӟ或是q行时渲染,或是来自外部视频。可以在每个pass中指定多个纹理单元。ogre?x)检硬件支持的能力Q必要时把一个pass折分成多个pass。D例来_(d)假设pass中指?个纹理单元,而硬件只支持4个,那么ogre?x)把q个pass拆分成两个,对这两个pass执行U理混合以达到相同的设计功能。纹理通常保存在video memory中,直到它们不再需要。ogre不会(x)每次需要时都通过ȝ传输U理Q除非纹理经常地?br />video memory中剔除。(q时发生?jin)纹理震荡,原因是有太多或太大的U理同时存在于vedio memory中)(j)?br />U理压羃
C囑Şg支持压羃U理。ogre只是单地把纹理按原样传送他们到囑Şg中去Q它不会(x)压羃U理?br />对于那些压羃q的U理Q也不必事先处理它,如果g不支持压~纹理,ogre?x)在q行时解压羃?br />实体
在渲染期_(d)Entity主要作ؓ(f)subentities的容器来用,subentities是实际的渲染单元QrenderableQ?br />subentity与submesh有一一对应的关p,后者提供原始的材质引用。概念上来讲Qentity(subentity)提供?jin)对象的渲染属性,而mesh(submesh)提供?jin)对象的l构属性?img src ="http://www.shnenglu.com/yuanyajie/aggbug/19703.html" width = "1" height = "1" />

清源游民 2007-03-13 11:31 发表评论
]]>《Pro Ogre 3D Programming?MW记 ?W五?场景理 场景查询http://www.shnenglu.com/yuanyajie/archive/2007/03/11/19573.html清源游民清源游民Sun, 11 Mar 2007 09:24:00 GMThttp://www.shnenglu.com/yuanyajie/archive/2007/03/11/19573.htmlhttp://www.shnenglu.com/yuanyajie/comments/19573.htmlhttp://www.shnenglu.com/yuanyajie/archive/2007/03/11/19573.html#Feedback0http://www.shnenglu.com/yuanyajie/comments/commentRss/19573.htmlhttp://www.shnenglu.com/yuanyajie/services/trackbacks/19573.html 场景查询
创徏查询的代h较大Q而执行不是。SceneQueryResualt只定义了(jin)两种成员Qmovables与worldFragments.
掩码也需要自己定义,自己解释。在一个u寚w盒子中查询灯光的例子如下Q?br />const unsigned int LIGHT_QUERY_MASK = 0x00000001; //掩码定义
Light* light1 = mSceneMgr->createLight("Light1");
Light* light2 = mSceneMgr->createLight("Light2");
light1->setPosition(12, 12, 12);
light2->setPosition(5, 5, 5);
light1->setQueryFlags(LIGHT_QUERY_MASK);
light2->setQueryFlags(LIGHT_QUERY_MASK);
AxisAlignedBoxSceneQuery* lightQuery =
mSceneMgr->createAABBQuery(
AxisAlignedBox(0, 0, 0, 10, 10, 10), LIGHT_QUERY_MASK);
// sometime later in the application's code, find out what lights are in the box
SceneQueryResult& results = lightQuery->execute(); //查询
// iterate through the list of items returned; there should only be one, and it
// should be light2 created above. The list iterator is MovableObject type.
SceneQueryResultMovableList::iterator it = results.movables.begin();
for (; it != results.movables.end(); it++)
{
// act only on the lights, which should be all we have
assert ((*it)->getQueryFlags() & LIGHT_QUERY_MASK) != 0);
// do whatever it was we needed to do with the lights
}
// destroy the query when we are done with it
mSceneMgr->destroyQuery(lightQuery);

我们知道地ŞL起伏不^的,当主角在上面行走旉要根据地形的高度调整Q可以光U查询来实现?br />原理比较单:(x)向主角脚下执行光U查询,与地形有一个交点,Ҏ(gu)交点的高度调整主角位|?br />Terrain Clamping
void Entity::clampToTerrain() {
static Ogre::Ray updateRay;
updateRay.setOrigin(m_controlledNode->getPosition() + Ogre::Vector3(0, 15, 0));
updateRay.setDirection(Ogre::Vector3::NEGATIVE_UNIT_Y);
m_raySceneQuery->setRay(updateRay);
Ogre::RaySceneQueryResult& qryResult = m_raySceneQuery->execute();
if (qryResult.size() == 0) {
// then we are under the terrain and need to pop above it
updateRay.setOrigin(m_controlledNode->getPosition());
updateRay.setDirection(Ogre::Vector3::UNIT_Y);
m_raySceneQuery->setRay(updateRay);
}
qryResult = m_raySceneQuery->execute();
Ogre::RaySceneQueryResult::iterator i = qryResult.begin();
if (i != qryResult.end() && i->worldFragment)
{
Ogre::SceneQuery::WorldFragment* wf = i->worldFragment;
m_controlledNode->setPosition(m_controlledNode->getPosition().x,
i->worldFragment->singleIntersection.y,
m_controlledNode->getPosition().z);
}
}
void Entity::init()
{
// lots of other irrelevant entity init stuff goes here
m_raySceneQuery = sm->createRayQuery(
Ogre::Ray(m_controlledNode->getPosition(),
Ogre::Vector3::NEGATIVE_UNIT_Y));
// move this node is such a way that it is above the terrain
clampToTerrain();
}



清源游民 2007-03-11 17:24 发表评论
]]>
《Pro Ogre 3D Programming?MW记 ?W五?场景理 地Şhttp://www.shnenglu.com/yuanyajie/archive/2007/03/09/19504.html清源游民清源游民Fri, 09 Mar 2007 09:25:00 GMThttp://www.shnenglu.com/yuanyajie/archive/2007/03/09/19504.htmlhttp://www.shnenglu.com/yuanyajie/comments/19504.htmlhttp://www.shnenglu.com/yuanyajie/archive/2007/03/09/19504.html#Feedback0http://www.shnenglu.com/yuanyajie/comments/commentRss/19504.htmlhttp://www.shnenglu.com/yuanyajie/services/trackbacks/19504.html Ogre中的地Ş

使用terrain.cfg
WorldTexture=terrain_texture.jpg  //地ŞU理
DetailTexture=terrain_detail.jpg  //l节U理
DetailTile=3                      //l节U理在一个地形小块中的^铺数
PageSource=Heightmap              //高度图数据源
Heightmap.image=terrain.png       //高度囑֐U?W合2^n+1
PageSize=513                      //高度囑֤?br />TileSize=65                       //地Ş块大小
MaxPixelError=3                   //军_使用层次l节时充许误?br />PageWorldX=1500                   //地Ş在世界中的范围x方向
PageWorldZ=1500                   //z方向
MaxHeight=100                     //世界中地形最大映高?br />MaxMipMapLevel=5                  //层次l节上限
#VertexNormals=yes                //在缓冲中计算点法线Q计机光照或GPUE序用到时打开
#VertexColors=yes         //在缓冲中讄点颜色Q假如有GPUE序需要时打开
#UseTriStrips=yes                 //对于现在的硬Ӟx
VertexProgramMorph=yes         //使用点E序q行LOD融合处理
LODMorphStart=0.2                 //LOD融合开始点Q高Q低LOD之间距离之比

下列参数用于提供自己的着色程序时使用Q这?x)提供自己定义的materialQ那么先前定义的
WorldTexture ?DetailTexture的设|不再用刎ͼ多余的了(jin)?/p>

MorphLODFactorParamName=morphFactor 
//假设VertexProgramMorph被设为yes,定制的material中包括一个高U顶点程序。它指定?jin)一个顶?br />//E序的参数名Q这个参数用于融合LOD,参数g0Q?Q?表示不调_(d)1表示完全调整C一ULOD
MorphLODFactorParamIndex         //用于materail中包含低U顶点程序的情况Q意义同?br />CustomMaterialName               //指定的materail名字

上述配置文g定义?jin)基于高度图的地形。这些参数定义可概括Zc:(x)Ogre使用W一cM高度图生地?br />mesh与材质。第二类是定制材质与GPU点E序Q这可以代替ogre自动产生的着色程序?br />另外的说明:(x)
TerrainScenceManager?x)把高度囑ֈ为向个pages,每个page由几个tilesl成.而它们也不过是个方便的名字,
它们都定义了(jin)在生的mesh中一l构成正方Ş的顶炚w?br />WorldTexture定义的纹理不必与目标地Ş一样大?br />PageWorldXQPageWorldZ可以~放世界中的地Ş?br />MaxHeight 在Y方向~放地Ş?br />DetailTexture 只用一个纹理,如用多层纹理,应该使用自定义materail?br />
从程序加载地?/font>
setWorldGeometry()有重载Ş式,一U用于加载配|文Ӟ另一U我们可在程序中使用Q以
辑ֈ手工加蝲的功能。这里,SceneData?typedef 为std:map,它存储了(jin)如我们在terrain.cfg
中看到那些值对。假设我们已l从某个二进制文件读入我们想要的内容到SceneData中。我们要?br />的就是把d的内容{换成setWorldGeometry()需要的cd。先看一下函数原型:(x)
Ogre::SceneManager::setWorldGeometry (  DataStreamPtr &  stream, 
  const String &  typeName = StringUtil::BLANK
 ) 
DataStreamPtr是一个智能指?因此从局部变量中q回是安全的,E序相当直观Q不再多说了(jin)?/p>

Ogre::DataStreamPtr Process_Loader::getSceneDataStream(SceneData &data) {
// create what looks like a config file for the edification of Ogre
std::string mem;
SceneData::iterator it;
for (it=data.begin(); it!=data.end(); it++) {
mem += it->first;
mem += "=";
mem += it->second;
mem += "\n";
}
void *pMem = (void *)new unsigned char[mem.length()+1];
memset(pMem, 0, mem.length()+1);
memcpy(pMem, mem.c_str(), mem.length() + 1);
// stuff this into a MemoryDataStream
Ogre::DataStreamPtr pStr(new Ogre::MemoryDataStream(pMem, mem.length() + 1));
return pStr;
}
// and then elsewhere in the world loader:
Ogre::DataStreamPtr pStr = getSceneDataStream(terrainDef);
m_sceneMgr->setWorldGeometry(pStr);



清源游民 2007-03-09 17:25 发表评论
]]>
《Pro Ogre 3D Programming?MW记 ?W五?场景理 W二部分 http://www.shnenglu.com/yuanyajie/archive/2007/03/09/19496.html清源游民清源游民Fri, 09 Mar 2007 06:25:00 GMThttp://www.shnenglu.com/yuanyajie/archive/2007/03/09/19496.htmlhttp://www.shnenglu.com/yuanyajie/comments/19496.htmlhttp://www.shnenglu.com/yuanyajie/archive/2007/03/09/19496.html#Feedback0http://www.shnenglu.com/yuanyajie/comments/commentRss/19496.htmlhttp://www.shnenglu.com/yuanyajie/services/trackbacks/19496.html 场景对象创徏
场景中的所有对象,包括可移动与不可Ud的:(x)lights, cameras, entities,particle system,
billboards, skyboxes, static geometry , world geometry.都由场景理器来创徏。场景中?br />M东西都由场景理器来理。Q何通过场景理器得到的东西Q都必须由场景管理器来销毁?br />用户不能delete通过由场景管理器得到的指针?br />场景l点只有一个父l点Q可能有多个子结炏V可以随意的attach ?detach q些场景中的l点?br />在明告诉场景管理器销毁这些结点前Q它们L存在。如果不x染场景中的某些结点上的内容,
我们可以很方便地对她们进行detach.场景中L存在一个Rootl点。可以把多个内容对象attach?br />同一个结点上。不能同时把一个实例对象挂C个场景结点上Q一个场景结点也不能有两个父l点?br />L场景l点在执行空间操作(q移Q旋转,~放Q而不是实体对象?br />场景查询
场景理器的W二个最常用的功能是q行场景查询。包括射U查询,球查询,l定盒查询,l定q面
查询Q相交查询。Terrain clampingQ在崎岖不^的\上,勇敢地向下发一束光Q不你告诉我你?br />多高Q我永远把你t在脚下..Q是不是不太像笔讎ͼ^_^)。所有这些查询都?maskble的,q表明可
以在查询时过滤掉不关?j)的对象cd。如球查询时Q只想看看它包含?jin)多lights,其他的对象即使包?br />在球里也不必q回Q实际上Ҏ(gu)不用计算?br />I间关系?D变换
world , parent , local世界I间中的变换是相对于全局坐标pȝ源点(0,0,0),q也是root scene node的位|。因此可以认Z界空间中的变换是相对于Root scene node的。父I间中的变换是相对于场点l点的父l点的,本地I间的变换是相对于物体所挂接的结点的。大多数情况下,我们?x)在父空间中做^U,在本地空间中做旋转,ogre中的q些操作Q都是在上述的这U方式下?br />object space
从模型导出的点数据与它的源点之间的关系是不变的Q当它被挂到场景l点上,q个l点是认ؓ(f)?br />它的源点。徏模时与导出时不假设测量单位,以世界单位导出(也就是无单位Q?br />ogreq移与设|位|不同:(x)q移可以有多个参照点Qworld,local,parent space),而用setPosition()
ӞL相对于parent-space 坐标pȝ?br />可移动的场景对象
Z资源的对象:(x)最普通的是mesh(陪伴着skeleton)Q这U类型的对象被资源管理系l管理?br />场景理器不负责实际的装载,它调用Ogreuq资源理器来完成?br />Z四边形的对象Q粒子系l,公告板,ribbon trail,overlay,天空盒。它们通常是面向相机的Q?br />使用动态材质。它们的主要资源是脚本,q些脚本定义?jin)如何映材质,以?qing)它们的生命期Q对于粒子系l与ribbon trail来说)。天I盒直接用场景管理器来定义?br />skyplane,skydome,skybox
主要的相似点是它们与相机保持一个常量的距离。它们可以在场景中其它对?br />之前或是之后渲染。它们用普通的ogre material,因此U理动画与其他纹理没有什么不同。它们可?br />被场景管理器打开或关闭,与相机的距离也可以设|?br />skyplane 是一个^面。用距离和法U定义它与相机的位置关系。可以弯Ԍ可以分多个段Q可对纹理进行多ơ^铺。skydome׃个^面组成,底部I。用改变纹理坐标的方式来达到外观上的曲率变化。有一个值用来调节,D低,曲率柔和,D高,陡峭。skybox 像skydome,但他不能“弯曜y(c)材质坐标。它可以使用立方材质。可使用g加速功能达到很好渲染效率?br />?/font>
使用光的限制Q单个通道通常最大支?个灯。用更多的灯,通过多通道?br />光与物体之间的距,军_光对物体实际的媄(jing)响。Ogre支持点光源,q等光,聚光灯?br />世界几何
当创建基于mesh的景物或兛_Q应该分成较?yu)的部分Q以便于裁减。Paging Scene Manager提供?jin)这L(fng)工具?br />I间分割Ҏ(gu)
Ogre是基于硬件加速渲染引擎,因此以最大化几何体batching的方式会(x)比基于实际多边Şq行I间分割
效果要好的多。Modern GPUs prefer to render a few large batches of geometry instead of
many small batches.
The more visible geometry you can render in a single batch, the better your application’s
performance is likely to be (within reason, of course; other classic issues such as fillrate and
overdraw can still take over if you just blindly blast polygons at the GPU, batched or not).

?rn)态几何用注?/font>Q?br />?rn)态几何在使用之间必须被徏立?br />使用相同材质的几何体被攑ֈ同一渲染操作?batch):different materials still require a separate batch.
努力的方向是Q最大化一个调用的三角形数Q最化调用的次数?br />不能Ud被包含在static geometry中的对象。只有一个世界{换应用到完整的static geometry对象?
比同栯模的movable geometry占用更多的内存?br />假如l中的Q何东西在视锥之内Q那么组中的所有对象都被渲染?/p>

 



清源游民 2007-03-09 14:25 发表评论
]]>
《Pro Ogre 3D Programming?MW记 ?W五?场景理 W一部分http://www.shnenglu.com/yuanyajie/archive/2007/03/08/19427.html清源游民清源游民Thu, 08 Mar 2007 07:08:00 GMThttp://www.shnenglu.com/yuanyajie/archive/2007/03/08/19427.htmlhttp://www.shnenglu.com/yuanyajie/comments/19427.htmlhttp://www.shnenglu.com/yuanyajie/archive/2007/03/08/19427.html#Feedback0http://www.shnenglu.com/yuanyajie/comments/commentRss/19427.htmlhttp://www.shnenglu.com/yuanyajie/services/trackbacks/19427.html Ogre 场景理

每个3D引擎都会(x)用scene graph 来组l它的可渲染对象。scene graph L?x)?f)?jin)更快地搜?ch)与查询做
优化Q提供给用户查找目标对象附近特定对象的功能,允许查找Q排序,剔除多边形,以实现更高效的渲染。偶?dng),scene graph也用于碰撞检。有Ӟ一个单独的scene graph可被用于E序中的所有子pȝQ包?br />x与物理?br />Ogre使用插g机制来实现场景管理功能。ScenceManager只是接口Q他可以有很多具体的实现。Ogre允许
在同一时刻同一场景中用多个Scene Manager,q样在不同的场景cd切换时带来好处?br />
场景理器的责Q
1Q创建,攄场景中的可移动对象,light,cameraQƈ可以在图形遍历中有效地访问它们?br />2Q加载,装配world geometry(它通常很大Q向四处延Q不可移动)(j)
3Q完成场景查询,例如可以回答q样的问题:(x)在世界空间的特定点画一个球体,它会(x)包含哪些对象Q?br />4Q剔除不可见对象Q把可见对象攑օ渲染队列q行渲染
5Q从当前可渲染的透视图中l织Q拣选各方向光照
6Q设|,渲染场景中的所有阴?br />7 讄Q渲染场景中的其他对象(如背景,天空盒)(j)
8 传递组l良好的内容到渲染系l进行渲?/p>

场景理器类?br />
以分析源码的方式讨论一下插件的加蝲机制与特定场景管理器是如何进行运用的?br />上一章提C(jin)以手工的方式初始化ogre,包括手工加蝲场景理器:(x)
root->loadPlugin("Plugin_OctreeSceneManager");
其实所谓的自动方式下,Root:Root()中也?x)间接调用到l(f)oadPlugin()Ҏ(gu)Q这已在前面的笔?br />(配置文gPlugins.cfg )中提到过。既然特定管理器以插件的形式Qdll文gQ给出,下面先看如何
加蝲dll. q入源码Q标可明执行顺序?br />void Root::loadPlugin(const String& pluginName)
 {
 // Load plugin library
    DynLib* lib = DynLibManager::getSingleton().load( pluginName ); //(1)
  // Store for later unload
 mPluginLibs.push_back(lib); //(4)
 // Call startup function
    DLL_START_PLUGIN pFunc = (DLL_START_PLUGIN)lib->getSymbol("dllStartPlugin"); //(5)
 // This must call installPlugin
 pFunc(); //(6)

 }
DynLib* DynLibManager::load( const String& filename)  //(2)
{
        DynLib* pLib = new DynLib(filename);
 pLib->load();       
        mLibList[filename] = pLib;
 return pLib;
}
void DynLib::load() //(3)
{
m_hInst = (DYNLIB_HANDLE)DYNLIB_LOAD( name.c_str() );
}
W?font color="#ff0000">(3)
中的宏定义如下:(x)
#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
#    define DYNLIB_HANDLE hInstance
#    define DYNLIB_LOAD( a ) LoadLibrary( a )
到此QDLL被加载到内存,W?font color="#ff0000">(4)
步,mPluginLibs是个STL容器Q它存放动态库指针?br />W?font color="#ff0000">(5)
步,q入源码可以看到
void* DynLib::getSymbol( const String& strName ) const throw()
    {
        return (void*)DYNLIB_GETSYM( m_hInst, strName.c_str() );
    }
其中宏定义:(x)define DYNLIB_GETSYM( a, b ) GetProcAddress( a, b )Q很昄Q它取得一个名?br />dllStartPlugin的函数指针:(x)不防再看看宏定义Q?typedef void (*DLL_START_PLUGIN)(void);
说明DLL_START_PLUGIN为参Cؓ(f)I,q回gؓ(f)I的函数指针?br />每个注册到ogre的dll都实C(jin)q个U定函数。对于我们当前讨论的场景理器Plugin_OctreeSceneManager
来讲Q我们可以找到其相应的定?它在W?font color="#ff0000">(6)
步中执行

OctreePlugin* octreePlugin;
extern "C" void _OgreOctreePluginExport dllStartPlugin( void )
{
    // Create new scene manager
    octreePlugin = new OctreePlugin(); //(6-1)

    // Register
    Root::getSingleton().installPlugin(octreePlugin); //(6-2)

}
E序执行?font color="#ff0000">(6-1)步,new 来一个OctreePlugin,我们看一下它的定义:(x)
class OctreePlugin : public Plugin
{
 public:
  OctreePlugin();
  const String& getName() const;
  void install();
   void initialise();
   void shutdown();
   void uninstall();
 protected:
  OctreeSceneManagerFactory* mOctreeSMFactory;
  TerrainSceneManagerFactory* mTerrainSMFactory;
  TerrainPageSourceListenerManager* mTerrainPSListenerManager;

};

我们?x)注意到它包含两个工厂类指?OctreeSceneManagerFactory,TerrainSceneManagerFactory
他们是用来生特定ScenManager的,E后讨论。先?font color="#ff0000">(6-2)步:(x)
void Root::installPlugin(Plugin* plugin)
{
 mPlugins.push_back(plugin);  //(6-2-1)
 plugin->install();             //(6-2-2)
 // if rendersystem is already initialised, call rendersystem init too
 if (mIsInitialised)
 {
 plugin->initialise();         //(6-2-3)
 }
}
//(6-2-1)步把插g攑ֈ容器中。看?font color="#ff0000">(6-2-2)做了(jin)什么:(x)
void OctreePlugin::install()
 {
  // Create objects
  mOctreeSMFactory = new OctreeSceneManagerFactory();
  mTerrainSMFactory = new TerrainSceneManagerFactory();
  mTerrainPSListenerManager = new TerrainPageSourceListenerManager();

 }
呵,刚才q说两个工厂cL针,现在把两个工厂徏hQ以后可以用来生产东西了(jin)?br />l箋看看(6-2-3):
void OctreePlugin::initialise()
 {
  // Register
  Root::getSingleton().addSceneManagerFactory(mOctreeSMFactory);
  Root::getSingleton().addSceneManagerFactory(mTerrainSMFactory);
 }
哦,把这两个工厂注册到Root中,让Root可以使用它们。啊q句话有炚w题,Root只是间接的用刎ͼ
直接雇主?SceneManagerEnumerator* mSceneManagerEnum;它被包含在Root中。于是我们可以看?br />void Root::addSceneManagerFactory(SceneManagerFactory* fact) //(6-2-3-1)
 {
  mSceneManagerEnum->addFactory(fact);
 }

工厂已经有了(jin)Q我们如何利用这个工厂生产出我们惛_的东?SceneManager)呢?
回忆上一章的手工初始化过E中Q我们一般用以下语句来创建SceneManager:
  SceneManager *sceneMgr = root->createSceneManager(ST_GENERIC); //(A)
也可以这L(fng)
  sceneMgr = ogre->createSceneManager("OctreeSceneManager"); //(B)
每个工厂c都用一个字W串表示其类型。上面说的两个工厂分别用的字符串ؓ(f)Q“TerrainSceneManager”,"OctreeSceneManager"
(A)语句肯定?x)调用工厂类的方法来产生实际的SceneManager,下面看源码验证一下:(x)
SceneManager* Root::createSceneManager(const String& typeName,
  const String& instanceName)
 {
  return mSceneManagerEnum->createSceneManager(typeName, instanceName);
 }
l箋挖:(x)
SceneManager* SceneManagerEnumerator::createSceneManager(
  const String& typeName, const String& instanceName)
 {
  SceneManager* inst = 0;
  for(Factories::iterator i = mFactories.begin(); i != mFactories.end(); ++i)
  {
   if ((*i)->getMetaData().typeName == typeName)
   {
    if (instanceName.empty())
    {
     // generate a name
     StringUtil::StrStreamType s;
     s << "SceneManagerInstance" << ++mInstanceCreateCount;
     inst = (*i)->createInstance(s.str());
    }
    else
    {
     inst = (*i)->createInstance(instanceName);
    }
    break;
   }
  }
 }
上述代码很简单:(x)因ؓ(f)执行(6-2-3-1)已经q实际工厂类实例q行?jin)注册。于是遍历每个工厂实例,
扑ֈcd相符的。找C后,如果没有传场景管理器实例的名字,pv个名字。然后用q个名字
生Z个实例来。CreateInstance没干什么,new 呗?br />SceneManager* OctreeSceneManagerFactory::createInstance(
 const String& instanceName)
{
 return new OctreeSceneManager(instanceName);
}
是q样。OctreeSceneManager and TerrainSceneManager 的功能都是由一个DLL提供的。它们的关系是:(x)class _OgreOctreePluginExport TerrainSceneManager : public OctreeSceneManagerQ按照一般的cdp逻辑Q?br />我们知道zcM般功能都比父cd大,父类应用于一般场景,子类针对特定场景。这个逻辑在这里是对的。本来是写读书笔讎ͼ跑题?jin),打住?/p>

 

 

 

 

 

 

 

 

 

 

 

 



清源游民 2007-03-08 15:08 发表评论
]]>《Pro Ogre 3D Programming?MW记 ?W四?开始用OGREhttp://www.shnenglu.com/yuanyajie/archive/2007/03/07/19361.html清源游民清源游民Wed, 07 Mar 2007 06:14:00 GMThttp://www.shnenglu.com/yuanyajie/archive/2007/03/07/19361.htmlhttp://www.shnenglu.com/yuanyajie/comments/19361.htmlhttp://www.shnenglu.com/yuanyajie/archive/2007/03/07/19361.html#Feedback0http://www.shnenglu.com/yuanyajie/comments/commentRss/19361.htmlhttp://www.shnenglu.com/yuanyajie/services/trackbacks/19361.html清源游民 gameogre@gmail.com
日志pȝQ?br />日志记录?jin)基于ogre的程序每ơ运行时的所有事Ӟpȝ初始化,状态,性能信息。输出的内容被放在磁盘文件上Q文件缺省名是ogre.log。也可以手动昄创徏日志pȝ,q需要在创徏Root对象之前实施?br />// create an instance of LogManager prior to using LogManager::getSingleton()
LogManager* logMgr = new LogManager;
Log *log = LogManager::getSingleton().createLog("mylog.log", true, true, false);
// third param is not used since we already created a log in the previous step
Root *root = new Root("", "");
可以用Ogre LogManager注册一个Log Listener, 以Q何方式重定向log data。可以用q种方式来屏蔽Q何日志信息。然后还一个更单的Ҏ(gu)辑ֈ上述目的Q在实例化Root之前Q当实例化一个LogManager后,不调用createLog()Ҏ(gu)?br />以下是实现日志信息截的代码片断Q?br />class MyLogListener : public LogListener
{
public:
void write (const String& name, const String& message,
LogMessageLevel level, bool maskDebug)
{
// redirect log output here as needed
};
MyLogListener *myListener = new MyLogListener;
// this is the same as calling LogManager::getSingletonPtr() after the
// LogManager has first been instanced; the same pointer value is returned
LogManager *logMgr = new LogManager;
LogMgr->addListener(myListener);
logMgr->createLog("mylog.log", true, false, true);
logMgr->setLogDetail(LL_NORMAL);
Root *root = new Root("", "", "mylog.log");
Ogre手动初始?/font>
int main(int argc, char *argv[])
{

 // tell Root not to load from any plugins or settings file
 Root *root = new Root("", "");

 // Load feature plugins. Scene managers will register
 // themselves for all scene types they support
 root->loadPlugin("Plugin_CgProgramManager");
 root->loadPlugin("Plugin_OctreeSceneManager");

 // load rendersystem plugin(s). The order is important in that GL
 // should be available on on platforms, while D3D9 would be available
 // only on Windows -- the try/catch will intercept the exception in this
 // case where D3D9 is not available and continue gracefully
.
 try {
  root->loadPlugin("RenderSystem_GL");
  root->loadPlugin("RenderSystem_Direct3D9");
 }
 catch (...) {}

 try {
  // We'll simulate the selection of a rendersystem on an arbirtary basis; normally
  // you would have your own code to present the user with options and select the
  // rendersystem on that basis. Since a GUI is beyond the scope of this example, we'll
  // just assume the user selected OpenGL.
  RenderSystemList *rList = root->getAvailableRenderers();
  RenderSystemList::iterator it = rList->begin();
  RenderSystem *rSys = 0;

  while (it != rList->end()) {
   
   rSys = *(it++);
   if (rSys->getName().find("OpenGL")) {
   
    root->setRenderSystem(rSys);
    break;
   }
  }

  // check to see if a render system was selected; if we reached the end of the list
  // without selecting a render system then none was found
.
  if (rSys == 0) {
   delete root;
   std::cerr << "No RenderSystem available, exiting..." << std::endl;
   return -1;
  }

  // We can initialize Root here if we want. "false" tells Root NOT to create
  // a render window for us
  root->initialise(false);

  // set up the render window with all default params
  RenderWindow *window = rSys->createRenderWindow(
   "Manual Ogre Window", // window title
   800,     // window width, in pixels
   600,     // window height, in pixels
   false,     // fullscreen or not
   0);      // use defaults for all other values

  // from here you can set up your camera and viewports as normal
  // get a pointer to the default base scene manager -- sufficient for our purposes

  SceneManager *sceneMgr = root->createSceneManager(ST_GENERIC);

  // create a single camera, and a viewport that takes up the whole window (default behavior)
  Camera *camera = sceneMgr->createCamera("MainCam");
  Viewport *vp = window->addViewport(camera);
  vp->setDimensions(0.0f, 0.0f, 1.0f, 1.0f);
  camera->setAspectRatio((float)vp->getActualWidth() / (float) vp->getActualHeight());
  camera->setFarClipDistance(1000.0f);
  camera->setNearClipDistance(5.0f);

  // Run the manual render loop. Since we are not using a frame listener in this case, we
  // will count to 15 seconds and then instead of exiting, we'll change the render window settings
  // and re-initialize it.
  bool renderLoop = true;
  Timer *timer = Ogre::PlatformManager::getSingleton().createTimer();
  timer->reset();
  float s = 0.0f;

  while (renderLoop && window->isActive()) {

   renderLoop = root->renderOneFrame();

   // accumulate total elapsed time
   s += (float)timer->getMilliseconds() / 1000.0f;

   // if greater than 15 seconds, break out of the loop
   if (s >= 15.0f)
    renderLoop = false;

   // we must call the windowing system's message pump each frame to
   // allow Ogre to process messages
   //PlatformManager::getSingleton().messagePump();
  }
 }
 catch (Exception &e) {
  std::cerr << e.getFullDescription() << std::endl;
 }

 delete root;
 return 0;
}

视口
通过视口上的一点与相机的原点生世界空间中的一条光U?br />// x and y are in "normalized" (0.0 to 1.0) screen coordinates
Ray getCameraToViewportRay(Real x, Real y) const;

视口,创徏多个视口Q通过Z序(高在上)(j) 定覆盖效果Q每个视口可以有不同的背景?br />// assume window is a valid pointer to an existing render window, and
// a valid pointer to an existing camera instance
Viewport *vpTop, *vpBottom;
// second parameter is z-order, remaining params are position and size,
vpBottom = window->addViewport(camera, 0);
// create a smaller viewport on top, in the center, 25% of main vp size
vpTop = window->addViewport(camera, 1,
0.375f, 0.375f,
0.25, 0.25);
// set the background of the top window to blue (the default is black
// need to set the bottom window explicitly)
vpTop->setBackgroundColour(ColourValue(0.0f, 0.0f, 1.0f));
// an alternate way to set the color is to use the manifest constant
// vpTop->setBackgroundColour(ColourValue::Blue);

在多视口情况下,overlay~省在每个视口中渲染。可以关掉。Skybox, Shadow也是如此?br />vpTop->setOverlaysEnabled(false);
vpTop->setSkiesEnabled(false);
vpTop->setShadowsEnabled(true);



清源游民 2007-03-07 14:14 发表评论
]]>
《Pro Ogre 3D Programming?MW记 ?W三?设计概要 W二部分http://www.shnenglu.com/yuanyajie/archive/2007/03/06/19280.html清源游民清源游民Tue, 06 Mar 2007 03:18:00 GMThttp://www.shnenglu.com/yuanyajie/archive/2007/03/06/19280.htmlhttp://www.shnenglu.com/yuanyajie/comments/19280.htmlhttp://www.shnenglu.com/yuanyajie/archive/2007/03/06/19280.html#Feedback0http://www.shnenglu.com/yuanyajie/comments/commentRss/19280.htmlhttp://www.shnenglu.com/yuanyajie/services/trackbacks/19280.html清源游民  mailto:gameogre@gmail.com

子系l概?/font>
Root Object
Root 是程序进入点Q它是一个façade c,提供?jin)访问子pȝ的方便的Ҏ(gu)。通过它可以开启ogre,也可能通过它关闭ogre?/font>
资源理
在渲染场景中使用的Q何东襉K被视源。所有的资源最l都被一个单个类对象理QResourceGroupManagerQ它负责定位资源Q初始化资源Q不真正装蝲Q?
在缺省情况下QOgre认识以下cd的资源:(x)
Mesh: 二进制格式,它也可包?morph 和 pose 动画数据
Skeleton:  可以被Mesh文g引用Q也可单独用,包含骨骼层次l构信息Q关键信息?
Material:  定义?jin)渲染一l几何体时的渲染状态,可以被mesh文g引用Q也可以手工使用?
GPU E序Q?program 支持HLSL, GLSL,Cg 与低U的 .asm Q这些文件会(x)在Q?material之间被剖析,因此在一个material之中被引用的GpuE序L有效的?
Compositor: 与Material很相|扩展名不?
Font: 用字体定义文件去定义在overlay中用的字体Q扩展名 .fontdef
每种资源都有自己的特定的ResourceManager,如,MaterialManager, FontManager。ResourceGroupManager负责通过名字查找资源Q它不负责实际的内存理d。这些Q务是由ResourceManager基类来完成的。ResourceGroupManager允许通过l名来加载,释放整组资源?
默认情况下,Ogre认ؓ(f)资源以一个磁盘文件的形式存在。然而,有些cd的资源可以手工管理,当前只有mesh, font 有手工资源加载的实现。其他类型的可以自己实现QOgre已经在它的框架中保留?jin)这U功能?
场景理
所有的具体实现都从SceneManagerz而来Q程序中怸此类交互。,可以有多个活动的SceneManager。它们用来管理SceneNode, SceneNode可以在场景中被移动。SceneNode也可以有层次l构?
场景实际内容l常也Entity实例的Ş式存在。它们被Scene Manager创徏QMovableObject实现。一个有效的Entity可以被attach 到SceneNode上面。Entity l常从磁盘上?mesh文g加蝲。然后也可以手工创徏内容对象Q如plane.当Entity被attach到SceneNode上时Q进行移动等操作是针对SceneNode的,而不是内容对象?
也可以把非内容对?灯,相机{?attach 到SceneNode上面?
渲染pȝ与渲染对?
RenderSystem 是Ogre与底层API的接? RenderTarget 是 渲染H口与渲染纹理的概括?
Ogre 扶持多个渲染H口。窗口可以通过Root对象自动、手动地创徏Q也可能通过RenderSystem创徏?

Ogre 理?/font>
Manager 是一个可以访问相关类型对象,理其生命周期的cR例如,ArchiveManager理Archive实现的创Z注册Q访问注册的Archive实现实例。Root对象创徏的副作用之一是初始化所有ogre Manager对象?
LogManager : 发送日志信息到输出?
ControllerManager: 理 controllers,后者是Z各种输入Qؓ(f)别的cM生状态g供用?
DynLibManager:  理动态链接库
PlatformManager: 把抽象的讉K转换成底层硬件与操作pȝ相关的细节?
CompositorManager: 讉K理 Compoitor framework.
ArchiveManager:  文gpȝ目录QZIP文g
ParticleSystemManager: _子pȝQ发器Q媄(jing)响器QaffectorQ?
SkeletonManager:  允许同名的skeleton对象重用
MeshManager :  理mesh, 允许同名mesh重用
HighLevelGpuProgramManager: l护Q加载,~译高GPUE序
GpuProgramManager: l护低GPUE序Q把~译的高UGPUE序转ؓ(f)汇编
ExternalTextureSourceManager:  理外部U理源类实例Q如视频?
FontManager:  理Overlay中用的字体
ResourceGroupManager: 加蝲Q生命期理Q所有注册的E序资源
OverlayManager: 加蝲Q创建,2D Overlay cd?
HardwareBufferManager: 理׃ng~冲Q 点~冲Q像素缓Ԍ索引~冲{?
TextureManager: 理U理
ȝQ?q一章无意覆盖关于Ogre的所有东西,只说明了(jin)一些普遍需要的Ogre对象Q和一些不太常打交道的ogre 对象?

 



清源游民 2007-03-06 11:18 发表评论
]]>
《Pro Ogre 3D Programming?MW记 ?W三?设计概要  W一部分http://www.shnenglu.com/yuanyajie/archive/2007/03/05/19264.html清源游民清源游民Mon, 05 Mar 2007 15:22:00 GMThttp://www.shnenglu.com/yuanyajie/archive/2007/03/05/19264.htmlhttp://www.shnenglu.com/yuanyajie/comments/19264.htmlhttp://www.shnenglu.com/yuanyajie/archive/2007/03/05/19264.html#Feedback0http://www.shnenglu.com/yuanyajie/comments/commentRss/19264.htmlhttp://www.shnenglu.com/yuanyajie/services/trackbacks/19264.html清源游民  gameogre@gmail.com

设计哲学
传统上,使用 Direct3D ?OpenGL 来渲染场景和对象Q需要遵循一pdE序处理的步骤Q调?API 讄渲染状态,调用 API 发送几何体信息Q通知 API ?GPU L染几何体。对每个几何体都是如此返复,直到当前帧被完全渲染。在一下同样如此?
使用面向对象的方法来渲染几何体简化了(jin)上述q程。通过处理l成场景的各U对象而不是原始的几何体。这些对象包括:(x)可运动对象,?rn)态对象(构成世界布局Q,光,相机{。那?3D API 则不再需要:(x)只是把这些对象放到场景中Q?Ogre 负责处理琐碎的细节。而且Q可以用更加直观的方法来操纵对象Q而不是用矩c(din)ȝ说来Q我们可以处理对象,它的属性,调用更直观的Ҏ(gu)Q而不再用点列表Q三角Ş列表Q旋转矩늭手段来管理了(jin)?
Ogre 提供?jin)面向对象的框架Q包括了(jin)对象模型中的渲染处理的所有部分。渲染系l抽象了(jin)底层 3D   API 的复杂性。场景图形功能被抽象成单独的接口Q这样一来,各种不同的场景图形管理算法可以即插即用。在场景中的所有可渲染对象Q无论是可移动的Q还是静(rn)态的Q都被一l公共接口抽象,q些接口提供?jin)实际的渲染操作Q例?techniques 和它所包含?passes Q?.
设计亮点
一“设计模式”的合理使用
Ogre 中大量用了(jin)l典的设计模式。例如,使用?Observer ”模式来通知应用E序特定事g的发生,?demo ?FrameListener 的用得程序可以接收  frame-started and frame-ended  事g通知。?Singleton ”模式强制实现类的单实例。?Iterator ”模式用来遍历数据结构的内容?
“Visitor?模式用来在对象上执行某种操作?Façade 模式用来抽象底层Q提供一个单一cL口?
?Factory? 用来创徏实例?
?场景图与内容分离
传统上,场景图与内容同处于同一l承体系下。它要求从场景结点子cd内容c,也就是说内容cM场景l点l承。实践证明这U设计非常糟p?首先Q?Ogre 操作场景囑Ş在接口层 , 它不假设特定囑Ş法的实现。实际上Q?Ogre 操作场景囑Ş仅仅通过它的{֐Q方法)(j)Q完全忽略底层的法实现?
W二Q?Ogre 的图形接口只兛_(j)囑Şl构Q不包含M内在的访问或理功能。后者被推到 Renderable 中,场景中的所有几何( movable or otherwise Q都从它l承。这?Renderalbes 的渲染属性(材质Q?materials Q被包含?Entity 对象中去?Entity 可以包含一个或多个 SubEntity 。这些子实体是实际的可渲染对象。下面是各对象的一个关pdQ?br />
通过q样的设计,场景理与场景内容充分解藕。过于场景图来说Q通过 Movable Object 几何Q渲染属性变得有效。注意到 Movable 不是?Scene Node l承而来的?Movable Object ?attached ?Scene Node 上去?. 当扩展,改变Q重构场景图形实现时对场景内容对象的设计与实现没有Q何媄(jing)响?
从另一斚w来说Q由于场景图形不需要知道内容类的Q何变化。只要实C些简单的场景囑Ş“确实“需要知道的一些接口。因此,我们可以L?attached 一些自定义的东西到场景l点上,比如声音信息{。(听说有个 OgreAL, 它包装了(jin) OepnAL Q猜惛_是这样做的吧Q?
三 插gl构
OGRe 被设计成可扩展的?Ogre 通过“基于契U的设计 ?来完成?Ogre 可以被设计成一l共同工作的lgQ它们通过一些已知接口来怺交流。这带来极大的灵zL,某种功能的不同实C改变非常Ҏ(gu)。D例来Ԍ׃ ogre 处理场景囑օ理是在接口U,用户可以随意的选择特定法的实现。而且Q当用户创徏一个新的实玎ͼ可以很容易的以插件的形式提供l?Ogre,  实现时只要遵?ogre 定义的一些接?. File archives , render systems 也以插g的Ş式提供,_子pȝ也是?插g形式的吸引h之处是,Z(jin)加入插gQ不需要重新编?Ogre ?. 插g可以在运行时加蝲?
四 g加速的渲染支持
Ogre 被设计成只支持硬件加速图形渲染,直接软g渲染不是它的选项?Ogre 使用完整的硬件加速能力,包括可编E?shaders ?Unreal 引擎能做什么, Ogre p做什么!Q( ^_^, 作者说的)(j)。引擎直接支持的全局光照 (precomputed Radiance Transfer {?) q没有实玎ͼ因ؓ(f)q些多数用于非实时计场合,因此不是什么问?.Ogre 现在和未来将可能只?Direct3D ?OpenGL ?
五,灉|的渲染队列结?
Ogre  采取一个新Ҏ(gu)来解军_景中各部分渲染次序问题。粗略地看,标准q程通常如下工作Q渲染地形或世界几何Q渲染可Ud对象Q渲染各U特效,渲染 OverLay, 渲染背景或天I盒 . 然而,正如典型的实CP像集成电(sh)路处理模块)(j)Q这个过E很难改?. 在许多例子中Q?很难改变渲染的顺序,D难以l护与不灉|的设计的?渲染队列的概忉|Q?Ogre 以一ơ一个的方式渲染一l可以排序的队列Q也已同L(fng)方式渲染每个队列中的内容。也是队列本n有优先Q同样队列中的对象也有自q优先U?br />
上图中,队列由后向前渲染Q?Background à OveryLay Q?, 在最前的队列中从左至x染?
在这U机制下重新l织渲染序非常单,只要重新分配优先U就可以?jin)。队列可以定Ӟ队列中的对象也可以。整个队列可以?turned on?and “turned off?Q队列中的对象也可以?每个队列提供?jin)事仉知Q如 prerender and postrender Q?, 应用E序有机?x)改变队列中的对象渲染。这个机制对于开发和l护复杂E序都相当有用?
六 健壮的材质系l?
Ogre 的材质由一个或多个 technique l成Q?technique ?pass 的集合?Pass 是材质别的渲染单元Q导致一ơ图形硬件的 ”draw?调用。可以有多个 pass, 每个 pass 是一ơ全新的渲染操作Q包括硬件渲染状态改变?
最吸引人的Ҏ(gu)是 automatic fallback ?Ogre 自上向下圎ͼ technique 列出的顺序)(j)L最适当?technique.Ogre q能力地重新组l?technique 中的 pass, 以迎合最的技术需求。例如,当前g只支持单U理单元Q而你E序中最复杂度的技术,需要至两个纹理单元,那么 ogre ?x)把一?pass 拆分成两个,通过混合两个单元U理的方式达到同L(fng)效果?
Ogre 材质pȝ也支?schemes 的概c(din)?Schemes 可以理解作ؓ(f)普遍的“非帔RQ高Q中Q低“不同等U的囑Ş讄。在q种情况下,可以定义四个 schemes , qؓ(f)每一个分?techniques( 复数 ) 。这样就可以 ogre 的所?technique fallback 查找那些属于特定 schemes ?techniques 。得材质管理更Ҏ(gu)炏V?
用材质脚本完成的事,同样也可以用代码的方式完成。代码的方式也支?schemes ?technique fallback ?
七 本地优化的几何与骨骼格式
Ogre 使用它单独的 mesh 与骨骼格式。不能直接加载第三Y件包生成的数据。社Z有{换第三文件格式的工具Q但它不?Ogre 库的一部分?Ogre 使用自己的格式是Z(jin)效率?
八  多种cd的动?
Ogre 支持三种cd的动画:(x)骨骼动画Q变形动画, Pose 动画
骨骼动画Q把点l定到骨g。对象的每个点可以受到四个独立的骨头媄(jing)响。每U媄(jing)响被赋于一个用数量表示的权重。骨骼动d在关键上执行前向运动学模式?Ogre 当前不支持逆向动画 .
Morph 动画是一U顶点动L术,他储存关键上的l对的顶点位|信息,在运行时在两个关键之间插倹{这?Pose 动画不同Q?Pose 动画存储的是偏移数据而不是绝对位|?Pose 动画可以混合以Ş成复杂动甅R?Morph 动画?Pose 动画功能有限Q因Z存储的是l对|因此难以与其?Morph 动画混合?Morph 动画?Pose 动画之间也不能؜?.
所有的动画cd都可以与骨骼动画混合使用 .
所有动ȝ型都可用Y件执行或是利?GPU g执行?
Ogre 动画是基于关键的,内插方式有线性与立方hq两U选择?
?ji)  Compositor Postprocessing ( 怎么译 ~?)
用来在一个视口中创徏二维的,全屏的后处理效果 . 例如模糊Q黑白电(sh)视,{等效果Q?Ogre 有个很好的示例)(j) Compositor 也有cM于材质系l的 technique ?pass 的概c(din)在视口最l被输出前,多个计算与渲染可被执行。像材质?fallbacks,Compositor framework 提供?fallback 处理Q例如,当输出的像素格式无效时。理?compositor 最Ҏ(gu)的方法是把它当成片段E序Q像素渲染)(j)的扩展。不同之处在于:(x)传统的图形管U每个材?pass 只充怸个片D늨序,?Compositor framework 则可以像打乒乓球一h来回回好多次?Compositor 脚本扫行?ViewPort 上,因此它可以面向Q何的 render target, 可以是可渲染U理Q主Q副渲染H口。与材质pȝ一P它除?jin)利用脚本实玎ͼ也可以用代码实现?
十 ?扩展资源理
?ogre 中,资源定义为:(x)渲染几何体到可渲染目标上用到M东西。很明显包括Q?mesh,   skeleton, material , overlay script , font , Compositor script, GPU program , texture ?
每种资源都有自己?manager, 它主要负责控制特定类型资源在内存中的占用数量。换句话_(d)它控制着资源实例的生命期。不q仅仅在一点上控制Q首先,它只能储存同样多的实例,取决于这U类型的资源所分配的内存。第二, ogre 不会(x)删除正被其他部分引用的实例?
资源本n实际负责加蝲自己。这是资源系l的一个设计特性:(x)手工资源加蝲。手工加载意味着资源加蝲Q处理,是利用一个方法调用实现的而不是从文gpȝ中隐式地加蝲?
资源?ogre 中有四种状态:(x)未定义, 声明Q未加蝲Q 加蝲?
未定义,说明 ogre 对它一无所知?
声明Q它已经在档案中q行?jin)?ch)引?
未加载,已经q行?jin)初始化Q脚本,已经被解析过?jin)?j)Q引用已l被创徏
加蝲Q已l在它的资源 manager 所理的内存池中占用空间了(jin)?
可以用“组”来理理各类资源。组中资源之间的关系是Q意的Q完全取决于E序员:(x)创徏 GUI 的所有资源可以分Zl,?A 字母开头的资源也可以分Zl,{等。有?~省的组QGeneral
?ogre 中查找某个资源实例时Q不?x)考虑Q资源所在的l。有Ӟ我们可以资源组命当成某U的 ?命名I间来用“?
Archives 中的资源是非手动加蝲的?Archives 是普通文件容器的单抽象。它包括文gpȝ?ZIP 档案。用户可以实现自定义cd?archive ?



清源游民 2007-03-05 23:22 发表评论
]]>
ORGE(Eihort)学习(fn)W记之GUI Demo W三部分 CEGUI初步http://www.shnenglu.com/yuanyajie/archive/2007/03/05/19227.html清源游民清源游民Mon, 05 Mar 2007 04:43:00 GMThttp://www.shnenglu.com/yuanyajie/archive/2007/03/05/19227.htmlhttp://www.shnenglu.com/yuanyajie/comments/19227.htmlhttp://www.shnenglu.com/yuanyajie/archive/2007/03/05/19227.html#Feedback0http://www.shnenglu.com/yuanyajie/comments/commentRss/19227.htmlhttp://www.shnenglu.com/yuanyajie/services/trackbacks/19227.html清源游民  gameogre@gmail.com

在以前的W记中已l对 CEGUI 的用做?jin)简单的介绍Q这里ؓ(f)?jin)完整性还是把?C Q?P 一下:(x)
使用 cegui 来制作界?, 不论在何U^C , 有基本的三大步骤要做 :
1, 创徏一?CEGUI::Render 实例
2, 创徏 CEGUI::System 对象
3, 调用各种Ҏ(gu)来渲染用L(fng)?
W一?, 在我使用?ogre 环境下用以下代码来创徏 CEGUI::Render 实例
Ogre3D
CEGUI::OgreCEGUIRenderer* myRenderer =
       new CEGUI::OgreCEGUIRenderer(myRenderWindow);
W二步相当简?, 可?new CEGUI::System(myRenderer);
W三步,基本上来Ԍ大部分^CQ如 direct3D, OpenGL, 我们在渲染@环的N调用 CEGUI::System::renderGUI 来开始界面的渲染。如果我们?ogre3d 引擎Q这一步不需?我们昄的执行?创徏 CEGUI H口Q我们可以用两UŞ式,一?C Q+代码Q二是编?XML layout 文g?
CEGUI 本n侦测用户输入Q这些不?CEGUI 的责任,而是E序的员的责仅R当有用户外部输入时Q我 们可以选择这些消息告?CEGUI Q这?CEGUI 才会(x)响应?
CEGUI 使用回调机制来进行消息处理。可以ؓ(f)某个H体的特定事件注册一个函敎ͼ当窗体事件发生时Q?CEGUI ?x)自动调用所注册的函数?
DEMO 中需要注意的?Render To Texture 的实现?
先创建在 ogre 中的 RTT:
RenderTexture * rttTex = mRoot->getRenderSystem()->createRenderTexture( "RttTex", 512, 512, TEX_
TYPE_2D , PF_R8G8B8 );
再{换成CEGUI可识别的:
// Retrieve CEGUI texture for the RTT
        CEGUI::Texture* rttTexture = mGUIRenderer->createTexture((CEGUI::utf8*)"RttTex");
Ҏ(gu)q个Texture生成?jin)一个ImageSet;
在ImageSet中定义了(jin)一个ImageQ名为RttImageQ?其大与上边的Texutre同样大小?
当在H口中增加一个static ImageӞ把其image属性设??RttImage ?卛_?



清源游民 2007-03-05 12:43 发表评论
]]>
Ogre 学习(fn)W记之 QGQԌI轨迹动画http://www.shnenglu.com/yuanyajie/archive/2007/03/02/19132.html清源游民清源游民Fri, 02 Mar 2007 09:36:00 GMThttp://www.shnenglu.com/yuanyajie/archive/2007/03/02/19132.htmlhttp://www.shnenglu.com/yuanyajie/comments/19132.htmlhttp://www.shnenglu.com/yuanyajie/archive/2007/03/02/19132.html#Feedback0http://www.shnenglu.com/yuanyajie/comments/commentRss/19132.htmlhttp://www.shnenglu.com/yuanyajie/services/trackbacks/19132.html  OGRE 中创建和实施轨迹动画的步骤大致如下:(x)

  1. 在主E序cȝ Application :: createScene ( ) 场景创徏Ҏ(gu)中进行以下工作:(x)

  Animation * Ogre::SceneManager::createAnimation (
   const String & name, // 动画名称
   Real length // 动画长度(U?
   ) [virtual]

  (2) 使用 createTrack Ҏ(gu)为动dq动画:(x)
   AnimationTrack * Ogre::Animation::createTrack (
   unsigned short handle, // 分配l轨q动ȝ索引句柄Q用于以后可能的调用
   Node * node // 指定要沿着q条轨迹q动的节?br />   )

  (3) 使用 createKeyFrame Ҏ(gu)q动dZpd关键帧:(x)
   KeyFrame * Ogre::AnimationTrack::createKeyFrame (
   Real timePos // 旉位置
   )
  
   (4) 使用 setTranslate ?setScale ?setRotation 三个Ҏ(gu)来设|关键每个旉位置上节点的位置、羃放、旋转属性:(x)
   void Ogre::KeyFrame::setTranslate ( const Vector3 & trans )
   void Ogre::KeyFrame::setScale ( const Vector3 & scale )
   void Ogre::KeyFrame::setRotation ( const Quaternion & rot )
  
   (5) 使用 createAnimationState Ҏ(gu)创徏一个动ȝ态来q踪q个轨迹Q?br />   AnimationState * Ogre::SceneManager::createAnimationState ( const String & animName ) [virtual]
  
   (6) 使用 setEnabled Ҏ(gu)来激zdȝ态:(x)
   void Ogre::AnimationState::setEnabled ( bool enabled )

  2. 在接收器cȝ Listener::frameStarted(const FrameEvent& evt) Ҏ(gu)中刷新动ȝ态:(x)
   void Ogre::AnimationState::addTime ( Real offset )



清源游民 2007-03-02 17:36 发表评论
]]>
OGRE学习(fn)W记?配置文g Resources.cfghttp://www.shnenglu.com/yuanyajie/archive/2007/03/02/19131.html清源游民清源游民Fri, 02 Mar 2007 09:33:00 GMThttp://www.shnenglu.com/yuanyajie/archive/2007/03/02/19131.htmlhttp://www.shnenglu.com/yuanyajie/comments/19131.htmlhttp://www.shnenglu.com/yuanyajie/archive/2007/03/02/19131.html#Feedback0http://www.shnenglu.com/yuanyajie/comments/commentRss/19131.htmlhttp://www.shnenglu.com/yuanyajie/services/trackbacks/19131.html resources.cfg

资源?OGRE 应用E序渲染q程中需要用到的U理囄、网格模型文件、骨骼动L件的ȝ?OGRE 应用E序需要在渲染前将q些资源载入内存Q那需要让 OGRE 引擎知道资源的搜索\径。特别的?OGRE 引擎支持直接d Zip 压羃文g中的内容Q所?Zip 文g也必被当成搜烦(ch)路径来指定。在 OGRE 引擎中具有虚拟文件系l的概念Q引擎内部蝲入资源文仉是通过虚拟文gpȝ来进行的Q引擎ƈ不关?j)资源文件来自一个普通文件夹?zip 压羃包甚至网l映。真正的文gd功能是通过插g来实现的Q所以大家在q行环境里可以发?Plugin_FileSystem.dll Q早期的 OGRE 版本q有 Plugin_Zip.dll Q在新的版本里被实现到引擎内部了(jin)。目前还没有实现对网l文件的直接讉K?

Z(jin)方便 OGRE E序在运行期间查找资源,使用?jin)资源配|文?resources.cfg 。这是一个文本文Ӟ我们可以?OGRE E序的可执行文g的同一文g夹下扑ֈ它。它的内容就是对资源路径的指定,CZ如下Q?

Zip=../../../Media/dragon.zip

Zip=../../../Media/knot.zip

Zip=../../../Media/skybox.zip

FileSystem=../../../Media/

如果资源在一?Zip 文g中,写 Zip=****** Q如果资源在一个普通的盘文g多w写 FileSystem=****** Q通常q两U情况都有。例如在 OGRE 自带?Demo 中,将大部分资源放在一个文件夹里,Ҏ(gu)的资源该文g夹中?Zip 文g里?

?OGRE 自带的例子框?setupResources() 展示?Resources.cfg 文g的用:(x)先利?ConfigFile cd文g内容q行?jin)解析,资源目录用ResourceGroupManager:: addResourceLocation()向OGREq行提交;



清源游民 2007-03-02 17:33 发表评论
]]>
OGRE学习(fn)W记?配置文gPlugins.cfghttp://www.shnenglu.com/yuanyajie/archive/2007/03/02/19130.html清源游民清源游民Fri, 02 Mar 2007 09:31:00 GMThttp://www.shnenglu.com/yuanyajie/archive/2007/03/02/19130.htmlhttp://www.shnenglu.com/yuanyajie/comments/19130.htmlhttp://www.shnenglu.com/yuanyajie/archive/2007/03/02/19130.html#Feedback0http://www.shnenglu.com/yuanyajie/comments/commentRss/19130.htmlhttp://www.shnenglu.com/yuanyajie/services/trackbacks/19130.html 

Plugins.cfg

Ogre的许多功能是以插件的形式提供?Ogre提供的以Plugin_开头的许多.DLL文g都是所谓的插g?br />Plugins.cfg指定?jin)插件的路径和插件文件? 它们可以攑֜其它文g多wQ但必须在本文g里指定\径?/p>

?windows q_插g的装入过E如下:(x)
Root::()
{
   if(!pluginFileName.empty())
   loadPlugins(pluginFileName);
?
――――――>
void Root::loadPlugins(const String& pluginsfile)
{
   ConfigFile cfg;
   cfg.load(pluginsfile);
    ...........................
   // 解析文gQ处理后目录与文g名联?
  for(;;)
   loadPlugin(plugindir + (*it))

} ――――――>

Root::loadplugin(const string&  pluginName)
{
   DyLibmanager::getsinleton.load(pluginName);
}
――――――>

DynLibManager::load(const string& filename)

{
        DynLib* pLib=new DynLib(filename);
        pLib->load();
}

――――――>

void DynLib::load()

{
      m_hInst=(DYNLIB_HANDLE)DYNLIB_LOAD(name.cstr());
}

?windows q_下有如下定义Q?

#define  DYNLIB_LOAD(a)     LoadLibrary(a)

到此Q?x.dll 插g被加载到内存中,可以使用插g的功能了(jin)^_^
以下Z个典型的 Plugins.cfg 文g的内容:(x)

# Defines plugins to load
# Define plugin folder
PluginFolder=.
# Define plugins

Plugin=RenderSystem_Direct3D9
Plugin=RenderSystem_GL
Plugin=Plugin_ParticleFX
Plugin=Plugin_BSPSceneManager
Plugin=Plugin_OctreeSceneManager
Plugin=Plugin_CgProgramManager
Plugins.cfg 文g内容相当直观Q不再赘q?



清源游民 2007-03-02 17:31 发表评论
]]>
OGRE学习(fn)W记?配置文g Ogre.cfghttp://www.shnenglu.com/yuanyajie/archive/2007/03/02/19128.html清源游民清源游民Fri, 02 Mar 2007 09:28:00 GMThttp://www.shnenglu.com/yuanyajie/archive/2007/03/02/19128.htmlhttp://www.shnenglu.com/yuanyajie/comments/19128.htmlhttp://www.shnenglu.com/yuanyajie/archive/2007/03/02/19128.html#Feedback0http://www.shnenglu.com/yuanyajie/comments/commentRss/19128.htmlhttp://www.shnenglu.com/yuanyajie/services/trackbacks/19128.html Ogre.cfg
OGRE 引擎会(x)在可执行文g所在的文g夹中生成一?ogre.cfg 文g该文件保存了(jin)本次对话框的讄l果Q下ơ显C对话框时会(x)上ơ的配置l果dq直接显C。例子框架用 mRoot->showConfigDialog() 来调出配|对话框。如果你认ؓ(f)在程序运行之前显CZ个对话框很难看,或者希望采用另外的形式Q比如专门的配置界面Q就象在大部分游戏中那样Q来配置渲染pȝQ只要你保在可执行文g的同一文g夹下存在有效?Ogre.cfg 配置文gQ就可以直接调用 Root 对象?restoreConfig() 函数来直接读入渲染系l配|信息,而不昄配置对话框?

Ogre::Root::showConfigDialog() ?x)有下述行?f)Q如果程序运行之间已存在一个有效的 ogre.cfg Q那么它?x)在昄对话框之前将配置文g的内容蝲入,如果用户对对话框q行?jin)操行,改变的配|参敎ͼ showConfigDialog() ?x)根据用L(fng)新选择依次调用 Root::setRenderSystem, RenderSystem::setConfigOption and Root::saveConfig Q在 ogreWin32ConfigDialog.cpp 中实玎ͼ写自q配置对话框时可以参考)(j)Q需要注意的是配|好的参敎ͼ只是?RenderSystem::initialise or RenderSystem::reinitialise 调用之后才被ȀzR?以下为典型的 ogre.cfg 文g的内?
Render System=Direct3D9 Rendering Subsystem
[Direct3D9 Rendering Subsystem]
Allow NVPerfHUD=No
Anti aliasing=None
Floating-point mode=Fastest
Full Screen=No
Rendering Device=ATI MOBILITY RADEON X300
VSync=No
Video Mode=800 x 600 @ 32-bit colour

[OpenGL Rendering Subsystem]
Colour Depth=32
Display Frequency=N/A
FSAA=0
Full Screen=No
RTT Preferred Mode=FBO
VSync=No
Video Mode=1024 x 768

Ҏ(gu)号中为可以选择的渲染子pȝQ而第一行指Z(jin)当前的选择是哪个子pȝQ方括号下面为各子系l的可选参敎ͼ在上的例子中分别列出?Direct3D 9 ?OpenGL 子系l的可选配|参数?br />Root(const String& pluginFileName = "plugins.cfg", const String& configFileName = "ogre.cfg", const String& logFileName = "Ogre.log");         ~Root();
Root 的构造函C递了(jin)ogre.cfg,只是单的文件名保存下来Q供其它Ҏ(gu)使用Q如上面曄提到q的 Root:saveConfig(void);

 

 



清源游民 2007-03-02 17:28 发表评论
]]>
ORGE(Eihort)学习(fn)W记之GUI Demo W二部分 OIS输入http://www.shnenglu.com/yuanyajie/archive/2007/03/02/19121.html清源游民清源游民Fri, 02 Mar 2007 07:27:00 GMThttp://www.shnenglu.com/yuanyajie/archive/2007/03/02/19121.htmlhttp://www.shnenglu.com/yuanyajie/comments/19121.htmlhttp://www.shnenglu.com/yuanyajie/archive/2007/03/02/19121.html#Feedback0http://www.shnenglu.com/yuanyajie/comments/commentRss/19121.htmlhttp://www.shnenglu.com/yuanyajie/services/trackbacks/19121.html清源游民  gameogre@gmail.com
在第一部分里分析了(jin) ExampleFrameListener 大部内容Q不q没有穷,它其实也包含?jin)输入部分。因?CEGUI 本n没输入侦功能,他需要外部力量的帮助。在 ogre1.4 之间?demo 中,输入部分?ogre 自带的,功能有限Q对于我q个菜鸟Q暂时还用不到特别的功能 ^_^ Q。新版本里,q脆把这部分L?jin),输入部分采用了(jin)新的类?OIS Q?Object-oriented Input Library . 他的作者本w就?OGRE team 的成员,我们可以怿Q他可以?Ogre 一起工作得很好 .OIS 支持键盘Q鼠标,游戏杆,最后一Ҏ(gu)时不讨论 . ?windows q_下, OIS 提供?jin)?DirectInput 的封装,基本的输入功能是由后者来实现的。既然是学习(fn)Q我们不防先大概理解一?DirectInput 基本功能与用流E以?OIS 是如何将q些功能装q去的。我的目的是要讨?CEGUI 的,现在转到?OIS, 又{C(jin) DirectxInput, g是离目标来远?jin)。呵Q在菜鸟的眼中,什么东襉K是菜Q都有营养,不防咀g一下下?CEGUI 固然是好东西Q但是如果我们菜鸟整天只?x)学一堆堆没完没了(jin)的类库,那么我们可能永远只是个菜鸟?jin),一句话Q知道他做了(jin)些什么,比光知道他怎么用那可是相当有效Q费话少说了(jin)Q先看一?DirectInput, ?MSDN 上直接抄?jin)一D, 懒得译? 下面W一D话Q说?jin)理解directInput需要了(jin)解的一些基本概念与术语Q因Z前看q一点,大概知道是些什么。而我现在主要是做学习(fn)W记Q不是教E,所以不解释?jin)?br />To understand DirectInput, it is essential to understand the following terms. 
DirectInput object: The root DirectInput interface. · Device: A keyboard, mouse, joystick, or other input device. ·  DirectInputDevice object: Code representing a keyboard, mouse, joystick, or other input device.·  
Device object: Code representing a key, button, trigger, and so on found on a DirectInput device object. Also called device object instance.
W二D话说明?jin)?DirectInput 的基本步骤, OIS 把这些东西封装v来了(jin) .
The following steps represent a simple implementation of DirectInput in which the application takes responsibility for ascertaining what device object (button, axis, and so on) generated each item of data.

1.  Create the DirectInput object. You use methods of this object to enumerate devices and create DirectInput device objects.

2.  Enumerate devices. This is not an essential step if you intend to use only the system mouse or keyboard. To ascertain what other input devices are available on the user's system, have DirectInput enumerate them. Each time DirectInput finds a device that matches the criteria you set, it gives you the opportunity to examine the device's capabilities. It also retrieves a unique identifier that you can use to create a DirectInput device object representing the device.

3.  Create a DirectInputDevice object for each device you want to use. To do this, you need the unique identifier retrieved during enumeration. For the system mouse or keyboard, you can use a standard GUID.

4.  Set up the device. For each device, first set the cooperative level, which determines the way the device is shared with other applications or the system. You must also set the data format used for identifying device objects, such as buttons and axes, within data packets. If you intend to retrieve buffered data—that is, events rather than states—you also need to set a buffer size. Optionally, at this stage you can retrieve information about the device and tailor the application's behavior accordingly. You can also set properties such as the range of values returned by joystick axes.

5.  Acquire the device. At this stage you tell DirectInput that you are ready to receive data from the device.

6.  Retrieve data. At regular intervals, typically on each pass through the message loop or rendering loop, get either the current state of each device or a record of events that have taken place since the last retrieval. If you prefer, you can have DirectInput notify you whenever an event occurs.

7.  Act on the data. The application can respond either to the state of buttons and axes or to events such as a key being pressed or released.

8.  Close DirectInput. Before exiting, your application should unacquire all devices and release them, then release the DirectInput object.

?jin)解了(jin)这些基本步骤,下面我们打开OIS的源码,看看上面q?步骤装C(jin)哪里。然后我们返?ExampleFrameListener, 看看 demo 中是如何使用 OIS ?.
W一个要看的是InputManagercR他提供?jin)^台无关的接口Q负责输入系l的创徏。没啥好说的Q看源码?只列出核?j)代?Q?br />InputManager * InputManager::createInputSystem( ParamList &paramList )
{    
      I(yng)nputManager* im = 0;
      #elif defined OIS_WIN32_PLATFORM 
           im = newWin32InputManager();
    #endif 
       im->_initialize(paramList); 
    return im;
}
自然Q我们只兛_(j)windowsq_下的。于是找到源码l看:
void Win32InputManager::_initialize( ParamList &paramList )

  //Create the device 
   hr = DirectInput8Create(hInst, DIRECTINPUT_VERSION, IID_IDirectInput8, (VOID**)&mDirectInput, NULL );
   /Ok, now we have DirectInput, parse whatever extra settings were sent to us 
    _parseConfigSettings( paramList ); 
    _enumerateDevices();
}

首先Q完成了(jin)8步骤中的W?步, Create the DirectInput object ?在_parseConfigSettings ( paramList ); 中对以后要创徏的设备(键盘Q鼠标等Q的属性,例如独占模式Q前台模式等。这些属性列表paramList   l过处理后,之后在创备的时候传入?
void Win32InputManager::_enumerateDevices()
{     //Enumerate all attached devices 
    mDirectInput->EnumDevices(NULL, _DIEnumKbdCallback, this, DIEDFL_ATTACHEDONLY);
}

完成?步骤中的W? 部分 Enumerate devices Q它是针Ҏ(gu)戏杆q类设计的,对于键盘Q鼠标ƈ不需要。InputManager 创徏之后Q就可以用它来创建键盘,鼠标?jin)。它提供?jin)如下的?gu)Q?
Object * Win32InputManager::createInputObject( TypeiType, boolbufferMode )
{   
  Object* obj = 0;   
    switch( iType ) 
    { 
    case OISKeyboard: obj = newWin32Keyboard( this, mDirectInput, bufferMode, kbSettings ); break; 
    case OISMouse: obj = newWin32Mouse( this, mDirectInput, bufferMode, mouseSettings ); break; 
    obj->_initialize(); 
    return obj;
}

鼠标Q键盘都有各自的cd装。下面以键盘ZQ看看它的源码中都做?jin)些什么:(x)
void Win32Keyboard::_initialize()
{

1      mDirectInput->CreateDevice(GUID_SysKeyboard, &mKeyboard, NULL);

2      mKeyboard->SetDataFormat(&c_dfDIKeyboard)

3      HWNDhwin = ((Win32InputManager*)mCreator)->getWindowHandle();

4      mKeyboard->SetCooperativeLevel( hwin, coopSetting)))

5      mKeyboard ->SetProperty( DIPROP_BUFFERSIZE, &dipdw.diph )))

6      HRESULThr = mKeyboard->Acquire(); 

}

q里可是做了(jin)不少的工?看看Ҏ(gu)名就可以明白。ؓ(f)说明方便加上?jin)标受?br />1Q?它做?步骤中的W?步, Create a DirectInputDevice object for each device you want to use ?
2, 3 4,5它们共同做了(jin)8步骤中的W?步- Set up the device 。这里面包括Q设|键盘的数据格式Q协作模式,其他属性。很明显Q?做了(jin)8 步步骤中的第5步- Acquire the device ?意思是告诉DirectInput,我准备从讑֤上获取数据了(jin)Q给我做好生Z着。准备工作都做好?jin),可以获取数据了(jin),通过讑֤提供的下面这个方法来做这件事。这是8 步骤中的W?件事- Retrieve data
void Win32Keyboard::capture()
{     if( mBuffered ) 
       _readBuffered(); 
       else 
       _read();
}

从源码中我们可以看到Q根据数据的不同Q进行了(jin)不同的处理。呵Q什么不同呢Q再从MSDN上抄一D吧Q一看就明白Q?Buffered and Immediate Data
DirectInput supplies two types of data: buffered and immediate. Buffered data is a record of events that are stored until an application retrieves them. Immediate data is a snapshot of the current state of a device. You might use immediate data in an application that is concerned only with the current state of a device - for example, a flight combat simulation that responds to the current position of the joystick and the state of one or more buttons. Buffered data might be the better choice where events are more important than states - for example, in an application that responds to movement of the mouse and button clicks. You can also use both types of data, as you might, for example, if you wanted to get immediate data for joystick axes but buffered data for the buttons.

呵,清楚?jin)吧。l看代码, capture()有两个分枝,分别处理~冲数据与立x据?br />首先是缓冲数据,d代码如下Q?
void Win32Keyboard::_readBuffered()
{
  DIDEVICEOBJECTDATA diBuff[KEYBOARD_DX_BUFFERSIZE]; 
    DWORD entries = KEYBOARD_DX_BUFFERSIZE;  
   mKeyboard->GetDeviceData( sizeof(DIDEVICEOBJECTDATA), diBuff, &entries, 0 ); 
    //Update keyboard and modifier states.. And, if listener, fire events 
    for(unsignedinti = 0; i < entries; ++i ) 
    { 
       KeyCode kc = (KeyCode)diBuff[ i ].dwOfs; 
                     if( diBuff[ i ].dwData & 0x80 ) 
       { 
          if( listener ) 
            istener->keyPressed( KeyEvent( this,kc,_translateText(kc) ) ); 
       } 
       else
       { 
           //Fire off event 
           if( listener ) 
            listener->keyReleased( KeyEvent( this, kc, 0 ) ); 
       } 
    }
}

q段代码中,GetDeviceData( sizeof(DIDEVICEOBJECTDATA), diBuff, &entries, 0 );取得?jin)缓冲数?d?jin)一个数l:(x)寸是EYBOARD_DX_BUFFERSIZE,可以看到entries也等于此倹{Entries的作用除?jin)开始调用时说明数组的大,同时在函数调用返回时说明数组里有多少个数据填入(没有_多的~冲数据Q当然填不满啦,假如entriesq回6Q说明还?个按键信息在~冲里等待处理)(j)。很明显Qfor循环是对这些未处理的信息进行处理。KeyCode kc = (KeyCode)diBuff[ i ].dwOfs; q是看看Q这个事件是由哪个键引走.KeyCode是个枚D型:(x)
enum KeyCode 
    { 
       C_1           = 0x02, 
       KC_2            = 0x03, 
       KC_3            = 0x04, 
       KC_A            = 0x1E, 
       KC_S            = 0x1F, 
       KC_D            = 0x20, 
    }

定?jin)是哪个键,接下来就要问了(jin),是按下还是释放?br /> if ( diBuff[ i ].dwData & 0x80 )  回答?jin)这个问?下面做的?
if ( listener ) 
            istener->keyPressed( KeyEvent( this,kc,_translateText(kc) ) );

它把相关的信息内容包装成KeyEventQ作为参数发l了(jin)Q已l注册了(jin)的侦听?可能不太明白Q解释一下:(x)当我们按下了(jin)某个键,可以认ؓ(f)是发生了(jin)个KeyEvent,E序里会(x)响应q个事gQ方法就是把某个cd例注册ؓ(f)侦听?listener),说白?jin)就是告诉OIS,当键盘按下释攄时候你告诉我啊Q我要响应他。这里OIS(g)到按键事g发生?jin),?gu)侦听者的hQ调用侦听者的Ҏ(gu)(keyPressed)。也许有疑问QOIS 怎么知道侦听者实C(jin)keypressedQ)(j)Ҏ(gu)呢?不急先看以下代码,在GUI demo里:(x)
class GuiFrameListener : publicExampleFrameListener, publicOIS::KeyListener, publicOIS::MouseListener
看到?jin)吧Q它l承自?OIS:KeyListener ,从OIS的源码中扑ֈ它:(x)
class _OISExport KeyListener 
    { 
    public: 
       virtual ~KeyListener() {} 
       virtual bool keyPressed( constKeyEvent &arg ) = 0; 
       virtual bool keyReleased( constKeyEvent &arg ) = 0;    
    };
哈哈Q他正是定义?jin)这两个接口Q既然承自他,当然也就拥有?jin)这两个接口Q于是GuiFrameListener成了(jin)合理合法的Listener?jin)?
哦,它在哪里注册的呢Q很?在GuiFrameListener的构造函数里我们看到Q?
{
       mMouse ->setEventCallback(this); 
       mKeyboard->setEventCallback(this);
}
l箋挖源码:(x)
virtual void Keyboard : QsetEventCallback ( KeyListener *keyListener ) {listener=keyListener;}
q下应该明白了(jin)吧。很明显GUI Demo里用了(jin)~冲模式.
剩下来就是立x式的数据?jin),他很好理解?x)
void Win32Keyboard::_read()

  mKeyboard->GetDeviceState( sizeof(KeyBuffer), &KeyBuffer ); 
}
它把键盘当下的状态保存到~冲中去Q要想知道哪个键是否按下Q只要对照缓农y(c)按囄(ch)骥”就可以?jin)?br /> bool Win32Keyboard::isKeyDown( KeyCodekey )

    return (KeyBuffer[key] & 0x80) != 0;
}
q个键按下了(jin)吗?那个键按下了(jin)吗?那那个呢Q呵Q真啰嗦Q得一个个的问?
于是我们 GUI Demo 中可以看C列的代码Q?
virtual bool processUnbufferedKeyInput(const FrameEvent& evt) 
       { 

            if(mKeyboard->isKeyDown(KC_A)) 
                      mTranslateVector.x = -mMoveScale;    // Move camera left 
            if(mKeyboard->isKeyDown(KC_D)) 
                    mTranslateVector.x = mMoveScale;      // Move camera RIGHT 
              if(mKeyboard->isKeyDown(KC_UP) || mKeyboard->isKeyDown(KC_W) ) 
                     mTranslateVector.z = -mMoveScale;     // Move camera forward 
              if(mKeyboard->isKeyDown(KC_DOWN) || mKeyboard->isKeyDown(KC_S) )  
                    mTranslateVector.z = mMoveScale;      // Move camera backward
?

我们用键盘要不是~冲模式Q要么立x式,不可能一起上Q这所有在 demo 中都能看刎ͼ demo 的作者懒得多写代?( 嘿嘿 ) Q它l承?ExampleFrameListener 的许多功能,?ExampleFrameListener 也实C(jin)些立x式的按键处理?Demo 没有用到。写?jin)这么多了(jin),q得 8  大步骤?Q?该第 7 步了(jin)吧:(x) ―?Act on the data Q?q有什么好说的呢?爱咋咋地Q最后一步,W?8 步――天龙八?! 呵错?jin),?Close DirectInput      其实很简单, OIS 把他们封装在各个cȝ析构函数里了(jin)Q想当然Q源码也不用贴了(jin) . 说了(jin) OIS  如何?DirectInput 装hQ参?8 大步骤,如何使用 OIS 也基本很明白?jin)。OIS Q就学到q里Q接下来该主角上?CEGUI 得休息了(jin)Q打字,资料,看代码,很篏?jin)?




清源游民 2007-03-02 15:27 发表评论
]]>
ORGE(Eihort)学习(fn)W记之GUI Demo W一部分 例子框架http://www.shnenglu.com/yuanyajie/archive/2007/03/01/19092.html清源游民清源游民Thu, 01 Mar 2007 13:47:00 GMThttp://www.shnenglu.com/yuanyajie/archive/2007/03/01/19092.htmlhttp://www.shnenglu.com/yuanyajie/comments/19092.htmlhttp://www.shnenglu.com/yuanyajie/archive/2007/03/01/19092.html#Feedback0http://www.shnenglu.com/yuanyajie/comments/commentRss/19092.htmlhttp://www.shnenglu.com/yuanyajie/services/trackbacks/19092.html清源游民  gameogre@gmail.com

下面直接涉及(qing)到相关类


首先看一?/span> ExampleFrameListener, 下面是类间关pd

 
ExampleFrameListener l承?FrameListener, 因此拥有?jin)它的两个方?

virtual bool frameStarted(constFrameEvent& evt)

virtual bool frameEnded(constFrameEvent& evt)

?ExampleApplication 中将它们注册?ogre 中,在适当的时候, ogre ?x)调用这两个?gu) . 下面是注册地点与时机

virtual void ExampleApplication::createFrameListener(void)

    {

        mFrameListener= newExampleFrameListener(mWindow, mCamera);

        mFrameListener->showDebugOverlay(true);

        mRoot->addFrameListener(mFrameListener);

}

createFrameListener ?ExampleApplication::setup() 中被调用.

ExampleFrameListener 又承了(jin) WindowEventListener.

WindowEventListerner 在ogre 1.4中是新加的。按照手册:(x)它是一?Callback class used to send out window events to client app. 它定义以下四个接?而显然例子程序中只用C(jin)两个
virtual void windowMoved(RenderWindow* rw)   {}

virtual void windowResized(RenderWindow* rw) {}

virtual void windowClosed(RenderWindow* rw)  {}

virtual void windowFocusChange(RenderWindow* rw) {}

q种所谓的回调cd何实玎ͼ下面只说明windows操作pȝ的情c(din)?

我们知道Qwindows操作pȝ监视pȝ中发生的一切,通过消息的方式通知相应的窗口。每个窗口类注册的时候,都指明一个回调过E,在那里处理传来的消息。应用程序又有各自的消息队列Q从消息队列中取得消息,然后分开l各H口.

不防从ogre的源码中看看上述windows基本q程如何实现Q这有助理解回调cȝ实现q程Q?

首先Qogre可以为我们创Z个窗口:(x)

mWindow = mRoot->initialise(true);//

于是我们q入到initialise()中看看吧Q它倒底做了(jin)些什么事情?

RenderWindow * Root::initialise(boolautoCreateWindow, constString& windowTitle)

{

// ……

mAutoWindow =  mActiveRenderer->initialise(autoCreateWindow, windowTitle);

// q里QRenderSystem* mActiveRenderer

// ……

}

mActivaRenderer 只是接口Q不用实际的事情Q实际的工作由它的子cd成,现只看DirectX实现:

RenderWindow * D3D9RenderSystem::initialise( boolautoCreateWindow, constString& windowTitle )

{

// ……………………

autoWindow = this->createRenderWindow( windowTitle, width, height,

              fullScreen, &miscParams );

// ………………… ..

}

好,l箋下去,看看createRenderWindow做了(jin)些什?

    

RenderWindow * D3D9RenderSystem::createRenderWindow(constString &name,

       unsigned int width, unsignedintheight, boolfullScreen,

       const NameValuePairList *miscParams)

{

// …………… ..

RenderWindow * win = newD3D9RenderWindow(mhInstance, mActiveD3DDriver,

           mPrimaryWindow ? mpD3DDevice : 0);

 

win ->create( name, width, height, fullScreen, miscParams);

// ………………

}

l箋

void D3D9RenderWindow::create(constString& name, unsignedintwidth, unsignedintheight,

       bool fullScreen, constNameValuePairList *miscParams)

{

// Register the window class

// NB allow 4 bytes of window data for D3D9RenderWindow pointer

    WNDCLASS wc = { 0, WindowEventUtilities::_WndProc, 0, 0, hInst,

           LoadIcon(0, IDI_APPLICATION), LoadCursor(NULL, IDC_ARROW),

              (HBRUSH)GetStockObject(BLACK_BRUSH), 0, "OgreD3D9Wnd" };

           RegisterClass(&wc);

// 定义?jin)窗口类Qƈ且进行注册,需要注意的是,你看看它把窗口类的回调函数的DZ(jin)什么?先记住,一?x)儿讨论它吧?

           // Create our main window

           // Pass pointer to self

           mIsExternal = false;

           mHWnd = CreateWindow("OgreD3D9Wnd", title.c_str(), dwStyle,

              mLeft, mTop, mWidth, mHeight, parentHWnd, 0, hInst, this);

// 调用win32API把窗口真正Create出来?

WindowEventUtilities ::_addRenderWindow(this);

// q一步也要注意到

}

l箋

void WindowEventUtilities::_addRenderWindow(RenderWindow* window)

{

    _msWindows.push_back(window);

}

_msWindows 定义为:(x)

typedef std::vector<RenderWindow*> Windows;

 static Windows _msWindows;

Q没什么,只是个stl容器Q把生成的窗口放q去?

到现在,容器cL册好?jin),回调函数也指定?jin)Q窗口也创徏出来?jin)。现在我们l思考我们最最初的问题Q?WindowEventListerner q个回调cL如何实现所谓的回调机制的,也就是说windowEventListerner不是定义?jin)四个接口,它响应特定的windows事gQ我们要讨论的就是这四个接口Ҏ(gu)如何被调用v来,实现所谓的回调机制?q记得注册窗口类的回调函数是什么吧Q?

WindowEventUtilities::_WndProc Q?呵呵Q只要在那里调用上述四个接口函数好?jin)?

哪问题又来了(jin)Q_WndProc到哪里找q四个接口函数呢Q?

?ExampleFrameListener cȝ构造函数里我们可以看到如下代码

//Register as a Window listener

WindowEventUtilities::addWindowEventListener(mWindow, this);

啊,q就是奥U所?到源码中看看吧?

void WindowEventUtilities::addWindowEventListener( RenderWindow* window, WindowEventListener* listener )

{

    _msListeners.inser t(std::make_pair(window, listener));

}

-msListeners 被定义成q样子:(x)

typedef std::multimap<RenderWindow*, WindowEventListener*> WindowEventListeners;

static WindowEventListeners _msListeners;

没有什么,是STL容器Q它使得H口(RenderWindow)?WindowEventListener)

l成?jin)亲密派对,H口有了(jin)什么消息,可以用对应的回调类响应?

只剩下一点秘密了(jin)Q到底怎么调用h的呢Q某某某说过Q源码之下,?jin)无U密Q那q源码吧:(x)

LRESULT CALLBACK WindowEventUtilities::_WndProc(HWNDhWnd, UINTuMsg, WPARAMwParam, LPARAMlParam)

{

WindowEventListeners ::iteratorstart = _msListeners.lower_bound(win),

                     end = _msListeners.upper_bound(win);

// 为遍历做准备

    switch( uMsg )   // 消息真的来了(jin)

  {

case WM_MOVE:

       //log->logMessage("WM_MOVE");

       win->windowMovedOrResized();

       for( ; start != end; ++start )

           (start->second)->windowMoved(win);

       break;

    case WM_SIZE:

       //log->logMessage("WM_SIZE");

       win->windowMovedOrResized();

       for( ; start != end; ++start )

           (start->second)->windowResized(win);

       break;

}

}

pP四个接口函数被调用v来了(jin)Q?

也许Q也许,关于消息q有些要说明的。消息如何܇出来的?

当看C(jin)如下代码Q突然就x个朋友,?x)?j)一W?

void WindowEventUtilities::messagePump()

{

    MSG   msg;

    while( PeekMessage( &msg, NULL, 0U, 0U, PM_REMOVE ) )

    {

       TranslateMessage( &msg );

       DispatchMessage( &msg );

    }

}

打破铁锅问到底吧Q它又如何被调用hQ?

void Root::startRendering(void)

    {

        while( !mQueuedEnd )

        {

           //Pump messages in all registered RenderWindow windows

           WindowEventUtilities::messagePump();

 

           if (!renderOneFrame())

                break;

        }

}

是q里?jin)。写的ؕ七八p,脑子也ؕ七八p,梳理一下吧?

首先QmWindow = mRoot->initialise(true);初始化,随便通过一pȝq锁反应create出来一个窗口,q把它的回调函数讑֮?WindowEventUtilities::_WndProc.

ExampleFrameListener l承?WindowEventListener 的四个约定接口函数。ƈ且在它的构造函数里调用 WindowEventUtilities::addWindowEventListener(mWindow, this); q行?jin)注册,以便特定H口消息发生时进行响? Root ::startRendering Q)(j)q入?jin)渲染@环,渲染每一帧前Q检widnows消息Qƈq行分发。于是消息进入到H口cȝ回调函数_WndProc,在函数内部根据消息的不同Q分别调用已注册的侦听器的约定接口函数?br>先写到这里吧Q原来只是想写写C(j)EGUI的用,谁知已经写了(jin)q么多了(jin)QCEGUIq一字未提。脑子ؕ?jin),先休息吧。下面还得说说OIS,CEGUI又得靠后?




清源游民 2007-03-01 21:47 发表评论
]]>
Q{QCEGUI 中文输入http://www.shnenglu.com/yuanyajie/archive/2007/02/28/19037.html清源游民清源游民Wed, 28 Feb 2007 02:25:00 GMThttp://www.shnenglu.com/yuanyajie/archive/2007/02/28/19037.htmlhttp://www.shnenglu.com/yuanyajie/comments/19037.htmlhttp://www.shnenglu.com/yuanyajie/archive/2007/02/28/19037.html#Feedback7http://www.shnenglu.com/yuanyajie/comments/commentRss/19037.htmlhttp://www.shnenglu.com/yuanyajie/services/trackbacks/19037.html刚刚搞CEGUI的时候大体看?jin)一下CEGUI。原以ؓ(f)其不支持中文?br />而且|上很多人都说不支持。。我也就没有l细看了(jin)?br />当用到Editbox的时候。又不得不用中文。 这时候问题就来了(jin)?br />先是用utf8方式转换辑ֈ中文昄的目的。可是中文输入却不行。网上有一U说法是两个字节链接v来即可。看?jin)一下编译器讄Q当前用的是多字节模式。就不得不这样做?jin)。不q估计我对C++q不深。搞?jin)一?x),q是p|?jin)。不q后来在|上有一个朋友说CEGUI本来支持中文的。但又看到其它h说的Q不解其a啊。再后来有一个叫老妖_|友l了(jin)我一份代码。结果真的成功了(jin)。可昄可输入中文。对于中文的字表׃个font文g创徏。方法如下:(x)
1:找一个中文字体文?.ttf)
2:创徏一个文本文Ӟ其存ؓ(f).font文g.
3:?font文g里写如下代码(我个假设一个chinese.ttf文g):
<?xml version="1.0" ?>
<Font Name="chinese" Filename="chinese.TTF" Type="FreeType" Size="10" NativeHorzRes="1024" NativeVertRes="768" AutoScaled="true"/>
// 说明:Name是在程序中要用到的名字, Filename是文g?FreeType可以是自定义?具体到官方网有说?Size是字体的大?E序中是不能调大的.因ؓ(f)字体生成U理后就是固定的.
4:在你写的E序的键盘和事g上处理上面正常情况下是这样子?CEGUI::System->injectChar((CEGUI::utf32)Key); // Key值就是你E序捉到的按键?我们需要将其改?

    if (ImmIsIME(GetKeyboardLayout(0)))
    {
     CEGUI::DbcsSupport::injectChar(Key);
    }
    else
    {
     CEGUI::System->injectChar((CEGUI::utf32)Key);
    }

    ImmIsIME(GetKeyboardLayout(0))目的是用于检则现在的输入法是否打开的。如果是在输英文状态我想你不会(x)画蛇添的。用这个需要imm32.lib的支持。MSDN上面也有说明?br />5:最后就是添加一份代码到你的CEGUI使用目里,如下Q?br />namespace CEGUI{
bool DbcsSupport::injectChar(utf32 code_point )
 {
#ifndef UNICODE
  static char     s_tempChar[3]  = "";
  static wchar_t  s_tempWchar[2] = L"";
  static bool s_flag = false;
  unsigned char  uch  = (unsigned char)code_point;
  if( uch >= 0xA1 )
  {
   if( !s_flag )
   {
    s_tempChar[0] = (char)uch; //W一个字?br />    s_flag = true;
    return true;
   }
   else if( uch >= 0xA1 )
   {
    s_tempChar[1] = (char)uch; //W二个字?br />    s_flag = false;
    MultiByteToWideChar( 0, 0, s_tempChar, 2, s_tempWchar, 1); //转成宽字?br />    s_tempWchar[1] = L'\0';
    utf32 code = (utf32)s_tempWchar[0];
    //Font* fnt = System::getSingleton().getDefaultFont();
    return CEGUI::System::getSingleton().injectChar( code );
   }
   else
   {
    return CEGUI::System::getSingleton().injectChar(code_point);
   }
  }
  else
  {
   s_flag = false;
   return CEGUI::System::getSingleton().injectChar(code_point);
  }
#else
  return CEGUI::System::getSingleton().injectChar(code_point );
#endif
 }
}

Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=1509217



清源游民 2007-02-28 10:25 发表评论
]]>
在OGRE中用CEGUI的笔?/title><link>http://www.shnenglu.com/yuanyajie/archive/2006/11/01/14485.html</link><dc:creator>清源游民</dc:creator><author>清源游民</author><pubDate>Wed, 01 Nov 2006 07:32:00 GMT</pubDate><guid>http://www.shnenglu.com/yuanyajie/archive/2006/11/01/14485.html</guid><wfw:comment>http://www.shnenglu.com/yuanyajie/comments/14485.html</wfw:comment><comments>http://www.shnenglu.com/yuanyajie/archive/2006/11/01/14485.html#Feedback</comments><slash:comments>5</slash:comments><wfw:commentRss>http://www.shnenglu.com/yuanyajie/comments/commentRss/14485.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/yuanyajie/services/trackbacks/14485.html</trackback:ping><description><![CDATA[ <p>使用 cegui 来制作界?, 不论在何U^C , 有基本的三大步骤要做 : <br />1, 创徏一?CEGUI::Render 实例 <br />2, 创徏 CEGUI::System 对象 <br />3, 调用各种Ҏ(gu)来渲染用L(fng)?<br />W一?, 在我使用?ogre 环境下用以下代码来创徏 CEGUI::Render 实例 <br />Ogre3D <br />CEGUI::OgreCEGUIRenderer* myRenderer = <br />       new CEGUI::OgreCEGUIRenderer(myRenderWindow); <br />W二步相当简?, 可?<br />new CEGUI::System(myRenderer); <br />W三步,基本上来Ԍ大部分^CQ如 direct3D, OpenGL, 我们在渲染@环的N调用 <br />CEGUI::System::renderGUI 来开始界面的渲染。如果我们?ogre3d 引擎Q这一步不需?<br />我们昄的执行。因?ogre 引擎已经考虑?jin)?<br />除了(jin)q三大步之外Q我们还有一些工作要做,首先Q我们需要加载数据文Ӟq且完成初始化工作?<br />CEGUI 使用?jin)许多类型的文g?CEGUI 使用一个称?ResourceProvider 的帮助对象,用它来做为核?CEGUI 库与外部文g加蝲pȝ的接口。通过实现一个特定的 ResourceProvider 对象Q?cegui 的渲染模块就可以与外部系l的资源理器、文件加载子pȝ无缝地集成?CEGUI 需要的数据文g便可以通过外部pȝ提供的功能来q行加蝲?CEGUI 中的大部分文件是?XML 的文件格式来保存的。缺省情况下Q?CEGUI 在内部?Xerces-C++ 库来分析 XML 文gQ?schema 来对 xml q行校验Q?schema 文g以标准的 .xsd 扩展名来保存 . 许多文g本质上都?XML 格式的文Ӟ但是Ҏ(gu)其意义不同,分别使用?jin)不同的文g扩展名?<br />.Imageset 文g可将一q图像看做若q小囑փ的集合。换名话_(d)是一q图像的某个区域看做一q独立的囄来用?<br />.Font 定义?jin)?CEGUI 中所使用的字体类型?<br />.scheme  可以许多数据组合在一起用,它也是装载与注册 widget 最方便的方法。在一?.scheme 文g中可以包括下列几U数据:(x) <br />Imagest,font, window Set, window Alias <br />window set 指定?jin)装载模块?.dll {)(j)的名Uͼ和一l可以注册到pȝ中的 widget. <br />window alias 提供?jin)别名的功能Q实现已l注册的 window/widget 的Ş式上的隐藏?<br />.Layout  包含?jin)窗口布局?xml 表示。每个嵌套的 'window' 元素定义?jin)被创徏?window 或是 widget."Property" 元素定义?jin)窗口的讄与属性倹{?<br />.config 是可供选择的配|文Ӟ他可指定一些缺省的属性?<br />我们使用 CEGUI 来制作图形界面,臛_要用以下三U文Ӟ(x) <br />.imageset, .Font . Scheme; <br />当然Q我们知道在一?Scheme 中是可以包括 imageset ?Font 的?<br />CEGUI::SchemeManager::getSingleton().loadScheme(?./datafiles/schemes/TaharezLook.scheme?; <br />// load in a font.  The first font loaded automatically becomes the default font. <br />CEGUI::FontManager::getSingleton().createFont(?./datafiles/fonts/Commonwealth-10.font?; <br />对于 ogre 的用者来Ԍ应该?resources.cfg 这些资源所在的目录加进厅R?<br />我们可用下面的语句来指定 cegui 所需要的~省?font ?cursor 资源?<br />?cegui 的概念里Q每?widget 都是一?window, 从编E的角度来讲Q每?widget c都是从同一个相同的 window 基类l承而来?. 因此Q?widget ?window 有着基本相同的行为?<br />H体的许多属性与讄在窗口层?wi)上是可以遗传的。高一U窗口的属性与行ؓ(f)?x)?jing)响到下一U窗口的属性与行ؓ(f)。例如附着在某?window 上的 window ?widget ?x)被?window 影响。当父窗口被 destroy Ӟ它所附属的所有的子窗口与 widget 也都被 destroy. <br />创徏 CEGUI H口Q我们可以用两UŞ式,一?C Q+代码Q二是编?XML layout 文g?<br />注意Q在 CEGUI 中,所有的 window 都是?WindowManager singleton object 来统一创徏的。我们首先得到这个对象:(x) <br />using namespace CEGUI; <br />WindowManager& wmgr = WindowManager::getSingleton(); <br />一般来Ԍ我们L创徏一?DefaultWindow 来做为我们将使用的窗口的 Root, 在这U方式下Q我们会(x)有比较好的灵zL?<br />Window* myRoot = wmgr.createWindow(“DefaultWindow? “root?; <br />System::getSingleton().setGUISheet(myRoot); <br />createwindows() 函数所使用的第一个参敎ͼ指明?jin)将要创建的H口cdQ它一般是在我们用的 .scheme 文g中所注册q的Q当然还有一些系l定义的QL有效的窗口类型如上面所提到?DefaultWindow.DefualtWindow 是不可见的,它只是做为所有窗口的 root 来用?<br />一般我们L要创Z?Framewindow, 它可以包括其他窗口与 widget Q本w也是可视的?<br />FrameWindow* fWnd = (FrameWindow*)wmgr.createWindow(“TaharezLook/FrameWindow? “testWindow?; <br />之后Q我们将创徏的窗口挂?root 上,形成一个层ơ关pR?<br />myRoot->addChildWindow(fWnd); <br />~辑 xml layout 文gQ可使用专门提供的制作工兗具体的使用Ҏ(gu)可以参阅相关文档Q这里说一下如何用制作好?xml layout 文g?<br />using namespace CEGUI; <br />Window* myRoot = WindowManager::getSingleton().loadWindowLayout(“test.layout?; <br />System::getSingleton().setGUISheet(myRoot); <br />首先Q将 layout 文g装蝲q来Q再指定根结炏V?<br />CEGUI 本n侦测用户输入Q这些不?CEGUI 的责任,而是E序的员的责仅R当有用户外部输入时Q我 <br />们可以选择这些消息告?CEGUI Q这?CEGUI 才会(x)响应?<br />?ceguir::System cM定义?jin)一l函敎ͼ它作为我们进行消息传递的接口?<br />bool injectMouseMove(float delta_x, float delta_y); <br />bool injectMousePosition(float x_pos, float y_pos); <br />bool injectMouseLeaves(void); <br />bool injectMouseButtonDown(MouseButton button); <br />bool injectMouseButtonUp(MouseButton button); <br />bool injectKeyDown(uint key_code); <br />bool injectKeyUp(uint key_code); <br />bool injectChar(utf32 code_point); <br />bool injectMouseWheelChange(float delta); <br />bool injectTimePulse(float timeElapsed); <br />q些函数的返回D明了(jin) CEGUI 是否已经传入的消息 consume 掉了(jin)?<br />CEGUI 使用回调机制来进行消息处理。可以ؓ(f)某个H体的特定事件注册一个函敎ͼ当窗体事件发生时Q?CEGUI ?x)自动调用所注册的函数?<br />bool TutorialApplication::handlePopMenu(constCEGUI::EventArgs& e) <br />?<br />// 。。。。。进行事件响?<br />?<br />void setupEventHandlers(void) <br />    { <br />       CEGUI::WindowManager& wmgr = CEGUI::WindowManager::getSingleton(); <br />       wmgr .getWindow((CEGUI::utf8*)"MyButton")->subscribeEvent( <br />       CEGUI ::PushButton::EventClicked, CEGUI::Event::Subscriber(&TutorialApplication::handlePopMenu, this)); <br />   } </p> <p>EventClicked :: pȝ预定义的事g . subscribeEvent:: 注册函数Q它事g与响应函数联接在一赗?<br />?ogre E序中,当侦听器收到键盘Q鼠标消息时Q首先经q适当的{换( CEGUI 可以识别Q再传递给 CEGUI 。下面这个函数执行鼠标键标识转换?<br />CEGUI::MouseButton convertOgreButtonToCegui(int buttonID) <br />{ <br />       switch (buttonID) <br />       { <br />       case MouseEvent::BUTTON0_MASK: <br />              return CEGUI::LeftButton; <br />       case MouseEvent::BUTTON1_MASK: <br />              return CEGUI::RightButton; <br />       case MouseEvent::BUTTON2_MASK: <br />              return CEGUI::MiddleButton; <br />       case MouseEvent::BUTTON3_MASK: <br />              return CEGUI::X1Button; <br />       default: <br />              return CEGUI::LeftButton; <br />       } <br />} </p> <p>?CEGUI 需要知道的键盘Q鼠标消息告知它。即?OGRE 处理q些消息旉知 CEGUI 。以下这函数说明?jin)用法?<br />       void mouseMoved (MouseEvent *e)// 鼠标Ud <br />       { <br />              CEGUI::System::getSingleton().injectMouseMove( <br />                   e->getRelX() * mGUIRenderer->getWidth(), <br />                   e->getRelY() * mGUIRenderer->getHeight()); <br />                   e->consume(); <br />       } </p> <p>       void mousePressed (MouseEvent *e)// 鼠标按下 <br />       { <br />              CEGUI::System::getSingleton().injectMouseButtonDown( <br />               convertOgreButtonToCegui(e->getButtonID())); <br />             e->consume(); <br />       } <br />       void mouseReleased (MouseEvent *e)// 鼠标弹v <br />       { <br />              CEGUI::System::getSingleton().injectMouseButtonUp( <br />              convertOgreButtonToCegui(e->getButtonID())); <br />              e->consume(); <br />       } </p> <p>       void keyPressed(KeyEvent* e)// 键按?<br />       { <br />              CEGUI::System::getSingleton().injectKeyDown(e->getKey()); <br />              CEGUI::System::getSingleton().injectChar(e->getKeyChar()); <br />              e->consume(); <br />       } <br />       void keyReleased(KeyEvent* e)// 键弹?<br />       { <br />             CEGUI::System::getSingleton().injectKeyUp(e->getKey()); <br />             e->consume(); </p> <p>       } <br />?CEGUI 中用中文的问题Q ?现在ȝ?jin)一下在 CEGUI 中显CZ文需要注意的事项 :<br />    1 、将 simhei.ttf copy to \ogrenew\Samples\Media\gui<br />    2 、将 simhei-12.font  拷到上目录内容ؓ(f) <br /><?xml version="1.0"  ?><br /><Font Name="SimHei-12" Filename="simhei.ttf" Type="Dynamic" Size="12" NativeHorzRes="800" NativeVertRes="600"  <br />AutoScaled="true"><br /><GlyphSet Glyphs=" 你好世界退出演C渲染到新材质徏~辑H口 " /> Q?<---- 自己要用到的汉字Q?<br /></Font> <br />注意大小写!Q?GlyphSet Glyphs 是在E序中要用到的汉字,它是?cegui 预生成一个字W图像集用的Q想当然?:-P Q如果修改了(jin)q个文gQ注意要?Unicode Q?UTF-8 Q的~码来保存,?vc7.1 中:(x)文g -> 高保存选项   的 ?~码   栏中选择?<br />    3 、在 TaharezLook.scheme ?<br />     <Font Name="Tahoma-12" Filename="tahoma-12.font" /> 后加?<br />     <Font Name="SimHei-12" Filename="simhei-12.font" />  注意大小?<br />     以上是一些准备工?<br />    4 、在自己的应用中讄默认字体 <br />    mGUISystem->setDefaultFont((CEGUI::utf8*)"Tahoma-12"); 改ؓ(f) <br />    mGUISystem->setDefaultFont((CEGUI::utf8*)"SimHei-12"); <br />    5 、在自己的应用程序中可以把相关?Text 属性该Z文了(jin)Q如Q?<br />    item = new CEGUI::ListboxTextItem((CEGUI::utf8*)" 退?", 6); <br />    同样要注意的是要保存?Unicode Q?UTF-8 Q的~码。同时这些字要是?simhei-12.font 中定义过的字Q当然也可以象那?CEGUIChieseDemo <br />那样用动态生成如Q?<br />    gfont->defineFontGlyphs(gfont->getAvailableGlyphs() + (utf8*)" 当前最?jng)_q_的框架率三角 "); <br />    ~译自己的程序,应该可以看C文了(jin)Q罗嗦一下,C只要有汉字出现的文g׃存ؓ(f) Unicode Q?UTF-8 Q编码的Q!Q?</p> <p> </p> <img src ="http://www.shnenglu.com/yuanyajie/aggbug/14485.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/yuanyajie/" target="_blank">清源游民</a> 2006-11-01 15:32 <a href="http://www.shnenglu.com/yuanyajie/archive/2006/11/01/14485.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>人物动画与绑定盒http://www.shnenglu.com/yuanyajie/archive/2006/10/26/14241.html清源游民清源游民Thu, 26 Oct 2006 08:30:00 GMThttp://www.shnenglu.com/yuanyajie/archive/2006/10/26/14241.htmlhttp://www.shnenglu.com/yuanyajie/comments/14241.htmlhttp://www.shnenglu.com/yuanyajie/archive/2006/10/26/14241.html#Feedback0http://www.shnenglu.com/yuanyajie/comments/commentRss/14241.htmlhttp://www.shnenglu.com/yuanyajie/services/trackbacks/14241.html在ogre?当mesh被动ȝ时?它的BoundingBox(AABB)是不更新?由此不能用它Ҏ(gu)做ؓ(f)撞(g)的代理.q个问题ȝ(ch)?jin)好几?最后是在论坛上扑ֈ?jin)答?不能更新的原因有二。一是代价太高。二是有?br />能硬件做skinngQ蒙皮)(j)Q不能用软g的方法访问硬件的数据?/p>

清源游民 2006-10-26 16:30 发表评论
]]>
OGRE学习(fn)C?/title><link>http://www.shnenglu.com/yuanyajie/archive/2006/10/24/14087.html</link><dc:creator>清源游民</dc:creator><author>清源游民</author><pubDate>Tue, 24 Oct 2006 06:13:00 GMT</pubDate><guid>http://www.shnenglu.com/yuanyajie/archive/2006/10/24/14087.html</guid><wfw:comment>http://www.shnenglu.com/yuanyajie/comments/14087.html</wfw:comment><comments>http://www.shnenglu.com/yuanyajie/archive/2006/10/24/14087.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/yuanyajie/comments/commentRss/14087.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/yuanyajie/services/trackbacks/14087.html</trackback:ping><description><![CDATA[如果一个h物有几个动画状?而在E序中需要对动画状态作切换?一定要先前的那个状态关?然后再作切换.<br />    //假设先前的动ȝ态是Wait,在切换到新的动画状态时,应该先将Waitx.是W一句话:以下为可能的代码片断.<br />    <u>mAnimationState->setEnabled(false);<br /></u>    mAnimationState = mEntity->getAnimationState( "Walk" );<br />    mAnimationState->setLoop( true );<br />    mAnimationState->setEnabled( true);<br />   //2006.10.24<img src ="http://www.shnenglu.com/yuanyajie/aggbug/14087.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/yuanyajie/" target="_blank">清源游民</a> 2006-10-24 14:13 <a href="http://www.shnenglu.com/yuanyajie/archive/2006/10/24/14087.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss> <footer> <div class="friendship-link"> <p>лǵվܻԴȤ</p> <a href="http://www.shnenglu.com/" title="精品视频久久久久">精品视频久久久久</a> <div class="friend-links"> </div> </div> </footer> <a href="http://www.glhu.cn" target="_blank">99Ʒþþþþþó</a>| <a href="http://www.upboss.cn" target="_blank">þþƷɫ鶹</a>| <a href="http://www.92slw.cn" target="_blank">þþþþۺһĻ</a>| <a href="http://www.yjpute.cn" target="_blank">99þۺϺݺۺϾþ</a>| <a href="http://www.setocaster.cn" target="_blank">ŷ龫Ʒþþþþþþžž </a>| <a href="http://www.ruan8.cn" target="_blank">þþwww˳ɾƷ</a>| <a href="http://www.tianyicpa.com.cn" target="_blank">˾þô߽AV</a>| <a href="http://www.czzdjsj.cn" target="_blank">һ㽶þֻ</a>| <a href="http://www.zhhhtch.cn" target="_blank">ɫþùƷ12p</a>| <a href="http://www.dbwlcom.cn" target="_blank">պAVþһ</a>| <a href="http://www.123yo.cn" target="_blank">Ʒþþþû</a>| <a href="http://www.fangfangmm.cn" target="_blank">þþþþþþƷŮ99</a>| <a href="http://www.niutuan.com.cn" target="_blank">þþݾþþ</a>| <a href="http://www.jrtz232.cn" target="_blank">þ޾Ʒվ</a>| <a href="http://www.lianliankan123.cn" target="_blank">þþþùƷ</a>| <a href="http://www.123yo.cn" target="_blank">ɫۺϾžþ</a>| <a href="http://www.kdplastics.cn" target="_blank">ݺݸɺݺݾþ</a>| <a href="http://www.wcjty.cn" target="_blank">þպƬ</a>| <a href="http://www.gpshd.cn" target="_blank">91þó</a>| <a href="http://www.guwz.cn" target="_blank">þ޾Ʒ˳ۺ</a>| <a href="http://www.spbbs.cn" target="_blank">þþƷֻо99Ʒ</a>| <a href="http://www.rh-hr.cn" target="_blank">ھƷþþþþþ97ţţ </a>| <a href="http://www.ichz.cn" target="_blank">þAVĻ</a>| <a href="http://www.z5621.cn" target="_blank">þþþþþþþ</a>| <a href="http://www.yrjiameng.cn" target="_blank">þۺŷ</a>| <a href="http://www.951ax.cn" target="_blank">޹˾þһþ </a>| <a href="http://www.hybdh.cn" target="_blank">þùƷһ</a>| <a href="http://www.98sr.cn" target="_blank">޾þһ</a>| <a href="http://www.p7751.cn" target="_blank">ݺݾþŷר</a>| <a href="http://www.d13722.cn" target="_blank">þþƷav鶹ͼƬ</a>| <a href="http://www.jxjkyt.cn" target="_blank">þAٸ۲ӰԺ</a>| <a href="http://www.zhongxiangka.cn" target="_blank">ھƷþþþþ99</a>| <a href="http://www.ijlm.cn" target="_blank">99ξþþŷƷվ</a>| <a href="http://www.kimhi.cn" target="_blank">þ99ۺϾƷҳ</a>| <a href="http://www.panxl.cn" target="_blank">þþƷֻоƷ2020</a>| <a href="http://www.mycqh.cn" target="_blank">ɫþþۺľþav</a>| <a href="http://www.ijlm.cn" target="_blank">þþƷȫۿ</a>| <a href="http://www.nuopie.cn" target="_blank">þҹ³˿ƬҹƷ</a>| <a href="http://www.liaojiaren.cn" target="_blank">þ޹Ʒһ</a>| <a href="http://www.seajack.cn" target="_blank">þþþþùƷ</a>| <a href="http://www.btalhb.cn" target="_blank">Ů޾Ʒþþۺ</a>| <script> (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })(); </script> </body>