<?xml version="1.0" encoding="gb2312"?>
<rss version="2.0">
<channel>
<title><![CDATA[红苹果乐园]]></title>
        <image>
        <title>http://hi.baidu.com</title>
        <link>http://hi.baidu.com</link>
        <url>http://img.baidu.com/img/logo-hi.gif</url>
        </image>
<description><![CDATA[从青苹果，到红苹果，经历了太多，也成长了很多，希望可以记录点点滴滴，作为以后回忆的家园！]]></description>
<link>http://hi.baidu.com/yuexiang%5F0207</link>
<language>zh-cn</language>
<generator>www.baidu.com</generator>
<ttl>5</ttl>


<item>
        <title><![CDATA[虚拟城市]]></title>
        <link><![CDATA[http://hi.baidu.com/yuexiang%5F0207/blog/item/a53faf242d32e93b8744f9dc.html]]></link>
        <description><![CDATA[
		
		<p>虚拟城市</p>
<p>关键词：虚拟城市，VRML, LOD</p>
<div class="spctrl"> </div>
　　虚拟城市是综合地运用GIS、遥感、遥测、网络、多媒体及虚拟仿真等技术，对城市内的基础设施、功能机制进行自动采集、动态监测管理和辅助决策的数字化城市。<br>
<div class="spctrl"> </div>
　　长期以来，城市规划人员的一个重要的工作就是进行各种设计或规划图的绘制，但是这些图纸并不能给人们提供一个直观的、富有真实感的场景。后来，人们虽然也使用纸板或木料来制作三维模型，以实现城市景观的三维可视化。但其制作的工作量巨大、费用昂贵、须具备较高的制作技巧，而且仅能从外围观看，无法进入，修改也很困难。鉴于以上原因，在计算机上建立三维虚拟城市成为必然。虚拟城市的建立能够全方位地、直观地给人们提供有关城市的各种具有真实感的场景信息，并可以以第一人称的身份进入城市，感受到与实地观察相似的真实感。虚拟城市的各种模型易于修改，而且可以实现城市信息的查询与分析功能。这些都是传统的方法所无法比拟的。本文用制作实例的方式探讨了虚拟城市的开发技术。<br>
<div class="spctrl"> </div>
　　1． 虚拟城市开发的基本原理<br>
<div class="spctrl"> </div>
　　要建立虚拟城市，首先要建立三维城市模型。三维城市空间中的典型实体对象一般具有以下几种：城市中的各种建筑物、街道、绿地、公共场所、城市地形、树木等。除此以外，还有一些辅助性的设施，如消防栓、变电站、喷泉、公园的长椅等。这些模型的制作可以采用编程的方法或者现有的三维模型制作软件来完成。所谓编程的方法是在程序中利用三维空间中的坐标点和图形绘制函数来实现模型的建立，由于城市模型的造型十分复杂，因而很难确定模型的具体几何数据，此方法多用来制作地形模型，对于其他模型的制作则很少采用。制作城市模型的最好的方法是使用现有的成熟的三维设计软件，如：3DSMAX、TRUESPACE等。<br>
<div class="spctrl"> </div>
　　虚拟城市除了能实现城市信息的三维可视化外，其另一个重要的功能就是能实现城市专题信息的查询功能，甚至实现一定的分析功能。可以将虚拟城市定义为以下公式：<br>
<div class="spctrl"> </div>
　　虚拟城市=三维城市模型+专题信息+查询功能+分析功能<br>
<div class="spctrl"> </div>
　　要实现一个虚拟城市系统可考虑以下两种方案：<br>
<div class="spctrl"> </div>
　　一种方案是利用高级语言和三维图形开发库的方法，常用的开发语言是C++，常用的图形开发库是OpenGL3D或者 Directx3D。此方法的特点是开发的灵活性强、能实现功能复杂的应用系统。其缺点是开发者须熟练掌握编程技术，并且具备较高的计算机图形学知识。另外，还要学习OpenGL3D或者 Directx3D的复杂开发技术。此方案的实现难度大，一般用户根本无法胜任。其实现的应用系统也很难满足网上使用的要求。<br>
<div class="spctrl"> </div>
　　第二种方案是使用专用的三维虚拟开发工具，目前广泛使用的是VRML语言。VRML（虚拟现实造型语言）是一种描述交互式三维世界和对象的文件格式。VRML允许描述对象并把对象组合到虚拟场景中，可以实现仿真系统，可模拟动画、具有动力学特性的物体。VRML能构造一个全交互的世界，其中的对象能对外部事件做出响应，并可在其中任意穿行。另外，其重要特性是支持虚拟场景的网上发布，并可实现多用户的实时参与。VRML比高级语言容易掌握，并且无须再去了解OpenGL3D或者 Directx3D之类的三维图形开发库，这对于普通用户来说无疑是一个福音。若配以Java程序的支持，也可实现功能较强大的系统。<br>
<div class="spctrl"> </div>
　　综合以上两种方法，对于功能不太复杂的应用，采用后一种方法较为合适。下面我们将就后一种方案详细介绍虚拟城市开发的技术细节。<br>
<div class="spctrl"> </div>
　　2． 虚拟城市的开发技术<br>
<div class="spctrl"> </div>
　　2．1．三维城市模型的建立<br>
<div class="spctrl"> </div>
　　虚拟场景的建立和建筑CAD中的场景的建立有着很大的区别，它首先强调的是模型的简单化，这是由虚拟现实的实时性要求决定的。在响应速度和场景的真实性发生冲突时，应牺牲一定的真实性，只要能在视觉上达到基本真实即可。因此，常用一些简单的框架来代替复杂模型，但为了保证一定的真实性，可采用贴图的方式来弥补视觉上的不足。贴图有以下两种制作方法：一种是使用绘画软件进行手工绘制、另一种是对建筑物的各个观察面进行拍照，然后用扫描仪扫描成相关贴图材质。第一种方法的颜色可限定在256色内，其压缩的比例较大，贴图文件较小，生成的场景文件也较小，适合网上传递和实时性的要求。后一种方法视觉效果好，但文件的压缩比例较小，贴图文件较大，生成的场景大，在网上传递和实时性方面不如前一种方法好。无论用哪一种方法都需考虑贴图的分辨率和尺寸，为了便于下载和渲染，在质量和大小允许的情况下，一幅贴图限为320*240（或240*320）像素、分辨率为72dpi，用JPEG压缩（采用最高压缩比）后约为20K字节。<br>
<div class="spctrl"> </div>
　　根据以上所述的贴图制作方法，虚拟场景中的对象模型可分为以下几类：<br>
<div class="spctrl"> </div>
　　(a)由简单几何体组成的简单模型：该类模型常用作远处建筑物的替身，在LOD方法中采用；<br>
<div class="spctrl"> </div>
　　(b) 赋予手绘贴图的模型；<br>
<div class="spctrl"> </div>
　　(c) 赋予照片材质的模型；<br>
<div class="spctrl"> </div>
　　(d) 赋予手绘和照片混合材质的模型；<br>
<div class="spctrl"> </div>
　　(e) 具有全部细节的精致模型；<br>
<div class="spctrl"> </div>
　　2．1．虚拟城市交互查询功能的建立<br>
<div class="spctrl"> </div>
　　为虚拟城市模型加入交互和查询功能可采用两种方法：通过编程加入相应的交互和查询功能、利用VRML的辅助工具来完成交互和查询功能的加入。后一种方法比较适合普通的用户。<br>
<div class="spctrl"> </div>
　　Kinetix制作了特殊的VRML输出嵌入程序，可以输出场景，包括几何、材质、动画制作等，嵌入程序也可制作特殊的VRML辅助工具来规定场景的交互元素。运行VRML嵌入 程序VRMLOUT.EXE即可安装VRML嵌入程序。<br>
<div class="spctrl"> </div>
　　通过VRML嵌入程序，可设置以下辅助工具：<br>
<div class="spctrl"> </div>
　　Anchor:可将某一实体作为热点，当被点击时，取出网上所指定的文件。若为VRML场景文件，则该场景被下载显示。若为其他类型文件，由浏览器决定如何处理；<br>
<div class="spctrl"> </div>
　　TouchSensor:对从指定设备的输入产生相应的事件，这些事件表示用户是否指向特定几何体，同时也表示用户何时何处按下定位设备的按钮；<br>
<div class="spctrl"> </div>
　　ProxSensor:接近感知器，指定当用户进入、离开或在立方体的区域内移动时产生的事件；<br>
<div class="spctrl"> </div>
　　TimeSensor:在时间变化是发出事件，可用来控制动画，也可用于某一时刻进行某项活动，或于某一时间间隔中产生事件；<br>
<div class="spctrl"> </div>
　　NavInfo:描述有关观察者和观察模式的物理特性；<br>
<div class="spctrl"> </div>
　　Background:设定场景的背景；<br>
<div class="spctrl"> </div>
　　Fog:设置雾化的效果；<br>
<div class="spctrl"> </div>
　　Sound:设定声音片段的有效范围，以产生随距离改变的音响效果；<br>
<div class="spctrl"> </div>
　　Billboard:是某一对象随用户一起旋转，以使之始终面向用户；<br>
<div class="spctrl"> </div>
　　LOD:允许浏览器在物体表示的不同层次细节间自动切换；<br>
<div class="spctrl"> </div>
　　Inline:可在文件中引入外部文件的场景，避免重复制作。<br>
<div class="spctrl"> </div>
　　通过以上辅助工具，就可制作出虚拟城市场景及其交互和查询功能。<br>
<div class="spctrl"> </div>
　　2．3．若干开发技巧介绍<br>
<div class="spctrl"> </div>
　　2.3.1 减少文件大小的方法<br>
<div class="spctrl"> </div>
　　(1) 使用实例：对于在场景中多次使用的对象，可在该对象首次使用时用DEF给物体命名，以后仅需通过名字即可引用该物体。<br>
<div class="spctrl"> </div>
　　(2) 使用原型：原型物体是指那些使用频繁且改动不大的物体。使用它可减少文件的大小。由于使用了DEF/USE方法，物体一旦定义，只要指定发生变化的公共接口即可。另外，原型显示出场景层次中哪一部分可修改，浏览器可自由地优化那些不修改的部分。<br>
<div class="spctrl"> </div>
　　(3) 压缩文件：在发布文件前，使用gzip工具压缩VRML文件和相关的HTML文件，大约可是文件减小10~100倍。<br>
<div class="spctrl"> </div>
　　2.3.2 提高渲染速度的技巧<br>
<div class="spctrl"> </div>
　　(1) 简化场景：简化场景有以下方法：<br>
<div class="spctrl"> </div>
　　·减少多边形的数目，这可极大地提高执行的性能；<br>
<div class="spctrl"> </div>
　　·使用纹理代替多边形造型，既可美化场景又可提高性能；<br>
<div class="spctrl"> </div>
　　·使用灰度图的纹理；<br>
<div class="spctrl"> </div>
　　·尽量少用光源，这将有效地提高渲染的速度；<br>
<div class="spctrl"> </div>
　　·使用布告板节点，此节点允许在场景中使用二维图象来模拟三维造型并旋转，从而始终面对观察者。此法既减小了文件又不影响真实效果，可用来制作树木、电线杆、路牌、消防栓等辅助性对象；<br>
<div class="spctrl"> </div>
　　(2)场景分割:将大的场景分为多个相对独立的小场景，通过Anchor节点为场景中逻辑上分离的部分建立连接关系；<br>
<div class="spctrl"> </div>
　　(3)自适应LOD节点：若在LOD的range域中未明确指定具体值，浏览器会在给定时刻决定哪一层物体需要显示。该节点允许根据硬件平台的能力调整场景的细节程度。在建立一条街道时，由于街道两边有许多精细的建筑物，要对它们进行实时渲染是不可能的，但又不能不可见，仅需让用户能以一定的速度前进即可。在此，可为每个建筑物建立两个LOD节点，一个是没有明确范围的外部LOD，另一个是具有near和far范围的内部LOD节点。内部节点能按建筑物与摄像机的距离调整层次，外部&quot;自适应LOD&quot;节点允许浏览器调整必要的多个建筑物以赶上场景的动态变化。<br>
<div class="spctrl"> </div>
　　(4) 碰撞检测要花费大量的处理时间，为提高对复杂物体的碰撞检测速度，可在Collision节点的proxy（替身）域指定某一更为简单的几何体作为该形体的替身，它与被替代的原形体占用大致相同的空间。这样，可大大减少检测时间。<br>
<div class="spctrl"> </div>
　　3． 结束语<br>
<div class="spctrl"> </div>
　　以上介绍了虚拟城市的基本原理和制作技巧，对于进行其他领域的虚拟现实应用制作同样有效，仅为场景中实体的不同。用VRML制作虚拟现实入门容易，但要达到很高的视觉效果和运行速度并非易事，须对VRML和图形学进行深入了解才可胜任。我们用它制作了虚拟校园，其运行效果较为满意。可以相信，随着VRML的不断发展，我们将可用它制作出功能更加强大的虚拟现实应用。<br>
<div class="spctrl"> </div>
　　另一方面网络上流行的虚拟城市是完全伪虚拟城市<br>
<div class="spctrl"> </div>
　　虚拟城市是在网络上的一种虚拟的模拟现实生活中的情景。比如像&ldquo;露雨虚拟城市&rdquo;http://www.luyu.net，就是一个典型的虚拟城市，包括游戏，生活，工作，交流都可以做到。 <br>
<div class="spctrl"> </div>
　　而到目前为止，最为成熟的虚拟城市是美国林登实验室开发运营的&ldquo;第二人生&rdquo;，其完全是开放式的平台，其中有纽约、有中国城，完全照搬了现实世界，并且用户可以通过客户端展示自己的一切创意，而在国内，虚拟城市也正在起步，目前国内较早的以用户创造内容为模式的虚拟城市如hipihi，novoking已经陷入运营困境，这类为客户端虚拟城市由于其技术限制，不能呈现出高仿真度的虚拟都市，人物和场景画面都比较粗糙。而另外一种非UGC（用户创造内容）模式的虚拟城市，如哈啪世界（hapaworld）也已出现，哈啪世界采用国外顶尖的Unreal3引擎进行开发，无论人物还是场景画面都具有高仿真的逼真效果，当然这类大客户端产品，要保证其流畅的运行，就需要较高的电脑配置，高性能的显卡以及足够大的网络带宽。<br> <a href="http://hi.baidu.com/yuexiang%5F0207/blog/item/a53faf242d32e93b8744f9dc.html">阅读全文</a>
		
		<br/><b>类别：</b><a href="http://hi.baidu.com/yuexiang%5F0207/blog/category/%C8%FD%CE%AC%B7%BD%C3%E6%D6%AA%CA%B6">三维方面知识</a>&nbsp;<a href="http://hi.baidu.com/yuexiang%5F0207/blog/item/a53faf242d32e93b8744f9dc.html#comment">查看评论</a>]]></description>
        <pubDate>2009-06-02  21:13</pubDate>
        <category><![CDATA[三维方面知识]]></category>
        <author><![CDATA[yuexiang_0207]]></author>
		<guid>http://hi.baidu.com/yuexiang%5F0207/blog/item/a53faf242d32e93b8744f9dc.html</guid>
</item>

<item>
        <title><![CDATA[viewport视口参数]]></title>
        <link><![CDATA[http://hi.baidu.com/yuexiang%5F0207/blog/item/775d1390ee7ba385a977a4ba.html]]></link>
        <description><![CDATA[
		
		<div class="real_blog" style="text-indent: 2em; height: auto! important">
<table style="table-layout: fixed; width: 100%; position: relative" cellspacing="0" cellpadding="0">
    <tbody>
        <tr>
            <td style="word-wrap: break-word" valign="top">
            <div class="real_blog" style="text-indent: 2em; height: auto! important">
            <table style="table-layout: fixed; width: 100%; position: relative" cellspacing="0" cellpadding="0">
                <tbody>
                    <tr>
                        <td style="word-wrap: break-word" valign="top">
                        <div style="overflow: hidden; position: relative; height: 100%"><img style="display: none" src="http://cnc.imgcache.qq.com/ac/b.gif">
                        <div align="center"> </div>
                        <img style="display: none" src="http://cnc.imgcache.qq.com/ac/b.gif">
                        <div style="font-size: 16px"><wbr></wbr><a href="http://i.msdn.microsoft.com/Bb199808.pubproperty(en-US,XNAGameStudio.30).gif" target="_blank" eventslistuid="e3"><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" src="http://i.msdn.microsoft.com/Bb199808.pubproperty(en-US,XNAGameStudio.30).gif" bloaded="true" loadingtimer="80580681" orgsrc="http://i.msdn.microsoft.com/Bb199808.pubproperty(en-US,XNAGameStudio.30).gif"></a><wbr></wbr><a href="http://msdn.microsoft.com/en-us/library/microsoft.xna.framework.graphics.viewport.aspectratio.aspx" target="_blank" eventslistuid="e4"><span style="color: #0033cc; line-height: 1.8em">AspectRatio</span><wbr></wbr></a><wbr></wbr>Gets the aspect ratio used by the viewport<wbr></wbr><a href="http://i.msdn.microsoft.com/Bb199808.pubproperty(en-US,XNAGameStudio.30).gif" target="_blank" eventslistuid="e5"><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" src="http://i.msdn.microsoft.com/Bb199808.pubproperty(en-US,XNAGameStudio.30).gif" bloaded="true" orgsrc="http://i.msdn.microsoft.com/Bb199808.pubproperty(en-US,XNAGameStudio.30).gif"></a><wbr></wbr><a href="http://msdn.microsoft.com/en-us/library/microsoft.xna.framework.graphics.viewport.height.aspx" target="_blank" eventslistuid="e6"><span style="color: #0033cc; line-height: 1.8em">Height</span><wbr></wbr></a><wbr></wbr>Gets or sets the height dimension of the viewport on the render-target surface, in pixels.<wbr></wbr><a href="http://i.msdn.microsoft.com/Bb199808.pubproperty(en-US,XNAGameStudio.30).gif" target="_blank" eventslistuid="e7"><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" src="http://i.msdn.microsoft.com/Bb199808.pubproperty(en-US,XNAGameStudio.30).gif" bloaded="true" orgsrc="http://i.msdn.microsoft.com/Bb199808.pubproperty(en-US,XNAGameStudio.30).gif"></a><wbr></wbr><a href="http://msdn.microsoft.com/en-us/library/microsoft.xna.framework.graphics.viewport.maxdepth.aspx" target="_blank" eventslistuid="e8"><span style="color: #0033cc; line-height: 1.8em">MaxDepth</span><wbr></wbr></a><wbr></wbr>Gets or sets the maximum depth of the clip volume.<wbr></wbr><a href="http://i.msdn.microsoft.com/Bb199808.pubproperty(en-US,XNAGameStudio.30).gif" target="_blank" eventslistuid="e9"><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" src="http://i.msdn.microsoft.com/Bb199808.pubproperty(en-US,XNAGameStudio.30).gif" bloaded="true" orgsrc="http://i.msdn.microsoft.com/Bb199808.pubproperty(en-US,XNAGameStudio.30).gif"></a><wbr></wbr><a href="http://msdn.microsoft.com/en-us/library/microsoft.xna.framework.graphics.viewport.mindepth.aspx" target="_blank" eventslistuid="e10"><span style="color: #0033cc; line-height: 1.8em">MinDepth</span><wbr></wbr></a><wbr></wbr>Gets or sets the minimum depth of the clip volume.<wbr></wbr><a href="http://i.msdn.microsoft.com/Bb199808.pubproperty(en-US,XNAGameStudio.30).gif" target="_blank" eventslistuid="e11"><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" src="http://i.msdn.microsoft.com/Bb199808.pubproperty(en-US,XNAGameStudio.30).gif" bloaded="true" orgsrc="http://i.msdn.microsoft.com/Bb199808.pubproperty(en-US,XNAGameStudio.30).gif"></a><wbr></wbr><a href="http://msdn.microsoft.com/en-us/library/microsoft.xna.framework.graphics.viewport.titlesafearea.aspx" target="_blank" eventslistuid="e12"><span style="color: #0033cc; line-height: 1.8em">TitleSafeArea</span><wbr></wbr></a><wbr></wbr>Returns the title safe area of the current viewport.<wbr></wbr><a href="http://i.msdn.microsoft.com/Bb199808.pubproperty(en-US,XNAGameStudio.30).gif" target="_blank" eventslistuid="e13"><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" src="http://i.msdn.microsoft.com/Bb199808.pubproperty(en-US,XNAGameStudio.30).gif" bloaded="true" orgsrc="http://i.msdn.microsoft.com/Bb199808.pubproperty(en-US,XNAGameStudio.30).gif"></a><wbr></wbr><a href="http://msdn.microsoft.com/en-us/library/microsoft.xna.framework.graphics.viewport.width.aspx" target="_blank" eventslistuid="e14"><span style="color: #0033cc; line-height: 1.8em">Width</span><wbr></wbr></a><wbr></wbr>Gets or sets the width dimension of the viewport on the render-target surface, in pixels.<wbr></wbr><a href="http://i.msdn.microsoft.com/Bb199808.pubproperty(en-US,XNAGameStudio.30).gif" target="_blank" eventslistuid="e15"><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" src="http://i.msdn.microsoft.com/Bb199808.pubproperty(en-US,XNAGameStudio.30).gif" bloaded="true" orgsrc="http://i.msdn.microsoft.com/Bb199808.pubproperty(en-US,XNAGameStudio.30).gif"></a><wbr></wbr><a href="http://msdn.microsoft.com/en-us/library/microsoft.xna.framework.graphics.viewport.x.aspx" target="_blank" eventslistuid="e16"><span style="color: #0033cc; line-height: 1.8em">X</span><wbr></wbr></a><wbr></wbr>Gets or sets the pixel coordinate of the upper-left corner of the viewport on the render-target surface.<wbr></wbr><a href="http://i.msdn.microsoft.com/Bb199808.pubproperty(en-US,XNAGameStudio.30).gif" target="_blank" eventslistuid="e17"><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" src="http://i.msdn.microsoft.com/Bb199808.pubproperty(en-US,XNAGameStudio.30).gif" bloaded="true" orgsrc="http://i.msdn.microsoft.com/Bb199808.pubproperty(en-US,XNAGameStudio.30).gif"></a><wbr></wbr><a href="http://msdn.microsoft.com/en-us/library/microsoft.xna.framework.graphics.viewport.y.aspx" target="_blank" eventslistuid="e18"><span style="color: #0033cc; line-height: 1.8em">Y</span><wbr></wbr></a><wbr></wbr>Gets or sets the pixel coordinate of the upper-left corner of the viewport on the render-target surface.<br>
                        x,y起点位置&nbsp;&nbsp; height,width宽度和高度, maxdepth,mindepth，Z值深度缓存、</div>
                        </div>
                        </td>
                    </tr>
                </tbody>
            </table>
            </div>
            </td>
        </tr>
    </tbody>
</table>
</div> <a href="http://hi.baidu.com/yuexiang%5F0207/blog/item/775d1390ee7ba385a977a4ba.html">阅读全文</a>
		
		<br/><b>类别：</b><a href="http://hi.baidu.com/yuexiang%5F0207/blog/category/%C8%FD%CE%AC%B7%BD%C3%E6%D6%AA%CA%B6">三维方面知识</a>&nbsp;<a href="http://hi.baidu.com/yuexiang%5F0207/blog/item/775d1390ee7ba385a977a4ba.html#comment">查看评论</a>]]></description>
        <pubDate>2009-05-25  16:41</pubDate>
        <category><![CDATA[三维方面知识]]></category>
        <author><![CDATA[yuexiang_0207]]></author>
		<guid>http://hi.baidu.com/yuexiang%5F0207/blog/item/775d1390ee7ba385a977a4ba.html</guid>
</item>

<item>
        <title><![CDATA[quaternion 的含义]]></title>
        <link><![CDATA[http://hi.baidu.com/yuexiang%5F0207/blog/item/07b64cce5aa40531b600c8b9.html]]></link>
        <description><![CDATA[
		
		<div style="font-size: 16px"><span style="font-size: 13px; line-height: 1.8em">在<span style="line-height: 1.8em; ">3D</span><wbr></wbr>程序中，通常用<span style="line-height: 1.8em; ">quaternion</span><wbr></wbr></span><wbr></wbr>来计算<span style="line-height: 1.8em; ">3D</span><wbr></wbr>物体的旋转角度，与<span style="line-height: 1.8em; ">Matrix</span><wbr></wbr>相比，<span style="line-height: 1.8em; ">quaternion</span><wbr></wbr><wbr></wbr>更加高效，占用的储存空间更小，此外也更便于插值。在数学上，<span style="line-height: 1.8em; ">quaternion</span><wbr></wbr><wbr></wbr>表示复数<span style="line-height: 1.8em; ">w+xi+yj+zk</span><wbr></wbr>，其中<span style="line-height: 1.8em; ">i,j,k</span><wbr></wbr>都是虚数单位：<wbr></wbr><br>
<span style="font-size: 13px; color: #0000ff; line-height: 1.8em; ">i*i = j*j = k*k= -1</span><wbr></wbr><br>
<span style="font-size: 13px; color: #0000ff; line-height: 1.8em; ">i*j = k, j*i = -k</span><wbr></wbr><br>
<br>
<span style="font-size: 13px; line-height: 1.8em"><span style="color: #000000; line-height: 1.8em">可以把<span style="line-height: 1.8em; ">quaternion</span><wbr></wbr></span><wbr></wbr>看做一个标量和一个<span style="line-height: 1.8em; ">3D</span><wbr></wbr>向量的组合。实部<span style="line-height: 1.8em; ">w</span><wbr></wbr>表示标量，虚部表示向量标记为<span style="line-height: 1.8em; ">V</span><wbr></wbr></span><wbr></wbr>，或三个单独的分量（<span style="line-height: 1.8em; ">x,y,z</span><wbr></wbr>）。所以<span style="line-height: 1.8em; ">quaternion</span><wbr></wbr><wbr></wbr>可以记为<span style="line-height: 1.8em; ">[ w, V</span><wbr></wbr>]<wbr></wbr>或<span style="line-height: 1.8em; ">[ w</span><wbr></wbr>，（<span style="line-height: 1.8em; ">x,y,x</span><wbr></wbr>）。对<span style="line-height: 1.8em; ">quaternion</span><wbr></wbr><wbr></wbr>最大的误解在于认为<span style="line-height: 1.8em; ">w</span><wbr></wbr>表示旋转角度，<span style="line-height: 1.8em; ">V</span><wbr></wbr><wbr></wbr>表示旋转轴。正确的理解应该是<span style="line-height: 1.8em; ">w</span><wbr></wbr>与旋转角度有关，<span style="line-height: 1.8em; ">v</span><wbr></wbr>与旋转轴有关。例如，要表示以向量<span style="line-height: 1.8em; ">N</span><wbr></wbr><wbr></wbr>为轴，轴旋α度<span style="line-height: 1.8em; ">,</span><wbr></wbr>相对的<span style="line-height: 1.8em; ">quaternion</span><wbr></wbr><wbr></wbr>应该是：<wbr></wbr><wbr></wbr><br>
<wbr></wbr><br>
<br>
<span style="font-size: 13px; line-height: 1.8em"><span style="color: #0000ff; line-height: 1.8em"><span style="line-height: 1.8em; ">q = [ cos(</span><wbr></wbr>α<span style="line-height: 1.8em; ">/ 2) , sin(</span><wbr></wbr>α<span style="line-height: 1.8em; ">/ 2) N</span><wbr></wbr>]</span><wbr></wbr></span><wbr></wbr><wbr></wbr><br>
<span style="font-size: 13px; line-height: 1.8em"><span style="color: #0000ff; line-height: 1.8em"><span style="line-height: 1.8em; ">&nbsp;&nbsp; =[ cos(</span><wbr></wbr>α<span style="line-height: 1.8em; ">/ 2) , ( sina(</span><wbr></wbr>α<span style="line-height: 1.8em; ">/ 2) N</span><wbr></wbr>x, sin(</span><wbr></wbr>α<span style="line-height: 1.8em; ">/ 2)N</span><wbr></wbr>y, sin(</span><wbr></wbr>α<span style="line-height: 1.8em; ">/ 2)N</span><wbr></wbr>z ) ]<wbr></wbr><wbr></wbr><wbr></wbr><br>
<wbr></wbr><br>
<br>
<span style="font-size: 13px; line-height: 1.8em"><span style="color: #000000; line-height: 1.8em">为了计算方便，一般要求<span style="line-height: 1.8em; ">N</span><wbr></wbr></span><wbr></wbr>为单位矢量。对<span style="line-height: 1.8em; ">quaternion</span><wbr></wbr></span><wbr></wbr>来说使用四个值就能记录旋转，而不是<span style="line-height: 1.8em; ">Matrix</span><wbr></wbr>所需的十六个值。为什么用<span style="line-height: 1.8em; ">quaternion</span><wbr></wbr><wbr></wbr>来计算旋转很方便呢<span style="line-height: 1.8em; ">?</span><wbr></wbr>先说过<span style="line-height: 1.8em; ">quaternion</span><wbr></wbr><wbr></wbr>是一个复数<span style="line-height: 1.8em; ">,</span><wbr></wbr>如果你还记得一点点复数的知识<span style="line-height: 1.8em; ">,</span><wbr></wbr>那么应该知道复数乘法<span style="line-height: 1.8em; ">(</span><wbr></wbr>叉乘<span style="line-height: 1.8em; ">)</span><wbr></wbr>的几何意义实际上就是对复数进行旋转。对最简单的复数<span style="line-height: 1.8em; ">p= x + yi</span><wbr></wbr>来说，和另一个复数<span style="line-height: 1.8em; ">q = ( con</span><wbr></wbr>α，<span style="line-height: 1.8em; ">sin</span><wbr></wbr>α<span style="line-height: 1.8em; ">)</span><wbr></wbr>相乘，则表示把<span style="line-height: 1.8em; ">p</span><wbr></wbr>沿逆时针方向旋转α：<wbr></wbr><wbr></wbr><br>
<wbr></wbr><br>
<br>
<span style="font-size: 13px; color: #000080; line-height: 1.8em; "><span style="color: #0000ff; line-height: 1.8em">p&rsquo; = pq</span><wbr></wbr> </span><wbr></wbr><br>
<br>
<br>
<div style="text-align: center"><span style="line-height: 1.8em; "><wbr></wbr></span><wbr></wbr></div>
<br>
<span style="font-size: 13px; line-height: 1.8em"><span style="color: #000000; line-height: 1.8em">当然，<span style="line-height: 1.8em; ">x+yi</span><wbr></wbr>的形式只能表示<span style="line-height: 1.8em; ">2D</span><wbr></wbr>变换，对<span style="line-height: 1.8em; ">3D</span><wbr></wbr>变换来说就需要使用<span style="line-height: 1.8em; "> quaternion</span><wbr></wbr></span><wbr></wbr>了，而且计算也要复杂一点。为了对<span style="line-height: 1.8em; ">3D</span><wbr></wbr>空间中的一个点<span style="line-height: 1.8em; ">p</span><wbr></wbr>（<span style="line-height: 1.8em; ">x,y,z</span><wbr></wbr>）进行旋转，需要先把它转换为<span style="line-height: 1.8em; ">quaternion</span><wbr></wbr></span><wbr></wbr>形式<span style="line-height: 1.8em; ">p = [0, ( x, y, z)]</span><wbr></wbr>，接下来前面讨论的内容，定义<span style="line-height: 1.8em; ">q = cos(</span><wbr></wbr>α<span style="line-height: 1.8em; ">/ 2) , sin(</span><wbr></wbr>α<span style="line-height: 1.8em; ">/ 2) N</span><wbr></wbr><wbr></wbr>为旋转<span style="line-height: 1.8em; ">quaternion</span><wbr></wbr><wbr></wbr>，这里<span style="line-height: 1.8em; ">N</span><wbr></wbr><wbr></wbr>为单位矢量长度的旋转轴，α为旋转角度。那么旋转之后的点<span style="line-height: 1.8em; ">p&rsquo;</span><wbr></wbr>则为：<wbr></wbr><wbr></wbr><br>
<wbr></wbr><br>
<br>
<span style="line-height: 1.8em; "><span style="font-size: 13px; line-height: 1.8em"><span style="color: #000080; line-height: 1.8em">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><wbr></wbr><span style="color: #0000ff; line-height: 1.8em">p&rsquo; = qpq-1</span><wbr></wbr></span><wbr></wbr></span><wbr></wbr> </div> <a href="http://hi.baidu.com/yuexiang%5F0207/blog/item/07b64cce5aa40531b600c8b9.html">阅读全文</a>
		
		<br/><b>类别：</b><a href="http://hi.baidu.com/yuexiang%5F0207/blog/category/%C8%FD%CE%AC%B7%BD%C3%E6%D6%AA%CA%B6">三维方面知识</a>&nbsp;<a href="http://hi.baidu.com/yuexiang%5F0207/blog/item/07b64cce5aa40531b600c8b9.html#comment">查看评论</a>]]></description>
        <pubDate>2009-05-25  16:40</pubDate>
        <category><![CDATA[三维方面知识]]></category>
        <author><![CDATA[yuexiang_0207]]></author>
		<guid>http://hi.baidu.com/yuexiang%5F0207/blog/item/07b64cce5aa40531b600c8b9.html</guid>
</item>

<item>
        <title><![CDATA[XNA Shader 程序设计（二）]]></title>
        <link><![CDATA[http://hi.baidu.com/yuexiang%5F0207/blog/item/4cd7ff1e6da52d17413417b8.html]]></link>
        <description><![CDATA[
		
		<div style="font-size: 16px">XNA Shader 程序设计<br>
教程2 - 漫反射<br>
<wbr></wbr><a href="http://images.cnblogs.com/cnblogs_com/cocoaleaves/1.jpg" target="_blank" eventslistuid="e3"><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; width: 398px; height: 298px; border-right-width: 0px" src="http://images.cnblogs.com/cnblogs_com/cocoaleaves/1.jpg" bloaded="true" loadingtimer="80578999" orgsrc="http://images.cnblogs.com/cnblogs_com/cocoaleaves/1.jpg"></a><wbr></wbr><br>
<br>
<br>
大家好，今天我们将在教程一的基础上继续学习，在光照算式中加上漫反射光。<br>
<br>
漫反射光<br>
<br>
环境光计算等式为：<br>
I = Aintensity * Acolor<br>
<br>
漫反射基于这个等式，添加了一道有方向的光线：<br>
I = Aintensity x Acolor + Dintensity x Dcolor x N.L (2.1)<br>
<br>
通过计算式，你可以看到我们仍然使用了环境光，但添加了两个变量，分别表示漫反射光的光强和颜色，还添加了两个向量N和L，L表示光照方向，N表示表面法线。<br>
<br>
我们可以认为漫反射表现了一个表面如何反射光线。法线方向N和光线方向L的夹角越小，表面反射的光就越强。<br>
<br>
<wbr></wbr><a href="http://images.cnblogs.com/cnblogs_com/cocoaleaves/2.jpg" target="_blank" eventslistuid="e4"><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" src="http://images.cnblogs.com/cnblogs_com/cocoaleaves/2.jpg" bloaded="true" loadingtimer="80579005" orgsrc="http://images.cnblogs.com/cnblogs_com/cocoaleaves/2.jpg"></a><wbr></wbr><br>
<br>
<br>
当L和N平行，反射光最强，当L与物体表面平行，反射光最弱。<br>
<br>
我们可以通过计算向量的点积（或叫数量积）来得到L与N的夹角。这条计算向量夹角的法则定义如下：N.L = |N| x |L| x cos(a)。|N|是向量N的长度，|L|是向量L的长度，cos(a)表示两向量的夹角。<br>
<br>
实现shader<br>
我们需要三个全局变量<br>
<br>
float4x4&nbsp;&nbsp;&nbsp;&nbsp; matWorldViewProj;<br>
float4x4&nbsp;&nbsp;&nbsp;&nbsp; matInverseWorld;<br>
float4&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; vLightDirection;<br>
<br>
我们仍然需要教程一中介绍的worldviewprojection矩阵，同时需要添加InverseWorld矩阵来变换法线，添加vLightDirection表示光线方向。<br>
<br>
我们仍需为顶点着色器定义OUT结构体，从而把数据传给像素着色器：<br>
struct OUT <br>
{ <br>
&nbsp;&nbsp;&nbsp;&nbsp; float4 Pos: POSITION; <br>
&nbsp;&nbsp;&nbsp;&nbsp; float3 L:&nbsp;&nbsp;&nbsp;&nbsp; TEXCOORD0; <br>
&nbsp;&nbsp;&nbsp;&nbsp; float3 N:&nbsp;&nbsp;&nbsp;&nbsp; TEXCOORD1; <br>
};<br>
<br>
我们把位置Pos，光线方向L，法线N存在不同的寄存器中。TEXCOORDn可以用来表示任意值，在我们没有使用贴图的情况下，我们用它来存储向量。<br>
<br>
OK，下面是顶点着色器：<br>
OUT VertexShader( float4 Pos: POSITION, float3 N: NORMAL ) <br>
{ <br>
&nbsp;&nbsp;&nbsp;&nbsp; OUT Out = (OUT) 0; <br>
&nbsp;&nbsp;&nbsp;&nbsp; Out.Pos = mul(Pos, matWorldViewProj); <br>
&nbsp;&nbsp;&nbsp;&nbsp; Out.L = normalize(vLightDirection); <br>
&nbsp;&nbsp;&nbsp;&nbsp; Out.N = normalize(mul(matInverseWorld, N)); <br>
&nbsp;&nbsp;&nbsp;&nbsp; return Out; <br>
}<br>
<br>
我们从模型文件中获得顶点和法线的数据然后传递给shader，然后变换位置坐标，归一化光线方向，变换并归一化物体表面的法线。<br>
<br>
然后，在像素着色器中，把TEXCOORD0的值给L，TEXCOORD1的值给N，寄存器的值来自顶点着色器。下面在像素着色器中实现算式2.1：<br>
<br>
float4 PixelShader(float3 L: TEXCOORD0, float3 N: TEXCOORD1) : COLOR <br>
{&nbsp;&nbsp;  <br>
&nbsp;&nbsp;&nbsp;&nbsp; float Ai = 0.8f; <br>
&nbsp;&nbsp;&nbsp;&nbsp; float4 Ac = float4(0.075, 0.075, 0.2, 1.0);<br>
&nbsp;&nbsp;&nbsp;&nbsp; float Di = 1.0f; <br>
&nbsp;&nbsp;&nbsp;&nbsp; float4 Dc = float4(1.0, 1.0, 1.0, 1.0); <br>
&nbsp;&nbsp;&nbsp;&nbsp; return Ai * Ac + Di * Dc * saturate(dot(L, N)); <br>
}<br>
<br>
<br>
下面是这个shader的technique<br>
technique DiffuseLight <br>
{ <br>
&nbsp;&nbsp;&nbsp;&nbsp; pass P0 <br>
&nbsp;&nbsp;&nbsp;&nbsp; { <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; VertexShader = compile vs_1_1 VertexShader(); <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; PixelShader = compile ps_1_1 PixelShader(); <br>
&nbsp;&nbsp;&nbsp;&nbsp; } <br>
} </div> <a href="http://hi.baidu.com/yuexiang%5F0207/blog/item/4cd7ff1e6da52d17413417b8.html">阅读全文</a>
		
		<br/><b>类别：</b><a href="http://hi.baidu.com/yuexiang%5F0207/blog/category/%C8%FD%CE%AC%B7%BD%C3%E6%D6%AA%CA%B6">三维方面知识</a>&nbsp;<a href="http://hi.baidu.com/yuexiang%5F0207/blog/item/4cd7ff1e6da52d17413417b8.html#comment">查看评论</a>]]></description>
        <pubDate>2009-05-25  16:39</pubDate>
        <category><![CDATA[三维方面知识]]></category>
        <author><![CDATA[yuexiang_0207]]></author>
		<guid>http://hi.baidu.com/yuexiang%5F0207/blog/item/4cd7ff1e6da52d17413417b8.html</guid>
</item>

<item>
        <title><![CDATA[XNA Shader 程序设计（一）]]></title>
        <link><![CDATA[http://hi.baidu.com/yuexiang%5F0207/blog/item/19763959415b04222834f0b8.html]]></link>
        <description><![CDATA[
		
		<div style="font-size: 16px">XNA Shader 程序设计<br>
教程 1 &ndash; 环境光<br>
<wbr></wbr><a href="http://images.cnblogs.com/cnblogs_com/cocoaleaves/123.png" target="_blank" eventslistuid="e3"><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; width: 399px; height: 300px; border-right-width: 0px" src="http://images.cnblogs.com/cnblogs_com/cocoaleaves/123.png" bloaded="true" loadingtimer="80575879" orgsrc="http://images.cnblogs.com/cnblogs_com/cocoaleaves/123.png"></a><wbr></wbr> <br>
XNA Shader系列教程将包含XNA的许多方面，如何使用GPU，如何在XNA下编写HLSL shader。开始我会将一些基础理论，然后更多的是实践。<br>
理论部分不会非常详细，但对于学习和实践编写shader足够了。我会讲一些HLSL的基础知识，HLSL语言如何工作还有一些值得学习的关键字。<br>
<br>
今天我会介绍XNA和HLSL，也会讲一个简单的环境光理论。<br>
<br>
前置知识<br>
XNA编程的知识，我不会讲太多关于如何加载贴图、3D模型、矩阵和数学。<br>
<br>
shader简史<br>
在DirectX8之前，GPU变换顶点像素的方法是固定的，叫做&ldquo;固定渲染管线&rdquo;。这样，开发者在把顶点和像素传给GPU后，就无法控制处理器的工作，所以游戏图像看起来都差不多。<br>
DirectX8 引入了顶点着色器（vertex shader）和像素着色器（pixel shader），于是开发者可以控制渲染管线中的顶点和像素，灵活性大大提高。<br>
开始汇编语言用于shader的开发，这就让shader开发变得十分困难，并且仅支持shader model 1.0。但DirectX9的发布改变了这种状况，开发者有机会一个叫做High Level Shading Language（HLSL）的C语言风格的高级语言代替汇编语言。这让shader更容易读、写和学习。<br>
DirectX10.0引入了一个新的shader，几何着色器（Geometry Shader），是Shader Model 4.0的一部分。但这需要高档的显卡还有Windows Vista。<br>
XNA支持Shader Model 1.0到3.0，可以在XP, VISTA和Xbox360上工作！<br>
<br>
Shaders?<br>
好了，历史讲够了……那么，什么是shader？<br>
让我说，shader就是用来让开发者定制那些顶点和像素在渲染管线中被怎样处理。<br>
如下图，程序渲染的时候会使用shader，顶点缓冲通过顶点着色器与把数据交给像素着色器，它们共同工作创建出帧缓冲内的图片。<br>
<wbr></wbr><a href="http://images.cnblogs.com/cnblogs_com/cocoaleaves/456.png" target="_blank" eventslistuid="e4"><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; width: 524px; height: 306px; border-right-width: 0px" src="http://images.cnblogs.com/cnblogs_com/cocoaleaves/456.png" bloaded="true" loadingtimer="80575895" orgsrc="http://images.cnblogs.com/cnblogs_com/cocoaleaves/456.png"></a><wbr></wbr> <br>
嘱咐大家一个重要问题，许多GPU并不支持所有的shader model，这在shader开发时要考虑到。一个shader应该有不用的方法来实现相似的特效，这样程序才能在老机器上跑起来。<br>
<br>
顶点着色器（Vertex Shaders）<br>
顶点着色器用于逐顶点操作顶点数据。例如，可以通过把模型的每个顶点沿法线方向平移使模型在渲染时看起来变&ldquo;胖&rdquo;（deform shaders）。<br>
<br>
顶点着色器从程序定义的顶点结构体中获取数据，是在顶点缓冲中读取并传递给shader。这就确定了顶点会包含什么属性：位置、颜色、法线、正切值等。<br>
<br>
顶点着色器把输出数据传递给一会要用到的像素着色器。可以通过在shader中定义一个结构体来确定顶点着色器要传递给下一层的数据，或者通过在shader中定义带关键字out的参数。输出可以是位置、雾、颜色、纹理坐标、正切值、光照方向等等。<br>
<br>
<br>
struct VS_OUTPUT<br>
{<br>
&nbsp;&nbsp;&nbsp;&nbsp; float4 Pos: POSITION;<br>
};<br>
VS_OUTPUT VS( float4 Pos: POSITION )<br>
{<br>
&nbsp;&nbsp;&nbsp;&nbsp; VS_OUTPUT Out = (VS_OUTPUT) 0;<br>
&nbsp;&nbsp;&nbsp;&nbsp; ...<br>
&nbsp;&nbsp;&nbsp;&nbsp; return Out;<br>
}<br>
// 或者<br>
float3 VS(out float2 tex : TEXCOORD0) : POSITION<br>
{<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; tex = float2(1.0, 1.0);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return float3(0.0, 1.0, 0.0);<br>
}<br>
<br>
<br>
像素着色器<br>
像素着色器逐像素的处理给定的模型、物体、顶点集。这就像一个金属盒，我们可以在里面制定自己的光照法则等等。像素着色器从顶点着色器的输出中读取数据，例如位置、法线、纹理坐标。<br>
<br>
<br>
float4 PS(float vPos : VPOS, float2 tex : TEXCOORD0) : COLOR<br>
{<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ...<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return float4(1.0f, 0.3f, 0.7f, 1.0f);<br>
}<br>
<br>
像素着色器可以有两个输出，颜色和深度。<br>
<br>
<br>
HLSL<br>
HLSL用来开发shader。在HLSL中，你可以定义变量、函数、数据类型等用来编写顶点和像素的处理逻辑。下面是HLSL中部分关键字的列表，并不全面，但是最常见。<br>
<br>
<span style="font-weight: bold"><wbr></wbr>HSLS</span><wbr></wbr><span style="font-weight: bold"><wbr></wbr>数据类型</span><wbr></wbr><br>
bool true 或 false<br>
int 32位整数<br>
half 16位整数<br>
float 32位浮点数<br>
double 64位浮点数<br>
<br>
<span style="font-weight: bold"><wbr></wbr>HSLS</span><wbr></wbr><span style="font-weight: bold"><wbr></wbr>向量</span><wbr></wbr><br>
float3 vectorTest<br>
float vectorTest[3]<br>
vector vectorTest<br>
float2 vectorTest<br>
bool3 vectorTest<br>
<br>
<span style="font-weight: bold"><wbr></wbr>HSLS</span><wbr></wbr><span style="font-weight: bold"><wbr></wbr>矩阵</span><wbr></wbr><br>
float3x3: 3x3浮点数矩阵<br>
float2x2: 2x2浮点数矩阵<br>
<br>
还有一些辅助函数，用来帮助我们进行复杂的数学运算。<br>
cos( x ) 返回x余弦值<br>
sin( x) 返回x正弦值<br>
cross( a, b ) 返回向量a和b的矢量积 <br>
dot( a,b ) 返回向量a和b的数量积<br>
normalize( v ) 返回向量v的单位向量 ( v / |v| )<br>
<br>
完整的列表: <a href="http://msdn2.microsoft.com/en-us/library/bb509611.aspx" target="_blank" eventslistuid="e5">http://msdn2.microsoft.com/en-us/library/bb509611.aspx</a><wbr></wbr><br>
<br>
HLSL 提供了大量函数，就等你用了！学习它们，你会知道如何解决各种问题。<br>
<br>
Effect文件<br>
Effect文件（.fx）让HLSL编写shader变得简单，你可以在fx文件中存储任何东西。包括变量、函数、结构体、顶点着色器、像素着色器、techiques/passes、贴图等等。<br>
<br>
我们已经知道了如何在shader中声明变量和结构体，但是technique/passes是什么？其实很简单，一个shader可以包含若干technique，每个technique在游戏中有唯一的名字，我们可以选择使用shader中的哪个technique，通过设置Effect类的CurrentTechnique属性。<br>
effect.CurrentTechnique = effect.Techniques[&quot;AmbientLight&quot;];<br>
<br>
这里，我们让&ldquo;effect&rdquo;使用technique&ldquo;AmbientLight&rdquo;。一个technique可以包含一个或多个pass，我们需要使用所有的pass才能达到最终效果。<br>
<br>
这是一个包含一个technique一个pass的shader的例子：<br>
technique Shader<br>
{<br>
&nbsp;&nbsp;&nbsp;&nbsp; pass P0<br>
&nbsp;&nbsp;&nbsp;&nbsp; {<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; VertexShader = compile vs_1_1 VS();<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; PixelShader = compile ps_1_1 PS();<br>
&nbsp;&nbsp;&nbsp;&nbsp; }<br>
}<br>
<br>
这是一个包含一个technique两个pass的shader的例子：<br>
technique Shader<br>
{<br>
&nbsp;&nbsp;&nbsp;&nbsp; pass P0<br>
&nbsp;&nbsp;&nbsp;&nbsp; {<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; VertexShader = compile vs_1_1 VS();<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; PixelShader = compile ps_1_1 PS();<br>
&nbsp;&nbsp;&nbsp;&nbsp; }<br>
pass P1<br>
&nbsp;&nbsp;&nbsp;&nbsp; {<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; VertexShader = compile vs_1_1 VS_Other();<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; PixelShader = compile ps_1_1 PS_Other();<br>
&nbsp;&nbsp;&nbsp;&nbsp; }<br>
}<br>
<br>
这是一个包含两个technique一个pass的shader的例子：<br>
technique Shader_11<br>
{<br>
&nbsp;&nbsp;&nbsp;&nbsp; pass P0<br>
&nbsp;&nbsp;&nbsp;&nbsp; {<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; VertexShader = compile vs_1_1 VS();<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; PixelShader = compile ps_1_1 PS();<br>
&nbsp;&nbsp;&nbsp;&nbsp; }<br>
}<br>
technique Shader_2a<br>
{<br>
&nbsp;&nbsp;&nbsp;&nbsp; pass P0<br>
&nbsp;&nbsp;&nbsp;&nbsp; {<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; VertexShader = compile vs_1_1 VS2();<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; PixelShader = compile ps_2_a PS2();<br>
&nbsp;&nbsp;&nbsp;&nbsp; }<br>
}<br>
<br>
我们可以看到一个technique有两个函数，一个是像素着色器，一个是顶点着色器。<br>
<br>
VertexShader = compile vs_1_1 VS2();<br>
PixelShader = compile ps_1_1 PS2();<br>
<br>
这是指这个technique将使用VS2()作为顶点着色器，PS2()作为像素着色器，支持shader model 1.1或更高。如果GPU支持更高版本的shader model就可以写更复杂的shader。<br>
<br>
<br>
在XNA中实现shader<br>
在XNA中实现shader很简单，加载使用一个shader只需要几行代码。下面列出了使用shader的步骤：<br>
<br>
1. 编写shader<br>
2. 把shader文件（.fx）加到&ldquo;Contents&rdquo;里面<br>
3. 实例化一个Effect类<br>
4. 初始化Effect对象<br>
5. 选择要使用的technique<br>
6. 开始shader<br>
7. 向shader传递参数<br>
8. 绘制场景、物体<br>
9. 结束shader<br>
<br>
<span style="font-weight: bold"><wbr></wbr>详细说明：</span><wbr></wbr><br>
1. 编写shader时，可以记事本、visual studio这样的编辑软件，也可以使用shader IDE。我个人喜欢nVidia的FX Composer： <a href="http://developer.nvidia.com/object/fx_composer_home.html" target="_blank" eventslistuid="e6">http://developer.nvidia.com/object/fx_composer_home.html</a><wbr></wbr><br>
<br>
2. 编写好shader后，把它拖到&ldquo;Content&rdquo;文件夹，获取属性名。<br>
<br>
3. XNA Framework提供了一个Effect类，用来加载和编译shader。用下面几行代码实例化这个类。<br>
<br>
Effect effect;<br>
Effect包含于&ldquo;Microsoft.Xna.Framework.Graphics&rdquo;命名空间，所以添加下面一行：<br>
using Microsoft.Xna.Framework.Graphics<br>
<br>
4. 初始化shader，我们可以使用Content从文件或者从项目中加载shader：<br>
<wbr></wbr><a href="http://images.cnblogs.com/cnblogs_com/cocoaleaves/789.png" target="_blank" eventslistuid="e7"><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; width: 274px; height: 119px; border-right-width: 0px" src="http://images.cnblogs.com/cnblogs_com/cocoaleaves/789.png" bloaded="true" loadingtimer="80575950" orgsrc="http://images.cnblogs.com/cnblogs_com/cocoaleaves/789.png"></a><wbr></wbr> <br>
effect = Content.Load&lt;Effect&gt;(&quot;Shader&quot;); <br>
Shader是你加到Content中的shader的属性名<br>
<br>
5. 选择你要使用的technique：<br>
effect.CurrentTechnique = effect.Techniques[&quot;AmbientLight&quot;];<br>
<br>
6. 开始使用一个Effect，要调用Begin()方法：<br>
effect.Begin();<br>
记住使用shader中的所有的pass。<br>
foreach (EffectPass pass in effect.CurrentTechnique.Passes)<br>
{<br>
&nbsp;&nbsp;&nbsp;&nbsp; // 开始当前pass<br>
&nbsp;&nbsp;&nbsp;&nbsp; pass.Begin();<br>
}<br>
<br>
7. 给shader传递参数有很多方法，下面的方法适合初学使用。<br>
注：这不是最快的方法，我在后面的教程中会介绍<br>
<br>
effect.Parameters[&quot;matWorldViewProj&quot;].SetValue( worldMatrix * viewMatrix * projMatrix);<br>
&ldquo;matWorldViewProj&rdquo;是在shader中定义的：float4*4 matWorldViewProj；matWorldViewProj被设成了worldMatrix * viewMatrix * projMatrix。<br>
<br>
SetValue设置了参数的值并传递给shader，GetValue&lt;Type&gt;可以从shader取回值，Type是要取回的值的类型。例如，GetValueInt32()从shader中取回一个整数。<br>
<br>
8.渲染你想用当前shader渲染的物体。<br>
<br>
9.结束这个pass，调用pass.End()。然后结束shader，调用Effect的End()方法：<br>
pass.End();<br>
effect.End();<br>
<br>
为了更好的理解，打开提供的源码实际地去读一下。<br>
<br>
环境光<br>
好了，我们终于要进行最后一步，实现这个shader！不错吧。<br>
首先，什么事&ldquo;环境光&rdquo;？<br>
环境光是存在于场景中的基础的光线。对于一个几乎全黑的屋子，那里的环境光将近于零，但当走在屋外，总会有点光使我们能看到东西。这个光没有方向，只是让物体能被看到，但是环境光有一个基本的颜色。<br>
<br>
环境光的计算式是：<br>
I = Aintensity x Acolor ( 1.1)<br>
<br>
l就是环境光，Aintensity是光强（通常在0.0到1.0之间），Acolor是环境光的颜色。这个颜色可以使硬编码的。<br>
<br>
好了，我们来实现这个shader。首先，我们需要一个变换矩阵：<br>
float4x4 matWorldViewProj;<br>
在shader的最开始声明，作为一个全局变量。<br>
<br>
下面，我们需要知道顶点着色器把什么值传递给像素着色器，通过定义一个结构体来实现（你可以任意命名）<br>
<br>
struct OUT<br>
{<br>
&nbsp;&nbsp;&nbsp;&nbsp; float4 Pos: POSITION;<br>
};<br>
<br>
我们创建了一个叫做OUT的结构体，包含了一个叫做Pos的类型为float4的变量。后面的:POSITION告诉GPU该把这个值放到哪个寄存器中。那么，寄存器是什么？寄存器就是GPU存储数据的一个容器。GPU用不同的寄存器存储位置、法线、纹理坐标等等。当在shader中定义变量时，我们必须同时指明GPU在哪里存储它。<br>
<br>
来看一下顶点着色器：<br>
<br>
OUT VertexShader( float4 Pos: POSITION )<br>
{<br>
&nbsp;&nbsp;&nbsp;&nbsp; OUT Out = (OUT) 0;<br>
&nbsp;&nbsp;&nbsp;&nbsp; Out.Pos = mul(Pos, matWorldViewProj);<br>
&nbsp;&nbsp;&nbsp;&nbsp; return Out;<br>
}<br>
<br>
我们创建了返回OUT类型的顶点着色器函数，参数为float4 Pos: POSITION。这是模型文件、程序中定义的顶点坐标位置。<br>
<br>
然后我们实例化了一个OUT结构体，叫做Out。这个结构体必须填充好数据，一遍后面的函数处理。<br>
输入的位置数据是没有处理过的，所以需要乘上worldviewprojection矩阵，把顶点变换到屏幕上正确的位置。<br>
OUT结构体只有这一个变量，所以我们的函数可以返回了。<br>
<br>
下面轮到像素着色器了。我们声明一个float4型的函数，返回的float4值存储在GPU的COLOR寄存器中。<br>
在像素着色器中我们会按公式计算环境光：<br>
<br>
float4 PixelShader() : COLOR<br>
{<br>
&nbsp;&nbsp;&nbsp;&nbsp; float Ai = 0.8f;<br>
&nbsp;&nbsp;&nbsp;&nbsp; float4 Ac = float4(0.075, 0.075, 0.2, 1.0);<br>
&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp; return Ai * Ac;<br>
}<br>
<br>
我们使用前面的环境光公式计算每个像素的颜色值。Ai是环境光强度，Ac是环境光颜色。<br>
<br>
最后，我们需要定义一个technique，并把像素着色器和顶点着色器绑定到这个technique上：<br>
technique AmbientLight<br>
{<br>
&nbsp;&nbsp;&nbsp;&nbsp; pass P0<br>
&nbsp;&nbsp;&nbsp;&nbsp; {<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; VertexShader = compile vs_1_1 VertexShader();<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; PixelShader = compile ps_1_1 PixelShader();<br>
&nbsp;&nbsp;&nbsp;&nbsp; }<br>
} </div> <a href="http://hi.baidu.com/yuexiang%5F0207/blog/item/19763959415b04222834f0b8.html">阅读全文</a>
		
		<br/><b>类别：</b><a href="http://hi.baidu.com/yuexiang%5F0207/blog/category/%C8%FD%CE%AC%B7%BD%C3%E6%D6%AA%CA%B6">三维方面知识</a>&nbsp;<a href="http://hi.baidu.com/yuexiang%5F0207/blog/item/19763959415b04222834f0b8.html#comment">查看评论</a>]]></description>
        <pubDate>2009-05-25  16:39</pubDate>
        <category><![CDATA[三维方面知识]]></category>
        <author><![CDATA[yuexiang_0207]]></author>
		<guid>http://hi.baidu.com/yuexiang%5F0207/blog/item/19763959415b04222834f0b8.html</guid>
</item>

<item>
        <title><![CDATA[Irrlicht引擎里的冲突检测与响应]]></title>
        <link><![CDATA[http://hi.baidu.com/yuexiang%5F0207/blog/item/be9362c74b4828d4d10060bf.html]]></link>
        <description><![CDATA[
		
		<div style="font-size: 16px">这是Irrlicht　SDK中给的一个例子，用来演示如何在Irricht中冲突检测与响应，其它的例子还有十三个，俺会陆续翻译出来。自己英语水平很洼，但对翻译又有点瘾，所以就帖到这里来，有译错或表达不好的地方请指正。<br>
<br>
　例7，碰撞检测与响应<br>
　　这一节，我将演示如何在Irrlicht引擎里进行碰撞检测。有三种方法：自动的碰撞检测，例如上下楼梯时移动全局坐标；手工拾取三角形和场景结点。<br>
　　演示程序效果图：<br>
　　开始吧！<br>
　　简单起见，我们拿那个加载并显示Quake3地图的例2开刀：在里面四处走动并从中拾取三角形。另外，为了说明场景结点的拾取我们再放三个精灵在里面。下面的代码启动引擎并加载Quake3地图。不再多加解释（详情参见例2）。 <br>
<br>
<br>
#include &lt;irrlicht.h&gt;<br>
#include &lt;iostream&gt;<br>
using namespace irr;<br>
<br>
#pragma comment(lib, &quot;Irrlicht.lib&quot;)<br>
<br>
int main()<br>
...{<br>
&nbsp;&nbsp; // let user select driver type<br>
&nbsp;&nbsp; video::E_DRIVER_TYPE driverType; <br>
printf(&quot;Please select the driver you want for this example: &quot;<br>
&nbsp;&nbsp;&nbsp;&nbsp; &quot; (a) Direct3D 9.0c&nbsp;&nbsp;<br>
(b) Direct3D 8.1 <br>
(c) OpenGL 1.5 &quot;&nbsp;&nbsp;<br>
&nbsp;&nbsp; &quot; (d) Software Renderer <br>
(e) Apfelbaum Software Renderer &quot;&nbsp;&nbsp;&nbsp;&nbsp; &quot;<br>
(f) NullDevice&nbsp;&nbsp; (otherKey) exit &quot;);&nbsp;&nbsp;<br>
char i; <br>
std::cin &gt;&gt; i; <br>
switch(i) <br>
...{&nbsp;&nbsp;<br>
case 'a': driverType = video::EDT_DIRECT3D9;break;&nbsp;&nbsp;<br>
case 'b': driverType = video::EDT_DIRECT3D8;break;&nbsp;&nbsp;<br>
case 'c': driverType = video::EDT_OPENGL;&nbsp;&nbsp;  break;&nbsp;&nbsp;<br>
case 'd': driverType = video::EDT_SOFTWARE; break;&nbsp;&nbsp;<br>
case 'e': driverType = video::EDT_SOFTWARE2;break;&nbsp;&nbsp;&nbsp;&nbsp;<br>
case 'f': driverType = video::EDT_NULL;&nbsp;&nbsp;&nbsp;&nbsp;  <br>
break;&nbsp;&nbsp; default: <br>
return 0; <br>
}&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp; // create device&nbsp;&nbsp; IrrlichtDevice *device = createDevice(driverType,<br>
&nbsp;&nbsp;&nbsp;&nbsp;  core::dimension2d&lt;s32&gt;(640, 480), 16, false);<br>
&nbsp;&nbsp; if (device == 0)&nbsp;&nbsp;  <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return 1; // could not create selected driver. <br>
video::IVideoDriver* driver = device-&gt;getVideoDriver();&nbsp;&nbsp;<br>
scene::ISceneManager* smgr = device-&gt;getSceneManager();&nbsp;&nbsp;<br>
device-&gt;getFileSystem()-&gt;addZipFileArchive(&quot;../../media/map-20kdm2.pk3&quot;);<br>
&nbsp;&nbsp;&nbsp;&nbsp; scene::IAnimatedMesh* q3levelmesh = smgr-&gt;getMesh(&quot;20kdm2.bsp&quot;);<br>
&nbsp;&nbsp;&nbsp;&nbsp; scene::ISceneNode* q3node = 0;<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp; if (q3levelmesh)<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; q3node = smgr-&gt;addOctTreeSceneNode(q3levelmesh-&gt;getMesh(0));<br>
<br>
　到此为止，我们已经像例2那样加载了Quake3地图。接下来的情况有所不同：我们创建了一个三角形的选择器。这是一个类，你可以用它来从场景结点中拾取三角形，以用作各种不同的用途，比如碰撞检测。引擎里有几种三角选择器，它们都可以用ISceneManager来创建。在这个例子中我们创建OctTreeTriangleSelector，你可以照字面意思理解，是的，这是个树状的选择器，&ldquo;树&rdquo;就是数据结构里面的树，我们以此来对三角形数目的输出做些优化。这样对像Quake3之类大的地图是很有用的。<br>
　　创建完三角形选择器就把它&ldquo;系&rdquo;到场景结点上去，此处是q3node。并不是必需这么做，这是&ldquo;懒汉&rdquo;式做法，不用再考虑选择器了，比如到底什么时候用不着了才好释放它。<br>
<br>
　　还是像例2，为了能在Quake3地图里面移动，我们添加一个FPS(First Person Shooter第一人称射击游戏)相机。但这一次，还要给相机加个特殊的animator：带冲突响应的animator(注3)。它会调整与自己关联的场景结点，使它看起来受重力影响并且不会穿墙而过。对于animator，我们要做的唯一的事情就是告诉它世界是个什么样子，场景结点有多大，重力有多大等等。把带冲突响应的animator加到相机上后，就不必再做任何关于碰撞检测的事――一切都是自动的！。下面有关碰撞检测的代码是是用来拾取的。还有一个令人高兴的、很酷的特性：可以把带冲突响应的animator的事附加到任何场景结点上，不只是相机。另外，它也可以与别的场景结点animator混合使用。如此以来，在Irrlicht引擎中使用冲突检测与响应就非常、非常地简单。<br>
　　好了，来看一下createCollisionResponseAnimator() 的参数。第一个参数是TriangleSelector，指明碰撞检测完成后世界看起来是个什么样子。　第二个参数是场景结点，指定受碰撞检测影响的对象，在我们的例子中就是相机。第三个定义对象的大小，即椭球半径。试一试：把半径改小后是不是能够靠墙更近呢？下一个参数是重力的大小和方向。你可以将方向设为（0,0,0）以消除重力。最后一个仅用于转换：否则的话，计算好碰撞检测的椭球会包住相机，而相机位于椭球的中央。但是从人的角度，我们习惯于&ldquo;眼睛在身体的上方&rdquo;，而眼睛在身体中间是同我们的现实世界相抵触的。所以我们用这个参数把场景结点从椭球中央上移50个单位。好，现在碰撞检测可以起作用了。<br>
<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp; scene::ICameraSceneNode* camera =&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  camera = smgr-&gt;addCameraSceneNodeFPS(0,100.0f,300.0f);<br>
&nbsp;&nbsp;&nbsp;&nbsp; camera-&gt;setPosition(core::vector3df(-100,50,-150));<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp; scene::ISceneNodeAnimator* anim =&nbsp;&nbsp;&nbsp;&nbsp; smgr-&gt;createCollisionResponseAnimator(<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; selector, camera, core::vector3df(30,50,30),<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; core::vector3df(0,-3,0),<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; core::vector3df(0,50,0));<br>
&nbsp;&nbsp;&nbsp;&nbsp; camera-&gt;addAnimator(anim);<br>
&nbsp;&nbsp;&nbsp;&nbsp; anim-&gt;drop();<br>
　　因为在Irrlicht里碰撞检测并不是很大的一块（引擎要做的事多着呢，译注）。下一节我将描述如何使用两种不同类型的拾取。但在这之前我会为场景稍作准备。需要三个用来拾取的角色：精灵，一个动态光源以照亮它们，一个用来指出交叉点的白板，还有，噢，我得把光标去掉。 ：)<br>
<br>
　　为了不致太复杂，我会在渲染循环里进行拾取。我们先定义两个指针用来保存当前和最后一个场景结点，然后进入循环。<br>
　　 <br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp; scene::ISceneNode* selectedSceneNode = 0;<br>
&nbsp;&nbsp;&nbsp;&nbsp; scene::ISceneNode* lastSelectedSceneNode = 0;<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp; int lastFPS = -1;<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp; while(device-&gt;run())&nbsp;&nbsp; if (device-&gt;isWindowActive())<br>
&nbsp;&nbsp;&nbsp;&nbsp; ...{<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; driver-&gt;beginScene(true, true, 0);<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; smgr-&gt;drawAll();<br>
　　用smgr-&gt;drawAll()绘制完全部场景后，开始第一次拾取：我们想知道自己正瞧着整个世界坐标中的哪个三角形。另外，准确一些，还想知道这是在Quake3地图中的哪个点。为此我们创建一个三维的射线：从相机位置开始，穿过目标点。<br>
　　然后向碰撞管理器询问：这条射线是否同存储在三角选择器里的三角形发生碰撞？如果是，我们画一个三维的三角形并把白板位置设在交叉点上。<br>
<br>
<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; core::line3d&lt;f32&gt; line;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; line.start = camera-&gt;getPosition();<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; line.end = line.start +<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  (camera-&gt;getTarget() - line.start).normalize() * 1000.0f;<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; core::vector3df intersection;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; core::triangle3df tri;<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (smgr-&gt;getSceneCollisionManager()-&gt;getCollisionPoint(<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; line, selector, intersection, tri))<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ...{<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; bill-&gt;setPosition(intersection);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; driver-&gt;setTransform(video::ETS_WORLD, core::matrix4());<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; driver-&gt;setMaterial(material);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; driver-&gt;draw3DTriangle(tri, video::SColor(0,255,0,0));<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>
　　Irrlicht引擎支持的另一种拾取方法是基于包围盒的节点拾取。每个场景结点已有一个包围盒包着，正因如此，拾取速度非常快，例如在拾取相机看到的场景结点时。再说明一次，我们是向碰撞管理器询问得到这个结果的，如果得到了一个场景结点，就通过取消它材质的光照特性而加亮它，当然，如果它不是白板或Quake3地图的话。<br>
　 <br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp; selectedSceneNode = smgr-&gt;getSceneCollisionManager()-&gt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; getSceneNodeFromCameraBB(camera);<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (lastSelectedSceneNode)<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; lastSelectedSceneNode-&gt;setMaterialFlag(<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; video::EMF_LIGHTING, true);<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (selectedSceneNode == q3node ||<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  selectedSceneNode == bill)<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; selectedSceneNode = 0;<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (selectedSceneNode)<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; selectedSceneNode-&gt;setMaterialFlag(<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  video::EMF_LIGHTING, false);<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; lastSelectedSceneNode = selectedSceneNode;<br>
　　就这些，下面要做的只是完成绘制。<br>
　<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; driver-&gt;endScene();<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int fps = driver-&gt;getFPS();<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (lastFPS != fps)<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ...{<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; core::stringw str = L&quot;Collision detection example - Irrlicht Engine [&quot;;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; str += driver-&gt;getName();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; str += &quot;] FPS:&quot;;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; str += fps;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; device-&gt;setWindowCaption(str.c_str());&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; lastFPS = fps;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp;&nbsp; }<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp; device-&gt;drop();<br>
&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp; return 0;<br>
}<br>
</div> <a href="http://hi.baidu.com/yuexiang%5F0207/blog/item/be9362c74b4828d4d10060bf.html">阅读全文</a>
		
		<br/><b>类别：</b><a href="http://hi.baidu.com/yuexiang%5F0207/blog/category/%C8%FD%CE%AC%B7%BD%C3%E6%D6%AA%CA%B6">三维方面知识</a>&nbsp;<a href="http://hi.baidu.com/yuexiang%5F0207/blog/item/be9362c74b4828d4d10060bf.html#comment">查看评论</a>]]></description>
        <pubDate>2009-05-25  16:38</pubDate>
        <category><![CDATA[三维方面知识]]></category>
        <author><![CDATA[yuexiang_0207]]></author>
		<guid>http://hi.baidu.com/yuexiang%5F0207/blog/item/be9362c74b4828d4d10060bf.html</guid>
</item>

<item>
        <title><![CDATA[在Direct3D程序中运用碰撞检测]]></title>
        <link><![CDATA[http://hi.baidu.com/yuexiang%5F0207/blog/item/70553263ac51bb680c33fabf.html]]></link>
        <description><![CDATA[
		
		几乎所有的3D游戏都离不开碰撞检测&mdash;&mdash;无论是各物体之间的碰撞检测，还是物体与场景之间的碰撞检测。在真实世界中，你是很自然地不能穿墙而过的，所以很多人在玩各种3D游戏的时候自然而然的忽视了碰撞检测这一过程的存在。然而，碰撞检测的过程是重要的。如果没有它，你在CS中就会毫无遮拦的飞来飞去&mdash;&mdash;如果考虑重力的话，则会一直不停地往下掉，直到符点数溢出（或你受不了这一漫长的过程而离开游戏）为止。碰撞检测是在编程时实现的。不要以为碰撞检测是在显示3D图像的同时由显卡完成的&mdash;&mdash;这是幼稚的看法&mdash;&mdash;现在没有什么硬件能支持碰撞检测。<br>
<br>
　　看了这些后你可能对碰撞检测产生了兴趣，或者你作为一个3D编程爱好者正在寻找碰撞检测的原理和方法，或者已经找了很长时间还没找到（我是不是有点贫:P），那么，就让我们一起来看一种十分有效而又易于理解的算法吧。<br>
<br>
　　这个算法是针对物体与场景之间的碰撞检测的。它要求你的场景是以很多的三角形组成的。目前几乎所有的3D程序的场景或者物体都是由许多三角形组成的，所以这一点不成问题。另外，你需要记录物体在上一帧的位置和当前帧的位置。这也很容易办到。除了这些，就每什么其他的要求了。那么我们来看一下它的原理。<br>
<br>
　　一、原理<br>
<br>
　　首先，根据物体的运动规律或用户的输入计算物体在即将渲染的一帧（当前帧）时的位置（这时还不用考虑碰撞检测的问题）然后，循环遍历场景中每一个三角形。在循环过程中，作如下操作：<br>
<br>
　　1、找到当前三角形所在的平面，我们暂且称之为平面S。沿平面法线方向对它做一个平移d，表示物体和平面之间所能接近的距离。<br>
<br>
　　2、判断物体在上一帧和当前帧时的位置OldPosition、NewPosition与平面S的关系：如果上一帧在平面前，而当前帧在平面后，如下图所示：<br>
<wbr></wbr><a href="http://school.ogdev.net/upload/img/5709714455.gif" target="_blank" eventslistuid="e3"><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; width: auto; height: auto; border-right-width: 0px" src="http://cnc.imgcache.qq.com/ac/qzone_v5/photo/photo_none_s.gif" bloaded="true" loadingtimer="80574463" orgsrc="http://school.ogdev.net/upload/img/5709714455.gif"></a><wbr></wbr><br>
<br>
　　则进一步做3。<br>
<br>
　　否则，跳过3、4，做5。<br>
<br>
　　3、因为前后两帧物体在平面的异侧，说明物体穿过了平面S。但这时还不能说物体与三角形发生了碰撞，因为平面是无边界的,还需进一步判断物体是否在三角形三条边范围之内穿过平面S。过三角形的三边，做垂直于三角形的平面PS1,PS2,PS3。并且令它们的法线指向三角形的内部，如下图所示：<br>
<br>
<wbr></wbr><a href="http://school.ogdev.net/upload/img/5712067048.gif" target="_blank" eventslistuid="e4"><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" src="http://school.ogdev.net/upload/img/5712067048.gif" bloaded="true" loadingtimer="80574481" orgsrc="http://school.ogdev.net/upload/img/5712067048.gif"></a><wbr></wbr><br>
<br>
　　为了体现物体和三角形所能接近的最短距离，这三个平面也需要做一个平移L，只不过是沿着其法线负方向：<br>
<br>
<wbr></wbr><a href="http://school.ogdev.net/upload/img/5714690534.gif" target="_blank" eventslistuid="e5"><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" src="http://school.ogdev.net/upload/img/5714690534.gif" bloaded="true" loadingtimer="80574499" orgsrc="http://school.ogdev.net/upload/img/5714690534.gif"></a><wbr></wbr><br>
<br>
<wbr></wbr><a href="http://school.ogdev.net/upload/img/57151109150.gif" target="_blank" eventslistuid="e6"><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" src="http://school.ogdev.net/upload/img/57151109150.gif" bloaded="true" loadingtimer="80574512" orgsrc="http://school.ogdev.net/upload/img/57151109150.gif"></a><wbr></wbr><br>
 <a href="http://hi.baidu.com/yuexiang%5F0207/blog/item/70553263ac51bb680c33fabf.html">阅读全文</a>
		
		<br/><b>类别：</b><a href="http://hi.baidu.com/yuexiang%5F0207/blog/category/%C8%FD%CE%AC%B7%BD%C3%E6%D6%AA%CA%B6">三维方面知识</a>&nbsp;<a href="http://hi.baidu.com/yuexiang%5F0207/blog/item/70553263ac51bb680c33fabf.html#comment">查看评论</a>]]></description>
        <pubDate>2009-05-25  16:37</pubDate>
        <category><![CDATA[三维方面知识]]></category>
        <author><![CDATA[yuexiang_0207]]></author>
		<guid>http://hi.baidu.com/yuexiang%5F0207/blog/item/70553263ac51bb680c33fabf.html</guid>
</item>

<item>
        <title><![CDATA[三维模型的优化方法]]></title>
        <link><![CDATA[http://hi.baidu.com/yuexiang%5F0207/blog/item/8cfb803335e1014bad4b5fbe.html]]></link>
        <description><![CDATA[
		
		<div class="real_blog" style="text-indent: 2em; height: auto! important">
<table style="table-layout: fixed; width: 100%; position: relative" cellspacing="0" cellpadding="0">
    <tbody>
        <tr>
            <td style="word-wrap: break-word" valign="top">
            <div style="overflow: hidden; position: relative; height: 100%"><img style="display: none" src="http://cnc.imgcache.qq.com/ac/b.gif">
            <div align="center"> </div>
            <img style="display: none" src="http://cnc.imgcache.qq.com/ac/b.gif">
            <div style="font-size: 16px">所谓的三维<wbr></wbr>模型<wbr></wbr>优化有两个方面：<br>
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1，对于模型<wbr></wbr>来说，减少三维<wbr></wbr>模型<wbr></wbr>的点、线、面的数目<br>
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2，对于贴图来说，使用UV贴图并减小贴图的大小。 <br>
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 当我们用Maya/3dMax/犀牛等三维<wbr></wbr>软件建立了三维<wbr></wbr>模型<wbr></wbr>之后如何对其进行优化呢？ <br>
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 第一，建模技巧<br>
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  比如楼房，多楼层的楼房可以用一个box来代替；删除模型<wbr></wbr>中的多余面；单个物体的面数不能很多；如果可以用贴图来表现复杂模型<wbr></wbr>就不要用模型<wbr></wbr>；将占用大块区域的模型<wbr></wbr>拆减成小模型<wbr></wbr>减轻系统压力。<br>
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 第二，贴图技巧<br>
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 最好不要用零散的多贴图，因为在系统加载贴图的时候如果贴图过多会增加硬盘的交互。使用一个UV贴图会减少交互，将其交给显存后就让它自己算去吧，有利于性能提升。<br>
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  第三，软件优化<br>
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 对于模型<wbr></wbr>，我们可以使用Deep Exploration来对其进行优化，这是一个极牛的软件。可以使用电驴搜索下载，这里就不提供下载了。对于贴图用ACDSee就好了，推荐使用3.1美化版。当然，如果能用photoshop装上DDS插件做成dds格式的贴图那是最棒的。 </div>
            </div>
            </td>
        </tr>
    </tbody>
</table>
</div> <a href="http://hi.baidu.com/yuexiang%5F0207/blog/item/8cfb803335e1014bad4b5fbe.html">阅读全文</a>
		
		<br/><b>类别：</b><a href="http://hi.baidu.com/yuexiang%5F0207/blog/category/%C8%FD%CE%AC%B7%BD%C3%E6%D6%AA%CA%B6">三维方面知识</a>&nbsp;<a href="http://hi.baidu.com/yuexiang%5F0207/blog/item/8cfb803335e1014bad4b5fbe.html#comment">查看评论</a>]]></description>
        <pubDate>2009-05-25  16:36</pubDate>
        <category><![CDATA[三维方面知识]]></category>
        <author><![CDATA[yuexiang_0207]]></author>
		<guid>http://hi.baidu.com/yuexiang%5F0207/blog/item/8cfb803335e1014bad4b5fbe.html</guid>
</item>

<item>
        <title><![CDATA[动画图形文件格式详解]]></title>
        <link><![CDATA[http://hi.baidu.com/yuexiang%5F0207/blog/item/a53c5533da303bf01a4cffbe.html]]></link>
        <description><![CDATA[
		
		一、GIF 格式 <br>
　　GIF(Graphics Interchange Format) 即 &ldquo; 图形交换格式 &rdquo; ，这种格式在 20 世纪 80 年代由美国一家著名的在线信息服务机构 CompuServe 开发而成。 GIF 格式的特点是压缩比高，得以在网络上大行其道。 GIF 图像格式还增加了渐显方式，用户可以先看到图像的大致轮廓，然后随着传输过程的继续而逐步看清图像中的细节部分，从而适应了用户的 &ldquo; 从朦胧到清楚 &rdquo; 的观赏心理。目前 Internet 上大量采用的彩色动画文件多为这种格式的文件，也称为 GIF89a 格式文件。很多图像 <a href="http://tech.sina.com.cn/introduction/focus/msie.shtml" target="_blank" eventslistuid="e3">浏览器 </a><wbr></wbr>如 <a href="http://tech.sina.com.cn/c/225.html" target="_blank" eventslistuid="e4">ACDSee </a><wbr></wbr>等都可以直接观看该类动画文件。 <br>
二、LIC(FLI ／ FLC) 格式 <br>
　　大凡玩过三维动画的朋友应该都会熟悉这种格式， FLIC 格式由大名鼎鼎的 Autodesk 公司研制而成，近水楼台先得月，在 Autodesk 公司出品的 Autodesk Animator 、 AnimatorPro 和 3DStudio 等动画制作软件中均采用了这种彩色动画文件格式。 FLIC 是 FLC 和 FLI 的统称： FLI 是最初的基于 320×200 分辨率的动画文件格式，而 FLC 进一步扩展，它采用了更高效的数据压缩技术，所以具有比 FLI 更高的压缩比，其分辨率也有了不少提高。 <br>
三、SWF 格式 ( <a href="http://tech.sina.com.cn/introduction/focus/flash.shtml" target="_blank" eventslistuid="e5">Flash </a><wbr></wbr>动画 ) <br>
　　Flash 是 Micromedia 公司的产品，严格说它是一种动画 ( 电影 ) 编辑软件。实际上它是制作出一种后缀名为 .swf 的动画，这种格式的动画能用比较小的体积来表现丰富的多媒体形式，并且还可以与 HTML 文件达到一种 &ldquo; 水乳交融 &rdquo; 的境界。 Flash 动画其实是一种 &ldquo; 准 &rdquo; 流 (Stream) 形式的文件，也就是说，我们在观看的时候，可以不必等到动画文件全部下载到本地再观看，而是随时可以观看，哪怕后面的内容还没有完全下载到 <a href="http://tech.sina.com.cn/introduction/focus/hd.shtml" target="_blank" eventslistuid="e6">硬盘 </a><wbr></wbr>，我们也可以开始欣赏动画。而且， Flash 动画是利用矢量技术制作的，不管你将画面放大多少倍，画面仍然清晰流畅，质量一点儿也不会因此而降低。 <a href="http://hi.baidu.com/yuexiang%5F0207/blog/item/a53c5533da303bf01a4cffbe.html">阅读全文</a>
		
		<br/><b>类别：</b><a href="http://hi.baidu.com/yuexiang%5F0207/blog/category/%C8%FD%CE%AC%B7%BD%C3%E6%D6%AA%CA%B6">三维方面知识</a>&nbsp;<a href="http://hi.baidu.com/yuexiang%5F0207/blog/item/a53c5533da303bf01a4cffbe.html#comment">查看评论</a>]]></description>
        <pubDate>2009-05-25  16:35</pubDate>
        <category><![CDATA[三维方面知识]]></category>
        <author><![CDATA[yuexiang_0207]]></author>
		<guid>http://hi.baidu.com/yuexiang%5F0207/blog/item/a53c5533da303bf01a4cffbe.html</guid>
</item>

<item>
        <title><![CDATA[3D Engine 的设计架构]]></title>
        <link><![CDATA[http://hi.baidu.com/yuexiang%5F0207/blog/item/c28bc823e9ae714cad34debd.html]]></link>
        <description><![CDATA[
		
		咱们谈谈你如何撰写一份提供优雅性能的3D引擎。你的引擎需要提供的包括：曲面(curved surfaces)、动态光线(dynamic lighting)、体雾(volumetric fog)、镜面(mirrors)、入口(portals)、天空体(skyboxes)、节点阴影(vertex shaders)、粒子系统(particle systems)、静态网格模型(static mesh models)、网格模型动画(animated mesh models)。假如你已经知道如何以上所述的所有功能顺利工作，你也许便能将那些东东一起置入到一个引擎当中。<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 在你开始撰写代码前你必须先构思一下如何去架构你的引擎。多数来讲，你一定是迫切地渴望去制作一个游戏，但如果你立即投入便开始为你的引擎撰写代码后，你一定会觉得非常难受，开发后期你可能会为置入新的特效与控制而不得不多次重写大量的局部代码，甚至以失败而放弃告终。花一点时间好好地为你引擎深谋远虑一番，这将会为你节省大量时间，也少一点头痛。你一定不会急切地去架构一个巨型的工程；或许你也会在引擎未完成时而干脆放弃它，然后去干的别的什么事儿。好了，当你掌握学习你所需知识的方式之前，也许你还不能完成那些事儿。将设计真正地完成确实是件美事，为之你会感觉更好，你将为之而耀眼！<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 让我们分析一下具备完整功能的3D游戏引擎的需要哪些基本部件。首先，这为具有相应3D经验但且还需一些指引的开发者提供了一些信息。这是一些并不难且能快速掌握但是你必须应用的内容条目。为将你的工作更好地进行下去，这里将对关于&ldquo;把多大的工作量&rdquo;与&ldquo;多少部分&rdquo;置入一个游戏引擎给出一个总概。我把这些成分称为 系统（System）、控制台（Console）、支持（Support），渲染/引擎 内核（Renderer/Engine Core）、游戏介质层（Game Interface）、以及工具/数据（Tools/Data）。<br>
<br>
Tools/Data （工具/数据）<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 在开发过程中，你总是需要一些数据，但不幸的是这并不象写文本文件或是定义一个立方体那么简单。至少，你得需要3d模型编辑器，关卡编辑器，以及图形程序。你可以通过购买，也可以在网上找一些免费的程序满足你的开发要求。不幸的是你可能还需要一些更多的工具可你却根本无法获得（还不存在呢），这时你只得自己动手去写。最终你很可能要自行设计编写一个关卡编辑器，因为你更本不可能获得你所需。你可能也会编写一些代码来为大量的文件打个包，整天面对应付成百上千个文件倒是非常痛苦的。你还必须写一些转换器或是插件将3d模型编辑器的模型格式转换成你自己的格式。你也需要一些加工游戏数据的工具，譬如可见度估算或是光线贴图。<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 一个基本的准则是，你可能要为设计工具而置入比游戏本身等量甚至更多的代码。开始你总能找到现成的格式和工具，但是经过一段时间以后你就能认识到你需要你的引擎有很大的特性，然后你就会放弃以前的撰写方式。<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 也许目前非常流行利用的第3方工具辅助开发，所以你必须时刻注意你的设计。因为一旦当你将你的引擎发布为opensouce或是允许修改，那也许在某天中会有某些人来应用你的开发成果，他们将其扩展或者做某些修改。<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  或许你也应该花大量时间去设计美术，关卡，音效，音乐和实体模型，这就和你设计撰写游戏，工具以及引擎一样。<br>
<br>
System （系统）<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 系统(system)是引擎与机器本身做通信交互的部件。一个优秀的引擎在待平台移植时，它的系统则是唯一需要做主要更改（扩加代码）的地方。我们把一个系统分为若干个子系统，其中包括：图形（Graphics）、输入（Input）、声音（Sound）、记时器（Timer）、配置（Configuration）。主系统负责初始化、更新、以及关闭所有的子系统。<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 图形子系统（Graphics Sub-System）在游戏里表现得非常直观，如果想在屏幕上画点什么的话，它（图形子系统）便干这事儿。 <a href="http://hi.baidu.com/yuexiang%5F0207/blog/item/c28bc823e9ae714cad34debd.html">阅读全文</a>
		
		<br/><b>类别：</b><a href="http://hi.baidu.com/yuexiang%5F0207/blog/category/%C8%FD%CE%AC%B7%BD%C3%E6%D6%AA%CA%B6">三维方面知识</a>&nbsp;<a href="http://hi.baidu.com/yuexiang%5F0207/blog/item/c28bc823e9ae714cad34debd.html#comment">查看评论</a>]]></description>
        <pubDate>2009-05-25  16:34</pubDate>
        <category><![CDATA[三维方面知识]]></category>
        <author><![CDATA[yuexiang_0207]]></author>
		<guid>http://hi.baidu.com/yuexiang%5F0207/blog/item/c28bc823e9ae714cad34debd.html</guid>
</item>


</channel>
</rss>