<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom"><title type="text">博客园_mazhenyu</title><subtitle type="text">男，28，北京 邮箱：malin213@tom.comVC++ .net OpenGLQQ:274955617</subtitle><id>http://feed.cnblogs.com/blog/u/13254/rss</id><updated>2012-02-08T05:58:16Z</updated><author><name>3D入魔</name><uri>http://www.cnblogs.com/mazhenyu/</uri></author><generator>CNBlogs BlogServer</generator><link rel="alternate" type="text/html" href="http://www.cnblogs.com/mazhenyu/"/><link rel="self" type="application/atom+xml" href="http://feed.cnblogs.com/blog/u/13254/rss"/><entry><id>http://www.cnblogs.com/mazhenyu/archive/2012/02/08/2342609.html</id><title type="text">概要设计和详细设计的区别与联系 (转)</title><summary type="text">http://www.blogjava.net/wealupa/archive/2009/04/27/267692.html软件设计采用自顶向下、逐次功能展开的设计方法，首先完成总体设计，然后完成各有机组成部分的设计。 根据工作性质和内容的不同，软件设计分为概要设计和详细设计。概要设计实现软件的总体设计、模块划分、用户界面设计、数据库设计等等；详细设计则根据概要设计所做的模块划分，实现各模块的算法设计，实现用户界面设计、数据结构设计的细化，等等。 概要设计是详细设计的基础，必须在详细设计之前完成，概要设计经复查确认后才可以开始详细设计。概要设计，必须完成概要设计文档，包括系统的总体设计文档、.</summary><published>2012-02-08T05:58:00Z</published><updated>2012-02-08T05:58:00Z</updated><author><name>3D入魔</name><uri>http://www.cnblogs.com/mazhenyu/</uri></author><link rel="alternate" href="http://www.cnblogs.com/mazhenyu/archive/2012/02/08/2342609.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/mazhenyu/archive/2012/02/08/2342609.html"/><content type="html">&lt;p style="text-indent: 2em"&gt;&lt;a href="http://www.blogjava.net/wealupa/archive/2009/04/27/267692.html" rel="nofollow"&gt;http://www.blogjava.net/wealupa/archive/2009/04/27/267692.html&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p style="text-indent: 2em"&gt;软件设计采用自顶向下、逐次功能展开的设计方法，首先完成总体设计，然后完成各有机组成部分的设计。 &lt;/p&gt;&#xD;
&lt;p style="text-indent: 2em"&gt;根据工作性质和内容的不同，软件设计分为概要设计和详细设计。概要设计实现软件的总体设计、模块划分、用户界面设计、数据库设计等等；详细设计则根据概要设计所做的模块划分，实现各模块的算法设计，实现用户界面设计、数据结构设计的细化，等等。&lt;/p&gt;&#xD;
&lt;p style="text-indent: 2em"&gt;概要设计是详细设计的基础，必须在详细设计之前完成，概要设计经复查确认后才可以开始详细设计。概要设计，必须完成概要设计文档，包括系统的总体设计文档、以及各个模块的概要设计文档。每个模块的设计文档都应该独立成册。&lt;/p&gt;&#xD;
&lt;p style="text-indent: 2em"&gt;详细设计必须遵循概要设计来进行。详细设计方案的更改，不得影响到概要设计方案；如果需要更改概要设计，必须经过项目经理的同意。详细设计，应该完成详细设计文档，主要是模块的详细设计方案说明。和概要设计一样，每个模块的详细设计文档都应该独立成册。&lt;/p&gt;&#xD;
&lt;p style="text-indent: 2em"&gt;概要设计里面的数据库设计应该重点在描述数据关系上，说明数据的来龙去脉，在这里应该结合我们的一下结果数据，说明这些结果数据的源点，我们这样设计的目的和原因。详细设计里的数据库设计就应该是一份完善的数据结构文档，就是一个包括类型、命名、精度、字段说明、表说明等内容的数据字典。&lt;/p&gt;&#xD;
&lt;p style="text-indent: 2em"&gt;概要设计里的功能应该是重点在功能描述，对需求的解释和整合，整体划分功能模块，并对各功能模块进行详细的图文描述，应该让读者大致了解系统作完后大体的结构和操作模式。详细设计则是重点在描述系统的实现方式，各模块详细说明实现功能所需的类及具体的方法函数，包括涉及到的sql语句等。&lt;/p&gt;&#xD;
&lt;p style="text-indent: 2em"&gt;&lt;a href="http://blog.csdn.net/skyly84/archive/2009/06/02/4236569.aspx" rel="nofollow"&gt;http://blog.csdn.net/skyly84/archive/2009/06/02/4236569.aspx&lt;/a&gt; &lt;/p&gt;&#xD;
&lt;p style="text-indent: 2em"&gt;&lt;strong&gt;概要设计与详细设计的区别&lt;/strong&gt; &lt;/p&gt;&#xD;
&lt;p style="text-indent: 2em"&gt;概要设计就是设计软件的结构，包括组成模块，模块的层次结构，模块的调用关系，每个模块的功能等等。同时，还要设计该项目的应用系统的总体数据结构和数据库结构，即应用系统要存储什么数据，这些数据是什么样的结构，它们之间有什么关系。 &lt;/p&gt;&#xD;
&lt;p style="text-indent: 2em"&gt;详细设计阶段就是为每个模块完成的功能进行具体的描述，要把功能描述转变为精确的、结构化的过程描述。&lt;/p&gt;&#xD;
&lt;p style="text-indent: 2em"&gt;&lt;font color="#ff0000"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 概要设计阶段通常得到软件结构图&lt;/font&gt; &lt;/p&gt;&#xD;
&lt;p style="text-indent: 2em"&gt;详细设计阶段常用的描述方式有：流程图、N-S图、PAD图、伪代码等&lt;/p&gt;&#xD;
&lt;p style="text-indent: 2em"&gt;概要设计和详细设计&lt;/p&gt;&#xD;
&lt;p style="text-indent: 2em"&gt;在软件设计中，大家经常问到的一个问题是：概要设计应该怎样一个概要法，详细设计应该怎样一个详细法？ &lt;/p&gt;&#xD;
&lt;p style="text-indent: 2em"&gt;这个问题在公司内部经常有人问。现在陈述一下。 &lt;/p&gt;&#xD;
&lt;p style="text-indent: 2em"&gt;我们公司的研发流程是瀑布型的，这个模型中的分析、设计阶段是基于经典的结构化方法。 &lt;/p&gt;&#xD;
&lt;p style="text-indent: 2em"&gt;&lt;font color="#0000ff"&gt;结构化设计方法的基本思路是：按照问题域，将软件逐级细化，分解为不必再分解的的模块，每个模块完成一定的功能，为一个或多个父模块服务（即接受调用），也接受一个或多个子模块的服务（即调用子模块）。模块的概念，和编程语言中的子程序或函数是对应的。&lt;/font&gt;&lt;/p&gt;&#xD;
&lt;p style="text-indent: 2em"&gt;&lt;/p&gt;&#xD;
&lt;p style="text-indent: 2em"&gt;这样一来，设计可以明显地划分成两个阶段： &lt;/p&gt;&#xD;
&lt;p style="text-indent: 2em"&gt;&lt;font color="#0000ff"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 概要（结构）设计阶段：把软件按照一定的原则分解为模块层次，赋予每个模块一定的任务，并确定模块间调用关系和接口。&lt;/font&gt; &lt;/p&gt;&#xD;
&lt;p style="text-indent: 2em"&gt;详细设计阶段：依据概要设计阶段的分解，设计每个模块内的算法、流程等。&lt;/p&gt;&#xD;
&lt;p style="text-indent: 2em"&gt;概要设计阶段：&lt;/p&gt;&#xD;
&lt;p style="text-indent: 2em"&gt;在这个阶段，设计者会大致考虑并照顾模块的内部实现，但不过多纠缠于此。&lt;font color="#0000ff"&gt;主要集中于划分模块、分配任务、定义调用关系。模块间的接口与传参在这个阶段要定得 十分细致明确，应编写严谨的数据字典，避免后续设计产生不解或误解。&lt;/font&gt;&lt;font color="#ff0000"&gt;概要设计一般不是一次就能做到位，而是反复地进行结构调整。&lt;/font&gt;典型的调整是合并功能重复的模块，或者进一步分解出可以复用的模块。在概要设计阶段，应最大限度地提取可以重用的模块，建立合理的结构体系，节省后续环节的工作量。 &lt;/p&gt;&#xD;
&lt;p style="text-indent: 2em"&gt;&lt;font color="#0000ff"&gt; 概要设计文档最重要的部分是分层数据流图、结构图、数据字典以及相应的文字说明等。&lt;/font&gt;以概要设计文档为依据，各个模块的详细设计就可以并行展开了。&lt;/p&gt;&#xD;
&lt;p style="text-indent: 2em"&gt;详细设计阶段:&lt;/p&gt;&#xD;
&lt;p style="text-indent: 2em"&gt;在这个阶段，各个模块可以分给不同的人去并行设计。在详细设计阶段，设计者的工作对象是一个模块，根据概要设计赋予的局部任务和对外接口，设计并表达出模块的算法、流程、状态转换等内容。这里要注意，如果发现有结构调整（如分解出子模块等）的必要，必须返回到概要设计阶段，将调整反应到概要设计文档中，而不 能就地解决，不打招呼。详细设计文档最重要的部分是模块的流程图、状态图、局部变量及相应的文字说明等。一个模块一篇详细设计文档。&lt;/p&gt;&#xD;
&lt;p style="text-indent: 2em"&gt;概要设计文档相当于机械设计中的装配图，而详细设计文档相当于机械设计中的零件图。文档的编排、装订方式也可以参考机械图纸的方法。 &lt;/p&gt;&#xD;
&lt;p style="text-indent: 2em"&gt;我们公司对模块的认识和传统定义有所不同，认为是较大的软件功能单元才可以称作模块。这种认识使大家对概要设计和详细设计的分工产生了混乱的理解，降低了文档的可用性，应该予以纠正。 &lt;/p&gt;&#xD;
&lt;p style="text-indent: 2em"&gt;&lt;font color="#0000ff"&gt;&amp;nbsp; 概要设计中较顶层的部分便是所谓的方案。方案文档的作用是在宏观的角度上保持设计的合理性。&lt;/font&gt;&lt;/p&gt;&#xD;
&lt;p style="text-indent: 2em"&gt;有的项目采用面向对象的分析、设计方法。可能在概要设计、详细设计的分工上疑问更多。其实，面向对象的分析、设计方法并没有强调结构化方法那样的阶段性，因此一般不引入概要、详细设计的概念。如果按照公司的文档体系，非要有这种分工的话，&lt;font color="#0000ff"&gt;可以将包的划分、类及对象间的关系、类的对外属性、方法及协作设计看做 概要设计；类属性、方法的内部实现看做详细设计。&lt;/font&gt;&lt;/p&gt;&#xD;
&lt;p style="text-indent: 2em"&gt;1.需求分析--产生软件功能规格说明书,需要确定用户对软件的需求,要作到明确、无歧义。不涉及具体实现方法。用户能看得明白，开发人员也可据此进行下面的工作（概要设计）。 &lt;/p&gt;&#xD;
&lt;p style="text-indent: 2em"&gt;2.概要设计--产生软件概要设计说明书，说明系统模块划分、选择的技术路线等，整体说明软件的实现思路。并且需要指出关键技术难点等。&amp;nbsp;&amp;nbsp; &lt;/p&gt;&#xD;
&lt;p style="text-indent: 2em"&gt;3.详细设计--产生软件详细设计说明书，对概要设计的进一步细化，一般由各部分的担当人员依据概要设计分别完成，然后在集成，是具体的实现细节。理论上要求可以照此编码。&lt;/p&gt;&#xD;
&lt;p style="text-indent: 2em"&gt;概要设计和详细设计的区别与联系&lt;/p&gt;&#xD;
&lt;p style="text-indent: 2em"&gt;软件设计采用自顶向下、逐次功能展开的设计方法，首先完成总体设计，然后完成各有机组成部分的设计。&lt;/p&gt;&#xD;
&lt;p style="text-indent: 2em"&gt;根据工作性质和内容的不同，软件设计分为概要设计和详细设计。概要设计实现软件的总体设计、模块划分、用户界面设计、数据库设计等等；详细设计则根据概要设计所做的模块划分，实现各模块的算法设计，实现用户界面设计、数据结构设计的细化，等等。&lt;/p&gt;&#xD;
&lt;p style="text-indent: 2em"&gt;概要设计是详细设计的基础，必须在详细设计之前完成，概要设计经复查确认后才可以开始详细设计。概要设计，必须完成概要设计文档，包括系统的总体设计文档、以及各个模块的概要设计文档。每个模块的设计文档都应该独立成册。&lt;/p&gt;&#xD;
&lt;p style="text-indent: 2em"&gt;详细设计必须遵循概要设计来进行。详细设计方案的更改，不得影响到概要设计方案；如果需要更改概要设计，必须经过项目经理的同意。详细设计，应该完成详细设计文档，主要是模块的详细设计方案说明。和概要设计一样，每个模块的详细设计文档都应该独立成册。&lt;/p&gt;&#xD;
&lt;p style="text-indent: 2em"&gt;概要设计里面的数据库设计应该重点在描述数据关系上，说明数据的来龙去脉，在这里应该结合我们的一下结果数据，说明这些结果数据的源点，我们这样设计的目的和原因。详细设计里的数据库设计就应该是一份完善的数据结构文档，就是一个包括类型、命名、精度、字段说明、表说明等内容的数据字典。&lt;/p&gt;&#xD;
&lt;p style="text-indent: 2em"&gt;概要设计里的功能应该是重点在功能描述，对需求的解释和整合，整体划分功能模块，并对各功能模块进行详细的图文描述，应该让读者大致了解系统作完后大体的结构和操作模式。详细设计则是重点在描述系统的实现方式，各模块详细说明实现功能所需的类及具体的方法函数，包括涉及到的sql语句等。&lt;/p&gt;&#xD;
&lt;p style="text-indent: 2em"&gt;概要设计，详细设计之间的关系是什么？&lt;/p&gt;&#xD;
&lt;p style="text-indent: 2em"&gt;Q:&lt;/p&gt;&#xD;
&lt;p style="text-indent: 2em"&gt;我的看法：&lt;/p&gt;&#xD;
&lt;p style="text-indent: 2em"&gt;&lt;font color="#ff0000"&gt; 概要设计只说明系统有多少个模块，各模块之间的接口和个模块本身的功能&lt;/font&gt;&lt;/p&gt;&#xD;
&lt;p style="text-indent: 2em"&gt;详细设计说明某个具体模块如何实现，粒度应该比程序略高一些&lt;/p&gt;&#xD;
&lt;p style="text-indent: 2em"&gt;但是问题来了，各个模块之间是有层次关系的，也有先后逻辑关系。这就说明，在概要设计中，还必须考虑模块的实现细节，否则，你怎么知道这个模块下面要划分子模块？你怎么知道各子模块的调用顺序？&lt;/p&gt;&#xD;
&lt;p style="text-indent: 2em"&gt;这就说明，概要设计和详细设计是重叠进行的，而软件工程书上说的确是顺序进行的，不知道是不是我的理解有问题。&lt;/p&gt;&#xD;
&lt;p style="text-indent: 2em"&gt;举个例子，例如排序程序，如果设计2个模块：&lt;/p&gt;&#xD;
&lt;p style="text-indent: 2em"&gt;一个主模块用于排序子模块用于交换2个变量，主模块调用子模块，但是子模块是怎么设计出来的呢？肯定是你先想到了用冒泡等排序方式的时候需要交换数据，这已经考虑了主模块足够多的细节，似乎属于"详细设计"了，但是目前进行的是概要设计，这就产生了我所说的重叠的情况。&lt;/p&gt;&#xD;
&lt;p style="text-indent: 2em"&gt;A:&lt;/p&gt;&#xD;
&lt;p style="text-indent: 2em"&gt;看看上面的帖子，有意思的居多。&lt;/p&gt;&#xD;
&lt;p style="text-indent: 2em"&gt;上面也有朋友说到用建筑的例子来比喻。&lt;/p&gt;&#xD;
&lt;p style="text-indent: 2em"&gt;软件的概要设计，主要是建立软件系统的整体架构，也就是我们在盖房子时候，需要先将房子的整个架子构建起来。&lt;/p&gt;&#xD;
&lt;p style="text-indent: 2em"&gt;软件的详细设计，主要是将软件系统的各个部分的具体设计方法、逻辑、功能采用文字方式进行表述。这样在实现过程中，Coding人员原则上严格按此进行代码实现即可。&lt;/p&gt;&#xD;
&lt;p style="text-indent: 2em"&gt;这样的一个最为简单的例证：我们可以将代码交付第三方来做。验证与跟踪采取设计来。&lt;/p&gt;&#xD;
&lt;p style="text-indent: 2em"&gt;我看上面还有一个朋友说：快速做代码。这个本身没有值得批评之处。但只要想一下，你写的代码没有任何设计思想、文档留下的情况，一旦你离开，如何维护？重新设计吗？还是花费几倍人力去研究你写的几千/万，甚至几十万行代码？如果是这样的，你没错，关键是你们老板太对了，钱算什么。&lt;/p&gt;&#xD;
&lt;p style="text-indent: 2em"&gt;另外的一个问题是：中国人如此聪明，但中国为什么没有出现巨型软件产品呢？个人英雄主义依然很严重，老板的短视利益行为大行其道。&lt;/p&gt;&#xD;
&lt;p style="text-indent: 2em"&gt;本文来自CSDN博客，转载请标明出处：&lt;a href="http://blog.csdn.net/skyly84/archive/2009/06/02/4236569.aspx" rel="nofollow"&gt;http://blog.csdn.net/skyly84/archive/2009/06/02/4236569.aspx&lt;/a&gt;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/mazhenyu/aggbug/2342609.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/mazhenyu/archive/2012/02/08/2342609.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/mazhenyu/archive/2012/01/06/2314001.html</id><title type="text">2011年投资总结及感悟</title><summary type="text">2011年对我而言是个“坑爹”的一年，总资产缩水20%左右，是一个失败的年头。体会一： 深刻体会到“君子不立危墙之下”这句话的道理。 中国的投资市场是一个很不规范的投机市场，几乎已经没有了投资回报的理念，钱都被大股东和原始股东圈走了，所有的市场投资人都是为他们买单的对象，减持已经成为这个市场的断头刃，正所谓“圣人不死，大盗不止”，应该是对这个市场彻底死心的时候了。体会二： 没有最坏只有更坏。市场的最后一跌是相当恐怖的，不要试图猜测这个市场的底线在哪里，其实市场的真实底线是没有底线，当看到形式不对早些离场才是上策。我是吃了很大的亏的，硬抗的感觉很受伤呀，呵呵。体会三： 与其把资金和精力放在中国的</summary><published>2012-01-06T02:13:00Z</published><updated>2012-01-06T02:13:00Z</updated><author><name>3D入魔</name><uri>http://www.cnblogs.com/mazhenyu/</uri></author><link rel="alternate" href="http://www.cnblogs.com/mazhenyu/archive/2012/01/06/2314001.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/mazhenyu/archive/2012/01/06/2314001.html"/><content type="html">&lt;p&gt;2011年对我而言是个&amp;#8220;坑爹&amp;#8221;的一年，总资产缩水20%左右，是一个失败的年头。&lt;/p&gt;&#xD;
&lt;p&gt;体会一： 深刻体会到&amp;#8220;君子不立危墙之下&amp;#8221;这句话的道理。 中国的投资市场是一个很不规范的投机市场，几乎已经没有了投资回报的理念，钱都被大股东和原始股东圈走了，所有的市场投资人都是为他们买单的对象，减持已经成为这个市场的断头刃，正所谓&amp;#8220;圣人不死，大盗不止&amp;#8221;，应该是对这个市场彻底死心的时候了。&lt;/p&gt;&#xD;
&lt;p&gt;体会二： 没有最坏只有更坏。市场的最后一跌是相当恐怖的，不要试图猜测这个市场的底线在哪里，其实市场的真实底线是没有底线，当看到形式不对早些离场才是上策。我是吃了很大的亏的，硬抗的感觉很受伤呀，呵呵。&lt;/p&gt;&#xD;
&lt;p&gt;体会三： 与其把资金和精力放在中国的股市中不如选择一门实业从小做起，未来（2012年4月份中旬前）打算全面从股市中撤出，不再玩了。以后的基金投资也只投资货币式基金了。&lt;/p&gt;&#xD;
&lt;p&gt;体会四： 当市场跌得一片惨绿，票价低廉时，手中却没有现金，这种感觉是很痛苦的。这是一个很深刻的教训，&amp;#8220;耐心&amp;#8221;是很重要的，现金为王，安全为上。&lt;/p&gt;&#xD;
&lt;p&gt;体会五： 越来越不看好未来5年的中国股票市场了，决定出局观望，歇歇心。即使有机会也不再赚这份钱了，呵呵。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;未来打算：&lt;/p&gt;&#xD;
&lt;p&gt;经过一年的痛苦折磨，决定再死扛一段时间等待2012.4月份市场反弹到一个高点减仓80%，最多保留10%-20%的仓位了，对这个市场已经缺少了最基本的信心，这实在是一个坑爹的市场，风险远远大于收益，到处都是骗局，我为鱼肉人为刀俎呀，本人的道行真的是玩过不他们，也不值得再跟他们玩下去了。在未来的5年内将不再把超过30%的资金投入此市场，甚至可以考虑空仓以对。&lt;/p&gt;&#xD;
&lt;p&gt;未来的精力将致力于实业的发展和个人能力的发展。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;2012年我将暂时告别股市，也许4年后我会回来，呵呵。　　&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;2012.1.6&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/mazhenyu/aggbug/2314001.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/mazhenyu/archive/2012/01/06/2314001.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/mazhenyu/archive/2011/12/27/2303365.html</id><title type="text">Internet上用ActiveX发布软件（转）</title><summary type="text">开发者在线 Builder.com.cn 更新时间:2007-10-21作者：Micronet 来源:yeskyhttp://www.builder.com.cn/2007/1021/569268.shtml互连网的广泛应用使得基于网络的软件成为现今软件应用的主流，软件计算环境正在由主机计算、PC计算向网络计算过渡，真正的网络计算时代已经来临。为方便企业软件的发行，众多企业在建立网站的同时，将企业的功能软件集成其中，给用户以最大程度的快捷和便利来应用本企业的软件，这样的应用使得现今软件已成为一种基于网络的服务，也使得软件的人机界面更为互动。然而如何实现和推广这样的应用就成为亟待解决的问题。微软</summary><published>2011-12-27T04:49:00Z</published><updated>2011-12-27T04:49:00Z</updated><author><name>3D入魔</name><uri>http://www.cnblogs.com/mazhenyu/</uri></author><link rel="alternate" href="http://www.cnblogs.com/mazhenyu/archive/2011/12/27/2303365.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/mazhenyu/archive/2011/12/27/2303365.html"/><content type="html">&lt;div &gt;&#xD;
&lt;h3 &gt;&lt;a href="http://www.builder.com.cn/" target="_blank"&gt;开发者在线 Builder.com.cn&lt;/a&gt; 更新时间:&lt;cite&gt;2007-10-21&lt;/cite&gt;作者：&lt;span&gt;Micronet&lt;/span&gt; 来源:yesky&lt;/strong&gt;&lt;/p&gt;&lt;/div&gt;&#xD;
&lt;div &gt;&lt;a href="http://www.builder.com.cn/2007/1021/569268.shtml"&gt;http://www.builder.com.cn/2007/1021/569268.shtml&lt;/a&gt;&lt;/div&gt;&#xD;
&lt;div &gt;互连网的广泛应用使得基于网络的软件成为现今软件应用的主流，软件计算环境正在由主机计算、PC计算向网络计算过渡，真正的网络计算时代已经来临。为方便企业软件的发行，众多企业在建立网站的同时，将企业的功能软件集成其中，给用户以最大程度的快捷和便利来应用本企业的软件，这样的应用使得现今软件已成为一种基于网络的服务，也使得软件的人机界面更为互动。然而如何实现和推广这样的应用就成为亟待解决的问题。微软文档在这些方面有非常全面的细节描述，但由于比较分散，文字表述比较抽象，会花费软件开发人员比较多的时间进行理解，故本文系统的介绍这方面的相关知识和具体实现，以方便其他人的软件开发和研究工作。&lt;br /&gt;&lt;br /&gt;　　&lt;strong&gt;一、介绍基于Internet发布的软件&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;　　1.1 基于Internet的软件发布模式：&lt;br /&gt;&lt;br /&gt;　　根据客户端和服务器端应用模式的不同，基于网络的软件可以分为C/S和B/S结构。&lt;br /&gt;&lt;br /&gt;　　对于C/S结构，发布者在服务器运行服务器端软件，并保持其状态，而使用者需安装软件发布商所提供的专用客户端，并按照发布商的说明完成客户机的设置工作。安装和运行过程有所不便。&lt;br /&gt;&lt;br /&gt;　　对于B/S结构，软件的发布可以有两种方式：&lt;br /&gt;&lt;br /&gt;　　(1)在服务器端发布，发布者制作组件并对组件注册，组件提供COM接口，供程序调用，如ASP就可以在网页中对组件进行调用，使客户端浏览者通过服务器完成计算或其他功能。&lt;br /&gt;&lt;br /&gt;　　(2)在客户端发布，通过访问企业网站，浏览者的浏览器自动下载已将ActiveX控件和需要的功能链接库打包的数据文件，检查并登记软件发行企业的数字签名，然后解开该压缩包，根据包内的配置文件完成功能部件和ActiveX控件的注册，最后，检查控件内脚本的安全性，自动完成客户端软件的安装和设置，并在网页的相应位置显示ActiveX控件（企业软件界面）供用户操作。&lt;br /&gt;&lt;br /&gt;　　以上B/S结构软件的两种发行方式可以混合使用，完成网络交互的复杂功能。&lt;br /&gt;&lt;br /&gt;　　1.2 数字签名介绍：&lt;br /&gt;&lt;br /&gt;　　用户同意下载并注册软件发布者提供的工具包，首先必须确保该包中控件的源代码是安全的，这就需要软件发布商以自己的身份标记该工具包。这个标记过程就是软件发布商对所发布软件的数字签名。&lt;br /&gt;&lt;br /&gt;　　1.3 软件出版商证书介绍：&lt;br /&gt;&lt;br /&gt;　　在签署文件之前，需要有一个软件出版商证明书。软件发布者必须向证书发放机构申请自己的证书。在申请过程中，必须生成一个密匙对，并向证书发放机构提供证明信息，如名字、地址以及公共密匙。证书发放机构在收到申请后生成一个符合工业标准X.509证书格式的软件出版商证书 。该证书确定并且包含公共密匙，以证书发放机构存档作为参考，并把一个拷贝以电子邮件的方式返回。收到该证书之后，软件发布者应在所有要发布的、用私人密匙签署的软件当中，包含一份该证书的拷贝。&lt;br /&gt;&lt;br /&gt;　　为方便软件的测试，也可以通过相关工具创建一个用于测试目的的测试证书，但是该证书不能用于发售代码。&lt;br /&gt;&lt;br /&gt;　　1.4 ActiveX控件的脚本安全介绍：&lt;br /&gt;&lt;br /&gt;　　代码签字可以向用户保证代码的可信度。但是运行一个ActiveX控件将带来新的安全性问题--控件被申明是可靠的，但如果使用不可信脚本代码访问就不能保证其安全性。&lt;br /&gt;&lt;br /&gt;　　为在网络上获得安全应用，表明所开发的控件有安全性的保障，ActiveX初始化和脚本操作都需要一个确定的安全性机制保证其安全性不被违背。&lt;br /&gt;&lt;br /&gt;　　IE具有三个安全性层次，当用户调用一个包含非安全性初始化和脚本操作的控件的网页时，IE分别给出下列基于当前安全级别的警告信息：&lt;br /&gt;&lt;br /&gt;　　低级：没有警告 &lt;br /&gt;&lt;br /&gt;　　中级：提示用户潜在的风险 &lt;br /&gt;&lt;br /&gt;　　高级：提示用户潜在的风险并且禁止控件运行 &lt;br /&gt;&lt;br /&gt;　　大多数控件开发者都是将IE的安全性级别设置为最低以便于开发调试。但是控件被其他浏览者应用时，安全级别却设定为默认的高级。因此开发者必须在控件代码编写时提供安全性保障代码。&lt;br /&gt;&lt;br /&gt;　　有两种方法提供控件的脚本操作安全性保证。第一种是使用组件分组管理器在组件导入以后在注册表上面创建正确的入口，IE在脚本操作之前检查注册表确认安全性；第二种是实现一个 IObjectSafety 接口到控件，如果IE发现控件支持 IObjectSafety，就在导入控件之前调用 IObjectSafety::SetInterfaceSafetyOptions 方法来确保安全性脚本操作。 &lt;/div&gt;&#xD;
&lt;div &gt;&lt;strong&gt;二、基于Internet发布软件的具体实现&lt;br /&gt;&lt;br /&gt;&lt;/strong&gt;　　2.1 制作测试软件出版商证书：&lt;br /&gt;&lt;br /&gt;　　使用Visual C++ 5.0 光盘中CAB&amp;amp;SIGN目录下的 MAKECERT和 CERT2SPC 公用程序。举例来说，制作分两步：&lt;br /&gt;&lt;br /&gt;　　（1）做一个私人密匙文件MYKEY.PVK 和一个公司证书CERT.CER，运行公用程序MAKECERT，命令为:&lt;br /&gt;&lt;br /&gt;MAKECERT -u:MyKey -n:CN=Company -k:MYKEY.PVK CERT.CER&lt;br /&gt;&lt;br /&gt;　　其中MyKey是密匙名，Company是公司名。注意：公用程序 MAKECERT 在命令行选项中区分大小写，因此必须使用小写的-u、-n以及-k，对于-n选项的值必须是大写的CN。&lt;br /&gt;&lt;br /&gt;　　（2）完成名为CERT.SPC测试软件出版商证书的制作，运行CERT2SPC，命令如下: &lt;br /&gt;CERT2SPC ROOT.CER CERT.CER CERT.SPC&lt;br /&gt;&lt;br /&gt;　　其中CERT.SPC文件是利用第一步创建的CERT.CER文件以及CAB&amp;amp;SIGN目录下提供的ROOT.CER文件创建的。&lt;br /&gt;&lt;br /&gt;　　2.2 打包待发布的ActiveX控件和相关链接库：&lt;br /&gt;&lt;br /&gt;　　使用CAB&amp;amp;SIGN目录下的CABARC.EXE，举例来说，过程分两步：&lt;br /&gt;&lt;br /&gt;　　（1） 创建一个INF文件：&lt;br /&gt;&lt;br /&gt;　　INF文件是一个文本文件，指定运行控件所需要下载和注册的组件(比如DLL或其它OCX)。一个INF文件描述了CAB压缩包中所有必须的文件。在缺省情况下，若客户端系统中有压缩包中的文件，则版本号相同的文件不被下载。一个INF文件(texture.inf)的示例为：&lt;br /&gt;&lt;br /&gt;&#xD;
&lt;table width="100%" bgcolor="#ffffff"&gt;&#xD;
&lt;tbody&gt;&#xD;
&lt;tr&gt;&#xD;
&lt;td&gt;[version]&lt;br /&gt;signature="$CHICAGO$"&lt;br /&gt;AdvancedINF=2.0&lt;br /&gt;[Add.Code]&lt;br /&gt;Cards.ocx=Cards.ocx&lt;br /&gt;mfc42.dll=mfc42.dll&lt;br /&gt;opengl32.dll=opengl32.dll&lt;br /&gt;glu32.dll=glu32.dll&lt;br /&gt;[Cards.ocx]&lt;br /&gt;file-win32-x86=thiscab&lt;br /&gt;clsid=&lt;br /&gt;FileVersion=1,0,0,1&lt;br /&gt;RegisterServer=yes&lt;br /&gt;[mfc42.dll]&lt;br /&gt;file-win32-x86=thiscab&lt;br /&gt;RegisterServer=yes&lt;br /&gt;[opengl32.dll]&lt;br /&gt;FileVersion=4,0,0,0&lt;br /&gt;hook=openglinstaller&lt;br /&gt;[glu32.dll]&lt;br /&gt;FileVersion=4,0,0,0&lt;br /&gt;hook=openglinstaller&lt;br /&gt;[openglinstaller]&lt;br /&gt;file-win32-x86=OpenGL95.cab&lt;br /&gt;run=%EXTRACT_DIR%OpenGL95.exe&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;　　其中条目[version]固定，条目[Add.Code]将需要下载的动态链接库和ActiveX 组件填写其中作为下载清单，其他以[Add.Code]中的文件名为条目名的表项是对这些文件的来源、版本、下载路径和是否需客户端系统注册的具体说明--关键字"file-win32-x86"指定平台是x86，其值"thiscab"也是一个关键字，意指包含该INF的CAB文件，也可以是其他同时被下载的cab文件名或者是一个网址；"clsid"是指待注册控件的CLSID；"RegisterServer=yes"表示对应文件需要系统注册；"hook"表示该文件位置要去hook语句所指示的条目里寻找；&lt;br /&gt;&lt;br /&gt;　　（2） 运行公用程序CABARC.EXE，对应于以上INF文件有如下命令行：&lt;br /&gt;&lt;br /&gt;&#xD;
&lt;table width="100%" bgcolor="#ffffff"&gt;&#xD;
&lt;tbody&gt;&#xD;
&lt;tr&gt;&#xD;
&lt;td&gt;CABARC -s 6144 n texturemap.cab cards.ocx mfc42.dll texture.inf&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;　　执行后创建了一个名为texturemap.cab的CAB文件。其中，CAB包中的文件需要在命令行列出，次序同它们在INF文件中的完全一致，-s选项为代码签署保留空间，n 命令指定创建的是CAB文件。&lt;br /&gt;&lt;br /&gt;　　2.3 对打包得到的文件进行数字签名：&lt;br /&gt;&lt;br /&gt;　　使用CAB&amp;amp;SIGN目录下的SIGNCODE.EXE，步骤如下：&lt;br /&gt;&lt;br /&gt;　　（1） 运行该程序，在需填写属性的第一页，选择打包好的文件（也可以直接是ActiveX控件所对应的文件，如OCX/DLL），填写发布软件名和发布商的网址(方便用户根据这些资料直观的判断是否运行该控件)；&lt;br /&gt;&lt;br /&gt;　　（2） 第二页是证书发放机构的列表，选择软件发布商所获得证书的所属机构；&lt;br /&gt;&lt;br /&gt;　　（3） 第三个用户填写页，选定软件开发商证书(SPC)文件名，另外，因为需在该证书的一个文件中查找密码、密匙，所以还需选定私人密匙(PVK)文件名；&lt;br /&gt;&lt;br /&gt;　　（4） 确认所填写的信息后，SIGNCODE就对文件进行签署。&lt;br /&gt;&lt;/div&gt;&#xD;
&lt;div &gt;2.4 使用组件分组管理器确保控件初始化和脚本操作安全性：&lt;br /&gt;&lt;br /&gt;　　如果一个控件使用组件分组管理器将自己注册为安全，则该控件的注册表入口就包含一个分组关键字，该关键字含一个或者两个子键，其中一个设置控件支持安全性初始化，另一个设置支持安全性脚本操作。安全性初始化子键对应CATID_SafeForInitializing，安全性脚本操作子键对应CATID_SafeForScripting(组件分组子键定义在 Comcat.h 文件，而安全性初始化和脚本操作子键定义在 Objsafe.h 文件)。&lt;br /&gt;&lt;br /&gt;　　要创建一个组件分组的子键，控件必须实现以下步骤：&lt;br /&gt;&lt;br /&gt;　　(1)创建一个组件分组管理器实例来接收 ICatRegister 接口的地址；&lt;br /&gt;&lt;br /&gt;　　(2)设置CATEGORYINFO结构变量；&lt;br /&gt;&lt;br /&gt;　　(3)调用ICatRegister::RegisterCategories方法，将以上设定的CATEGORYINFO结构变量作为参数传递。&lt;br /&gt;在控件编写时就需添加如下的全局函数：&lt;br /&gt;&lt;br /&gt;&#xD;
&lt;table width="100%" bgcolor="#ffffff"&gt;&#xD;
&lt;tbody&gt;&#xD;
&lt;tr&gt;&#xD;
&lt;td&gt;HRESULT CreateComponentCategory(CATID catid, WCHAR *catDescription)&lt;br /&gt;{&lt;br /&gt;ICatRegister* pcr = NULL; &lt;br /&gt;HRESULT hr = S_OK;&lt;br /&gt;//创建一个组件管理器实例(进程内) &lt;br /&gt;hr=CoCreateInstance(CLSID_StdComponentCategoriesMgr,NULL,CLSCTX_INPROC_SERVER,IID_ICatRegister,(void**)&amp;amp;pcr); &lt;br /&gt;if (FAILED(hr)) return hr; &lt;br /&gt;//确信HKCRComponent Categories键已经被注册 &lt;br /&gt;CATEGORYINFO catinfo; &lt;br /&gt;catinfo.catid = catid; &lt;br /&gt;catinfo.lcid = 0x0409;//英语&lt;br /&gt;//确信提供的描述在127个字符以内 &lt;br /&gt;int len = wcslen(catDescription); &lt;br /&gt;if (len＞127) len = 127; &lt;br /&gt;wcsncpy(catinfo.szDescription,catDescription,len); &lt;br /&gt;//确信描述使用''结束 &lt;br /&gt;catinfo.szDescription[len] = ''; &lt;br /&gt;hr = pcr-＞RegisterCategories(1,&amp;amp;catinfo); &lt;br /&gt;pcr-＞Release(); &lt;br /&gt;return hr; &lt;br /&gt;} &lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;　　当一个子键被创建到需要的分组，控件应该按以下步骤注册到该分组：&lt;br /&gt;&lt;br /&gt;　　(1)创建一个组件分组管理器实例接收ICatRegister接口地址；&lt;br /&gt;&lt;br /&gt;　　(2)调用ICatRegister::RegisterClassImplCategories方法，将控件的CLSID和需要的category ID 作为参数传递。&lt;br /&gt;&lt;br /&gt;　　对应的全局函数为：&lt;br /&gt;&lt;br /&gt;&#xD;
&lt;table width="100%" bgcolor="#ffffff"&gt;&#xD;
&lt;tbody&gt;&#xD;
&lt;tr&gt;&#xD;
&lt;td&gt;HRESULT RegisterCLSIDInCategory(REFCLSID clsid, CATID catid)&lt;br /&gt;{&lt;br /&gt;//注册组件分组信息&lt;br /&gt;ICatRegister* pcr = NULL;&lt;br /&gt;HRESULT hr = S_OK;&lt;br /&gt;hr=CoCreateInstance(CLSID_StdComponentCategoriesMgr,NULL,CLSCTX_INPROC_SERVER,IID_ICatRegister,(void**)&amp;amp;pcr);&lt;br /&gt;if(SUCCEEDED(hr)) &lt;br /&gt;{ &lt;br /&gt;//注册已实现的类到分组&lt;br /&gt;CATID rgcatid[1]; rgcatid[0] = catid;&lt;br /&gt;hr = pcr-＞RegisterClassImplCategories(clsid,1,rgcatid);&lt;br /&gt;}&lt;br /&gt;if(pcr != NULL) pcr-＞Release();&lt;br /&gt;return hr;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;　　ActiveX的注册是在函数DLLRegisterServer中进行的，在组件中 DLLRegisterServer 函数调用了CreateComponentCategory和RegisterCLSIDInCategory函数来保证控件的安全性初始化和脚本操作。所以DLLRegisterServer应添加如下代码：&lt;br /&gt;&lt;br /&gt;//注册控件是安全性初始化的&lt;br /&gt;hr=CreateComponentCategory(CATID_SafeForInitializing,L"Controls safely initializable from persistent data!");&lt;br /&gt;if(FAILED(hr))return hr;&lt;br /&gt;CLSID m_clsid;//本控件的的clsid&lt;br /&gt;CLSIDFromString(L"",&amp;amp;m_clsid);&lt;br /&gt;hr=RegisterCLSIDInCategory(m_clsid,CATID_SafeForInitializing);&lt;br /&gt;if(FAILED(hr))return hr;&lt;br /&gt;//注册控件是安全性脚本操作的&lt;br /&gt;hr=CreateComponentCategory(CATID_SafeForScripting,L"Controls safely scriptable!");&lt;br /&gt;if(FAILED(hr))return hr;&lt;br /&gt;hr=RegisterCLSIDInCategory(m_clsid,CATID_SafeForScripting);&lt;br /&gt;if(FAILED(hr))return hr; &lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;　　注意，一个创建安全性分组入口到注册表的控件，也应该负责卸载所有分组信息。要卸载一个已经安全性初始化和脚本操作的控件，应该按以下步骤：&lt;br /&gt;&lt;br /&gt;　　(1)创建一个组件分类管理器实例接收ICatRegister接口地址； &lt;br /&gt;&lt;br /&gt;　　(2)调用ICatRegister::UnRegisterClassImplCategories方法，将控件的CLSID和必要的category ID作为参数传递。&lt;br /&gt;&lt;br /&gt;　　对应全局函数如下：&lt;br /&gt;&lt;br /&gt;&#xD;
&lt;table width="100%" bgcolor="#ffffff"&gt;&#xD;
&lt;tbody&gt;&#xD;
&lt;tr&gt;&#xD;
&lt;td&gt;HRESULT UnRegisterCLSIDInCategory(REFCLSID clsid,CATID catid) &lt;br /&gt;{&lt;br /&gt;ICatRegister* pcr=NULL; HRESULT hr=S_OK;&lt;br /&gt;hr=CoCreateInstance(CLSID_StdComponentCategoriesMgr,NULL,CLSCTX_INPROC_SERVER,IID_ICatRegister,(void**)&amp;amp;pcr); &lt;br /&gt;if(SUCCEEDED(hr)){// 从分组卸载组件 &lt;br /&gt;CATID rgcatid[1]; rgcatid[0]=catid; &lt;br /&gt;hr=pcr-＞UnRegisterClassImplCategories(clsid,1,rgcatid); &lt;br /&gt;}&lt;br /&gt;if(pcr!=NULL)pcr-＞Release();&lt;br /&gt;return hr;&lt;br /&gt;}&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;　　控件卸载时调用的是DLLUnRegisterServer函数，故需在该函数中添加如下代码：&lt;br /&gt;&lt;br /&gt;&#xD;
&lt;table width="100%" bgcolor="#ffffff"&gt;&#xD;
&lt;tbody&gt;&#xD;
&lt;tr&gt;&#xD;
&lt;td&gt;CLSID m_clsid; //本控件的clsid&lt;br /&gt;CLSIDFromString(L"",&amp;amp;m_clsid);&lt;br /&gt;hr=UnRegisterCLSIDInCategory(m_clsid,CATID_SafeForInitializing);&lt;br /&gt;if(FAILED(hr))return hr;&lt;br /&gt;hr=UnRegisterCLSIDInCategory(m_clsid,CATID_SafeForScripting);&lt;br /&gt;if(FAILED(hr))return hr;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;2.5 在网页中嵌入ActiveX文件包实现基于Internet软件发布：&lt;br /&gt;&lt;br /&gt;　　给出一个嵌入实例：&lt;br /&gt;&lt;br /&gt;&#xD;
&lt;table width="100%" bgcolor="#ffffff"&gt;&#xD;
&lt;tbody&gt;&#xD;
&lt;tr&gt;&#xD;
&lt;td&gt;＜object style="LEFT:0px;TOP:0px" codebase="texturemap.cab#version=1,0,0,1" width="640" height="480" align="baseline" border="0" classid="clsid:0F968806-D214-11D5-9022-5254AB123A61" name="texture" VIEWASTEXT＞&lt;br /&gt;＜param name="_Version" value="65536"＞&lt;br /&gt;＜param name="_ExtentX" value="2646"＞&lt;br /&gt;＜param name="_ExtentY" value="1323"＞&lt;br /&gt;＜param name="_StockProps" value="2"＞&lt;br /&gt;＜/object＞&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;　　其中name属性是控件对应的对象名，实现在网页中对控件定义的方法进行调用、属性进行设置；codebase属性指示的是控件包的下载位置，除了cab文件外，也可以直接指向一个OCX 文件或者DLL文件，但要发布软件，这些文件都必须事先签署过；codebase中的version表示控件的版本号，当控件在客户端不存在或现有控件的版本比codebase属性中指定的版本旧时，浏览器将下载并注册指定的文件；classid属性指定的是控件的CLSID，客户端系统将通过此ID在注册表中寻找该控件是否已被注册，并确定控件的版本以决定是否重新下载注册。Width,height属性定义控件在浏览器中的客户视窗大小。&lt;br /&gt;&lt;br /&gt;　　在将ActiveX嵌入后就需要实现调用控件中设定的方法和属性。可以通过VBScript脚本进行调用，如：&lt;br /&gt;&lt;br /&gt;&#xD;
&lt;table width="100%" bgcolor="#ffffff"&gt;&#xD;
&lt;tbody&gt;&#xD;
&lt;tr&gt;&#xD;
&lt;td&gt;＜script language="VBscript"＞&lt;br /&gt;Sub window_onload()&lt;br /&gt;texture.Radius=5&lt;br /&gt;end sub&lt;br /&gt;＜/script＞&lt;br /&gt;＜input type=button onclick='call texture.servertexturemapping("218.108.175.187","Apple.bmp")'＞&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;　　其中servertexturemapping是控件中定义的方法，Radius是控件中定义的属性。&lt;br /&gt;&lt;br /&gt;　　&lt;strong&gt;三、总结&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;　　基于Internet发布软件降低了对系统软件的要求，避免了用户或者专业人员对客户端的安装和设置，实现软件安装访问自动化、自由化。而安全证书机制的引入，又确保了软件的安全性，使得基于Internet发布软件实现高效、快捷、实用。本文的目的就是系统的介绍基于Internet发布软件的各类相关概念和实现流程。 &lt;img src="http://www.cnblogs.com/mazhenyu/aggbug/2303365.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/mazhenyu/archive/2011/12/27/2303365.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/mazhenyu/archive/2011/12/27/2303179.html</id><title type="text">ASP与ActiveX控件交互实战 (转)</title><summary type="text">ASP与ActiveX控件交互实战http://www.builder.com.cn/2007/0902/484022.shtml开发者在线 Builder.com.cn 更新时间:2007-09-02作者：佚名 来源:网络本文关键词： ASP ActiveX 交互 ActiveX控件运行在客户端。我们可以获得客户端的一些信息，如IC卡的信息,客户端的验证等等。但是ActiveX控件也有许多缺点：客户端的部署很困难，如客户端不能正确下载，下载了以后不能正确执行，下载的时候需要设置IE的安全级别等等。更多的时候，我都在使用COM组件来扩展ASP的功能。准确地说，是服务端运行的ActivexDll</summary><published>2011-12-27T03:11:00Z</published><updated>2011-12-27T03:11:00Z</updated><author><name>3D入魔</name><uri>http://www.cnblogs.com/mazhenyu/</uri></author><link rel="alternate" href="http://www.cnblogs.com/mazhenyu/archive/2011/12/27/2303179.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/mazhenyu/archive/2011/12/27/2303179.html"/><content type="html">&lt;h1 &gt;ASP与ActiveX控件交互实战&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p &gt;&lt;a href="http://www.builder.com.cn/2007/0902/484022.shtml"&gt;http://www.builder.com.cn/2007/0902/484022.shtml&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;h3 &gt;&lt;a href="http://www.builder.com.cn/" target="_blank"&gt;开发者在线 Builder.com.cn&lt;/a&gt; 更新时间:&lt;cite&gt;2007-09-02&lt;/cite&gt;作者：&lt;span&gt;佚名&lt;/span&gt; 来源:网络&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;h2 &gt;本文关键词： &lt;a href="http://www.builder.com.cn/files/list-0-0-63898-1-1.htm" target="_blank"&gt;ASP&lt;/a&gt; &lt;a href="http://www.builder.com.cn/files/list-0-0-70943-1-1.htm" target="_blank"&gt;ActiveX&lt;/a&gt; &lt;a href="http://www.builder.com.cn/files/list-0-0-70942-1-1.htm" target="_blank"&gt;交互&lt;/a&gt; &lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;div &gt;&#xD;
&lt;div style="text-align: left; overflow: hidden; word-break: break-all" summary="JuUawHlmVV"&gt;&#xD;
&lt;p&gt;ActiveX控件运行在客户端。我们可以获得客户端的一些信息，如IC卡的信息,客户端的验证等等。但是ActiveX控件也有许多缺点：客户端的部署很困难，如客户端不能正确下载，下载了以后不能正确执行，下载的时候需要设置IE的安全级别等等。&amp;nbsp;&lt;br /&gt;&lt;br /&gt;更多的时候，我都在使用COM组件来扩展ASP的功能。准确地说，是服务端运行的Activex&amp;nbsp;Dll组件。使用Server.CreateObject(&amp;#8220;工程名.类名&amp;#8221;)即可完成对组件的调用。这种方式问题很少,只要组件中以PUBLIC对外暴露方法既可。但是，有时候我们必须使用ACTIVEX&amp;nbsp;控件(*.OCX)嵌入到网页中执行来获取客户端的信息。这就有了许许多多的一些问题。&amp;nbsp;&lt;br /&gt;&lt;br /&gt;这是我们需要解决的N个问题(从简单到难)&amp;nbsp;&lt;br /&gt;&lt;br /&gt;1．&amp;nbsp;如何从服务端获取数据，传递到ActiveX控件中。&amp;nbsp;&lt;br /&gt;&lt;br /&gt;1）&amp;nbsp;初始化时使用参数绑定&amp;nbsp;&lt;br /&gt;&lt;br /&gt;2）&amp;nbsp;运行时得到数据&amp;nbsp;&lt;br /&gt;&lt;br /&gt;2．&amp;nbsp;ActiveX控件得到客户端的信息，如何传递到服务端。&amp;nbsp;&lt;br /&gt;&lt;br /&gt;3．&amp;nbsp;安全性&amp;nbsp;&lt;br /&gt;&lt;br /&gt;1）&amp;nbsp;数字签名&amp;nbsp;&lt;br /&gt;&lt;br /&gt;2）&amp;nbsp;使用IOBJSAFE接口&amp;nbsp;&lt;br /&gt;&lt;br /&gt;好了，我们开始实例学习。&amp;nbsp;&lt;br /&gt;&lt;br /&gt;这个功能演示了如何制作一个简单的控件,并嵌入网页中执行。&amp;nbsp;工作环境:WINXP+VB6+IE6&amp;nbsp;&lt;br /&gt;&lt;br /&gt;我的IE安全设置为安全级别-中。所有的Activex选项设为启用。&amp;nbsp;&lt;br /&gt;&lt;br /&gt;打开vb6,新建ActiveX控件工程。&amp;nbsp;&lt;br /&gt;&lt;br /&gt;工程名:fOcx，用户控件名:UC1&amp;nbsp;&lt;br /&gt;&lt;br /&gt;为了方便，我们使用ActiveX控件接口向导&amp;#8230;,菜单-&amp;gt;外接程序-&amp;gt;外接程序管理器-&amp;gt;VB&amp;nbsp;6&amp;nbsp;ActiveX控件接口向导。确定即可。&amp;nbsp;&lt;br /&gt;&lt;br /&gt;打开ActiveX控件接口向导，下一步，对于可用名称和选定名称我们默认下一步，新建自定义成员，GetInfo类型:属性，下一步，共有方法中选择我们刚才添加的GetInfo,映射到控件选择TxtInfo,成员选择Text,下一步直到完成。代码窗口中会生成一些我们不需要的，删除，剩下的代码如下：&amp;nbsp;&lt;br /&gt;&lt;br /&gt;Option&amp;nbsp;Explicit&amp;nbsp;&lt;br /&gt;&lt;br /&gt;'注意！不要删除或修改下列被注释的行！&amp;nbsp;&lt;br /&gt;&lt;br /&gt;'MappingInfo=txtinfo,txtinfo,-1,Text&amp;nbsp;&lt;br /&gt;&lt;br /&gt;Public&amp;nbsp;Property&amp;nbsp;Get&amp;nbsp;GetInfo()&amp;nbsp;As&amp;nbsp;String&amp;nbsp;&lt;br /&gt;&lt;br /&gt;GetInfo&amp;nbsp;=&amp;nbsp;txtinfo.Text&amp;nbsp;&lt;br /&gt;&lt;br /&gt;End&amp;nbsp;Property&amp;nbsp;&lt;br /&gt;&lt;br /&gt;Public&amp;nbsp;Property&amp;nbsp;Let&amp;nbsp;GetInfo(ByVal&amp;nbsp;New_GetInfo&amp;nbsp;As&amp;nbsp;String)&amp;nbsp;&lt;br /&gt;&lt;br /&gt;txtinfo.Text()&amp;nbsp;=&amp;nbsp;New_GetInfo&amp;nbsp;&lt;br /&gt;&lt;br /&gt;PropertyChanged&amp;nbsp;"GetInfo"&amp;nbsp;&lt;br /&gt;&lt;br /&gt;End&amp;nbsp;Property&amp;nbsp;&lt;br /&gt;&lt;br /&gt;'从存贮器中加载属性值&amp;nbsp;&lt;br /&gt;&lt;br /&gt;Private&amp;nbsp;Sub&amp;nbsp;UserControl_ReadProperties(PropBag&amp;nbsp;As&amp;nbsp;PropertyBag)&amp;nbsp;&lt;br /&gt;&lt;br /&gt;txtinfo.Text&amp;nbsp;=&amp;nbsp;PropBag.ReadProperty("GetInfo",&amp;nbsp;"Text1")&amp;nbsp;&lt;br /&gt;&lt;br /&gt;End&amp;nbsp;Sub&amp;nbsp;&lt;br /&gt;&lt;br /&gt;'将属性值写到存储器&amp;nbsp;&lt;br /&gt;&lt;br /&gt;Private&amp;nbsp;Sub&amp;nbsp;UserControl_WriteProperties(PropBag&amp;nbsp;As&amp;nbsp;PropertyBag)&amp;nbsp;&lt;br /&gt;&lt;br /&gt;Call&amp;nbsp;PropBag.WriteProperty("GetInfo",&amp;nbsp;txtinfo.Text,&amp;nbsp;"Text1")&amp;nbsp;&lt;br /&gt;&lt;br /&gt;End&amp;nbsp;Sub&amp;nbsp;&lt;br /&gt;&lt;br /&gt;OK,好了，我们编译成fOcx.ocx文件，然后F5直接运行,VB会打开一个测试页。如下：&amp;nbsp;&lt;br /&gt;&lt;br /&gt;E:Program&amp;nbsp;FilesMicrosoft&amp;nbsp;Visual&amp;nbsp;StudioVB98UC1.html&amp;nbsp;&lt;br /&gt;&lt;br /&gt;同时，打开你的IE浏览器,看到了吧，你做的控件出现在了这个测试页中。&amp;nbsp;&lt;br /&gt;&lt;br /&gt;你可以打开测试页，可以看到ClsID,比如：890D1028-298B-45CF-9A64-6ED5A5BACBC9&amp;nbsp;&lt;br /&gt;&lt;br /&gt;因为VB编译的时候已经完成注册.所以无法模拟客户端没有安装该控件时出现的提示.&amp;nbsp;我们继续&amp;nbsp;&lt;br /&gt;&lt;br /&gt;使用regsvr32&amp;nbsp;F:csdn_vbcom+_activeXsample1fOcx.ocx&amp;nbsp;&amp;#8211;u卸载&amp;nbsp;&lt;br /&gt;&lt;br /&gt;或者&amp;nbsp;打开注册表,在HKEY_CLASSES_ROOTCLSID下面找到&amp;nbsp;890D1028-298B-45CF-9A64-6ED5A5BACBC9项,删除之,当然这种方式还有项存在而没有删除干净.&amp;nbsp;&lt;br /&gt;&lt;br /&gt;此时浏览http://yang/uc1.htm,由于IE中ActiveX设置为启动，所以，控件会显示出来。&amp;nbsp;&lt;br /&gt;&lt;br /&gt;下载后的ocx到哪里去了&lt;br /&gt;&lt;br /&gt;打开该目录(可能有所不同)E:WINDOWS.0Downloaded&amp;nbsp;Program&amp;nbsp;Files,看到了吧,fOcx.UC1文件在这个目录下.&amp;nbsp;&lt;br /&gt;&lt;br /&gt;原理:客户端下载该控件后,自动注册,然后放在上述这个目录下.这时我们可以打开注册表看看CLSID,呵呵,还是以前的那个.&amp;nbsp;&lt;br /&gt;&lt;br /&gt;我们可以右键看看fOcx.UC1的属性,看看相关内容,这里显示了该OCX所依赖的所有文件.所以,你的OCX尽量减少使用高级控件或者第三方的控件,否则,下载就有些问题了.&amp;nbsp;&lt;br /&gt;&lt;br /&gt;如果IE中关于ActiveX的选项设为禁用,那么浏览器就会出现对话框&amp;#8221;当前安全设置禁止运行该页中的ActiveX控件.因此可能无法正确显示该页&amp;#8221;，这个就需要其他的方式来处理了。&amp;nbsp;&lt;br /&gt;&lt;br /&gt;一般用户默认的都是禁用ActiveX选项,所以让用户自己设置不太合适。&lt;/p&gt;&#xD;
&lt;p&gt;我们来看看如何从服务端获取数据，传递到ActiveX控件中。&amp;nbsp;&lt;br /&gt;&lt;br /&gt;1）&amp;nbsp;初始化时使用参数绑定&amp;nbsp;&lt;br /&gt;&lt;br /&gt;2）&amp;nbsp;运行时得到数据&amp;nbsp;&lt;br /&gt;&lt;br /&gt;打开vb6,新建ActiveX控件工程。&amp;nbsp;&lt;br /&gt;&lt;br /&gt;工程名:fOcx，用户控件名:UC2&amp;nbsp;&lt;br /&gt;&lt;br /&gt;为了方便，我们使用ActiveX控件接口向导&amp;#8230;,菜单-&amp;gt;外接程序-&amp;gt;外接程序管理器-&amp;gt;VB&amp;nbsp;6&amp;nbsp;ActiveX控件接口向导。确定即可。&amp;nbsp;&lt;br /&gt;&lt;br /&gt;打开ActiveX控件接口向导，下一步，对于可用名称和选定名称我们默认下一步，新建自定义成员，GetInfo类型:属性，下一步，共有方法中选择我们刚才添加的GetInfo,映射到控件选择TxtInfo,成员选择Text,下一步直到完成。代码窗口中会生成一些我们不需要的，删除，&amp;nbsp;&lt;br /&gt;&lt;br /&gt;'注意！不要删除或修改下列被注释的行！&amp;nbsp;&lt;br /&gt;&lt;br /&gt;'MappingInfo=txtinfo,txtinfo,-1,Text&amp;nbsp;&lt;br /&gt;&lt;br /&gt;Public&amp;nbsp;Property&amp;nbsp;Get&amp;nbsp;GetInfo()&amp;nbsp;As&amp;nbsp;String&amp;nbsp;&lt;br /&gt;&lt;br /&gt;GetInfo&amp;nbsp;=&amp;nbsp;txtinfo.Text&amp;nbsp;&lt;br /&gt;&lt;br /&gt;End&amp;nbsp;Property&amp;nbsp;&lt;br /&gt;&lt;br /&gt;Public&amp;nbsp;Property&amp;nbsp;Let&amp;nbsp;GetInfo(ByVal&amp;nbsp;New_GetInfo&amp;nbsp;As&amp;nbsp;String)&amp;nbsp;&lt;br /&gt;&lt;br /&gt;txtinfo.Text()&amp;nbsp;=&amp;nbsp;New_GetInfo&amp;nbsp;&lt;br /&gt;&lt;br /&gt;PropertyChanged&amp;nbsp;"GetInfo"&amp;nbsp;&lt;br /&gt;&lt;br /&gt;End&amp;nbsp;Property&amp;nbsp;&lt;br /&gt;&lt;br /&gt;Private&amp;nbsp;Sub&amp;nbsp;Command1_Click()&amp;nbsp;&lt;br /&gt;&lt;br /&gt;Label2.Caption&amp;nbsp;=&amp;nbsp;GetInfo()&amp;nbsp;&lt;br /&gt;&lt;br /&gt;End&amp;nbsp;Sub&amp;nbsp;&lt;br /&gt;&lt;br /&gt;'从存贮器中加载属性值&amp;nbsp;&lt;br /&gt;&lt;br /&gt;Private&amp;nbsp;Sub&amp;nbsp;UserControl_ReadProperties(PropBag&amp;nbsp;As&amp;nbsp;PropertyBag)&amp;nbsp;&lt;br /&gt;&lt;br /&gt;txtinfo.Text&amp;nbsp;=&amp;nbsp;PropBag.ReadProperty("GetInfo",&amp;nbsp;"Text1")&amp;nbsp;&lt;br /&gt;&lt;br /&gt;End&amp;nbsp;Sub&amp;nbsp;&lt;br /&gt;&lt;br /&gt;'将属性值写到存储器&amp;nbsp;&lt;br /&gt;&lt;br /&gt;Private&amp;nbsp;Sub&amp;nbsp;UserControl_WriteProperties(PropBag&amp;nbsp;As&amp;nbsp;PropertyBag)&amp;nbsp;&lt;br /&gt;&lt;br /&gt;Call&amp;nbsp;PropBag.WriteProperty("GetInfo",&amp;nbsp;txtinfo.Text,&amp;nbsp;"Text1")&amp;nbsp;&lt;br /&gt;&lt;br /&gt;End&amp;nbsp;Sub&amp;nbsp;&lt;br /&gt;&lt;br /&gt;编译成OCX控件.运行生成的测试页.Text中默认的是Text1&amp;nbsp;如何将服务器端的数据传递给OCX呢?&amp;nbsp;使用Microsoft&amp;nbsp;ActiveX&amp;nbsp;Control&amp;nbsp;Pad这个工具,可以很容易找到.&amp;nbsp;直接用这个工具把测试页打开.&amp;nbsp;&lt;br /&gt;&lt;br /&gt;菜单-&amp;gt;Edit-&amp;gt;Edit&amp;nbsp;Activex&amp;nbsp;Control,呵呵,打开了一个可视化的界面.&amp;nbsp;&lt;br /&gt;&lt;br /&gt;看到了吧,有一个属性框,我们可以进行设置，设置完成以后的代码如下：&amp;nbsp;&lt;br /&gt;&lt;br /&gt;&amp;lt;HTML&amp;gt;&amp;nbsp;&lt;br /&gt;&lt;br /&gt;&amp;lt;HEAD&amp;gt;&amp;nbsp;&lt;br /&gt;&lt;br /&gt;&amp;lt;TITLE&amp;gt;New&amp;nbsp;Page&amp;lt;/TITLE&amp;gt;&amp;nbsp;&lt;br /&gt;&lt;br /&gt;&amp;lt;/HEAD&amp;gt;&amp;nbsp;&lt;br /&gt;&lt;br /&gt;&amp;lt;BODY&amp;gt;&amp;nbsp;&lt;br /&gt;&lt;br /&gt;&amp;lt;OBJECT&amp;nbsp;ID="GetClient"&amp;nbsp;WIDTH=507&amp;nbsp;HEIGHT=440&amp;nbsp;CLASSID="CLSID:890D1028-298B-45CF-9A64-6ED5A5BACBC9"&amp;nbsp;CODEBASE="http://localhost/xml/fOcx.ocx"&amp;gt;&amp;nbsp;&lt;br /&gt;&lt;br /&gt;&amp;lt;PARAM&amp;nbsp;NAME="_ExtentX"&amp;nbsp;VALUE="13414"&amp;gt;&amp;nbsp;&lt;br /&gt;&lt;br /&gt;&amp;lt;PARAM&amp;nbsp;NAME="_ExtentY"&amp;nbsp;VALUE="11642"&amp;gt;&amp;nbsp;&lt;br /&gt;&lt;br /&gt;&amp;lt;PARAM&amp;nbsp;NAME="GetInfo"&amp;nbsp;VALUE="这是ocx得到的客户端读卡器的信息"&amp;gt;&amp;nbsp;&lt;br /&gt;&lt;br /&gt;&amp;lt;/OBJECT&amp;gt;&amp;nbsp;&lt;br /&gt;&lt;br /&gt;&amp;lt;/BODY&amp;gt;&amp;nbsp;&lt;br /&gt;&lt;br /&gt;&amp;lt;/HTML&amp;gt;&amp;nbsp;&lt;br /&gt;&lt;br /&gt;增加了ID,ID就是我们用来访问的标志.还有我们的属性GetInfo,我们也设定初始值了&amp;nbsp;好了,运行.&amp;nbsp;Text中就出现了我们设定的值&amp;#8221;这是ocx得到的客户端读卡器的信息&amp;#8221;&amp;nbsp;&lt;br /&gt;&lt;br /&gt;我们把上边的页面改成asp的,看代码:&amp;nbsp;&lt;br /&gt;&lt;br /&gt;&amp;lt;HTML&amp;gt;&amp;nbsp;&lt;br /&gt;&lt;br /&gt;&amp;lt;HEAD&amp;gt;&amp;nbsp;&lt;br /&gt;&lt;br /&gt;&amp;lt;TITLE&amp;gt;龙卷风测试页&amp;lt;/TITLE&amp;gt;&amp;nbsp;&lt;br /&gt;&lt;br /&gt;&amp;lt;/HEAD&amp;gt;&amp;nbsp;&lt;br /&gt;&lt;br /&gt;&amp;lt;BODY&amp;gt;&amp;nbsp;&lt;br /&gt;&lt;br /&gt;&amp;lt;%&amp;nbsp;&lt;br /&gt;&lt;br /&gt;dim&amp;nbsp;sValue&amp;nbsp;&lt;br /&gt;&lt;br /&gt;sValue="这是ocx得到的客户端读卡器的信息"&amp;nbsp;&lt;br /&gt;&lt;br /&gt;%&amp;gt;&amp;nbsp;&lt;br /&gt;&lt;br /&gt;&amp;lt;OBJECT&amp;nbsp;ID="GetClient"&amp;nbsp;WIDTH=507&amp;nbsp;HEIGHT=440&amp;nbsp;CLASSID="CLSID:56DFCA88-F5B8-4879-853B-97FE504423FD"&amp;nbsp;CODEBASE="http://localhost/xml/fOcx.ocx"&amp;gt;&amp;nbsp;&lt;br /&gt;&lt;br /&gt;&amp;lt;PARAM&amp;nbsp;NAME="_ExtentX"&amp;nbsp;VALUE="13414"&amp;gt;&amp;nbsp;&lt;br /&gt;&lt;br /&gt;&amp;lt;PARAM&amp;nbsp;NAME="_ExtentY"&amp;nbsp;VALUE="11642"&amp;gt;&amp;nbsp;&lt;br /&gt;&lt;br /&gt;&amp;lt;PARAM&amp;nbsp;NAME="GetInfo"&amp;nbsp;VALUE="&amp;lt;%=sValue%&amp;gt;"&amp;gt;&amp;nbsp;&lt;br /&gt;&lt;br /&gt;&amp;lt;/OBJECT&amp;gt;&amp;nbsp;&lt;br /&gt;&lt;br /&gt;&amp;lt;/BODY&amp;gt;&amp;nbsp;&lt;br /&gt;&lt;br /&gt;&amp;lt;/HTML&amp;gt;&amp;nbsp;&lt;br /&gt;&lt;br /&gt;OK,运行即可&amp;nbsp;&lt;br /&gt;&lt;br /&gt;我们看看第二种情况&amp;nbsp;&lt;br /&gt;&lt;br /&gt;运行时得到数据&amp;nbsp;&lt;br /&gt;&lt;br /&gt;&amp;lt;HTML&amp;gt;&amp;nbsp;&lt;br /&gt;&lt;br /&gt;&amp;lt;HEAD&amp;gt;&amp;nbsp;&lt;br /&gt;&lt;br /&gt;&amp;lt;TITLE&amp;gt;龙卷风测试页&amp;lt;/TITLE&amp;gt;&amp;nbsp;&lt;br /&gt;&lt;br /&gt;&amp;lt;%&amp;nbsp;&lt;br /&gt;&lt;br /&gt;dim&amp;nbsp;sValue&amp;nbsp;&lt;br /&gt;&lt;br /&gt;sValue="这是ocx得到的客户端读卡器的信息"&amp;nbsp;&lt;br /&gt;&lt;br /&gt;%&amp;gt;&amp;nbsp;&lt;br /&gt;&lt;br /&gt;&amp;lt;SCRIPT&amp;nbsp;ID=clientEventHandlersJS&amp;nbsp;LANGUAGE=javascript&amp;gt;&amp;nbsp;&lt;br /&gt;&lt;br /&gt;&amp;lt;!--&amp;nbsp;&lt;br /&gt;&lt;br /&gt;function&amp;nbsp;button1_onclick()&amp;nbsp;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;br /&gt;//--&amp;gt;&amp;nbsp;&lt;br /&gt;&lt;br /&gt;&amp;lt;/SCRIPT&amp;gt;&amp;nbsp;&lt;br /&gt;&lt;br /&gt;&amp;lt;/HEAD&amp;gt;&amp;nbsp;&lt;br /&gt;&lt;br /&gt;&amp;lt;BODY&amp;gt;&amp;nbsp;&lt;br /&gt;&lt;br /&gt;&amp;lt;OBJECT&amp;nbsp;ID="GetClient"&amp;nbsp;WIDTH=507&amp;nbsp;HEIGHT=440&amp;nbsp;CLASSID="CLSID:56DFCA88-F5B8-4879-853B-97FE504423FD"&amp;nbsp;CODEBASE="http://localhost/xml/fOcx.ocx"&amp;gt;&amp;nbsp;&lt;br /&gt;&lt;br /&gt;&amp;lt;PARAM&amp;nbsp;NAME="_ExtentX"&amp;nbsp;VALUE="13414"&amp;gt;&amp;nbsp;&lt;br /&gt;&lt;br /&gt;&amp;lt;PARAM&amp;nbsp;NAME="_ExtentY"&amp;nbsp;VALUE="11642"&amp;gt;&amp;nbsp;&lt;br /&gt;&lt;br /&gt;&amp;lt;/OBJECT&amp;gt;&amp;nbsp;&lt;br /&gt;&lt;br /&gt;&amp;lt;INPUT&amp;nbsp;id=button1&amp;nbsp;type=button&amp;nbsp;value=Button&amp;nbsp;name=button1&amp;nbsp;LANGUAGE=javascript&amp;nbsp;onclick="return&amp;nbsp;button1_onclick()"&amp;gt;&amp;nbsp;&lt;br /&gt;&lt;br /&gt;&amp;lt;/BODY&amp;gt;&amp;nbsp;&lt;br /&gt;&lt;br /&gt;&amp;lt;/HTML&amp;gt;&amp;nbsp;&lt;br /&gt;&lt;br /&gt;运行后,点击按钮即可看到效果.&amp;nbsp;&lt;/p&gt;&#xD;
&lt;p&gt;问题提出:&amp;nbsp;&lt;br /&gt;&lt;br /&gt;ActiveX控件得到客户端的信息，如何传递到服务端???&amp;nbsp;一种方法就是得到值后,使用Get,Post方式提交,这可能也是最常用的.&amp;nbsp;&lt;br /&gt;&lt;br /&gt;有没有更好一些的方法呢?&amp;nbsp;能不能在控件中直接向服务器发出请求而得到数据呢?&amp;nbsp;&lt;br /&gt;&lt;br /&gt;打开vb6,新建ActiveX控件工程。&amp;nbsp;&lt;br /&gt;&lt;br /&gt;工程名:fOcx，用户控件名:UC3&amp;nbsp;&lt;br /&gt;&lt;br /&gt;添加1个按钮，2个文本框&amp;nbsp;&lt;br /&gt;&lt;br /&gt;代码如下：&amp;nbsp;&lt;br /&gt;&lt;br /&gt;Option&amp;nbsp;Explicit&amp;nbsp;&lt;br /&gt;&lt;br /&gt;Private&amp;nbsp;Sub&amp;nbsp;Command1_Click()&amp;nbsp;&lt;br /&gt;&lt;br /&gt;'注意字符串和数字的写法有些区别&amp;nbsp;&lt;br /&gt;&lt;br /&gt;'使用AsyncRead通过HTTP发送你的请求&amp;nbsp;&lt;br /&gt;&lt;br /&gt;UserControl.AsyncRead&amp;nbsp;"http://yang/xml/activex.asp?s1="&amp;nbsp;&amp;amp;am ... nbsp;&amp;amp;&amp;nbsp;"",&amp;nbsp;vbAsyncTypeByteArray&amp;nbsp;&lt;br /&gt;&lt;br /&gt;UserControl.AsyncRead&amp;nbsp;"http://yang/xml/activex.asp?s1="&amp;nbsp;&amp;amp;&amp;nbsp;Text1.Text,&amp;nbsp;vbAsyncTypeByteArray&amp;nbsp;&lt;br /&gt;&lt;br /&gt;End&amp;nbsp;Sub&amp;nbsp;&lt;br /&gt;&lt;br /&gt;'AsyncReadComplete&amp;nbsp;事件用来从asp页面接受和分析。&amp;nbsp;&lt;br /&gt;&lt;br /&gt;'当容器刚完成一个异步读取请求时&amp;nbsp;,&amp;nbsp;发生该事件?&amp;nbsp;&lt;br /&gt;&lt;br /&gt;'AsyncProp&amp;nbsp;中的数值指定了已完成的某个异步数据读取请求,&amp;nbsp;&lt;br /&gt;&lt;br /&gt;'它与前一个&amp;nbsp;AsyncRead&amp;nbsp;方法调用中的数据匹配。&amp;nbsp;&lt;br /&gt;&lt;br /&gt;'AsyncReadComplete&amp;nbsp;事件过程中应包含错误处理代码，因为错误状态会终止下载。&amp;nbsp;&lt;br /&gt;&lt;br /&gt;'如果发生了这种情况，当访问&amp;nbsp;AsyncProperty&amp;nbsp;对象的&amp;nbsp;Value&amp;nbsp;属性时将会发生错误。&amp;nbsp;&lt;br /&gt;&lt;br /&gt;Private&amp;nbsp;Sub&amp;nbsp;UserControl_AsyncReadComplete(AsyncProp&amp;nbsp;As&amp;nbsp;AsyncProperty)&amp;nbsp;&lt;br /&gt;&lt;br /&gt;On&amp;nbsp;Error&amp;nbsp;GoTo&amp;nbsp;errhandle&amp;nbsp;&lt;br /&gt;&lt;br /&gt;Text2.Text&amp;nbsp;=&amp;nbsp;ByteArrayToString(AsyncProp.Value)&amp;nbsp;&lt;br /&gt;&lt;br /&gt;errhandle:&amp;nbsp;&lt;br /&gt;&lt;br /&gt;Err.Raise&amp;nbsp;601,&amp;nbsp;"异步读取发生了错误",&amp;nbsp;Err.Description&amp;nbsp;&lt;br /&gt;&lt;br /&gt;End&amp;nbsp;Sub&amp;nbsp;&lt;br /&gt;&lt;br /&gt;'将字节数组转换成字符串&amp;nbsp;&lt;br /&gt;&lt;br /&gt;Public&amp;nbsp;Function&amp;nbsp;ByteArrayToString(bytArray()&amp;nbsp;As&amp;nbsp;Byte)&amp;nbsp;As&amp;nbsp;String&amp;nbsp;&lt;br /&gt;&lt;br /&gt;Dim&amp;nbsp;sAns&amp;nbsp;As&amp;nbsp;String&amp;nbsp;&lt;br /&gt;&lt;br /&gt;sAns&amp;nbsp;=&amp;nbsp;StrConv(bytArray,&amp;nbsp;vbUnicode)&amp;nbsp;&lt;br /&gt;&lt;br /&gt;ByteArrayToString&amp;nbsp;=&amp;nbsp;sAns&amp;nbsp;&lt;br /&gt;&lt;br /&gt;End&amp;nbsp;Function&amp;nbsp;&lt;br /&gt;&lt;br /&gt;我们来看看http://yang/xml/activex.asp这个文件&amp;nbsp;&lt;br /&gt;&lt;br /&gt;&amp;lt;%&amp;nbsp;&lt;br /&gt;&lt;br /&gt;dim&amp;nbsp;str&amp;nbsp;&lt;br /&gt;&lt;br /&gt;str=request("s1")&amp;nbsp;&lt;br /&gt;&lt;br /&gt;if&amp;nbsp;str="name"&amp;nbsp;then&amp;nbsp;&lt;br /&gt;&lt;br /&gt;response.write&amp;nbsp;("龙卷风")&amp;nbsp;&lt;br /&gt;&lt;br /&gt;elseif&amp;nbsp;str="age"&amp;nbsp;then&amp;nbsp;&lt;br /&gt;&lt;br /&gt;response.write&amp;nbsp;("26")&amp;nbsp;&lt;br /&gt;&lt;br /&gt;else&amp;nbsp;&lt;br /&gt;&lt;br /&gt;response.write&amp;nbsp;("没有可用信息返回")&amp;nbsp;&lt;br /&gt;&lt;br /&gt;end&amp;nbsp;if&amp;nbsp;&lt;br /&gt;&lt;br /&gt;%&amp;gt;&amp;nbsp;&lt;br /&gt;&lt;br /&gt;很简单，使用request接受参数,response返回。&amp;nbsp;&lt;br /&gt;&lt;br /&gt;这个例子可以进一步处理，将服务器名以属性的方式传递给控件。&amp;nbsp;&lt;br /&gt;&lt;br /&gt;比如：&amp;lt;PARAM&amp;nbsp;NAME="ServerName"&amp;nbsp;VALUE="192.168.0.1&amp;nbsp;"&amp;gt;&amp;nbsp;&lt;br /&gt;&lt;br /&gt;然后在程序中得到，就可以使用了，如：&amp;nbsp;UserControl.AsyncRead&amp;nbsp;"http://192.168.0.1/xml/activex.asp?s1="&amp;nbsp; ... t&amp;nbsp;&amp;amp;&amp;nbsp;"",&amp;nbsp;vbAsyncTypeByteArray&amp;nbsp;&lt;br /&gt;&lt;br /&gt;然后在程序中得到就可以灵活处理了。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://developer.51cto.com/art/200511/10528.htm"&gt;查看本文来源&lt;/a&gt;&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;img src="http://www.cnblogs.com/mazhenyu/aggbug/2303179.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/mazhenyu/archive/2011/12/27/2303179.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/mazhenyu/archive/2011/12/24/2300203.html</id><title type="text">VBO与Displaylists的进一步讨论 (转)</title><summary type="text">VBO与Displaylists的进一步讨论 Posted on 2006-04-21 22:50 panhongwei 阅读(257) 评论(0) 编辑 收藏 所属分类: 大规模地形渲染 --&amp;gt;之前写的关于VBO与Displaylists的讨论不是很详细，现在重新整理一下，不过需要注意的我的测试结果是在没做view frustum culling的前提下给出的。关于Display List 和 VBO Display List 把OpenGL命令进行编译，保存在显卡上，并且允许保存Vertex Array优点： 将图形绘制和数据管理交给OpenGL进行管理，给OpenGL带来更多优化的</summary><published>2011-12-24T02:56:00Z</published><updated>2011-12-24T02:56:00Z</updated><author><name>3D入魔</name><uri>http://www.cnblogs.com/mazhenyu/</uri></author><link rel="alternate" href="http://www.cnblogs.com/mazhenyu/archive/2011/12/24/2300203.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/mazhenyu/archive/2011/12/24/2300203.html"/><content type="html">&lt;div id="article_content" &gt;&#xD;
&lt;div &gt;&#xD;
&lt;p&gt;&lt;strong&gt;&lt;a id="AjaxHolder_ctl01_TitleUrl"  href="http://www.cnblogs.com/micrographics/archive/2006/04/21/381782.html"&gt;&lt;u&gt;&lt;font style="font-size: 13pt" color="#0000ff"&gt;VBO与Displaylists的进一步讨论&lt;/font&gt;&lt;/u&gt;&lt;/a&gt; &lt;/strong&gt;&lt;/p&gt;Posted on 2006-04-21 22:50 &lt;a href="http://www.cnblogs.com/micrographics/"&gt;&lt;u&gt;&lt;font color="#0000ff"&gt;panhongwei&lt;/font&gt;&lt;/u&gt;&lt;/a&gt; 阅读(257) &lt;a href="http://www.cnblogs.com/micrographics/articles/381782.html#Post"&gt;&lt;u&gt;&lt;font color="#0000ff"&gt;评论(0)&lt;/font&gt;&lt;/u&gt;&lt;/a&gt; &amp;nbsp;&lt;a href="http://www.cnblogs.com/micrographics/admin/EditPosts.aspx?postid=381782"&gt;&lt;u&gt;&lt;font color="#0000ff"&gt;编辑&lt;/font&gt;&lt;/u&gt;&lt;/a&gt; &lt;a href="http://www.cnblogs.com/micrographics/articles/381782.html#"&gt;&lt;u&gt;&lt;font color="#0000ff"&gt;收藏&lt;/font&gt;&lt;/u&gt;&lt;/a&gt; 所属分类: &lt;a href="http://www.cnblogs.com/micrographics/category/55581.html"&gt;&lt;u&gt;&lt;font color="#0000ff"&gt;大规模地形渲染&lt;/font&gt;&lt;/u&gt;&lt;/a&gt; &lt;img src="http://www.cnblogs.com/micrographics/aggbug/381782.html?type=1&amp;amp;webview=1" width="1" height="1"  alt="" /&gt; &lt;!--&#xD;
&lt;rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"&#xD;
xmlns:dc="http://purl.org/dc/elements/1.1/"&#xD;
xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/"&gt;&#xD;
&lt;rdf:Description rdf:about="http://www.cnblogs.com/micrographics/archive/2006/04/21/381782.html" dc:identifier="http://www.cnblogs.com/micrographics/archive/2006/04/21/381782.html" dc:title="VBO与Displaylists的进一步讨论" trackback:ping="http://www.cnblogs.com/micrographics/services/trackbacks/381782.aspx"  /&gt;&#xD;
&lt;/rdf:RDF&gt;&#xD;
--&gt;&lt;/div&gt;&#xD;
&lt;div &gt;&#xD;
&lt;p&gt;之前写的关于VBO与Displaylists的讨论不是很详细，现在重新整理一下，不过需要注意的我的测试结果是在没做view frustum culling的前提下给出的。&lt;br /&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;span&gt;关于&lt;span&gt;Display List &lt;/span&gt;和&lt;span&gt; VBO&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span&gt;Display List&lt;/span&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span&gt;把&lt;span&gt;OpenGL&lt;/span&gt;命令进行编译，保存在显卡上，并且允许保存&lt;span&gt;Vertex Array&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;span&gt;优点：&lt;/span&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span&gt;将图形绘制和数据管理交给&lt;span&gt;OpenGL&lt;/span&gt;进行管理，给&lt;span&gt;OpenGL&lt;/span&gt;带来更多优化的机会，而且&lt;span&gt;Display lists&lt;/span&gt;可以放在显卡中，避免了数据在总线上的传输而带来的瓶颈。另外，数据可以通过&lt;span&gt;DMA&lt;/span&gt;传递到显卡进行绘制，减少了&lt;span&gt;CPU&lt;/span&gt;调用，并且可以一次性传输成批的数据和命令。&lt;/span&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;span&gt;缺点：&lt;/span&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span&gt;存储过多的&lt;span&gt;OpenGL&lt;/span&gt;命令会加重内存负担（这个还需要测试具体数字）&lt;/span&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span&gt;编译时间太长&lt;/span&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span&gt;仅限于静态&lt;span&gt;Geometry&lt;/span&gt;（即每个&lt;span&gt;display list&lt;/span&gt;绘制的三角形列表不会改变）&lt;/span&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;span&gt;测试发现，预先分配&lt;span&gt;Display Lists&lt;/span&gt;的长度变化不会对速度造成影响，前提是每帧绘制的三角形数目不会超过一个瓶颈。这样说来，预先创建的&lt;span&gt;Display lists&lt;/span&gt;数目只要没有超过系统瓶颈（&lt;span&gt;?&lt;/span&gt;），影响速度的是实际使用的&lt;span&gt;Display lists&lt;/span&gt;个数，或者说每帧绘制的三角形个数。&lt;/span&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;span&gt;对比发现，&lt;span&gt;VBO&lt;/span&gt;的效率会随着&lt;span&gt;VBO&lt;/span&gt;实际使用数目的增加而急剧下降。尤其是&lt;span&gt;VBOs&lt;/span&gt;所占用的空间超过显存时，存在内存和现存之间的数据传输，从而会带来瓶颈。&lt;/span&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;span&gt;使用&lt;span&gt;display lists&lt;/span&gt;每秒种绘制的三角形数目最大可以接近&lt;ST1:CHMETCNV w:st="on" unitname="m" sourcevalue="100" hasspace="False" negative="False" numbertype="1" tcsc="0"&gt;&lt;span&gt;100M&lt;/span&gt;&lt;/ST1:CHMETCNV&gt;，并保持&lt;span&gt;40&lt;/span&gt;帧&lt;span&gt;/&lt;/span&gt;秒 以上的帧率，但使用&lt;span&gt;VBO&lt;/span&gt;每秒种绘制的三角形数目最大也就&lt;ST1:CHMETCNV w:st="on" unitname="m" sourcevalue="30" hasspace="False" negative="False" numbertype="1" tcsc="0"&gt;&lt;span&gt;30M&lt;/span&gt;&lt;/ST1:CHMETCNV&gt;左右，帧率&lt;span&gt;15&lt;/span&gt;左右。&lt;/span&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span&gt;Vertex Array&lt;/span&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span&gt;批量传输和绘制数据，减少单个绘制命令的调用参数，&lt;span&gt;CPU&lt;/span&gt;和&lt;span&gt;GPU&lt;/span&gt;之间的瓶颈，在&lt;span&gt;OpenGL&lt;/span&gt;程序中已经不推荐使用。&lt;/span&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span&gt;VBO&lt;/span&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;VBO&lt;span&gt;是包含在&lt;span&gt;OpenGL1.5&lt;/span&gt;里面的一个扩展，它的设计旨在结合&lt;span&gt;immediate mode,displaylist&lt;/span&gt;和&lt;span&gt;vertex array&lt;/span&gt;的优点，并且避开了他们各自的一些不足。最让人激动的是，数据既可以完全存入&lt;span&gt;VBO&lt;/span&gt;交给&lt;span&gt;OpenGL&lt;/span&gt;进行管理，同时也提供了一种更加另外的功能，在不影响数据传输效率的情况下，动态改变&lt;span&gt;VBO&lt;/span&gt;的数据。&lt;/span&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;span&gt;令我同时也令不少人不解的是，在测试中大家发现使用&lt;span&gt;VBO&lt;/span&gt;并没有带来预期的性能上的大幅提升，我在自己的地形渲染算法中反复测试发现使用&lt;span&gt;display lists&lt;/span&gt;&lt;/span&gt;&lt;span&gt;比使用&lt;/span&gt;&lt;span&gt;VBO&lt;/span&gt;&lt;span&gt;更能带来效率上的大幅提高。&lt;/span&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;span&gt;在我的测试中，当每帧绘制的三角形数据都较少时，使用&lt;/span&gt;&lt;span&gt;VBOs&lt;/span&gt;&lt;span&gt;和&lt;/span&gt;&lt;span&gt;Display lists&lt;/span&gt;&lt;span&gt;都能带来速度上的提高，但是当每帧绘制的三角形数目逐渐增加时，&lt;/span&gt;&lt;span&gt;VBOs&lt;/span&gt;&lt;span&gt;的速度会急剧下降，而&lt;/span&gt;&lt;span&gt;Display lists&lt;/span&gt;&lt;span&gt;则保持稳定，知道达到令一个数据量级上的三角形数目才会使速度降低。&lt;/span&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;span&gt;需要研究的问题：&lt;/span&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;span&gt;第一：&lt;/span&gt;&lt;span&gt;Display lists&lt;/span&gt;&lt;span&gt;使用效率都与那些因素有关？&lt;/span&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&amp;nbsp;&lt;span&gt;每个&lt;/span&gt;&lt;span&gt;list&lt;/span&gt;&lt;span&gt;绘制的三角形数目，同时绘制的&lt;/span&gt;&lt;span&gt;Lists&lt;/span&gt;&lt;span&gt;的总数&lt;/span&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;span&gt;第二：影响&lt;/span&gt;&lt;span&gt;VBO&lt;/span&gt;&lt;span&gt;速度下降的主要因素？&lt;/span&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span&gt;每个&lt;/span&gt;&lt;span&gt;VBO&lt;/span&gt;&lt;span&gt;存储的三角形数目，同时绘制的&lt;/span&gt;&lt;span&gt;VBOS&lt;/span&gt;&lt;span&gt;的总数&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;帧存的大小&lt;/span&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;span&gt;第三：分析&lt;/span&gt;&lt;span&gt;Display lists&lt;/span&gt;&lt;span&gt;性能超过&lt;/span&gt;&lt;span&gt;VBO&lt;/span&gt;&lt;span&gt;的原因？&lt;/span&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;VBO&lt;span&gt;在每帧绘制时候都有状态转变（&lt;/span&gt;&lt;span&gt;state-change&lt;/span&gt;&lt;span&gt;），导致&lt;/span&gt;&lt;span&gt;CPU&lt;/span&gt;&lt;span&gt;过多的干涉和数据的重新传输？&lt;/span&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span&gt;二者在地层实现上存在的差异？是否新的显卡对&lt;/span&gt;&lt;span&gt;VBO&lt;/span&gt;&lt;span&gt;的支持更好一些？&lt;/span&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span&gt;现有硬件对&lt;/span&gt;&lt;span&gt;VBO&lt;/span&gt;&lt;span&gt;的支持：&lt;/span&gt;&lt;span&gt;hardware-support &lt;/span&gt;&lt;span&gt;和&lt;/span&gt;&lt;span&gt; software-support&lt;/span&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;span&gt;第四：看来需要重新设计一下&lt;/span&gt;&lt;span&gt;vbo array &lt;/span&gt;&lt;span&gt;和&lt;/span&gt;&lt;span&gt; display list array&lt;/span&gt;&lt;span&gt;的调度算法，原来的&lt;/span&gt;&lt;span&gt;FIFO&lt;/span&gt;&lt;span&gt;效率不够高，考虑使用&lt;/span&gt;&lt;span&gt;LRU&lt;/span&gt;&lt;span&gt;算法。总之要保证在每次使用的&lt;/span&gt;&lt;span&gt;CHUNCK&lt;/span&gt;&lt;span&gt;个数不太多时，尽量减少不必要的&lt;/span&gt;&lt;span&gt;VBO&lt;/span&gt;&lt;span&gt;或&lt;/span&gt;&lt;span&gt;DISPLAY LIST&lt;/span&gt;&lt;span&gt;的创建和维护。尤其是在使用&lt;/span&gt;&lt;span&gt;VBO&lt;/span&gt;&lt;span&gt;时，每次创建的&lt;/span&gt;&lt;span&gt;VBO&lt;/span&gt;&lt;span&gt;个数太多，会造成显存不足，从而大大影响系统性能。&lt;/span&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;span&gt;第四：关于内存消耗&lt;/span&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;span&gt;使用&lt;/span&gt;&lt;span&gt;VBO&lt;/span&gt;&lt;span&gt;耗费内存最大，其次是&lt;/span&gt;&lt;span&gt;displaylist&lt;/span&gt;&lt;span&gt;，最后是&lt;/span&gt;&lt;span&gt;immediate&lt;/span&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;span&gt;使用&lt;/span&gt;&lt;span&gt;nvidia gDEBugger&lt;/span&gt;&lt;span&gt;测试发现，使用&lt;/span&gt;&lt;span&gt;display list&lt;/span&gt;&lt;span&gt;耗费的帧存是&lt;/span&gt;&lt;span&gt;VBO&lt;/span&gt;&lt;span&gt;耗费的一半&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;span&gt;关键问题：当地形数据量巨大时，绘制同样细节程度的地形，为了不重新生成新的&lt;/span&gt;&lt;span&gt;VBO&lt;/span&gt;&lt;span&gt;而维持的&lt;/span&gt;&lt;span&gt;VBO&lt;/span&gt;&lt;span&gt;数组个数会急剧增大，进而导致&lt;/span&gt;&lt;span&gt;AGP &lt;/span&gt;&lt;span&gt;内存占用量增加。当&lt;/span&gt;&lt;span&gt;AGP&lt;/span&gt;&lt;span&gt;内存不够用的时候，使用&lt;/span&gt;&lt;span&gt;VBO&lt;/span&gt;&lt;span&gt;或&lt;/span&gt;&lt;span&gt;Display list&lt;/span&gt;&lt;span&gt;的性能优势就体现不出来了。&lt;/span&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;span&gt;不过通过测试发现，使用动态&lt;/span&gt;&lt;span&gt;VBO&lt;/span&gt;&lt;span&gt;在速度上还是优于&lt;/span&gt;&lt;span&gt;immediate mode.&lt;/span&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;span&gt;注意：在显示设置中关闭垂直同步，不然最高&lt;/span&gt;&lt;span&gt;FPS&lt;/span&gt;&lt;span&gt;不会超过最大刷新率&lt;/span&gt;&lt;span&gt;!!!&lt;/span&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;span&gt;FOLLOW_MODE&lt;/span&gt;&lt;span&gt;与&lt;/span&gt;&lt;span&gt;FLY_MODE&lt;/span&gt;&lt;span&gt;的测试结果不同，前者没有做裁减，所以所有的三角形都要画，这样使用&lt;/span&gt;&lt;span&gt;VBO&lt;/span&gt;&lt;span&gt;和不使用&lt;/span&gt;&lt;span&gt;VBO&lt;/span&gt;&lt;span&gt;效率差别不大。但在&lt;/span&gt;&lt;span&gt;FLY_MODE&lt;/span&gt;&lt;span&gt;下，&lt;/span&gt;&lt;span&gt;VBO&lt;/span&gt;&lt;span&gt;的性能明显要高于不使用非&lt;/span&gt;&lt;span&gt;VBO&lt;/span&gt;&lt;span&gt;。&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;img src="http://www.cnblogs.com/mazhenyu/aggbug/2300203.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/mazhenyu/archive/2011/12/24/2300203.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/mazhenyu/archive/2011/12/23/2299174.html</id><title type="text">向量在另一个向量上的投影 (转) 图画的很好，呵呵</title><summary type="text">向量在另一个向量上的投影 若v向量为单位向量,则结果为 uv向量的点积 * v向量.即: 某个方向力u, 在v方向上的分量.</summary><published>2011-12-23T03:39:00Z</published><updated>2011-12-23T03:39:00Z</updated><author><name>3D入魔</name><uri>http://www.cnblogs.com/mazhenyu/</uri></author><link rel="alternate" href="http://www.cnblogs.com/mazhenyu/archive/2011/12/23/2299174.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/mazhenyu/archive/2011/12/23/2299174.html"/><content type="html">&lt;p&gt;&lt;strong&gt;&lt;a id="viewpost1_TitleUrl" href="http://www.cnitblog.com/linghuye/archive/2009/03/19/55548.html"&gt;向量在另一个向量上的投影&lt;/a&gt; &lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;div &gt;&lt;img border="0" src="http://www.cnitblog.com/images/cnitblog_com/linghuye/U_proj_on_V_readme.jpg"  alt="" /&gt;&lt;br /&gt;&lt;br /&gt;若v向量为单位向量,则结果为 uv向量的点积 * v向量.&lt;br /&gt;即: 某个方向力u, 在v方向上的分量.&lt;br /&gt;&lt;/div&gt;&lt;img src="http://www.cnblogs.com/mazhenyu/aggbug/2299174.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/mazhenyu/archive/2011/12/23/2299174.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/mazhenyu/archive/2011/12/22/2298498.html</id><title type="text">基于UML和ASP.NET实现三层B/S结构系统开发（转）</title><summary type="text">基于UML和ASP.NET实现三层B/S结构系统开发2008-06-15 14:46摘 要 进行良好的系统分析和设计是软件项目开发的关键，构架设计的合理与否往往决定了项目的成败。本文结合一个项目的开发，阐述了基于UML的系统建模过程和基于ASP.NET实现面向对象的三层结构应用系统的方法。 关键词 ASP.NET； 三层结构； UML建模； 系统开发架构设计是软件开发的基础，并往往决定一个项目的成败。三层结构是目前流行的架构设计模式，它是在由 Buschmann等提出的“层模式”[1]基础上发展起来的，由表示层、业务逻辑层和数据访问层三个层次结构组成。它通过分解来管理问题的复杂性，同时还可以.</summary><published>2011-12-22T13:33:00Z</published><updated>2011-12-22T13:33:00Z</updated><author><name>3D入魔</name><uri>http://www.cnblogs.com/mazhenyu/</uri></author><link rel="alternate" href="http://www.cnblogs.com/mazhenyu/archive/2011/12/22/2298498.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/mazhenyu/archive/2011/12/22/2298498.html"/><content type="html">&lt;div &gt;基于UML和ASP.NET实现三层B/S结构系统开发&lt;/div&gt;&#xD;
&lt;div &gt;2008-06-15 14:46&lt;/div&gt;&#xD;
&lt;table style="table-layout: fixed; width: 100%"&gt;&#xD;
&lt;tbody&gt;&#xD;
&lt;tr&gt;&#xD;
&lt;td&gt;&#xD;
&lt;div  id="blog_text"&gt;&#xD;
&lt;p&gt;&lt;strong&gt;摘 要&lt;/strong&gt; 进行良好的系统分析和设计是软件项目开发的关键，构架设计的合理与否往往决定了项目的成败。本文结合一个项目的开发，阐述了基于UML的系统建模过程和基于ASP.NET实现面向对象的三层结构应用系统的方法。&lt;br /&gt;&lt;br /&gt;　　&lt;strong&gt;关键词&lt;/strong&gt; ASP.NET； 三层结构； UML建模； 系统开发&lt;br /&gt;架构设计是软件开发的基础，并往往决定一个项目的成败。三层结构是目前流行的架构设计模式，它是在由 Buschmann等提出的&amp;#8220;层模式&amp;#8221;[1]基础上发展起来的，由表示层、业务逻辑层和数据访问层三个层次结构组成。它通过分解来管理问题的复杂性，同时还可以有效地重复使用业务逻辑并保留与昂贵资源（如数据库）的重要连接[2,3]。&lt;br /&gt;&lt;br /&gt;　　基于ASP.NET能够充分发挥其完全面向对象的技术特点，实现三层结构B/S系统架构，从而提高开发效率，增强系统的可维护性和扩展性。本文结合一个&amp;#8220;学生成绩管理系统&amp;#8221;的开发，研究如何基于UML进行三层B/S结构的系统建模，及其在ASP.NET下的应用实现。&lt;br /&gt;&lt;br /&gt;　　&lt;strong&gt;1 三层结构系统模型&lt;/strong&gt;&lt;br /&gt;　　架构设计是非常高级的设计，也是系统设计的关键，主要是定义和说明包（子系统），以及包与包之间的相互依赖与通信机制。系统构架模型的合理与否将决定系统的可维护性、扩展性和开发效率。&lt;br /&gt;&lt;br /&gt;　　包通常所需要处理的是要么是一个具体的功能区域（业务逻辑），要么是一个具体的技术区域（技术逻辑）。业务逻辑主要考虑的是对系统业务功能的实现，而技术逻辑则是进一步考虑用户界面、数据库或通信机制等形成的技术方案。把技术逻辑和业务逻辑区分开来是极其重要的，这是为了当修改程序的某一部分时不会对另一部分产生影响，更加便于进行&amp;#8220;复用&amp;#8221;，同时易于应对来自业务逻辑的变更需求。&lt;br /&gt;&lt;br /&gt;　　三层结构是一种成熟、简单并得到普遍应用的应用程序架构，它将应用程序结构划分三层独立的包，包括用户表示层、业务逻辑层、数据访问层。其中将实现人机界面的所有表单和组件放在表示层，将所有业务规则和逻辑的实现封装在负责业务逻辑组件中，将所有和数据库的交互封装在数据访问组件中。其结构如下图1所示：&lt;br /&gt;&lt;img height="101" src="http://www.uml.org.cn/UMLApplication/images/200713016845228.jpg" width="472" border="0"  alt="" /&gt;&lt;br /&gt;　　&lt;strong&gt;图1 三层结构示意图&lt;/strong&gt;&lt;br /&gt;三层结构是一种严格分层方法，即数据访问层只能被业务逻辑层访问，业务逻辑层只能被表示层访问，用户通过表示层将请求传送给业务逻辑层，业务逻辑层完成相关业务规则和逻辑，并通过数据访问层访问数据库获得数据，然后按照相反的顺序依次返回将数据显示在表示层。&lt;br /&gt;&lt;br /&gt;　　&lt;strong&gt;2 三层B/S结构的学生管理系统开发&lt;/strong&gt;&lt;br /&gt;　　下面通过一个学生管理系统的开发，说明三层B/S结构系统从UML建模到基于ASP.NET进行实现的完整开发过程，UML建模工具采用的是Rational Rose。&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;　2.1 需求分析&lt;/strong&gt;&lt;br /&gt;　　软件需求分析是系统开发的第一步也是最重要的一个环节，其基本任务是准确地回答&amp;#8220;系统做什么？&amp;#8221;这个问题，这需要在对用户需求进行充分调研的基础上，深入理解并描述出软件的功能、性能、接口等方面的需求，可以使用UML建模作为需求分析和系统设计的有效方法。&lt;br /&gt;&lt;br /&gt;　　分析的目的是为了获得和描述系统中所有的要求，因此分析阶段是一种典型的与用户或客户合作的过程，通常由开发人员同用户或客户共同完成。在这个阶段，开发人员不应该考虑代码或程序实现的细节，而应该把精力放在对现有业务逻辑的理解上，通过与用户之间的充分沟通，逐步理解并描述出得到用户确认的系统模型，包括用例模型和领域（domain，系统中关键的类）模型。&lt;br /&gt;&lt;strong&gt;&lt;br /&gt;　　2.1.1 用例模型&lt;/strong&gt;&lt;br /&gt;　　软件开发人员在对用户进行需求调研的过程中，用户往往并不能立即准确描述出未来系统应该提供一些什么样的功能。因此，需要开发人员理解和分析需求，并将系统应该具有的功能通过用例图直观的描述出来，方便用户理解并做出评判，开发人员从而可以根据用户的反馈不断调整用例模型，直至完全正确、充分描述清楚系统功能。&lt;br /&gt;&lt;br /&gt;　　用例建模主要是分离出系统的活动参与者(Actor)和用例(Use Case)，用例是指对系统提供的功能的一种描述，而活动参与者是那些可能使用这些用例的人或外部系统，通过用例图可以描述出系统外部的执行者、系统的用例，以及它们之间的联系。本学生管理系统的用例图见图2。&lt;br /&gt;&lt;br /&gt;　　用例模型还需要进一步对每个用例进行详细描述，进一步说明用例的名称、基本事件流和备选事件流、前置条件和后置条件等，并形成文档。限于篇幅，这里就不多说了。&lt;br /&gt;　　&lt;img height="427" src="http://www.uml.org.cn/UMLApplication/images/200713016101856.jpg" width="483" border="0"  alt="" /&gt;&lt;br /&gt;&lt;strong&gt;　图2 用例图&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;2.1.2 领域建模&lt;/strong&gt;&lt;br /&gt;　　分析过程中还要详细地列举领域(domain ，系统中关键的类)，为了进行领域分析，需要充分理解用例模型，也可以与用户及领域专家组织一次集体研讨会谈，尝试找出所有必须处理的关键概念以及它们之间的相互关系，并最终分析出域类图。下图3为本系统的域类图。&lt;br /&gt;&lt;br /&gt;　　需要强调的是：在本阶段，对领域进行分析的类图还是处于&amp;#8220;草图&amp;#8221;状态。定义的操作和属性不是最后的版本，只是在本阶段看来比较合适。后期将通过动态行为分析不断得出新的操作，这是一个逐步完善和发展的过程。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;2.2 系统设计&lt;br /&gt;&lt;/strong&gt;　系统设计的目的是产生一个可用的、完整的解决方案，并且能够比较容易地将方案转换成程序代码。这个阶段在三层结构的架构设计模型基础上，将考虑所有的实现技术问题，对分析阶段的模型进行扩展和细化，分析阶段定义的类进一步扩充，定义新的类来处理技术方面的问题，并形成最后的UML模型。&lt;br /&gt;&lt;br /&gt;　　推动不断进行详细设计的方法是对每个用例进行动态建模，描述如何通过类图中的对象协作实现用例中的功能，由于一开始对系统的认识是很不够的，前面建立的类往往随着动态建模的深入，发现存在缺陷或不够完整，需要对分析中得到的域类图进行不断修正和调整，扩展形成业务逻辑包。同时，随着对用户界面、数据库访问等技术实现的深入建模，不断建立新的用户界面类（如窗体、控件）和数据访问类，形成用户界面包和数据访问包。&lt;br /&gt;&lt;br /&gt;　　本学生管理系统经过详细设计后，在域类图基础上进行扩展后形成的业务逻辑包类图如下图4所示。&lt;br /&gt;　　&lt;img height="414" src="http://www.uml.org.cn/UMLApplication/images/2007130161013485.jpg" width="620" border="0"  alt="" /&gt; &lt;br /&gt;&lt;strong&gt;　图3 域类图&lt;/strong&gt;&lt;img height="413" src="http://www.uml.org.cn/UMLApplication/images/2007130161024709.jpg" width="577" border="0"  alt="" /&gt; &lt;br /&gt;　　&lt;strong&gt;图4 业务逻辑包类图&lt;/strong&gt;&lt;br /&gt;新建立的数据访问包类图如下图5所示。所有的数据访问类都定义了一个基类DBCommon，该基类包含属性 DBConnectionString，通过该属性可以获得数据库连接字符串。还包括一个方法GetDataView，可以实现在数据库中执行查询获得一个DataView。这些属性和方法被所有的数据访问类继承，可以直接使用。&lt;br /&gt;&lt;img height="438" src="http://www.uml.org.cn/UMLApplication/images/2007130161034253.jpg" width="566" border="0"  alt="" /&gt; &lt;br /&gt;&lt;strong&gt;图5 数据访问包&lt;/strong&gt;&lt;br /&gt;关于用户界面包的类图比较简单，主要是通过界面设计，设计出窗体及控件等界面元素，并根据动态建模时需要涉及的用户界面访问动作，定义所引起的相关事件，这些方面都在窗体类中进行定义，并组成用户界面包，这里就不详细介绍。&lt;br /&gt;动态建模通常采用的方法是使用UML中的时序图描述用例，一个时序图针对某个用例中的一个&amp;#8220;场景&amp;#8221;进行分析。所谓&amp;#8220;场景&amp;#8221;是指一个用例中事件发展的一条路线。根据活动参与者的不同输入或行为，通常一个用例会有多个&amp;#8220;场景&amp;#8221;，也就需要分析出多个时序图。通过时序图描述一个场景中各个对象之间所进行的通信，同时可以分析出系统中相应的类需要具备的操作，从而不断扩充和细化类的设计。如果需要进一步描述类的状态变化情况和操作流程，可以使用UML中的状态图和活动图。&lt;br /&gt;&lt;img height="404" src="http://www.uml.org.cn/UMLApplication/images/2007130161048626.jpg" width="454" border="0"  alt="" /&gt; &lt;br /&gt;&lt;strong&gt;　图6 登录场景&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;　　动态建模时产生的时序图较多，这里无法一一阐述。图6给出了登录系统场景的时序图，在用户界面包中定义了一个LoginForm类，其对应的Web窗体为用户登录窗体页面Login.aspx，图6描述了在该窗体中实现用户登录的场景。&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;　2.3 基于ASP.NET的系统实现&lt;/strong&gt;&lt;br /&gt;　　前面系统设计动态模型时，通过时序图已经对每个用例的各项功能所涉及的场景进行了详尽的描述，按照时序图的规定把每个用例都分别进行编码实现即可。下面结合学生管理系统中的&amp;#8220;登录系统&amp;#8221;用例，介绍基于ASP.NET进行系统实现的方法。&lt;br /&gt;首先需要考虑分包，ASP.NET中包对应的就是命名空间。在本学生管理系统中，规定业务逻辑包的命名空间为 ResultManage.BusinessRule，数据访问包的命名空间为ResultManage.DataAccess，而用户界面包的命名空间为ResultManage.Web。&lt;br /&gt;&lt;br /&gt;　　然后进行业务逻辑包和数据访问包中相关类的设计，对于&amp;#8220;登录系统&amp;#8221;用例，从上图6的登录场景时序图中可以看出，相关的类有业务逻辑包的Users类和数据访问包的UsersDB类，分别对这些类的属性和方法进行定义和实现，并设计一些测试用例或测试程序对其进行单元测试。&lt;br /&gt;&lt;br /&gt;　　最后按照用户界面包和上图6的登录场景时序图中的规定，对用户登录窗体页面Login.aspx进行设计实现，其实现登录的代码如下所示：&lt;/p&gt;&#xD;
&lt;div &gt;&#xD;
&lt;div &gt;&lt;a  href="http://bbs.51aspx.com/showtopic-1125.html###"&gt;[运行代码]&lt;/a&gt; &lt;a  href="http://bbs.51aspx.com/showtopic-1125.html###"&gt;[复制到剪贴板]&lt;/a&gt; &lt;a  title="点击展开/收起该源码" href="http://bbs.51aspx.com/showtopic-1125.html###"&gt;[ &amp;#177; ]&lt;/a&gt;&lt;/div&gt;CODE:&lt;/div&gt;&#xD;
&lt;div &gt;private void btnLogin_Click(object sender, System.EventArgs e)&lt;br /&gt;{&lt;br /&gt;//获得用户登录信息&lt;br /&gt;string UserName = txbUserName.Text;&lt;br /&gt;string Password = txbPassword.Text;&lt;br /&gt;try&lt;br /&gt;{&lt;br /&gt;if (Users.Login(UserName , Password)) //检查用户登录信息&lt;br /&gt;{&lt;br /&gt;//创建身份验证票&lt;br /&gt;FormsAuthentication.SetAuth(UserName, false);&lt;br /&gt;//显示欢迎信息&lt;br /&gt;ShowWelcomeMessage(UserName);&lt;br /&gt;}&lt;br /&gt;else&lt;br /&gt;{&lt;br /&gt;Message.Text = &amp;amp;quot;用户登录失败！&amp;amp;quot;;&lt;br /&gt;}&lt;br /&gt;}&lt;br /&gt;catch (SqlException sqlexception)&lt;br /&gt;{&lt;br /&gt;//提示数据库操作错误信息51aspx.com&lt;br /&gt;Response.Write(sqlexception.Message); &lt;br /&gt;}&lt;br /&gt;}&lt;br /&gt;代码中对于业务的处理，通过调用业务逻辑包Users类的Login方法实现登录信息的检查，其代码如下：&lt;br /&gt;public static bool Login(string UserName , string Password)&lt;br /&gt;{&lt;br /&gt;if (UserName == &amp;amp;quot;&amp;amp;quot;)&lt;br /&gt;{&lt;br /&gt;return false;&lt;br /&gt;}&lt;br /&gt;else&lt;br /&gt;{&lt;br /&gt;//检查数据库中是否存在符合的用户&lt;br /&gt;return UsersDB.CheckLogin(UserName , Password);&lt;br /&gt;}&lt;br /&gt;}&lt;/div&gt;&#xD;
&lt;p&gt;&lt;br /&gt;&lt;br /&gt;上述Users类的Login方法的代码中，首先进行业务逻辑检查，判断用户名是否为空，涉及数据库访问则通过数据访问类完成，通过数据访问包的UsersDB类的CheckLogin方法从数据库中检查是否存在符合相应登录信息的用户。&lt;br /&gt;&lt;br /&gt;　　前面已经提到，包括UsersDB类在内的数据访问层所有类都从一个基类DBCommon继承，该基类封装了所有数据库访问类公共的特性，其中包括定义了公共属性：数据连接字符串DBConnectionString。UsersDB类的CheckLogin方法中使用 DBConnectionString进行数据库的连接，并调用数据库中存储过程CheckLogin查找用户登录信息是否正确。&lt;br /&gt;&lt;br /&gt;　　&lt;strong&gt;3 结束语&lt;/strong&gt;&lt;br /&gt;　　本文介绍了三层B/S结构系统的UML建模和基于ASP.NET进行实现的过程和方法，实现的三层结构不仅程序逻辑上结构清晰，而且由于容易发生需求变更的业务逻辑部分实现了分离，因此具有更强的可扩展性和可维护性。同时这种系统在部署时具有很强的灵活性，可以将各个包分别编译成.NET组件，安装在多台服务器。较典型的是用户界面包安装在Web服务器，业务逻辑包安装在应用服务器，数据访问包安装在数据库服务器或进一步分离，从而实现多级分布的部署方式，实现更好的可伸缩性和安全性，满足大规模的企业级B/S应用系统的需求。&lt;br /&gt;&lt;br /&gt;　　&lt;strong&gt;参考文献&lt;/strong&gt;&lt;br /&gt;　　1 Frank Buschmann, Regin Meunier, Hans Rohnert et al. Pattern-Oriented Software Architecture[M]. New York: John Wiley &amp;amp; Sons Ltd, 1996.1~50&lt;br /&gt;　　2 T.J. Popp. Software Architecture Development for Produce Line Software[A]. Proceedings of the 18th IEEE Digital Avionics Systems Conference[C]. USA:IEEE Computer Society Press, 1999. 106~111&lt;br /&gt;　　3孙昌爱，金茂忠，刘超. 软件体系结构研究综述. 软件学报[J]，2002，13(7)：1228~1237&lt;br /&gt;收稿日期：4月17日 修改日期：4月30日&lt;/p&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;&lt;img src="http://www.cnblogs.com/mazhenyu/aggbug/2298498.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/mazhenyu/archive/2011/12/22/2298498.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/mazhenyu/archive/2011/12/22/2298494.html</id><title type="text">关于B/S结构系统开发语言的选择(转)</title><summary type="text">关于B/S结构系统开发语言的选择2010-01-23 10:51现在主流的网站开发语言无外乎asp、php、asp.net、jsp四种。很多初学者或客户对于用于网站开发即B/S结构系统的程序语言选择比较迷茫，这里综合我们多年的开发经验进行一些分析：网页从开始简单的html到复杂的服务语言，走过了10多个年头，各种技术层出不穷，单个的主流技术也在不断翻新的版本，经常有客户一来就问是否A语言运行速度更快？是否B语言安全性更高？是否C语言是现在最先进的？然后凭自己的主观想象或者参考一些行业者片面的说法就指定必须用某种语言结合某种数据库来发开，盲目的认为这样的开发结果就是最先进的最好的。其实不管ASP</summary><published>2011-12-22T13:31:00Z</published><updated>2011-12-22T13:31:00Z</updated><author><name>3D入魔</name><uri>http://www.cnblogs.com/mazhenyu/</uri></author><link rel="alternate" href="http://www.cnblogs.com/mazhenyu/archive/2011/12/22/2298494.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/mazhenyu/archive/2011/12/22/2298494.html"/><content type="html">&lt;div &gt;关于B/S结构系统开发语言的选择&lt;/div&gt;&#xD;
&lt;div &gt;2010-01-23 10:51&lt;/div&gt;&#xD;
&lt;table style="table-layout: fixed; width: 100%"&gt;&#xD;
&lt;tbody&gt;&#xD;
&lt;tr&gt;&#xD;
&lt;td&gt;&#xD;
&lt;div  id="blog_text"&gt;&#xD;
&lt;p&gt;现在主流的网站开发语言无外乎asp、php、asp.net、jsp四种。很多初学者或客户对于用于网站开发即B/S结构系统的程序语言选择比较迷茫，这里综合我们多年的开发经验进行一些分析：&lt;/p&gt;&#xD;
&lt;p&gt;网页从开始简单的html到复杂的服务语言，走过了10多个年头，各种技术层出不穷，单个的主流技术也在不断翻新的版本，经常有客户一来就问是否A语言运行速度更快？是否B语言安全性更高？是否C语言是现在最先进的？然后凭自己的主观想象或者参考一些行业者片面的说法就指定必须用某种语言结合某种数据库来发开，盲目的认为这样的开发结果就是最先进的最好的。其实不管ASP、PHP、ASP.net、JSP哪种语言，它们能成为网站的开发主流语言，就直接说明着这四种语言本身并没有太大的优缺点，而关键在于开发它的人或公司是否擅长于使用它和用它做出来的东西是否符合该系统要达到的目的，所谓擅长的标准，应该就是使用该语言的人能在高效率、高质量的前提下实现其所有功能，大多数公司团队或个人都有自己擅长的程序语言，只要能通过各自擅长的语言达到系统建设的目的，我们又何必太在乎语言的本身是否优劣，如果说优劣也只能是指最终开发出的系统是否考虑完善。下面我们就对四种语言进行逐一分析和对比，看怎样的条件下选择用怎样的语言才能开发出适合自身情况需要的系统搭建。&lt;/p&gt;&#xD;
&lt;p&gt;HTML:当然这是网页最基本的语言,每一个服务器语言都需要它的支持,要学习,每个开发者都必须要掌握，这个肯定是开始,这里就不说了.&lt;/p&gt;&#xD;
&lt;p&gt;主流网站开发语言之ASP:ASP是微软（Microsoft）所开发的一种后台脚本语言（请注意ASP是种脚本，严格来说并不是种开发语言，这也是它和一些语言最大的本质区别，），它的语法和Visual BASIC类似，可以像SSI（Server Side Include）那样把后台脚本代码内嵌到HTML页面中。ASP在执行的时候，是由IIS调用程序引擎，解释执行嵌在HTML中的ASP代码，最终将结果和原来的HTML一同送往客户端。ASP的简单易用是其最大的特点，特别是和ACCESS这种小型数据库结合后相当方便，说到这里不得不插说一下数据库：&lt;/p&gt;&#xD;
&lt;p&gt;Access：微软Office带的小型数据库系统，一般与Asp，Asp.Net配合使用。这个数据库极度适合小型企业的网站,对于数据量低于10万条的网站来说，完全没有问题.其实ACESS已经能满足相当多的网站数据量需求，不要去盲目的选择使用大型数据库，一方面增加不必要的工作量如环境搭建，一方面会增加费用。&lt;/p&gt;&#xD;
&lt;p&gt;MYSQL：一种免费的中型数据库系统，一般与PHP配合使用.&amp;nbsp;&amp;nbsp; 对于PHP程序员来说，MYSQL是最好的选择.&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; MSSQL（SQL Server）：微软公司的大型数据库系统，一般Asp，Asp.Net使用，目前比较流行的版本有2000，2005.&amp;nbsp;&amp;nbsp; 网站数据量超过了十万\二十万,那就改用MSSQL数据库吧.&lt;/p&gt;&#xD;
&lt;p&gt;主流网站开发语言之PHP: Php和Asp一样也是，也是属于脚本语言，一般连接的数据库为MySql数据库，当然它也能和Access数据库和MsSql(SqlServer)数据库等其他数据库连接。PHP的源代码完全公开，PHP属于免费软件，也就是说他的资源是free的。 Php从安全性上比Asp要好，当然这里说的是相对而言，一个好的程序员把安全性做好的话，都差不多，不过Php的安全性要比Asp要好，为什么这么说呢。这里主要原因是这样的，PHP的搭建服务器环境相对复杂(需要安装Apache + MySql + PHP)，而Asp的搭建环境比较简单(只需要安装IIS就可以了)，所以学PHP的门槛比Asp的门槛要高，所以很多人就偏向Asp学习的人就多了，自然研究Asp漏洞的人就多了，而PHP会的人就少，所以研究漏洞的人就更少了，从这点来说PHP的安全性比ASP的安全性要高些。而且还有一点就是 Apache 的环境最好是Unix，当然Windows下也是可以安装的。&lt;/p&gt;&#xD;
&lt;p&gt;平台无关性是PHP的最大优点，但是在优点的背后，还是有一些小小的缺点的。如果在PHP中不使用ODBC，而用其自带的数据库函数（这样的效率要比使用ODBC高）来连接数据库的话， 使用不同的数据库，PHP的函数名不能统一。这样，使得程序的移植变得有些麻烦。不过，作为目前应用最为广泛的一种后台语言，PHP的优点还是异常明显的。&lt;/p&gt;&#xD;
&lt;p&gt;主流网站开发语言之ASP.NET:ASP.net是Microsoft.net的一部分，作为战略产品，不仅仅是 Active Server Page (ASP) 的下一个版本；它还提供了一个统一的 Web 开发模型，其中包括开发人员生成企业级 Web 应用程序所需的各种服务。ASP.NET 的语法在很大程度上与 ASP 兼容，同时它还提供一种新的编程模型和结构，可生成伸缩性和稳定性更好的应用程序，并提供更好的安全保护。可以通过在现有 ASP 应用程序中逐渐添加 ASP.NET 功能，随时增强 ASP 应用程序的功能。ASP.NET 是一个已编译的、基于 .NET 的环境，可以用任何与 .NET 兼容的语言（包括 Visual Basic .NET、C# 和 JScript .NET.）创作应用程序。另外，任何 ASP.NET 应用程序都可以使用整个 .NET Framework。开发人员可以方便地获得这些技术的优点，其中包括托管的公共语言运行库环境、类型安全、继承等等。ASP.NET 可以无缝地与 WYSIWYG HTML 编辑器和其他编程工具（包括 Microsoft Visual Studio .NET）一起工作。这不仅使得 Web 开发更加方便，而且还能提供这些工具必须提供的所有优点，包括开发人员可以用来将服务器控件拖放到 Web 页的 GUI 和完全集成的调试支持。微软为ASP.net设计了这样一些策略：易于写出结构清晰的代码、代码易于重用和共享、可用编译类语言编写等等，目的是让程序员更容易开发出Web应用，满足计算向Web转移的战略需要。ASP.net 的速度 是 ASP不能比拟的。ASP.net 是编译语言，所以，当第一次加载的时候，它会把所有的程序进行编译(其中包括 worker进程，还有对语法进行编译，形成一个程序集)，当程序编译后，执行速度几乎为0，而ASP是把代码交给VBScript解释器或Jscript解释器来解释，当然速度没有编译过的程序快了。&lt;/p&gt;&#xD;
&lt;p&gt;主流网站开发语言之JSP:JSP和Servlet要放在一起讲，是因为它们都是Sun公司的J2EE（Java 2 platform Enterprise Edition）应用体系中的一部分。&lt;/p&gt;&#xD;
&lt;p&gt;Servlet的形式是HTML代码和后台程序分开的,是服务器接到客户端的请求后，进行应答，打开一个线程（Thread），将结果发送给客户。由于线程与线程之间可以通过生成自己的父线程（Parent Thread）来实现资源共享，这样就减轻了服务器的负担，所以，Java Servlet可以用来做大规模的应用服务。&lt;/p&gt;&#xD;
&lt;p&gt;虽然在形式上JSP和ASP或PHP看上去很相似&amp;#8212;&amp;#8212;都可以被内嵌在HTML代码中。但是，它的执行方式和ASP或PHP完全不同。在JSP被执行的时候，JSP文件被JSP解释器（JSP Parser）转换成Servlet代码，然后Servlet代码被Java编译器编译成 .class 字节文件，这样就由生成的Servlet来对客户端应答。所以，JSP可以看做是Servlet的脚本语言（Script Language）版。&lt;/p&gt;&#xD;
&lt;p&gt;由于JSP/Servlet都是基于Java的，所以它们也有Java语言的最大优点&amp;#8212;&amp;#8212;平台无关性，也就是所谓的&amp;#8220;一次编写，随处运行（WORA &amp;#8211; Write Once, Run Anywhere）&amp;#8221;。除了这个优点，JSP/Servlet的效率以及安全性也是相当惊人的。因此，JSP/Servlet虽然在国内目前的应用并不广泛，但是其前途不可限量。&lt;/p&gt;&#xD;
&lt;p&gt;在调试JSP代码时，如果程序出错，JSP服务器会返回出错信息，并在浏览器中显示。这时，由于JSP是先被转换成Servlet后再运行的，所以，浏览器中所显示的代码出错的行数并不是JSP源代码的行数，而是指转换后的Servlet程序代码的行数。这给调试代码带来一定困难。所以，在排除错误时，可以采取分段排除的方法（在可能出错的代码前后输出一些字符串，用字符串是否被输出来确定代码段从哪里开始出错），逐步缩小出错代码段的范围，最终确定错误代码的位置。&lt;/p&gt;&#xD;
&lt;p&gt;如今主流的Web服务器软件主要由IIS或Apache组成。IIS支持ASP且只能运行在Windows平台下，Apache支持PHP，CGI，JSP且可运行于多种平台，虽然Apache是世界使用排名第一的Web服务器平台，但是众所周知，Windows以易用而出名，也因此占据不少的服务器市场。&lt;/p&gt;&#xD;
&lt;p&gt;vb一般指vb6.0,是传统的win32编程。vb.net和asp.net是基于微软.net平台的语言。说java好主要是因为java的j2ee部分做企业级开发很强大，而且跨平台。c#是.net平台上最好用的语言，现在只能运行在windows系统。 web开发方面.net和j2ee的竞争很激烈，难说以后鹿死谁手。 现在做网站大部分都是asp.net或jsp的，asp.net容易上手，比较普及，但是平台单一，jsp虽然上手难，但是跨平台，安全性高。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;我们常用的开发组合:&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;IIS环境下&lt;/p&gt;&#xD;
&lt;p&gt;1.ASP+ACCESS&lt;/p&gt;&#xD;
&lt;p&gt;2.ASP+SQL SERVER&lt;/p&gt;&#xD;
&lt;p&gt;3.ASP.NET+ACCESS&lt;/p&gt;&#xD;
&lt;p&gt;4.ASP.NET+SQL SERVER&lt;/p&gt;&#xD;
&lt;p&gt;APACHE环境下&lt;/p&gt;&#xD;
&lt;p&gt;5. JSP +Oracale&lt;/p&gt;&#xD;
&lt;p&gt;6.JSP+MYSQL&lt;/p&gt;&#xD;
&lt;p&gt;7.PHP+MYSQL&lt;/p&gt;&#xD;
&lt;p&gt;总结对比：&lt;/p&gt;&#xD;
&lt;p&gt;asp&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; asp.net&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; php&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; jsp&lt;br /&gt;主要适用&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; 网站&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 网站管理系统&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 网站&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 管理系统&lt;br /&gt;网站规模&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; 小型&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 大中小&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 中小型&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 大中&lt;br /&gt;学习难度&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; 简单&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 中&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 简单&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 难&lt;br /&gt;开发速度&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 快&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 中&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 快&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 慢&lt;br /&gt;国内流行程度&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 较&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 较&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 较&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 一般&lt;/p&gt;&#xD;
&lt;p&gt;可以说在ASP.net的推出并随着微软的强势支持下,同为微软产品的ASP在微软停止对其更新后，确实快过时了，在未来jsp和asp.net将会有巨大的潜力，但PHP凭借其开源的特性也会占有一定份额。 因此在国内来说，ASP.net和PHP在大多数的网站应用中现在已经是主流中的主流，JSP一般用于一些超大型的网站开发或者管理系统开发。&lt;/p&gt;综上所述，我们评价其速度也好，安全性也好，开发难易度也好，成本投入也好等等都是相对而言，都是相对于一个B/S系统的发展需要和适合自身条件投入而言。如果要用ASP+MSSQL开发一个新浪或者163这种巨型门户网站也不是不可以，但如果要这样做我们也可以使这种组合够速度、够安全，但这会增加开发者巨大的工作量去研究配合提高它的速度、安全性、和考虑负载的均衡。经常看到有些公司打出用JSP建站的口号，以此为卖点，客户不要盲目觉得JSP就是最先进的，也许ASP是一把小刀，JSP是一把菜刀，用来削个苹果不见得是更大的菜刀适合吧，一些网络公司或软件公司用不成熟的JSP技术做出来的东西那不叫JSP，不叫J2EE，不见得后缀名为JSP的就能真正发挥了JSP的所有特性，因此国内经常看到一些JSP网站速度其慢，甚至效果不如ASP。JSP本身的特性就决定了用这种语言来开发毕将是高成本的投入，那些花很少的成本做个JSP站点我们肯定要持怀疑的态度来认真审视，而花出高达几倍甚至数十倍的成本来硬撑个JSP小站点我想也不是一般人能够接受的，所以选择怎样的组合完成怎样的事以达到怎样的目的才是重点，也许这也不仅仅是这个行业的特点，也适用于其他行业。&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;&lt;img src="http://www.cnblogs.com/mazhenyu/aggbug/2298494.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/mazhenyu/archive/2011/12/22/2298494.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/mazhenyu/archive/2011/12/20/2294458.html</id><title type="text">面向GPU的多LOD因子的大规模场景可视化策略 (转)</title><summary type="text">面向GPU的多LOD因子的大规模场景可视化策略 面向GPU的多LOD因子的大规模场景可视化策略张嘉华 梁成 陈利强 陈春华 newzjh@msn.com aliceliang@163.net sailmer@hotmail.com musalan@msn.com华南理工大学计算机科学与工程学院（510640）图 1. 多LOD因子控制的大规模地形渲染（C1=1.03,C2=19.55,C3=0.868 下山脉地区三维漫游）摘要伴随着计算机图形处理器，真实感图形学，虚拟现实等领域的快速发展，主流的NV30等GPU渲染吞吐量已经达到每秒渲染1.5亿个三角形，如何在地形渲染中充分地利用GPU能力呢？</summary><published>2011-12-20T03:29:00Z</published><updated>2011-12-20T03:29:00Z</updated><author><name>3D入魔</name><uri>http://www.cnblogs.com/mazhenyu/</uri></author><link rel="alternate" href="http://www.cnblogs.com/mazhenyu/archive/2011/12/20/2294458.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/mazhenyu/archive/2011/12/20/2294458.html"/><content type="html">&lt;h1 &gt;&lt;a id="ctl02_TitleUrl"  href="http://www.cnblogs.com/javazjh/archive/2011/09/08/2171727.html"&gt;面向GPU的多LOD因子的大规模场景可视化策略&lt;/a&gt; &lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;div &gt;&lt;/div&gt;&#xD;
&lt;div &gt;&#xD;
&lt;div id="cnblogs_post_body"&gt;&#xD;
&lt;p&gt;面向GPU的多LOD因子的大规模场景可视化策略&lt;/p&gt;&#xD;
&lt;p&gt;张嘉华 梁成 陈利强 陈春华 &lt;/p&gt;&#xD;
&lt;p&gt;newzjh@msn.com aliceliang@163.net sailmer@hotmail.com musalan@msn.com&lt;/p&gt;&#xD;
&lt;p&gt;华南理工大学计算机科学与工程学院（510640）&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/javazjh/201109/201109081829182609.gif"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image002" border="0" alt="clip_image002" src="http://images.cnblogs.com/cnblogs_com/javazjh/201109/20110908182918134.gif" width="734" height="205" /&gt;&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;图&lt;/strong&gt;&lt;strong&gt; 1&lt;/strong&gt;. 多LOD因子控制的大规模地形渲染（C&lt;sub&gt;1&lt;/sub&gt;=1.03,C&lt;sub&gt;2&lt;/sub&gt;=19.55,C&lt;sub&gt;3&lt;/sub&gt;=0.868 下山脉地区三维漫游）&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;&lt;br /&gt;&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;摘要&lt;a name="OLE_LINK1"&gt;&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;伴随着计算机图形处理器，真实感图形学，虚拟现实等领域的快速发展，主流的NV30等GPU渲染吞吐量已经达到每秒渲染1.5亿个三角形，如何在地形渲染中充分地利用GPU能力呢？本文提出了一套面向GPU基于层迭四叉树下的多尺度LOD超大规模场景可视化策略。我们的策略能够提供稳定的视觉，高度的漫游流畅感和沉浸感，对于16K&amp;#215;16K grid Puget Sound和16K&amp;#215;8K grid Great canyon等场景，能够以每秒100帧以上速度漫游整个场景&lt;/p&gt;&#xD;
&lt;p&gt;关键字：&lt;/p&gt;&#xD;
&lt;p&gt;大规模场景 LOD GPU 四叉树 三角列&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/javazjh/201109/201109081829194835.gif"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image004" border="0" alt="clip_image004" src="http://images.cnblogs.com/cnblogs_com/javazjh/201109/201109081829196820.gif" width="692" height="473" /&gt;&lt;/a&gt;&lt;strong&gt; &lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;图 4&lt;/strong&gt;. 澳洲大宝礁三维可视化漫游&lt;/p&gt;&#xD;
&lt;p&gt;(70400&amp;#215;54400 grid高分辨率Terra卫星影像)&lt;/p&gt;&#xD;
&lt;p&gt;引言&lt;/p&gt;&#xD;
&lt;p&gt;随着 &amp;#8220;数字地球&amp;#8221;构想的提出以及海量空间数据可视化等研究的开展，超大规模地形可视化在国家安全，高分辨率卫星、航拍、遥感影像空间数据可视化，大规模人工植物群、视景仿真、虚拟军事环境，电子沙盘等领域有着其广泛的发展空间，一直以来是计算机真实感图形学、虚拟现实、地学仿真等领域的研究热点，吸引了大量国内外学者的研究兴趣。&lt;/p&gt;&#xD;
&lt;p&gt;主要贡献：在本文中，我们提出了&lt;a name="OLE_LINK6"&gt;两级层迭泛型四叉树下的多&lt;/a&gt;LOD因子的超大规模场景可视化策略，它能够充分利用了GPU能力，对于Puget Sound等具有代表性的场景能够以100FPS稳定漫游，我们独立开发的World Builder 2005、World Explorer 2005、World Solution 2005展现了本文策略的效果，有效论证了我们策略的正确性，完成了多个领域的应用案例展示。下面是我们贡献的分点阐述：&lt;/p&gt;&#xD;
&lt;p&gt;l 在节点评价方面探讨了全局的LOD评价因子&amp;#8212;&amp;#8212;摄像机移动速度，探讨了符合节点形状的静态误差评价方法 (Part4,Page11-12)&lt;/p&gt;&#xD;
&lt;p&gt;l 实验测定了每次调用渲染函数渲染的最佳三角形数目，论证了三角形带累积渲染的优势, 充分地通过Direct3D / OpenGL图形接口利用GPU (Part5,Page13-14)&lt;/p&gt;&#xD;
&lt;p&gt;l 在多分辨率地形组织方面，提出层迭泛型四叉树地形组织方法和泛型哈希表节点标记策略 (Part3,Page7-11)&lt;/p&gt;&#xD;
&lt;p&gt;l 在裂缝处理方面提出了边界样式和顶点位移的方法 (Part5,Page13-16)&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/javazjh/201109/20110908182919200.jpg"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image006" border="0" alt="clip_image006" src="http://images.cnblogs.com/cnblogs_com/javazjh/201109/201109081829197725.jpg" width="397" height="280" /&gt;&lt;/a&gt; &lt;a href="http://images.cnblogs.com/cnblogs_com/javazjh/201109/201109081829196330.jpg"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image008" border="0" alt="clip_image008" src="http://images.cnblogs.com/cnblogs_com/javazjh/201109/201109081829205806.jpg" width="390" height="275" /&gt;&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;C&lt;sub&gt;1&lt;/sub&gt;=0.2 C&lt;sub&gt;1&lt;/sub&gt;=0.4&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/javazjh/201109/201109081829202459.jpg"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image010" border="0" alt="clip_image010" src="http://images.cnblogs.com/cnblogs_com/javazjh/201109/201109081829201935.jpg" width="401" height="285" /&gt;&lt;/a&gt; &lt;a href="http://images.cnblogs.com/cnblogs_com/javazjh/201109/201109081829208904.jpg"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image012" border="0" alt="clip_image012" src="http://images.cnblogs.com/cnblogs_com/javazjh/201109/2011090818292017.jpg" width="387" height="273" /&gt;&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;C&lt;sub&gt;1&lt;/sub&gt;=0.8 C&lt;sub&gt;1&lt;/sub&gt;=1.6&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;图&lt;/strong&gt;&lt;strong&gt; 3&lt;/strong&gt;. 不同细节层次下的Puget Sound&lt;/p&gt;&#xD;
&lt;p&gt;本文是在我们过往对大规模场景的研究的基础上进行的，主要围绕大规模场景可视化流程组织的，伴随着论文的撰写同时我们独立开发了一整套分布式的大规模场景漫游、协同仿真平台，我们的灵感主要来源于寻找一种能够充分利用GPU的地形可视化策略，能够快速查询节点状态和属性，进行空间的拓扑索引；设计一种LOD策略，能够尽可能简化地形渲染，使地形屏幕贡献度大，人们视觉比较敏感的区域能够得到更高精度显示，减少动态细节层次改变带来的地形节点几何形状变化程度，保持视觉稳定性和漫游的流畅感和沉浸感。&lt;/p&gt;&#xD;
&lt;p&gt;我们的这套面向GPU的多LOD 评价因子的超大规模场景可视化策略具有下面这些优点：&lt;/p&gt;&#xD;
&lt;p&gt;l 多LOD评价因子 &lt;br /&gt;摒弃过往缺乏考虑节点几何形状的静态因子评价方法，提出适合四叉树能够通过地形起伏程度阈值控制的静态因子评价，同时引入摄像机移动速度作为评价因子，充分考虑更种因素在节点渲染过程中的屏幕贡献度和人的视觉敏感区域&lt;/p&gt;&#xD;
&lt;p&gt;l 稳定的视觉 &lt;br /&gt;双重帧约束(自适应的LOD帧约束和图形接口层上的帧约束)，保持平滑流畅的漫游视觉&lt;/p&gt;&#xD;
&lt;p&gt;l 高的渲染吞吐量 &lt;br /&gt;Triangle Lists累积渲染大大降低调用渲染函数的次数，保持渲染流水线操作的尽可能连续，充分利用GPU&lt;/p&gt;&#xD;
&lt;p&gt;l 连续的索引缓冲和顶点缓冲 &lt;br /&gt;不同LOD级别差异的节点预定义的边界样式和顶点插值高程代替实际高程的裂缝消除方法能够有效地增加顶点缓冲和索引缓冲中连续的数据部分，加速图形渲染&lt;/p&gt;&#xD;
&lt;p&gt;l 多级地形组织 &lt;br /&gt;多级四叉树地形模型，既具有分块地形更新灵活的特点，又具有多分辨率LOD地形模型的多LOD因子控制的特点&lt;/p&gt;&#xD;
&lt;p&gt;l 丰富的无限级别地形细节 &lt;br /&gt;无限级别分形非线性自相似内插，能够提供无限的更丰富的地形细节&lt;/p&gt;&#xD;
&lt;p&gt;l 内存消耗和时间消耗动态平衡的节点标记 &lt;br /&gt;泛型哈希表节点标记策略，能够动态地调节哈希表控制因子，改变哈希表存储桶的大小，在节点状态标记内存消耗和时间消耗之间达到最佳平衡，&lt;/p&gt;&#xD;
&lt;p&gt;除前面引言部分外，本文由五部分组成,第一部分介绍在这个领域的过往相关工作，第二部分介绍探讨了我们的地形数据组织策略，第三部分介绍我们探讨的各种LOD评价因子，第四部分介绍我们提出的面向GPU的多分辨率LOD地形下的裂缝消除和顶点跃动消除的方法。最后介绍了我们的实验后的结论，并探讨了我们策略的应用前景。&lt;/p&gt;&#xD;
&lt;p&gt;1、相关工作&lt;/p&gt;&#xD;
&lt;p&gt;在大规模地形场景可视化和地形LOD模型问题上，过去已经有不少的工作。从网格特征考虑可分为基于非规则三角网格(Tin)和基于均匀网格(Grid)两种生成方法。从地形分层细分上考虑可以分为二叉树，四叉树，八叉树等，下面介绍几个主要的相关工作：&lt;/p&gt;&#xD;
&lt;p&gt;96年，Lindstrom等提出了连续的实时的LOD高度场方法，该方法使用规则格网，通过一个用户可以控制的屏幕空间误差阙值控制细节简化程度，使用层次四叉树从最高精度的底层自底向上(bottom-up)对整个场景地形逐步简化三角形直到达到指定控制量。该方法通过维持地形块的活动分割和只访问能够在连续的帧间改变的顶点实现帧约束，通过维持顶点拓扑关系的二叉树消除裂缝。&lt;/p&gt;&#xD;
&lt;p&gt;97年，Duchaineau等提出了ROAM实时自适应网格方法，该方法使用带有二元三角形树（BBT,binary triangle tree）基于优先级产生连续的地形网格。该方法通过两个优先级队列进行分割和合并三角形操作。一个队列负责维持具有优先级顺序的待分割三角形的列表，该队列中优先级最高的三角形首先细分，另一个队列包含具有优先级顺序的待合并的三角形列表。这使得ROAM方法具有帧约束的特点，分割和合并操作可以通过顶点渐变平滑进行。&lt;/p&gt;&#xD;
&lt;p&gt;98年，rottger等人在[Lindstrom96]的基础上，与Lindstrom等自底而上的方法不同，提出了一种基于四叉树的自顶而下的策略，该策略每帧只访问整个地形的一部分，但该方法需要分析整个地形数据[rottger 98]。该方法在裂缝处理上，通过忽略高分辨率节点边上中点顶点来消除裂缝。他们还探讨了LOD误差评价方法，具有两个评价因子，动态因子以节点到观察者的距离评价，静态因子以地形在世界空间的起伏程度来评价。对于静态因子，他们通过计算四叉树节点四条边的中点和两条斜边的中点误差最大值来计算。但是，这种取6个节点的误差最大值作为评价并没有充分考虑到节点的几何形状，缺乏理论依据，其误差评价因子只有两种，并不能充分准确地反映节点误差及其屏幕贡献度。&lt;/p&gt;&#xD;
&lt;p&gt;98年Hugues Hoppe等人在他们过往提供一种可以从任意网格增减三角形的方法[Hoppe96]的基础上通过提出了基于视向的渐进网格（VDPMs）。VDPMs提供了一个基于非规则格网（tin）的框架，能够提供更多渐进格网优化，具有处理凹陷等更为复杂的地形特征的能力，通过实时生成几何变形产生平滑的顶点分割和边折叠，通过屏幕误差来反映几何细分渐变，通过强制分块地形边界顶点不分割来处理裂缝。但是该方法具有难以支持随着地形动态改变而实时变化的网格的缺陷，需要跟踪网格的拓扑结构，难于生成和裁减。&lt;/p&gt;&#xD;
&lt;p&gt;2001年，Lindstrom和Pascucci提出了一种新的简单的容易实现的，易于内存管理和可靠的误差分析的地形LOD方法，该工作在过往许多地形可视化工作的基础上提供一个规则格网的自顶而下的框架，能够out-of-core的基于视向的大规模地形细化，支持快速的视锥剔除，三角带渲染，可选择的细化。该方法在磁盘上组织数据,通过操作系统内存映射，能够动态加载分块地形数据到物理内存。&lt;/p&gt;&#xD;
&lt;p&gt;随着近年来GPU的迅速发展，GPU的Vertex Shader和Pixel Shader图形芯片可编程能力已经日益受到重视，过往的工作诸如视锥剔除、分块映射内存等通用计算和海量数据管理在一定层面上已经可以部分移到GPU中，因此本文探讨了面向GPU的大规模场景可视化策略，提出了一些新的方法。&lt;/p&gt;&#xD;
&lt;p&gt;2、层迭泛型多分辨率LOD四叉树地形&lt;/p&gt;&#xD;
&lt;p&gt;四叉树结构可以直接地表示规则网格的数字地面模型。树中的每一个节点覆盖场景中一个2&lt;sup&gt;n&lt;/sup&gt;&amp;#215;2&lt;sup&gt;n&lt;/sup&gt;的地形区域，树的根节点表示整个地形。节点扩展时将地形沿平面上的两轴平分成四个子块，分别对应它的四个子节点依次逐层细分。&lt;/p&gt;&#xD;
&lt;p&gt;一个传统的四叉树结构可定义如下：&lt;/p&gt;&#xD;
&lt;p&gt;struct QuadtreeNode&lt;/p&gt;&#xD;
&lt;p&gt;{&lt;/p&gt;&#xD;
&lt;p&gt;QuadtreeNode *pSon[4] ; &amp;#8741;4 个子结点指针&lt;/p&gt;&#xD;
&lt;p&gt;QuadtreeNode *pParent ; &amp;#8741;父结点指针&lt;/p&gt;&#xD;
&lt;p&gt;&amp;#8741;消除拼接缝标志&lt;/p&gt;&#xD;
&lt;p&gt;Bool bCent ,bLeft ,bRight ,bTop ,bBottom;&lt;/p&gt;&#xD;
&lt;p&gt;float Error ; &amp;#8741;结点覆盖区域最大误差&lt;/p&gt;&#xD;
&lt;p&gt;}&lt;/p&gt;&#xD;
&lt;p&gt;传统的四叉树模型生成时，每个节点都采样一次，从而不同的层对应不同的分辨率。建立全分辨率的四叉树对于超大规模场景来说会消耗大量内存。&lt;/p&gt;&#xD;
&lt;p&gt;2.1 两级四叉树地形组织&lt;/p&gt;&#xD;
&lt;p&gt;考虑到场景是超大规模的，本文把整个场景划分成三个层次，最顶层是World，中间是分块的Block，底层是QuadtreeNode结点。每个分块的Block是一可变的动态四叉树，每个结点类型为QuadtreeNode，而所有的Block又组成整个场景的静态全分辨率四叉树，也就是说，Block的数量跟场景大小成正比，LOD渐进简化是以Block为单位。因此，对整个超大规模场景，四叉树的设计可以分两种情况考虑：对于整个场景而言，整个场景所管理的各层Block是一棵全分辨率四叉树，以Block为单位；而对于每一个Block而言，是一个组织着大量QuadtreeNode的动态可变四叉树，以QuadtreeNode为单位。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/javazjh/201109/201109081829213397.gif"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image013" border="0" alt="clip_image013" src="http://images.cnblogs.com/cnblogs_com/javazjh/201109/20110908182921365.gif" width="418" height="315" /&gt;&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;图9.&lt;/strong&gt; 两级四叉树地形组织&lt;/p&gt;&#xD;
&lt;p&gt;本文提出的上述组织方式有如下优点：&lt;/p&gt;&#xD;
&lt;p&gt;1. 与过去全分辨率四叉树方法相比，可以解决了过去整个场景中大量节点的问题，在我们的整个场景中，只存在一棵管理Block的全分辨率四叉树，以及当前活动的处于视锥范围内的Block里的动态可变四叉树。那些非活动Block里的大量节点不在生成，节省了大量的内存空间。&lt;/p&gt;&#xD;
&lt;p&gt;2. 与纯动态四叉树组织方法相比，地形数据的载入更新均以Block（块）为单位，避免了每帧都需要对整棵四叉树进行更新，只对当前处于视锥范围内活动的Block分别构建可变动态四叉树。同时方便本文后面部分能够实现后台异步的块的读入和更新。&lt;/p&gt;&#xD;
&lt;p&gt;3. 对于每个Block里的动态可变四叉树，我们把采样与四叉树模型分开，在建立四叉树模型时并没有采样的操作，得到的四叉树也不存在底层限制，当四叉树节点大小比Grid格网还要小的时候，不中止节点细分，而对节点内顶点进行分形内插高程，这对于距离屏幕相当近的节点，我们仍然能够达到一定精度，不存在约束四叉树由于约束带来的局部C&lt;sub&gt;2&lt;/sub&gt;- LOD因素调整失效。&lt;/p&gt;&#xD;
&lt;p&gt;2.2 上层全分辨率分块地形四叉树&lt;/p&gt;&#xD;
&lt;p&gt;对于整个场景的以Block为单位的全分辨率四叉树，我们利用.net framework 2.0新提供的泛型直接构建一泛型类Quadtree&amp;lt;Block&amp;gt;，该类实现了IEnumerable&amp;lt;T&amp;gt;接口的GetEnumerator方法，使我们能够以for each方式快速地以根－左上－右上－左下－右下的顺序遍历整棵树，隐藏了具体迭代遍历的细节，对类外而言具有非常可观的面向接口优点。每个Block没有固定的大小，只有最底层的节点负责载入和释放数据，其他节点只负责记录有关的信息。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/javazjh/201109/201109081829212558.gif"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image014" border="0" alt="clip_image014" src="http://images.cnblogs.com/cnblogs_com/javazjh/201109/201109081829219526.gif" width="455" height="243" /&gt;&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;图&lt;/strong&gt;&lt;strong&gt;10.&lt;/strong&gt; 分块视锥剔除&lt;/p&gt;&#xD;
&lt;p&gt;我们首先按传统四叉树对上层分块地形四叉树进行视锥判断，对于渲染的每一帧，确定那些地形块处在视锥之内，对处在地形块之内的地形数据构建动态可变四叉树进行LOD简化，把简化后的树节点输出到负责地形渲染的类，因此在地形块类内需要静态的地形块队列，代表当前处在视锥范围内的地形块集合，当有新的地形块进入视锥范围，就添加到这集合，离开视锥范围就删除。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/javazjh/201109/201109081829212907.gif"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image015" border="0" alt="clip_image015" src="http://images.cnblogs.com/cnblogs_com/javazjh/201109/201109081829215099.gif" width="468" height="240" /&gt;&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;VB=Vertex Buffer S&lt;sub&gt;0&lt;/sub&gt;=Stream Loader 0&lt;/p&gt;&#xD;
&lt;p&gt;VS=Vertex Shader&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/javazjh/201109/201109081829212068.gif"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image017" border="0" alt="clip_image017" src="http://images.cnblogs.com/cnblogs_com/javazjh/201109/201109081829213496.gif" width="463" height="224" /&gt;&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;摄像机移动前 摄像机移动后&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/javazjh/201109/201109081829227989.gif"&gt;&lt;img style="background-image: none; border-right-width: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image018" border="0" alt="clip_image018" src="http://images.cnblogs.com/cnblogs_com/javazjh/201109/201109081829221610.gif" width="43" height="13" /&gt;&lt;/a&gt; 处于视锥中的地形块&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/javazjh/201109/201109081829228055.gif"&gt;&lt;img style="background-image: none; border-right-width: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image019" border="0" alt="clip_image019" src="http://images.cnblogs.com/cnblogs_com/javazjh/201109/201109081829238088.gif" width="43" height="13" /&gt;&lt;/a&gt; 进入视锥的地形块&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/javazjh/201109/201109081829234217.gif"&gt;&lt;img style="background-image: none; border-right-width: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image020" border="0" alt="clip_image020" src="http://images.cnblogs.com/cnblogs_com/javazjh/201109/201109081829244807.gif" width="43" height="15" /&gt;&lt;/a&gt; 离开视锥的地形块&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;图&lt;/strong&gt;&lt;strong&gt;11.&lt;/strong&gt; 分块地形更新&lt;/p&gt;&#xD;
&lt;p&gt;通过上图发现，我们的地形分块更新策略与过往策略相比，我们能够充分利用GPU，我们的策略通过地形分块视锥判断，只对分块地形中刚进入视锥范围，离开视锥范围，以及细节层次需要较大变动的地形块进行处理，进行细节层次简化和顶点索引缓冲组织，并把这些缓冲加载到Video Memory中，确保显存中的前端部分对应大量较小改变的相对静态的存有分块地形顶点数据的Vertex Buffer。&lt;/p&gt;&#xD;
&lt;p&gt;传统的地形更新方法每帧都需要遍历一次所有的地形块以确定哪些块进入了视锥范围，哪些离开了，实际上，活动地形块集合（所有处于视锥范围内的地形块的总和）的变化速度是很慢的，除非用户有大幅度的镜头移动动作，否则对于超大规模地形场景而言，地形块集合甚至有可能在很长一段时间都不需要更新。近年来，有不少学者提出了多线程模型下的地形策略，本文在此基础上作了改进，充分利用.net的异步回调机制，提出了一种新的多线程更新模式。另一方面，传统的更新方法，在地形数据加载和释放的瞬间由于运算量的大幅增加，会占用大量时间，出现迟滞现象，使画面在加载或释放数据的时间内得不到渲染。我们的更新方法考虑到.net framework 2.0的自动内存回收服务，可使托管内存堆中没有引用的资源在后台自动缓慢回收，避免了瞬时更新或回收大量内存资源带来的渲染迟滞。因此，需要把需要加载或释放的数据分成几部分，每加载一部分，就交出控制权给系统，以分配更多的处理时间给其它线程，以使更新数据的同时仍然能够保持画面的连续性。&lt;/p&gt;&#xD;
&lt;p&gt;2.3 下层动态可变四叉树&lt;/p&gt;&#xD;
&lt;p&gt;对于处于视锥范围内的每个Block，分别构建动态可变四叉树，采取广度遍历，利用.net framework 2.0新提供的泛型队列（Collections.Generics.Queue &amp;lt; QuadtreeNode &amp;gt;)实现四叉树遍历。首先，我们建立一个QuadtreeNode结构，用以记录每个节点的信息。然后，我们使用两个队列current_queue 和 next_queue进行遍历，一个队列记录当前已遍历的节点，另一个队列则保存由已遍历节点生成的新节点。当处理某层节点的时候，我们先清空next_queue，再依次对current_queue的节点进行判断，如果当前节点在视锥之外，则可直接丢弃；如果当前节点在视锥之内且达到精度要求，则送入渲染；否则将节点分割成四个子节点，送入next_queue。&lt;/p&gt;&#xD;
&lt;p&gt;3 泛型哈希表节点标记策略&lt;/p&gt;&#xD;
&lt;p&gt;对于多分辨率地形，往往需要对于每一个节点记录很多情况，例如：四条边是否存在裂缝，当前节点是否被渲染了，子节点是否存在，子节点是否需要进行视锥剔除等等。这些情况过去比较常见的处理方法就是直接在节点数据结构里添加成员，如谭兵等提出的DEM四叉树节点数据结构就包含4个裂缝标记[19]，采用这种方法需要每个节点都开辟一定的内存空间来存放这些布尔型的标记变量，并且节点四叉树如果在渲染时动态建立计算判断裂缝存在会消耗大量时间，如果在一开始就建立静态的全四叉树对于超大规模场景会消耗极大内存，并且如果对于分块地形，如果当前的活动地形块不止一个，不能处理两个相邻节点分别处在不同地形块所产生的裂缝，由此可见直接在树结构节点记录标记并不是最合适的方法。&lt;/p&gt;&#xD;
&lt;p&gt;潘李亮提出了采用二维的标记数组来记录这些如裂缝是否存在这样的状态变量。对于这种方法，首先创建一个跟场景一样大的M&amp;#215;N的二维数组，用布尔值true或者false记录节点的状态。如图12所示，节点中的9个顶点均对应场景中的一个位置，也对应标记数组的一个元素，可以用节点中心点对应的标记数组元素记录节点是否已经被渲染，用节点四边界点对应标记数组元素记录节点边界是否存在裂缝，或者裂缝是否已经被消除这样的布尔型值。使用标记数组可以很容易解决相邻节点处于不同地形块中的裂缝问题，然而它同样会消耗大量的内存空间。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/javazjh/201109/201109081829247315.gif"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image021" border="0" alt="clip_image021" src="http://images.cnblogs.com/cnblogs_com/javazjh/201109/201109081829247872.gif" width="187" height="193" /&gt;&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;图&lt;/strong&gt;&lt;strong&gt;12.&lt;/strong&gt; 标记数组&lt;/p&gt;&#xD;
&lt;p&gt;本文提出泛型哈希表代替二维标记数组，成功地解决了标记数组大内存消耗量的问题。使用VS.net2005 FrameWork2.0最新提供的泛型数据结构，结合大规模地形的节点情况，我们采用了Hashtable&amp;lt;long,mark&amp;gt;。Hashtable&amp;lt;long,mark&amp;gt;是一个&amp;#8220;键－值&amp;#8221;对的集合，它里面每一个元素都有一个键（key）值和一个数据值（Value）。&lt;/p&gt;&#xD;
&lt;p&gt;key为节点(x,y)，sizex为场景横向大小，作为哈希表的长度，&lt;a href="http://images.cnblogs.com/cnblogs_com/javazjh/201109/20110908182924380.gif"&gt;&lt;img style="background-image: none; border-right-width: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image023" border="0" alt="clip_image023" src="http://images.cnblogs.com/cnblogs_com/javazjh/201109/201109081829242888.gif" width="240" height="17" /&gt;&lt;/a&gt;，获取key的哈希值。&lt;/p&gt;&#xD;
&lt;p&gt;Value标记值可以是布尔型，也可以是其它基本数据类型或枚举，以位向量的形式把各种标记组合起来。在本文工作中，我们定义了一个枚举来指定位的设置，清零，探测，如下：&lt;/p&gt;&#xD;
&lt;p&gt;Enum NodeFlag&lt;/p&gt;&#xD;
&lt;p&gt;{&lt;/p&gt;&#xD;
&lt;p&gt;Rendered=2 //节点是否已经被渲染了&lt;/p&gt;&#xD;
&lt;p&gt;Divided=4 //节点是否已经被分割为4个子节点&lt;/p&gt;&#xD;
&lt;p&gt;Can_be_divided=8//节点能够被分割&lt;/p&gt;&#xD;
&lt;p&gt;Disabled=16 //节点被禁用了&lt;/p&gt;&#xD;
&lt;p&gt;&amp;#8230;&amp;#8230;&lt;/p&gt;&#xD;
&lt;p&gt;}&lt;/p&gt;&#xD;
&lt;p&gt;泛型Hashtable&amp;lt;long,mark&amp;gt;是一种与传统的哈希表完全不同的技术，称为二度哈希（rehasing，也有称其为双精度哈希double hashing）。其工作原理如下：首先定义一个包含多个哈希函数的（H&lt;sub&gt;1&lt;/sub&gt;，H&lt;sub&gt;2&lt;/sub&gt;，&amp;#8230;，H&lt;sub&gt;n&lt;/sub&gt;）的集合，当我们要从哈希表中添加或获取元素时，首先用H&lt;sub&gt;1&lt;/sub&gt;；如果产生冲突，则尝试H&lt;sub&gt;2&lt;/sub&gt;，&amp;#8230;，一直到H&lt;sub&gt;n&lt;/sub&gt;。各个哈希函数基本相似，只是选用不同的乘法因子，如式3-1。&lt;/p&gt;&#xD;
&lt;p&gt;在检索时候，二度哈希执行了sizex次挖掘，表中的每一个位置都要有且仅有一次访问，即，对于给定的key，对哈希表中的同一位置不会同时使用H&lt;sub&gt;i&lt;/sub&gt;和H&lt;sub&gt;j&lt;/sub&gt;。而且，保证1 + (((GetRehash(key) &amp;gt;&amp;gt; 5) + 1) % (sizex &amp;#8211; 1))与sizex互为素数。这样，使用二度哈希的策略，既避免了冲突，又提高了检索效率。&lt;/p&gt;&#xD;
&lt;p&gt;此外，哈希表为我们提供了在速度与内存消耗之间调整的初始化变量值，哈希表构造函数中的加载因子指示了元素与存储桶的最大比率。加载因子越大，哈希表越密集，空间越小，对于我们的超大规模场景标记越是有利。理论上，加载因子1.0是速度和大小之间的最佳平衡，但是，微软认为加载因子的最佳值为0.72，和.net framework1.1不同，.net framework2.0即是使用1.0作为加载因子，系统也会将其转变为0.72，因此，我们直接使用0.72, 当实际加载因子达到此加载因子时，存储桶的数目自动增加到比当前存储桶数大两倍的最小质数。如果不做精度上的严格要求，当发生冲突时,挖掘操作的预期次数为1/(1-lf)(lf为LoadFactor)，取lf=0.72即为3.5。&lt;/p&gt;&#xD;
&lt;p&gt;二维标记数组与哈希表相比在具体实现细节上并不需要象哈希表一样在分类的存储桶中查找对象元素，从某个角度上看二维数组可以看作是m&amp;#215;n 个储存桶，每个储存桶对应同集同义词，速度显然比哈希表快，然而这样每个储存桶只存放一个数据或者甚至没有数据（该坐标位置对应点并没有需要标记的状态）大大消耗了很大内存，而且对与超大规模场景来说，使用超大范围下限的二维数组无论在访问或者清空整个数组来说都是需要很大的工程量。而哈希表由于灵活的储存桶方式，能够通过动态调整加载因子在速度和内存消耗上调整到一个合理的平衡位置。&lt;/p&gt;&#xD;
&lt;p&gt;除此之外，由于二维标记数组内存空间位置的固定性，当摄像机镜头发生大幅移动时，当前活动的Block发生改变，沽空了大量非活动Block数据对应的位置标记，形成了大面积的内存断片状待回收空间，使.net framework的GC自动垃圾回收线程服务带来了非常巨大的压力，容易产生视觉延迟和图像不稳定，而哈希表分桶存储的特点使得随着摄像机的移动，能够动态地从哈希表中删除远离摄像机的标记，有效地回收存储空间，尽可能的避免冲突。经过我们的实验验证，尽管仍然有冲突存在，但基本控制在本策略容忍的范围内。&lt;/p&gt;&#xD;
&lt;p&gt;E1不同的节点标记方法对比实验&lt;/p&gt;&#xD;
&lt;p&gt;前文提及了三种不同的多分辨率地形节点标记方法：二维标记数组，哈希表，节点数据结构添加标记成员。我们就这三种方法在不同的地形场景大小下进行了比较。实验时采用第三种优化后的视锥剔除方法，测试场景地形起伏平缓，地形静态误差对图形贡献度的影响足够小，多纹理通道下地形纹理和细节纹理同时渲染，实验时每帧分10次共渲染约10000个三角形，不进行帧约束，为了保证摄像机位置对帧速的影响足够小，摄像机位置在不同场景载入后置场景中心位置上方。改变节点标记方法时，不改变场景中其它参数。实验时，在不同场景大小，通过改变标记方法，观察FPS值的变化，比较各种标记方法对于不同大小场景的优异。下表给出了我们实验的数据，表中数据单元格中的数值表示该格对应状态下的FPS值。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;表&lt;/strong&gt;&lt;strong&gt;7.&lt;/strong&gt; 各种标记策略对比 &#xD;
&lt;table border="1" cellspacing="0" cellpadding="0"&gt;&#xD;
&lt;tbody&gt;&#xD;
&lt;tr&gt;&#xD;
&lt;td valign="top" width="14%"&gt;&#xD;
&lt;p&gt;场景&lt;/p&gt;&#xD;
&lt;p&gt;大小&lt;/p&gt;&#xD;
&lt;p&gt;(数据点)&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td valign="top" width="17%"&gt;&#xD;
&lt;p&gt;标记&lt;/p&gt;&#xD;
&lt;p&gt;数组&lt;/p&gt;&#xD;
&lt;p&gt;(FPS)&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td valign="top" width="51%"&gt;&#xD;
&lt;p&gt;哈希表&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td valign="top" width="17%"&gt;&#xD;
&lt;p&gt;节点数据结构添加标记成员(FPS)&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&#xD;
&lt;tr&gt;&#xD;
&lt;td valign="top" width="17%"&gt;&#xD;
&lt;p&gt;加载&lt;/p&gt;&#xD;
&lt;p&gt;因子&lt;/p&gt;&#xD;
&lt;p&gt;0.5&lt;/p&gt;&#xD;
&lt;p&gt;(FPS)&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td valign="top" width="17%"&gt;&#xD;
&lt;p&gt;加载&lt;/p&gt;&#xD;
&lt;p&gt;因子&lt;/p&gt;&#xD;
&lt;p&gt;0.72&lt;/p&gt;&#xD;
&lt;p&gt;(FPS)&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td valign="top" width="17%"&gt;&#xD;
&lt;p&gt;加载&lt;/p&gt;&#xD;
&lt;p&gt;因子&lt;/p&gt;&#xD;
&lt;p&gt;2.0&lt;/p&gt;&#xD;
&lt;p&gt;(FPS)&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&#xD;
&lt;tr&gt;&#xD;
&lt;td valign="top" width="14%"&gt;&#xD;
&lt;p&gt;&lt;a name="_Hlk100839517"&gt;256&lt;sup&gt;2&lt;/sup&gt;&lt;/a&gt;&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td valign="top" width="17%"&gt;&#xD;
&lt;p&gt;105.3&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td valign="top" width="17%"&gt;&#xD;
&lt;p&gt;99.7&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td valign="top" width="17%"&gt;&#xD;
&lt;p&gt;96.6&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td valign="top" width="17%"&gt;&#xD;
&lt;p&gt;88.4&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td valign="top" width="17%"&gt;&#xD;
&lt;p&gt;82.6&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&#xD;
&lt;tr&gt;&#xD;
&lt;td valign="top" width="14%"&gt;&#xD;
&lt;p&gt;512&lt;sup&gt;2&lt;/sup&gt;&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td valign="top" width="17%"&gt;&#xD;
&lt;p&gt;102.2&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td valign="top" width="17%"&gt;&#xD;
&lt;p&gt;97.2&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td valign="top" width="17%"&gt;&#xD;
&lt;p&gt;96.0&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td valign="top" width="17%"&gt;&#xD;
&lt;p&gt;87.1&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td valign="top" width="17%"&gt;&#xD;
&lt;p&gt;81.5&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&#xD;
&lt;tr&gt;&#xD;
&lt;td valign="top" width="14%"&gt;&#xD;
&lt;p&gt;1024&lt;sup&gt;2&lt;/sup&gt;&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td valign="top" width="17%"&gt;&#xD;
&lt;p&gt;99.8&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td valign="top" width="17%"&gt;&#xD;
&lt;p&gt;95.4&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td valign="top" width="17%"&gt;&#xD;
&lt;p&gt;95.5&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td valign="top" width="17%"&gt;&#xD;
&lt;p&gt;84.6&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td valign="top" width="17%"&gt;&#xD;
&lt;p&gt;80.2&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&#xD;
&lt;tr&gt;&#xD;
&lt;td valign="top" width="14%"&gt;&#xD;
&lt;p&gt;2048&lt;sup&gt;2&lt;/sup&gt;&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td valign="top" width="17%"&gt;&#xD;
&lt;p&gt;97,6&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td valign="top" width="17%"&gt;&#xD;
&lt;p&gt;94.3&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td valign="top" width="17%"&gt;&#xD;
&lt;p&gt;95.2&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td valign="top" width="17%"&gt;&#xD;
&lt;p&gt;83.5&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td valign="top" width="17%"&gt;&#xD;
&lt;p&gt;76.8&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&#xD;
&lt;tr&gt;&#xD;
&lt;td valign="top" width="14%"&gt;&#xD;
&lt;p&gt;4096&lt;sup&gt;2&lt;/sup&gt;&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td valign="top" width="17%"&gt;&#xD;
&lt;p&gt;94.4&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td valign="top" width="17%"&gt;&#xD;
&lt;p&gt;93.2&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td valign="top" width="17%"&gt;&#xD;
&lt;p&gt;94.7&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td valign="top" width="17%"&gt;&#xD;
&lt;p&gt;82.2&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td valign="top" width="17%"&gt;&#xD;
&lt;p&gt;74.4&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&#xD;
&lt;tr&gt;&#xD;
&lt;td valign="top" width="14%"&gt;&#xD;
&lt;p&gt;8192&lt;sup&gt;2&lt;/sup&gt;&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td valign="top" width="17%"&gt;&#xD;
&lt;p&gt;89.6&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td valign="top" width="17%"&gt;&#xD;
&lt;p&gt;90.2&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td valign="top" width="17%"&gt;&#xD;
&lt;p&gt;92.2&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td valign="top" width="17%"&gt;&#xD;
&lt;p&gt;79.5&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td valign="top" width="17%"&gt;&#xD;
&lt;p&gt;72.5&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&#xD;
&lt;tr&gt;&#xD;
&lt;td valign="top" width="14%"&gt;&#xD;
&lt;p&gt;16384&lt;sup&gt;2&lt;/sup&gt;&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td valign="top" width="17%"&gt;&#xD;
&lt;p&gt;76.2&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td valign="top" width="17%"&gt;&#xD;
&lt;p&gt;84.4&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td valign="top" width="17%"&gt;&#xD;
&lt;p&gt;89.9&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td valign="top" width="17%"&gt;&#xD;
&lt;p&gt;77.0&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td valign="top" width="17%"&gt;&#xD;
&lt;p&gt;70.2&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&#xD;
&lt;tr&gt;&#xD;
&lt;td valign="top" width="14%"&gt;&#xD;
&lt;p&gt;65536&lt;sup&gt;2&lt;/sup&gt;&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td valign="top" width="17%"&gt;&#xD;
&lt;p&gt;59.8&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td valign="top" width="17%"&gt;&#xD;
&lt;p&gt;66.6&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td valign="top" width="17%"&gt;&#xD;
&lt;p&gt;78.8&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td valign="top" width="17%"&gt;&#xD;
&lt;p&gt;71.5&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td valign="top" width="17%"&gt;&#xD;
&lt;p&gt;61.6&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/p&gt;&#xD;
&lt;p&gt;从上表可以看出，标记数组由于其只需要根据索引坐标获取对应的二维数组元素查找速度相当快，但是消耗大量的内存。而节点数据结构直接添加标记成员方法耗内存小，但需要花费相当多时间进行遍历和查找节点状态。而哈希表正是介于两者之间，能够通过加载因子在查找速度和内存消耗之间调整。对于小的场景来说，场景小，标记数量不多，消耗的内存也不多，显然标记数组的高速查找更体现优势。然而随着场景大小的增加，标记数组需要对应更大的二维数组，消耗越多的内存，每帧清空重置整个数组的时候花费了相当多的时间，哈希表的优势逐渐体现出来。&lt;/p&gt;&#xD;
&lt;p&gt;我们通过实验发现，对于大小在4097&amp;#215;4097以下的场景，二维数组比哈希表快，在256&amp;#215;256场景中，二维数组快出差不多10帧每秒，而当场景大小超过4097&amp;#215;4097，哈希表的优势逐渐显现。在我们实验的Puget Sound场景中比二维数组快出了20多帧每秒。由此可见，当使用哈希表进行节点标记，并且加载因子处在1.0的最佳速度和内存大小平衡状态下，对于大于4096&amp;#215;4096大小的场景能取得较快的速度，基于哈系表的节点状态标记策略是目前大规模场景节点状态标记的一个最优策略。&lt;/p&gt;&#xD;
&lt;p&gt;4、LOD评价因子&lt;/p&gt;&#xD;
&lt;p&gt;通常在进行地形的LOD简化过程中，用以下两个因素作为衡量标准，一是动态因素，常通过计算待渲染节点经过投影后在屏幕的大小或节点到摄像机的距离来表示。二是静态因素，也就是地表粗糙程度以及地形的起伏程度。地形起伏的程度越厉害，需要的层次细节精度越高，地形起伏的程度越小，需要的层次细节精度越低，渲染较小的三角形就可以近似表达了。&lt;/p&gt;&#xD;
&lt;p&gt;4.1 节点静态因素的评价&lt;/p&gt;&#xD;
&lt;p&gt;节点的静态因素定义为一个能够准确衡量节点LOD程度的一个指标，直接影响着地形细节层次简化的效果。计算节点的静态因素到目前已经有比较多的方法，如谭兵等提出的评价误差平面方法等。通常对于基于二叉树的节点，只需要简单计算该节点继续细分与无细分相差的插值误差。&lt;/p&gt;&#xD;
&lt;p&gt;而对于四叉树则需要考虑更多的因素，潘李亮提出取以下各值的最大值为静态因素参考值：四边界插值误差值，两条对角线插值误差值，以及四个子节点最大误差值的一半（另一些学者认为应直接取四个子节点的最大误差）。这种计算方法中取四个子节点最大误差的方法相当直接快捷，但没有理论依据，并不符合节点几何形状。地形的静态因素是在地形生成过程中计算，属于预处理阶段，并不需要在渲染时每帧计算一遍，因此计算的复杂程度并不会影响渲染效果，并不需要进行任何粗略或者近似的计算。&lt;/p&gt;&#xD;
&lt;p&gt;本文采用了一种基于四叉树的静态因素评价方法。取（P&lt;sub&gt;1&lt;/sub&gt;,P&lt;sub&gt;2&lt;/sub&gt;,P&lt;sub&gt;3&lt;/sub&gt;,P&lt;sub&gt;4&lt;/sub&gt;,A&lt;sub&gt;1&lt;/sub&gt;,A&lt;sub&gt;2&lt;/sub&gt;,A&lt;sub&gt;3&lt;/sub&gt;,A&lt;sub&gt;4&lt;/sub&gt;,C&lt;sub&gt;5&lt;/sub&gt;&amp;#215;2）10个误差中的最大误差为参考值，与上述方法相同首先需要计算四边界插值误差和两对角线插值误差，只是后四个误差不再简单地取四个子节点误差的某个倍数，我们以图7为例说明如何精确地求这4个误差。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;图&lt;/strong&gt;&lt;strong&gt;13.&lt;/strong&gt; 节点静态因素计算&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/javazjh/201109/201109081829249856.gif"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image024" border="0" alt="clip_image024" src="http://images.cnblogs.com/cnblogs_com/javazjh/201109/20110908182924413.gif" width="325" height="309" /&gt;&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;假设A&lt;sub&gt;1&lt;/sub&gt;,A&lt;sub&gt;2&lt;/sub&gt;,A&lt;sub&gt;3&lt;/sub&gt;,A&lt;sub&gt;4&lt;/sub&gt;四个子节点的静态误差已经求出，我们先把A&lt;sub&gt;1&lt;/sub&gt;的静态误差值赋予A&lt;sub&gt;1&lt;/sub&gt;节点的四个角点C&lt;sub&gt;1&lt;/sub&gt;,P&lt;sub&gt;2&lt;/sub&gt;,P&lt;sub&gt;1&lt;/sub&gt;,C&lt;sub&gt;5&lt;/sub&gt;，同理A&lt;sub&gt;2&lt;/sub&gt;，A&lt;sub&gt;3&lt;/sub&gt;,A&lt;sub&gt;4&lt;/sub&gt;的静态误差值均赋予它们的四个角点。P&lt;sub&gt;1&lt;/sub&gt;取A&lt;sub&gt;1&lt;/sub&gt;,A&lt;sub&gt;3&lt;/sub&gt;两个误差值的较大的那个，P&lt;sub&gt;2&lt;/sub&gt;取A&lt;sub&gt;1&lt;/sub&gt;,A&lt;sub&gt;2&lt;/sub&gt;大的一个，同理P&lt;sub&gt;3&lt;/sub&gt;,P&lt;sub&gt;4&lt;/sub&gt;均取关联的两个子节点误差值的大者。然后把P&lt;sub&gt;1&lt;/sub&gt;,P&lt;sub&gt;2&lt;/sub&gt;,P&lt;sub&gt;3&lt;/sub&gt;,P&lt;sub&gt;4&lt;/sub&gt;四个点的静态误差值倍乘以一个K，K定义为下式：&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/javazjh/201109/201109081829242921.gif"&gt;&lt;img style="background-image: none; border-right-width: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image026" border="0" alt="clip_image026" src="http://images.cnblogs.com/cnblogs_com/javazjh/201109/201109081829245429.gif" width="92" height="44" /&gt;&lt;/a&gt; （4-1）&lt;/p&gt;&#xD;
&lt;p&gt;其中C&lt;sub&gt;2&lt;/sub&gt;为节点的静态因素控制量，用以调节节点地形起伏陡峭程度对细节层次精度效果的影响。倍乘K之后的四个误差值，以及四条边中点误差值和两条对角线的误差值，取这10个误差值的最大者作为C&lt;sub&gt;5&lt;/sub&gt;该节点的静态误差值。下图说明了静态因素评价的方法。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/javazjh/201109/201109081829244350.gif"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image027" border="0" alt="clip_image027" src="http://images.cnblogs.com/cnblogs_com/javazjh/201109/201109081829252954.gif" width="427" height="233" /&gt;&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/javazjh/201109/201109081829251874.gif"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image028" border="0" alt="clip_image028" src="http://images.cnblogs.com/cnblogs_com/javazjh/201109/201109081829252431.gif" width="252" height="232" /&gt;&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;图&lt;/strong&gt;&lt;strong&gt;14.&lt;/strong&gt; 节点静态因素计算&lt;/p&gt;&#xD;
&lt;p&gt;从上面可见，要求出C&lt;sub&gt;5&lt;/sub&gt;的最大静态误差值必须先计算出A&lt;sub&gt;1&lt;/sub&gt;,A&lt;sub&gt;2&lt;/sub&gt;,A&lt;sub&gt;3&lt;/sub&gt;,A&lt;sub&gt;4&lt;/sub&gt;四个子节点的误差值，可见每一个节点的静态误差都必须先求它的四个子节点的静态误差值，这样一个过程可以迭代实现。&lt;/p&gt;&#xD;
&lt;p&gt;4.2 镜头移动速度&amp;#8212;&amp;#8212;全局的LOD评价因子&lt;/p&gt;&#xD;
&lt;p&gt;在过去一般认为节点到摄像机的距离以及节点的静态因素（起伏陡峭程度）以及节点的大小是考虑是否需要继续对该节点进行LOD简化的重要选择尺度，然而考虑这些因素并不充分，因为我们镜头的运动速度也会对屏幕渲染效果产生重要影响，因此评估一个节点对屏幕效果的贡献度应该考虑上镜头移动速度这样一个因素。&lt;/p&gt;&#xD;
&lt;p&gt;在本文中，我们将探讨一个全局的LOD评价因子&amp;#8212;&amp;#8212;镜头移动速度（待渲染节点的模糊程度）。相比之下，镜头移动速度作为一个因子比其它选择尺度并没那么重要，但它确确实实影响了渲染效果。当我们的镜头移动速度越快的时候，看到的景象越模糊，节点需要达到的精度越低，当我们镜头移动速度越慢的时候，看到的景象越清晰，节点需要达到的精度越高。因此，镜头移动速度是一个全局的LOD选择尺度,它是保持场景漫游平滑度的一个重要调整量。&lt;/p&gt;&#xD;
&lt;p&gt;一般认为通过调节其它几个LOD评价因子可以保持每帧渲染的节点数趋于稳定，然而当我们加入了镜头移动速度这个因子，如果每帧渲染的节点数还保持恒定就不符合实际情况了，因为镜头的快速移动会造成画面模糊，我们渲染的节点的精度都需要一定降低，因此镜头移动速度相对其它LOD评价因子，是一个后期考虑的因素。&lt;/p&gt;&#xD;
&lt;p&gt;镜头移动速度的评估目前还没有成熟的方法，我们初步用了一种方法，计算出前后两帧之间摄像机的位移矢量的大小（移动的距离）作为评价因子。&lt;/p&gt;&#xD;
&lt;p&gt;4.3 综合节点评价函数&lt;/p&gt;&#xD;
&lt;p&gt;综合考虑节点静态因素和节点到屏幕距离以及节点大小、摄像机移动速度这几个LOD评价因子，在[Rotter98]等工作的基础上，经过对各种可能情况的组合对比实验，选择最优实验结果，我们得到以下的节点评价公式：&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/javazjh/201109/201109081829254939.gif"&gt;&lt;img style="background-image: none; border-right-width: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image030" border="0" alt="clip_image030" src="http://images.cnblogs.com/cnblogs_com/javazjh/201109/201109081829257447.gif" width="240" height="52" /&gt;&lt;/a&gt; （3-2）&lt;/p&gt;&#xD;
&lt;p&gt;&lt;em&gt;&lt;/em&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;em&gt;L&lt;/em&gt;为节点到摄像机的距离，&lt;em&gt;v&lt;/em&gt;为镜头移动速度，&lt;em&gt;d&lt;/em&gt;为节点大小（节点宽度），&lt;em&gt;d&lt;/em&gt;&lt;em&gt;&lt;sub&gt;2&lt;/sub&gt;&lt;/em&gt;为节点的静态误差（节点地形起伏陡峭程度），&lt;em&gt;C&lt;/em&gt;&lt;em&gt;&lt;sub&gt;1&lt;/sub&gt;&lt;/em&gt;为节点的动态误差控制阙值，用以调节节点到摄像机距离对LOD节点屏幕贡献度的影响，&lt;em&gt;C&lt;/em&gt;&lt;em&gt;&lt;sub&gt;2&lt;/sub&gt;&lt;/em&gt;为节点的地形起伏程度对LOD屏幕贡献度控制阙值，&lt;em&gt;C&lt;/em&gt;&lt;em&gt;&lt;sub&gt;3&lt;/sub&gt;&lt;/em&gt;为摄像机移动速度对LOD节点屏幕贡献度控制阙值。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/javazjh/201109/201109081829251384.gif"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image032" border="0" alt="clip_image032" src="http://images.cnblogs.com/cnblogs_com/javazjh/201109/201109081829252497.gif" width="517" height="379" /&gt;&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/javazjh/201109/201109081829268385.gif"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image034" border="0" alt="clip_image034" src="http://images.cnblogs.com/cnblogs_com/javazjh/201109/201109081829269498.gif" width="514" height="409" /&gt;&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;图&lt;/strong&gt;&lt;strong&gt;15.&lt;/strong&gt; 各LOD因素评价示意&lt;/p&gt;&#xD;
&lt;p&gt;5、基于Triangle List的累积渲染&lt;/p&gt;&#xD;
&lt;p&gt;Direct3D为我们提供了六种图元类型，如下表。其中在地形渲染中常用的是后三种。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;表&lt;/strong&gt;&lt;strong&gt;8.&lt;/strong&gt; 各种三角形渲染模式 &#xD;
&lt;table border="1" cellspacing="0" cellpadding="0"&gt;&#xD;
&lt;tbody&gt;&#xD;
&lt;tr&gt;&#xD;
&lt;td valign="top" width="170"&gt;&#xD;
&lt;p&gt;PointList&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td valign="top" width="170"&gt;&#xD;
&lt;p&gt;表示一系列离散的点&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&#xD;
&lt;tr&gt;&#xD;
&lt;td valign="top" width="170"&gt;&#xD;
&lt;p&gt;LineList&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td valign="top" width="170"&gt;&#xD;
&lt;p&gt;表示一系列离散的线段集合&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&#xD;
&lt;tr&gt;&#xD;
&lt;td valign="top" width="170"&gt;&#xD;
&lt;p&gt;LineStrip&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td valign="top" width="170"&gt;&#xD;
&lt;p&gt;表示连续的折线段&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&#xD;
&lt;tr&gt;&#xD;
&lt;td valign="top" width="170"&gt;&#xD;
&lt;p&gt;TrangleList&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td valign="top" width="170"&gt;&#xD;
&lt;p&gt;表示一系列离散的三角形集合。每三个顶点绘制一个单独的三角形，该种方法常常和顶点索引配合使用。&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&#xD;
&lt;tr&gt;&#xD;
&lt;td valign="top" width="170"&gt;&#xD;
&lt;p&gt;TrangleStrip&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td valign="top" width="170"&gt;&#xD;
&lt;p&gt;三角形带是一系列相连的三角形，每两个相邻的三角形共享两个顶点。常用于复杂Mesh&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&#xD;
&lt;tr&gt;&#xD;
&lt;td valign="top" width="170"&gt;&#xD;
&lt;p&gt;TrangleFan&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td valign="top" width="170"&gt;&#xD;
&lt;p&gt;表示扇形组织的三角形集合，与三角形带相似，每个集合中的所有的三角形都共享一个中心顶点。&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/javazjh/201109/2011090818292655.gif"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image035" border="0" alt="clip_image035" src="http://images.cnblogs.com/cnblogs_com/javazjh/201109/201109081829268975.gif" width="470" height="184" /&gt;&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;a . Triangle Lists&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/javazjh/201109/201109081829269531.gif"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image036" border="0" alt="clip_image036" src="http://images.cnblogs.com/cnblogs_com/javazjh/201109/2011090818292688.gif" width="432" height="232" /&gt;&lt;/a&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/javazjh/201109/201109081829269008.gif"&gt;&lt;img style="background-image: none; border-right-width: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image037" border="0" alt="clip_image037" src="http://images.cnblogs.com/cnblogs_com/javazjh/201109/201109081829261516.gif" width="240" height="127" /&gt;&lt;/a&gt;b. Triangle Strips&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/javazjh/201109/201109081829262072.gif"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image038" border="0" alt="clip_image038" src="http://images.cnblogs.com/cnblogs_com/javazjh/201109/201109081829275137.gif" width="395" height="306" /&gt;&lt;/a&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/javazjh/201109/201109081829278517.gif"&gt;&lt;img style="background-image: none; border-right-width: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image039" border="0" alt="clip_image039" src="http://images.cnblogs.com/cnblogs_com/javazjh/201109/201109081829279074.gif" width="240" height="185" /&gt;&lt;/a&gt;图c Triangle Fans&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;图&lt;/strong&gt;&lt;strong&gt;16.&lt;/strong&gt; DirectX 9.0提供的后三种图元&lt;/p&gt;&#xD;
&lt;p&gt;我们以一个四叉树节点为例，比较后三种以三角形形式组织的图元类型在地形渲染上的差别。一个四叉树节点包含9个顶点，我们的目标是以最快的速度把这9个顶点连接的三角形渲染出来。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/javazjh/201109/201109081829277994.gif"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image040" border="0" alt="clip_image040" src="http://images.cnblogs.com/cnblogs_com/javazjh/201109/201109081829278550.gif" width="423" height="120" /&gt;&lt;/a&gt;Triangle Lists Triangle Strips Triangle Fans&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;图&lt;/strong&gt;&lt;strong&gt;17.&lt;/strong&gt; 单个四叉树节点在三种不同图元类型下对比&lt;/p&gt;&#xD;
&lt;p&gt;从上面三个图可以很容易看出对于单个四叉树，需要渲染的三角形数目是一样的，Triangle Lists以集合的形式通过索引把一个个的三角形组合到一起，然后一次全部渲染；Triangle Strips以三角形链形式组织，需要分两次渲染；而Triangle Fans以扇形形式组织，同样只需要一次即可，并且可以不使用索引。单从一个节点考虑，并不能容易看出三种模式在树结构地形渲染中的优缺。&lt;/p&gt;&#xD;
&lt;p&gt;注：也可以用Triangle Lists按扇形形式把三角形组合起来渲染，但组织相对不如直接用Triangle Lists简单&lt;/p&gt;&#xD;
&lt;p&gt;接下来考虑大面积多个节点的情况，以2&amp;#215;2个连续同细节层次级别的节点地形为例。三种图元类型组织如图11&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/javazjh/201109/201109081829272695.gif"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image041" border="0" alt="clip_image041" src="http://images.cnblogs.com/cnblogs_com/javazjh/201109/201109081829276075.gif" width="445" height="139" /&gt;&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;Triangle Lists Triangle Strips Triangle Fans&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;图&lt;/strong&gt;&lt;strong&gt;18.&lt;/strong&gt; 2&amp;#215;2四叉树节点在三种不同图元类型下对比&lt;/p&gt;&#xD;
&lt;p&gt;三种图元类型需要渲染的三角形数是相等的，但是Triangle Lists只调用了一次渲染三角形的函数，而Triangle Strips有多少行三角形带就至少需要调用多少遍，对于2&amp;#215;2的地形块（如图11中）调用了4次，而Triangle Fans有多少个节点就需要调用多少次渲染函数, 对于2&amp;#215;2的地形（如图11右）共有4个节点因此共调用了4次。由此可见Triangle Lists随着节点的增多并不需要频繁增加调用渲染函数的次数。&lt;/p&gt;&#xD;
&lt;p&gt;在大量顶点的场景中，如果单纯使用顶点缓冲，很可能有大量的顶点重复添加到顶点缓冲中。比如说对于一个立方体，如果纯粹以顶点形式组织，我们需要创建36个顶点。实际上，我们只涉及8个不同的顶点而已，即立方体的8个顶点。对于小量顶点而言，没有什么区别，但是对于存在大量三角形的程序，减少重复顶点来节约空间就显得很重要了。Direct3D8之后都为我们提供了索引缓冲的机制让我们以索引形式组织三角形，避免顶点重复添加到顶点缓冲。&lt;/p&gt;&#xD;
&lt;p&gt;过往许多文献都认为triangle strip组织更有优势，认为在三角形带组织过程中三角形带可以把边界连续的三角形顶点共享，减少顶点缓冲中顶点数目，然而对地形节点而已，地形节点的细节层次确定后，顶点数目就基本一致，在无需处理边界裂缝改变节点拓扑关系的情况下，每个节点的顶点数目都是8个，对于每个分块地形，去除顶点缓冲中重复的顶点后，顶点数目是一致的。因此无论triangle List，triangle strip还是triangle fan顶点缓冲中顶点数目是基本一致的，交给GPU vertex shader进行顶点变换的顶点数目是一致的，差别只在于triangle strip索引数目相对triangle List要少，而每个索引只占16bit的存储空间相对每个顶点占200多bit的&lt;/p&gt;&#xD;
&lt;p&gt;// 48+64+32+32=176&amp;lt;192&lt;/p&gt;&#xD;
&lt;p&gt;Structure CustomVertex&lt;/p&gt;&#xD;
&lt;p&gt;{&lt;/p&gt;&#xD;
&lt;p&gt;//{float x, float y, float z}48bit&lt;/p&gt;&#xD;
&lt;p&gt;D3DVector3 Position;&lt;/p&gt;&#xD;
&lt;p&gt;//{float r, float g, float b,float z}64bit&lt;/p&gt;&#xD;
&lt;p&gt;D3DRGBAColor Diffuse;&lt;/p&gt;&#xD;
&lt;p&gt;// {float tv1 ,float tu1}24bit&lt;/p&gt;&#xD;
&lt;p&gt;D3DVector2 Texture1;&lt;/p&gt;&#xD;
&lt;p&gt;// {float tv2 ,float tu2}24bit&lt;/p&gt;&#xD;
&lt;p&gt;D3DVector2 Texture2;&lt;/p&gt;&#xD;
&lt;p&gt;}&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/javazjh/201109/201109081829281092.gif"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image042" border="0" alt="clip_image042" src="http://images.cnblogs.com/cnblogs_com/javazjh/201109/201109081829286108.gif" width="321" height="535" /&gt;&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;注：我们这里假设顶点缓冲了显存初始地址&lt;strong&gt;&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;图&lt;/strong&gt;&lt;strong&gt;19.&lt;/strong&gt; Triangle List节点索引组织方案&lt;/p&gt;&#xD;
&lt;p&gt;在同时使用顶点缓冲和索引缓冲组织三角形时，对于任何地形结点而言，顶点数量是一致的，只是索引数量不同，Triangle Strips和Triangle Fans与纯顶点缓冲情况下相类似，用到的索引数量小了，但是图形接口需要比较多次调用渲染函数，而Triangle Lists虽然用索引数量增加了，但是却大大降低了调用渲染函数次数，很大程度上，使显示设备能够连续地渲染三角形。表9对比了图19所示意对于一个结点在同时使用顶点缓冲和索引缓冲的区别。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;表&lt;/strong&gt;&lt;strong&gt;9.&lt;/strong&gt; 不同节点数量数据对比 &#xD;
&lt;table border="1" cellspacing="0" cellpadding="0"&gt;&#xD;
&lt;tbody&gt;&#xD;
&lt;tr&gt;&#xD;
&lt;td width="32%"&gt;&amp;nbsp;&lt;/td&gt;&#xD;
&lt;td width="15%"&gt;&#xD;
&lt;p&gt;结点数&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td width="15%"&gt;&#xD;
&lt;p&gt;顶点数&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td width="15%"&gt;&#xD;
&lt;p&gt;索引数&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td width="19%"&gt;&#xD;
&lt;p&gt;绘制函数&lt;/p&gt;&#xD;
&lt;p&gt;调用次数&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&#xD;
&lt;tr&gt;&#xD;
&lt;td width="32%"&gt;&#xD;
&lt;p&gt;图5-3所示&lt;/p&gt;&#xD;
&lt;p&gt;Triangle Lists&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td width="15%"&gt;&#xD;
&lt;p&gt;1&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td width="15%"&gt;&#xD;
&lt;p&gt;9&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td width="15%"&gt;&#xD;
&lt;p&gt;24&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td width="19%"&gt;&#xD;
&lt;p&gt;1&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&#xD;
&lt;tr&gt;&#xD;
&lt;td width="32%"&gt;&#xD;
&lt;p&gt;图5-3所示&lt;/p&gt;&#xD;
&lt;p&gt;Triangle Strips&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td width="15%"&gt;&#xD;
&lt;p&gt;1&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td width="15%"&gt;&#xD;
&lt;p&gt;9&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td width="15%"&gt;&#xD;
&lt;p&gt;12&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td width="19%"&gt;&#xD;
&lt;p&gt;2&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&#xD;
&lt;tr&gt;&#xD;
&lt;td width="32%"&gt;&#xD;
&lt;p&gt;图5-3所示&lt;/p&gt;&#xD;
&lt;p&gt;Triangle Fans&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td width="15%"&gt;&#xD;
&lt;p&gt;1&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td width="15%"&gt;&#xD;
&lt;p&gt;9&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td width="15%"&gt;&#xD;
&lt;p&gt;9&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td width="19%"&gt;&#xD;
&lt;p&gt;1&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&#xD;
&lt;tr&gt;&#xD;
&lt;td width="32%"&gt;&#xD;
&lt;p&gt;图5-4所示&lt;/p&gt;&#xD;
&lt;p&gt;Triangle Lists&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td width="15%"&gt;&#xD;
&lt;p&gt;4&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td width="15%"&gt;&#xD;
&lt;p&gt;25&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td width="15%"&gt;&#xD;
&lt;p&gt;96&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td width="19%"&gt;&#xD;
&lt;p&gt;1&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&#xD;
&lt;tr&gt;&#xD;
&lt;td width="32%"&gt;&#xD;
&lt;p&gt;图5-4所示&lt;/p&gt;&#xD;
&lt;p&gt;Triangle Strips&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td width="15%"&gt;&#xD;
&lt;p&gt;4&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td width="15%"&gt;&#xD;
&lt;p&gt;25&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td width="15%"&gt;&#xD;
&lt;p&gt;40&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td width="19%"&gt;&#xD;
&lt;p&gt;4&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&#xD;
&lt;tr&gt;&#xD;
&lt;td width="32%"&gt;&#xD;
&lt;p&gt;图5-4所示&lt;/p&gt;&#xD;
&lt;p&gt;Triangle Fans&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td width="15%"&gt;&#xD;
&lt;p&gt;4&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td width="15%"&gt;&#xD;
&lt;p&gt;25&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td width="15%"&gt;&#xD;
&lt;p&gt;36&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td width="19%"&gt;&#xD;
&lt;p&gt;4&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/p&gt;&#xD;
&lt;p&gt;当前主流的图形显示卡都支持在每一次调用渲染函数时一并渲染多达数万个三角形，显然，对于有大量节点构成的地形来说，采用Triangle Strips或者Triangle Fans是不明智的，而采用Triangle Lists把三角形累积到一定数量再调用渲染函数一并渲染能够最大限度通过Direct3D / OpenGL图形接口利用GPU。&lt;/p&gt;&#xD;
&lt;p&gt;E2每次调用函数渲染三角形数量最优值测定&lt;/p&gt;&#xD;
&lt;p&gt;在每帧的图形渲染上，每次调用渲染函数渲染的三角形数量对整体渲染速度以及FPS值都有着一定的影响，每次调用渲染函数渲染的三角形数量小，需要调用渲染函数的次数相对就增多，花在循环控制运算量上的时间也就多了，渲染的三角形数量多，超出了图形接口的能力就会降低渲染速度，那么每次调用渲染函数渲染多少三焦形是最合适的呢？为了大致测定每次调用渲染函数最优的渲染三角形的数量，我们在FX6500带128M显存的图形卡上进行实验，图形卡支持多通道纹理，支持Direct9.0，支持顶点着色，实验时，为了避免额外运算，以循环形式把设置好顶点缓冲和索引缓冲的三角形交给DrawIndexedPrimitives函数渲染，限定每帧渲染10000个三角形，不约束帧数，实验时只改变每次调用渲染函数时的三角形数量，观察每秒钟渲染的三角形数量的变化以及FPS值的变化。实现时同时使用LOD简化方法。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/javazjh/201109/201109081829284713.gif"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image044" border="0" alt="clip_image044" src="http://images.cnblogs.com/cnblogs_com/javazjh/201109/201109081829297843.gif" width="539" height="285" /&gt;&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;图&lt;/strong&gt;&lt;strong&gt; 20&lt;/strong&gt;. Triangle Lists累积渲染&lt;/p&gt;&#xD;
&lt;p&gt;根据实验证明Direct3D的三角形渲染函数的每次调用处理1000个左右的三角形是最合适的，对于我们的地形场景来说，每帧大约渲染的三角形数稳定在8000－12000左右，也就是说每帧大约要调用渲染函数8－10次。为了保证该经验值的有效性，我们改变每帧渲染的三角形总数量，以及调整API相关的约束帧控制，发现总数量的变化以及受控制的FPS变化对每次调用渲染函数渲染的三角形数目的最优值影响不多，最能影响该经验值的是每帧调用该函数的次数，也就是循环的次数。我们初步认为如下经验值是比较合理的：对于GFMX400以上的显示卡累积约1200至1350个三角形调用一次渲染函数能够达到最大速度，在每帧平均渲染5000－8000个三角形状态下能够比每个节点用Triangle Fans模式渲染FPS（每秒渲染的帧数）值大9－11左右。&lt;/p&gt;&#xD;
&lt;p&gt;由此可见，采用Triangle Lists组织三角形比Triangle Fans组织三角形更具优势，Triangle Lists是三角形的集合，我们只要把三角形累计到一定数量，设置好顶点和索引，一次渲染就可，我们可以明显看出Triangle Fans方式组织对于每一个节点都需要调用一次渲染函数，而Triangle Lists则只有从节点中添加的三角形数量累积到一定数量才渲染，让图形接口一次调用中渲染比较多的三角形，降低GPU和CPU控制权相互转让的时间，降低反复调用渲染函数的时间，同时由于最佳累积量处于1000左右，可以用16位索引，避免了32位索引，降低了传输带宽，充分利用GPU。&lt;/p&gt;&#xD;
&lt;p&gt;6、边界裂缝处理&lt;/p&gt;&#xD;
&lt;p&gt;6.1 基于边界样式的裂缝处理方法&lt;/p&gt;&#xD;
&lt;p&gt;对大规模地形进行细节层次简化时，由于节点的细节层次不同会产生裂缝，如两个相邻的节点，邻近摄像机镜头的节点比另外一个节点可能具有更高分辨率，造成相邻节点细节层次的差异，从而产生裂缝。下图说明了裂缝的产生。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/javazjh/201109/20110908182929352.gif"&gt;&lt;img style="background-image: none; border-right-width: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image046" border="0" alt="clip_image046" src="http://images.cnblogs.com/cnblogs_com/javazjh/201109/201109081829298192.gif" width="156" height="72" /&gt;&lt;/a&gt; &lt;a href="http://images.cnblogs.com/cnblogs_com/javazjh/201109/20110908182929700.gif"&gt;&lt;img style="background-image: none; border-right-width: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image048" border="0" alt="clip_image048" src="http://images.cnblogs.com/cnblogs_com/javazjh/201109/201109081829293209.gif" width="144" height="72" /&gt;&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;图&lt;/strong&gt;&lt;strong&gt; 21&lt;/strong&gt;. 多分辨率LOD模型节点间裂缝&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/javazjh/201109/201109081829297353.gif"&gt;&lt;img style="background-image: none; border-right-width: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image046[1]" border="0" alt="clip_image046[1]" src="http://images.cnblogs.com/cnblogs_com/javazjh/201109/201109081829299861.gif" width="156" height="72" /&gt;&lt;/a&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/javazjh/201109/201109081829293242.gif"&gt;&lt;img style="background-image: none; border-right-width: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image050" border="0" alt="clip_image050" src="http://images.cnblogs.com/cnblogs_com/javazjh/201109/201109081829297386.gif" width="156" height="69" /&gt;&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;图&lt;/strong&gt;&lt;strong&gt; 22&lt;/strong&gt;. 多分辨率LOD模型细节层次切换顶点跃动&lt;/p&gt;&#xD;
&lt;p&gt;裂缝处理方法从大体上可分为两种，一种是在低分辨率的节点添加一条边，另外一种是在高分辨率的节点删掉一条边。边删除方法通过在产生裂缝的边界处删除顶点及该顶点到节点中心点连线以消除相邻节点细节层次差异带来的裂缝。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/javazjh/201109/201109081829307943.gif"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image051" border="0" alt="clip_image051" src="http://images.cnblogs.com/cnblogs_com/javazjh/201109/201109081829301323.gif" width="589" height="140" /&gt;&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;图a 裂缝处理前 图b 裂缝处理后&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;图&lt;/strong&gt;&lt;strong&gt;23.&lt;/strong&gt; 传统的裂缝消除&lt;/p&gt;&#xD;
&lt;p&gt;上图示意了传统的边界裂缝处理方法，图12-a中两个黑点表示该边界上因相邻节点细节层次级别差异带来插值误差裂缝的顶点，图12-b通过删除这两个顶点，及这两个顶点到节点中心点连线消除了裂缝。使用这种消除裂缝方法，通常是采用Triangle Fans模式，因为该模式可以方便地分别判断各边界上是否存在引起裂缝的顶点，存在的话则忽略该顶点，不存在的话则渲染该顶点。然而这种裂缝消除方法不单不适应我们前面Triangle Lists累积三角形渲染策略，还因为合并了二个带来裂缝的三角形而同时降低了裂缝所在边界及节点中心点区域的精度。&lt;/p&gt;&#xD;
&lt;p&gt;上述这些方法都实现了裂缝的消除，但是都并不能够充分利用Direct3D、OpenGL的硬件渲染能力，无论添加边或者删除边或多或少都添加或删除了三角形，并不能够保证每个节点渲染的三角形数目的一致性，对于相邻节点层次相差超过1时处理并无优势。&lt;/p&gt;&#xD;
&lt;p&gt;本文在上述方法的基础上提出了边界样式方法，在删除边界引起插值误差带来裂缝的顶点的同时，不改变节点中心区域精度。通过实验我们发现，实际的场景中出现裂缝时，边界两边的相邻节点细节层次差别一般不会超过3级，因此，我们预先定义的裂缝的边界样式及处理方法，当场景绘制出现裂缝时，直接与预先定义好到的样式尝试匹配，如果裂缝存在情况已被考虑，则可以直接根据已定义的处理方法改变索引，从而消除裂缝。&lt;/p&gt;&#xD;
&lt;p&gt;图14中，我们以4&amp;#215;4的模板、细节层次差别1级为例，给出了16种可能的边界样式，通过裂缝位置匹配确定裂缝的种类。图中灰色区域的三角形表示节点中在消除裂缝的同时精度（分辨率）不变的三角形，而白色区域的三角形表示存在裂缝的边界。我们通过修改，将裂缝边界处的精度（分辨率）降低了1级，最终达到消除裂缝的效果。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/javazjh/201109/201109081829307976.gif"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image052" border="0" alt="clip_image052" src="http://images.cnblogs.com/cnblogs_com/javazjh/201109/201109081829307452.gif" width="418" height="420" /&gt;&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;图&lt;/strong&gt;&lt;strong&gt;24.&lt;/strong&gt;相邻节点细节层次相差1时的16种边界样式&lt;/p&gt;&#xD;
&lt;p&gt;下面两个图中，我们具体给出了裂缝出现的情况和处理方法，包括细节层次差别1级和2级，确定裂缝位置后，根据细节层次差别的不同，确定最终的裂缝处理方案。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/javazjh/201109/201109081829308009.gif"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image053" border="0" alt="clip_image053" src="http://images.cnblogs.com/cnblogs_com/javazjh/201109/201109081829306929.gif" width="196" height="99" /&gt;&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;a. 相邻节点细节层次相差1时的裂缝消除&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/javazjh/201109/201109081829307485.gif"&gt;&lt;img style="background-image: none; border-right-width: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image054" border="0" alt="clip_image054" src="http://images.cnblogs.com/cnblogs_com/javazjh/201109/201109081829314454.gif" width="196" height="99" /&gt;&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;b. 相邻节点细节层次相差2时的裂缝消除&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;图&lt;/strong&gt;&lt;strong&gt;25.&lt;/strong&gt; 边界样式节点裂缝消除&lt;/p&gt;&#xD;
&lt;p&gt;在5.1中，我们论述过索引缓冲渲染机制，显然，在具体组织边界样式过程中，我们无需删除或添加顶点的数目，只需要在用索引组织顶点的时候，先组织中央区域三角形，再考虑各边界裂缝存在情况，如果存在裂缝，则在组织三角形时忽略某些顶点即能顺利消除边界裂缝。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/javazjh/201109/201109081829315566.gif"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image056" border="0" alt="clip_image056" src="http://images.cnblogs.com/cnblogs_com/javazjh/201109/201109081829315915.gif" width="533" height="404" /&gt;&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;图&lt;/strong&gt;&lt;strong&gt;26.&lt;/strong&gt; 边界样式节点裂缝消除&lt;/p&gt;&#xD;
&lt;p&gt;5.3 用插值高程代替实际高程的裂缝消除方法&lt;/p&gt;&#xD;
&lt;p&gt;5.2所提及的方法在边界索引组织时，需要花费一定的时间周期计算和判断边界情况，同时由于三角形的合并，在顶点缓冲中分布着一系列离散的顶点。&lt;/p&gt;&#xD;
&lt;p&gt;本文在相关工作中提到的方法都是在裂缝边界处合并高精度的三角形或者修改高精度三角形的顶点（索引）。这样做有利于保持场景网格的拓扑关系，便于场景的其他绘制时，以三角形为单位的矢量计算。&lt;/p&gt;&#xD;
&lt;p&gt;但如果对光照、地形模型精度等要求不是很高，在地形实时渲染中不需要强调完整的拓扑网格，或者允许面积为零的三角形存在。&lt;/p&gt;&#xD;
&lt;p&gt;本文在此基础上，再提出了一种既不改变顶点缓冲中顶点组织顺序又不改变索引缓冲中索引组织顺序的裂缝消除方法。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/javazjh/201109/201109081829316471.gif"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image057" border="0" alt="clip_image057" src="http://images.cnblogs.com/cnblogs_com/javazjh/201109/20110908182931616.gif" width="542" height="181" /&gt;&lt;/a&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/javazjh/201109/201109081829313124.gif"&gt;&lt;img style="background-image: none; border-right-width: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image058" border="0" alt="clip_image058" src="http://images.cnblogs.com/cnblogs_com/javazjh/201109/201109081829325981.gif" width="240" height="82" /&gt;&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;图a 裂缝消除前 图b 裂缝消除后&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;图&lt;/strong&gt;&lt;strong&gt;27.&lt;/strong&gt; 用插值高程代替实际高程消除裂缝&lt;/p&gt;&#xD;
&lt;p&gt;这种方法分别对存在裂缝的别界顶点用插值高程代替实际高程，如上图a，只需要把A点的高程值（Y坐标值）设为B点的高程值即可实现裂缝的&amp;#8220;缝合&amp;#8221;。&lt;/p&gt;&#xD;
&lt;p&gt;这种方法保持了每个节点顶点数目和索引数目的一致性，使得顶点缓冲中顶点的顺序尽可能地符合渲染顺序，但是对于各插值处而言，均比边界样式方法多渲染了一个位置重复的顶点，增加了渲染三角形的数目，从渲染量的角度而言增大了GPU流水线的负担，但从组织的角度而言更合理更接近人们的常规组织方式。&lt;/p&gt;&#xD;
&lt;p&gt;通过我们的实验证明，这种方法与基于边界样式的裂缝消除方法，速度比较接近，略慢于边界样式方法，但比传统的方法都要快。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;表&lt;/strong&gt;&lt;strong&gt;10.&lt;/strong&gt; 各种裂缝消除方法对比 &#xD;
&lt;table border="1" cellspacing="0" cellpadding="0"&gt;&#xD;
&lt;tbody&gt;&#xD;
&lt;tr&gt;&#xD;
&lt;td&gt;&#xD;
&lt;p&gt;裂缝消除方法类型&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td&gt;&#xD;
&lt;p&gt;顶点缓冲中顶点分布&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td&gt;&#xD;
&lt;p&gt;特点&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&#xD;
&lt;tr&gt;&#xD;
&lt;td&gt;&#xD;
&lt;p&gt;不消除&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td&gt;&#xD;
&lt;p&gt;顶点顺序与渲染顺序比较接近&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td&gt;&#xD;
&lt;p&gt;无&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&#xD;
&lt;tr&gt;&#xD;
&lt;td&gt;&#xD;
&lt;p&gt;边界裂缝处增加顶点及增加到低层次节点中心点连线&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td&gt;&#xD;
&lt;p&gt;无序，按索引组织渲染顶点时，顶点处于顶点缓冲中位置距离大，访问跳跃频繁&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td&gt;&#xD;
&lt;p&gt;增加顶点计算量大，GPU渲染吞吐量增大，节点精度增加&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&#xD;
&lt;tr&gt;&#xD;
&lt;td&gt;&#xD;
&lt;p&gt;边界删除一个顶点及该顶点到节点中心点的连线方法&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td&gt;&#xD;
&lt;p&gt;顶点顺序与渲染顺序比较接近&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td&gt;&#xD;
&lt;p&gt;删除顶点计算量大，渲染量减少，节点精度降低明显&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&#xD;
&lt;tr&gt;&#xD;
&lt;td&gt;&#xD;
&lt;p&gt;边界样式方法&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td&gt;&#xD;
&lt;p&gt;跳跃，存在忽略始终没用到的顶点&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td&gt;&#xD;
&lt;p&gt;边界判断运算大，渲染量减少，节点精度降低不明显，中心区域精度没变化&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&#xD;
&lt;tr&gt;&#xD;
&lt;td&gt;&#xD;
&lt;p&gt;用插值高程代替实际高程方法&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td&gt;&#xD;
&lt;p&gt;顶点顺序与渲染顺序比较接近&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td&gt;&#xD;
&lt;p&gt;边界判断运算较小，渲染量大，节点精度降低不明显&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/p&gt;&#xD;
&lt;p&gt;从上述可以看出，本文5.2，5.3提出的两种方法，在速度上比过往方法没有非常明显的提高，但是前者保证了节点中心精度不变，后者保证了顶点缓冲中顶点顺序与渲染顺序尽可能接近，更易于代码编写和三角形组织。&lt;/p&gt;&#xD;
&lt;p&gt;结果与讨论&lt;/p&gt;&#xD;
&lt;p&gt;我们对多种地理数据进行了实验，如下：&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;表&lt;/strong&gt;&lt;strong&gt;12.&lt;/strong&gt; 各种地形数据源 &#xD;
&lt;table border="1" cellspacing="0" cellpadding="0"&gt;&#xD;
&lt;tbody&gt;&#xD;
&lt;tr&gt;&#xD;
&lt;td valign="top" width="37%"&gt;&#xD;
&lt;p&gt;数据集&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td valign="top" width="35%"&gt;&#xD;
&lt;p&gt;格网大小&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td valign="top" width="27%"&gt;&#xD;
&lt;p&gt;来源&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&#xD;
&lt;tr&gt;&#xD;
&lt;td valign="top" width="37%"&gt;&#xD;
&lt;p&gt;Puget Sound&lt;/p&gt;&#xD;
&lt;p&gt;（普及特湾）&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td valign="top" width="35%"&gt;&#xD;
&lt;p&gt;32768&amp;#215;32768&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td valign="top" width="27%"&gt;&#xD;
&lt;p&gt;USGS 1:10m DEM ,1:0.1m高程&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&#xD;
&lt;tr&gt;&#xD;
&lt;td valign="top" width="37%"&gt;&#xD;
&lt;p&gt;Grand Canyon&lt;/p&gt;&#xD;
&lt;p&gt;（美洲大峡谷）&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td valign="top" width="35%"&gt;&#xD;
&lt;p&gt;32768&amp;#215;16384&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td valign="top" width="27%"&gt;&#xD;
&lt;p&gt;USGS 1:10m DEM ,1:0.1m高程&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&#xD;
&lt;tr&gt;&#xD;
&lt;td valign="top" width="37%"&gt;&#xD;
&lt;p&gt;Rockies&lt;/p&gt;&#xD;
&lt;p&gt;（落基山脉）&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td valign="top" width="35%"&gt;&#xD;
&lt;p&gt;70400&amp;#215;54400&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td valign="top" width="27%"&gt;&#xD;
&lt;p&gt;Terra地球卫星影像&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/p&gt;&#xD;
&lt;p&gt;我们在3.0GHz Pentium 4 CPU，1 GB system memory , nVIDIA Geforce FX 6600 GPU with 128M video memory（出厂参数为每秒处理502Million个三角形）环境下进行了实验，实验以640&amp;#215;480&amp;#215;32bit全屏幕模式下，90度视锥宽度环境下进行。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/javazjh/201109/201109081829326571.jpg"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image060" border="0" alt="clip_image060" src="http://images.cnblogs.com/cnblogs_com/javazjh/201109/201109081829325731.jpg" width="588" height="472" /&gt;&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;54400&amp;#215;74400落基山脉一部分&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/javazjh/201109/201109081829323572.jpg"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image062" border="0" alt="clip_image062" src="http://images.cnblogs.com/cnblogs_com/javazjh/201109/201109081829331097.jpg" width="593" height="301" /&gt;&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;32768&amp;#215;16384 Grand Canyon（美洲大峡谷）&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;图&lt;/strong&gt;&lt;strong&gt;35.&lt;/strong&gt; 我们策略实时渲染的两个场景效果&lt;/p&gt;&#xD;
&lt;p&gt;我们在带有视锥剔除、多LOD评价因子，约束帧FPS为60的情况下和同类研究作了对比，我们得到88Million三角形每秒的渲染量，进一步接近目前主流显示卡（如NVidia GeForce FX 5900 / 6200 / 6600等，价值约100－150美金，每秒渲染300Million－600Million个三角形，参考附录一）的三角形处理能力。我们还在相同环境下运行了下表后三种方法所附实验程序，下表是详细的对比数据：&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;表&lt;/strong&gt;&lt;strong&gt;13.&lt;/strong&gt; 不同方案FPS60下的渲染对比 &#xD;
&lt;table border="1" cellspacing="0" cellpadding="0"&gt;&#xD;
&lt;tbody&gt;&#xD;
&lt;tr&gt;&#xD;
&lt;td&gt;&#xD;
&lt;p&gt;方案&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td&gt;&#xD;
&lt;p&gt;我们同一机器(Nvidia GF FX6600GT)上测得的每秒渲染的三角形数量&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td&gt;&#xD;
&lt;p&gt;原论文报告的数据&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&#xD;
&lt;tr&gt;&#xD;
&lt;td&gt;&#xD;
&lt;p&gt;Our approach&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td&gt;&#xD;
&lt;p&gt;88Million&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td&gt;&#xD;
&lt;p&gt;/&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&#xD;
&lt;tr&gt;&#xD;
&lt;td&gt;&#xD;
&lt;p&gt;Geometry Clipmaps (2004)&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td&gt;&#xD;
&lt;p&gt;55Million&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td&gt;&#xD;
&lt;p&gt;59Million&lt;/p&gt;&#xD;
&lt;p&gt;(Radeon 9800XT)&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&#xD;
&lt;tr&gt;&#xD;
&lt;td&gt;&#xD;
&lt;p&gt;Cignoni et (2003)&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td&gt;&#xD;
&lt;p&gt;59Million&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td&gt;&#xD;
&lt;p&gt;16Million&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&#xD;
&lt;tr&gt;&#xD;
&lt;td&gt;&#xD;
&lt;p&gt;Lindstrom (2002)&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td&gt;&#xD;
&lt;p&gt;18Million&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td&gt;&#xD;
&lt;p&gt;2.4Million&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&#xD;
&lt;tr&gt;&#xD;
&lt;td&gt;&#xD;
&lt;p&gt;VDPM Hoppe(1998)&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td&gt;&#xD;
&lt;p&gt;3Million&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td&gt;&#xD;
&lt;p&gt;0.48Million&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/p&gt;&#xD;
&lt;p&gt;通过上表对比，我们发现，我们策略的FPS略低于Geometry Clipmaps，但是我们的累积渲染策略在同样条件下，每秒渲染了更多的三角形，获得了更高的精度，我们发现在640&amp;#215;480分辨率下，我们比其它方法多渲染的三角形并没有得到明显的效果呈现，部分三角形光栅化后小于1个象素点，并没有明显的视觉精度提高，但是随着我们屏幕分辨率的提高，在1280&amp;#215;1024的分辨率下，我们在稳定的视觉环境下得到了更高的精度，帧速减小带来的高精度渲染是值得，我们发现与其它世界空间误差评价策略相比，我们的策略能够使得更多的三角形在投影变换到屏幕空间后呈现小的象素点，不存在一个三角形光栅化后占有多个屏幕象素的情况。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;表&lt;/strong&gt;&lt;strong&gt;14.&lt;/strong&gt; 不同方案的更新速度 &#xD;
&lt;table border="1" cellspacing="0" cellpadding="0"&gt;&#xD;
&lt;tbody&gt;&#xD;
&lt;tr&gt;&#xD;
&lt;td valign="top"&gt;&#xD;
&lt;p&gt;Update step \ Differen schemes&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td valign="top"&gt;&#xD;
&lt;p&gt;our approach&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td valign="top"&gt;&#xD;
&lt;p&gt;Geometry Clipmaps&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&#xD;
&lt;tr&gt;&#xD;
&lt;td valign="top"&gt;&#xD;
&lt;p&gt;update chunk block&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td&gt;&#xD;
&lt;p&gt;3&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td&gt;&#xD;
&lt;p&gt;/&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&#xD;
&lt;tr&gt;&#xD;
&lt;td valign="top"&gt;&#xD;
&lt;p&gt;Computation of static error&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td&gt;&#xD;
&lt;p&gt;3&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td&gt;&#xD;
&lt;p&gt;3&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&#xD;
&lt;tr&gt;&#xD;
&lt;td valign="top"&gt;&#xD;
&lt;p&gt;Decompression or Synthesis&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td&gt;&#xD;
&lt;p&gt;/&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td&gt;&#xD;
&lt;p&gt;3&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&#xD;
&lt;tr&gt;&#xD;
&lt;td valign="top"&gt;&#xD;
&lt;p&gt;load to video memory (load vertex buffer and index buffer)&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td&gt;&#xD;
&lt;p&gt;1&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td&gt;&#xD;
&lt;p&gt;3&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&#xD;
&lt;tr&gt;&#xD;
&lt;td valign="top"&gt;&#xD;
&lt;p&gt;Normal map computation&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td&gt;&#xD;
&lt;p&gt;/&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td&gt;&#xD;
&lt;p&gt;11&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&#xD;
&lt;tr&gt;&#xD;
&lt;td valign="top"&gt;&#xD;
&lt;p&gt;Total&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td&gt;&#xD;
&lt;p&gt;7&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td&gt;&#xD;
&lt;p&gt;20-11=9&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/p&gt;&#xD;
&lt;p&gt;应用与展望&lt;/p&gt;&#xD;
&lt;p&gt;本文的这套超大规模场景策略，能够应用在国家安全，精确制导、高分辨率卫星航拍遥感影像可视化，超大规模城市建模衍变仿真、人工植物群、虚拟现实场景漫游、虚拟战场，电子沙盘等领域，有着重要的研究意义和经济价值。&lt;/p&gt;&#xD;
&lt;p&gt;本研究能应用于精确制导模拟，能够监控整个导弹发射，非惯导轨迹飞行等过程，有俯视，镜头跟踪等观察模式。&lt;/p&gt;&#xD;
&lt;p&gt;本研究可以应用于赛博空间、虚拟城市等领域，实现超大规模城市建模衍变仿真，能对城市中多达40000的建筑物、树木、人等场景对象实时渲染，多级道路样式和基于OL-System文法的区域迭代等能够模拟城市从小镇到大都市的发展过程，在城市规划、衍变模拟等有着深远的研究意义。已有辐射状和悉尼状城市等多个案例演示。&lt;/p&gt;&#xD;
&lt;p&gt;本研究可应用于高分辨率卫星、航拍、遥感影像空间数据可视化等方面，支持基于DEM,DOM的海量空间数据，能进行地物标注，支持俯视、轴视等观察模式，已有突尼斯海湾，塔克拉马干沙漠，澳洲大宝礁等多个案例演示。&lt;/p&gt;&#xD;
&lt;p&gt;本研究可应用于地学分析，VRGIS等领域上，能进行多种地学测量，地表区域分析，地形分层显示，地貌、植被属性查询, 无级别比列尺等操作,已有火山口、深邃、山峰，海岸线等多个空间测量，3DGIS操作，地貌科学分析案例演示。&lt;/p&gt;&#xD;
&lt;p&gt;本研究可应用于地学仿真实验、虚拟战场、虚拟军事环境等，代替传统的人工沙盘作业，为地学实验提供快捷准确有效的数据，在短时间内模拟整个大规模场景的变化，不必长时间进行实地观察分析，对地理群体特征进行可视化分析研究，代替部分在现实世界中难以进行或费时、费力、昂贵的地学试验。&lt;/p&gt;&#xD;
&lt;p&gt;本研究可用于飞行模拟、地区观光等领域上，进行景点路线导游，有鸟群跟踪，第一人称漫步等多种漫游模式，已有夏威夷四大岛，Coiba Island等案例演示。&lt;/p&gt;&#xD;
&lt;p&gt;此外，还可应用于大规模人工植物群仿真，三维游戏引擎等方面，根据本文策略开发的原型&amp;#8212;&amp;#8212;World Creative Suite，World Explorer , World Solution SDK已经可以应用上述领域，World Builder能通过分形或Perlin Noise等方法根据分形维度、地表样式、分布序列、道路树木数量等生成与现实地形相近的人工地形。&lt;/p&gt;&#xD;
&lt;p&gt;参考文献&lt;/p&gt;&#xD;
&lt;p&gt;1. A.E.W. Mason &amp;amp; E.H. Blake &amp;#8220;A Graphical Representation of the State Spaces of Hierarchical Level-of-Detail Scene Descriptions&amp;#8221; &lt;em&gt;IEEE Transactions on Visualization and Computer Graphics&lt;/em&gt;, 2001 7(1) 70-73.&lt;/p&gt;&#xD;
&lt;p&gt;2. B. D. Larsen &amp;amp; N. J. Christensen. &lt;em&gt;&amp;#8220;&lt;/em&gt;Real-time Terrain Rendering using Smooth Hardware Optimized Level of Detail&amp;#8221;. &lt;em&gt;WSCG 2003&lt;/em&gt; 11(2) 282-289.&lt;/p&gt;&#xD;
&lt;p&gt;3. C. Dachsbacher &amp;amp; M. Stamminger. &amp;#8220;Rendering Procedural Terrain by Geometry Image Warping&amp;#8221; Eurographics 2004.&lt;/p&gt;&#xD;
&lt;p&gt;4. D.Cline &amp;amp; P.K.Egbert &amp;#8220;Terrain decimation through quadtree morphing&amp;#8221; &lt;em&gt;IEEE Transactions on Visualization and Computer Graphics 2001 &lt;/em&gt;7(1) 62-69.&lt;/p&gt;&#xD;
&lt;p&gt;5. F.Losasso &amp;amp; Hugues.Hoppe &amp;#8220;Geometry Clipmaps: Terrain Rendering Using Nested Regular Grids&amp;#8221; &lt;em&gt;ACM SIGGRAPH 2004 Proc.&lt;/em&gt;&lt;/p&gt;&#xD;
&lt;p&gt;6. H.Hoppe &amp;#8220;Smooth view-dependent level-of-detail control and its application to terrain rendering&amp;#8221; &lt;em&gt;IEEE Visualization 1998&lt;/em&gt; 35-42.&lt;/p&gt;&#xD;
&lt;p&gt;7. J.Levenberg &amp;#8220;Fast view-dependent level-of-detail rendering using cached geometry&amp;#8221; &lt;em&gt;IEEE Visualization 2002 Proc&lt;/em&gt;.&lt;/p&gt;&#xD;
&lt;p&gt;8. P.Lindholm et &amp;#8220;A user-programmable vertex engine&amp;#8221; &lt;em&gt;ACM SIGGRAPH 2001 Proc&lt;/em&gt;, 149-158.&lt;/p&gt;&#xD;
&lt;p&gt;9. M.Duchaineau et &amp;#8220;ROAMing terrain: Real-time op-timally adapting meshes&amp;#8221; &lt;em&gt;IEEE Visualization 1997 Proc&lt;/em&gt;, 81-88.&lt;/p&gt;&#xD;
&lt;p&gt;10. Pajarola &amp;#8220;Large scale terrain visualization using the restricted quadtree triangulation&amp;#8221; IEEE Visualization 1998 Proc 19-26.&lt;/p&gt;&#xD;
&lt;p&gt;11. P.Lindstrom et &amp;#8220;Real-time, continuous level of detail rendering of height fields&amp;#8221; &lt;em&gt;ACM SIGGRAPH 1996 Proc&lt;/em&gt;, 109-118.&lt;/p&gt;&#xD;
&lt;p&gt;12. P.Lindstrom &amp;amp; V.Pascucci &amp;#8220;Terrain simplification simpli-fied: A general framework for view-dependent out-of-core visualization&amp;#8221; &lt;em&gt;IEEE Transactions on Visualization and Computer Graphics 2002 &lt;/em&gt;8(3), 239-254.&lt;/p&gt;&#xD;
&lt;p&gt;13. P.Lindstrom &amp;amp; V.Pascucci &amp;#8220;Visualization of large terrains made easy&amp;#8221; IEEE Visualization 2001 Pro 363-370.&lt;/p&gt;&#xD;
&lt;p&gt;14. P.Cignoni et &amp;#8220;Planet-Sized Batched Dynamic Adaptive Meshes (P-BDAM)&amp;#8221; &lt;em&gt;IEEE Visualization 2003 Proc&lt;/em&gt;.&lt;/p&gt;&#xD;
&lt;p&gt;15. 谭兵, 徐青, 马东洋 &amp;#8220;用约束四叉树实现地形的实时多分辨率绘&amp;#8221;. 计算机辅助设计与图形学学报, 2003 15(3).&lt;/p&gt;&#xD;
&lt;p&gt;16. 谭兵, 徐青, 周杨 &amp;#8220;大区域地形可视化技术的研&amp;#8221;. 中国图象图形学报, 2003 8(5).&lt;/p&gt;&#xD;
&lt;p&gt;17. 王宏武, 董士海 &amp;#8220;一个与视点相关的动态多分辨率地形模型&amp;#8221;. 计算机辅助设计与图形学学报 2000 12(8).&lt;/p&gt;&#xD;
&lt;p&gt;附录一：常见GPU处理三角形能力和显存大小 &#xD;
&lt;table border="1" cellspacing="0" cellpadding="0"&gt;&#xD;
&lt;tbody&gt;&#xD;
&lt;tr&gt;&#xD;
&lt;td valign="top" width="39%"&gt;&#xD;
&lt;p&gt;型号&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td valign="top" width="25%"&gt;&#xD;
&lt;p&gt;每秒处理的三角形数量&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td valign="top" width="35%"&gt;&#xD;
&lt;p&gt;显存(video memory)&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&#xD;
&lt;tr&gt;&#xD;
&lt;td valign="top" width="39%"&gt;&#xD;
&lt;p&gt;ATI RADEON X800 XT&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td valign="top" width="25%"&gt;&#xD;
&lt;p&gt;7.8亿(780M)&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td valign="top" width="35%"&gt;&#xD;
&lt;p&gt;256MB/512MB&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&#xD;
&lt;tr&gt;&#xD;
&lt;td valign="top" width="39%"&gt;&#xD;
&lt;p&gt;ATI RADEON 9800 XT&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td valign="top" width="25%"&gt;&#xD;
&lt;p&gt;4.12亿(412M)&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td valign="top" width="35%"&gt;&#xD;
&lt;p&gt;256M&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&#xD;
&lt;tr&gt;&#xD;
&lt;td valign="top" width="39%"&gt;&#xD;
&lt;p&gt;ATI RADEON 9700&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td valign="top" width="25%"&gt;&#xD;
&lt;p&gt;3.25亿(325M)&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td valign="top" width="35%"&gt;&#xD;
&lt;p&gt;128M&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&#xD;
&lt;tr&gt;&#xD;
&lt;td valign="top" width="39%"&gt;&#xD;
&lt;p&gt;ATI RADEON 9000&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td valign="top" width="25%"&gt;&#xD;
&lt;p&gt;0.5亿(50M)&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td valign="top" width="35%"&gt;&#xD;
&lt;p&gt;128M/64M&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&#xD;
&lt;tr&gt;&#xD;
&lt;td valign="top" width="39%"&gt;&#xD;
&lt;p&gt;nVidia GeForce FX 6800&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td valign="top" width="25%"&gt;&#xD;
&lt;p&gt;6亿(600M)&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td valign="top" width="35%"&gt;&#xD;
&lt;p&gt;256MB/512MB&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&#xD;
&lt;tr&gt;&#xD;
&lt;td valign="top" width="39%"&gt;&#xD;
&lt;p&gt;nVidia GeForce FX 5950&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td valign="top" width="25%"&gt;&#xD;
&lt;p&gt;3.56亿(356M)&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td valign="top" width="35%"&gt;&#xD;
&lt;p&gt;128MB/256MB&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&#xD;
&lt;tr&gt;&#xD;
&lt;td valign="top" width="39%"&gt;&#xD;
&lt;p&gt;nVidia GeForce FX 5900&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td valign="top" width="25%"&gt;&#xD;
&lt;p&gt;3.38亿(338M)&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td valign="top" width="35%"&gt;&#xD;
&lt;p&gt;128MB/256MB&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&#xD;
&lt;tr&gt;&#xD;
&lt;td valign="top" width="39%"&gt;&#xD;
&lt;p&gt;nVidia GeForce FX 5600&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td valign="top" width="25%"&gt;&#xD;
&lt;p&gt;1.13亿(113M)&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td valign="top" width="35%"&gt;&#xD;
&lt;p&gt;256MB&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&#xD;
&lt;tr&gt;&#xD;
&lt;td valign="top" width="39%"&gt;&#xD;
&lt;p&gt;nVidia GeForce FX 5200&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td valign="top" width="25%"&gt;&#xD;
&lt;p&gt;8100万(81M)&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td valign="top" width="35%"&gt;&#xD;
&lt;p&gt;128MB&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&#xD;
&lt;tr&gt;&#xD;
&lt;td valign="top" width="39%"&gt;&#xD;
&lt;p&gt;nVIDIA GeForce 4 MX400&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td valign="top" width="25%"&gt;&#xD;
&lt;p&gt;3500万(35M)&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td valign="top" width="35%"&gt;&#xD;
&lt;p&gt;128M/64M&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&#xD;
&lt;tr&gt;&#xD;
&lt;td valign="top" width="39%"&gt;&#xD;
&lt;p&gt;nVIDIA GeForce 2 MX400&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td valign="top" width="25%"&gt;&#xD;
&lt;p&gt;2000万(20M)&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td valign="top" width="35%"&gt;&#xD;
&lt;p&gt;128M/64M&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&#xD;
&lt;tr&gt;&#xD;
&lt;td valign="top" width="39%"&gt;&#xD;
&lt;p&gt;nVIDIA GeForce 2 MX200&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td valign="top" width="25%"&gt;&#xD;
&lt;p&gt;2000万(20M)&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td valign="top" width="35%"&gt;&#xD;
&lt;p&gt;32M&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/p&gt;&#xD;
&lt;p&gt;附录二：Vertex Shader指令&lt;/p&gt;&#xD;
&lt;p&gt;Vertex Shader简单指令: &#xD;
&lt;table border="1" cellspacing="0" cellpadding="0"&gt;&#xD;
&lt;tbody&gt;&#xD;
&lt;tr&gt;&#xD;
&lt;td width="12%"&gt;&#xD;
&lt;p&gt;指令&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td width="25%"&gt;&#xD;
&lt;p&gt;目的操作数&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td width="20%"&gt;&#xD;
&lt;p&gt;源操作数&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td width="41%"&gt;&#xD;
&lt;p&gt;说明&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&#xD;
&lt;tr&gt;&#xD;
&lt;td width="12%"&gt;&#xD;
&lt;p&gt;ABS&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td width="25%"&gt;&#xD;
&lt;p&gt;v&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td width="20%"&gt;&#xD;
&lt;p&gt;v&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td width="41%"&gt;&#xD;
&lt;p&gt;求绝对值&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&#xD;
&lt;tr&gt;&#xD;
&lt;td width="12%"&gt;&#xD;
&lt;p&gt;ADD&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td width="25%"&gt;&#xD;
&lt;p&gt;v&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td width="20%"&gt;&#xD;
&lt;p&gt;v,&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td width="41%"&gt;&#xD;
&lt;p&gt;v&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&#xD;
&lt;tr&gt;&#xD;
&lt;td width="12%"&gt;&#xD;
&lt;p&gt;ARL&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td width="25%"&gt;&#xD;
&lt;p&gt;a&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td width="20%"&gt;&#xD;
&lt;p&gt;v&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td width="41%"&gt;&#xD;
&lt;p&gt;载入到地址寄存器&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&#xD;
&lt;tr&gt;&#xD;
&lt;td width="12%"&gt;&#xD;
&lt;p&gt;DP3&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td width="25%"&gt;&#xD;
&lt;p&gt;ssss&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td width="20%"&gt;&#xD;
&lt;p&gt;v,&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td width="41%"&gt;&#xD;
&lt;p&gt;v&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&#xD;
&lt;tr&gt;&#xD;
&lt;td width="12%"&gt;&#xD;
&lt;p&gt;DP4&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td width="25%"&gt;&#xD;
&lt;p&gt;ssss&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td width="20%"&gt;&#xD;
&lt;p&gt;v,&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td width="41%"&gt;&#xD;
&lt;p&gt;v&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&#xD;
&lt;tr&gt;&#xD;
&lt;td width="12%"&gt;&#xD;
&lt;p&gt;DPH&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td width="25%"&gt;&#xD;
&lt;p&gt;ssss&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td width="20%"&gt;&#xD;
&lt;p&gt;v,&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td width="41%"&gt;&#xD;
&lt;p&gt;v&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&#xD;
&lt;tr&gt;&#xD;
&lt;td width="12%"&gt;&#xD;
&lt;p&gt;DST&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td width="25%"&gt;&#xD;
&lt;p&gt;v&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td width="20%"&gt;&#xD;
&lt;p&gt;v,&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td width="41%"&gt;&#xD;
&lt;p&gt;v&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&#xD;
&lt;tr&gt;&#xD;
&lt;td width="12%"&gt;&#xD;
&lt;p&gt;EX2&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td width="25%"&gt;&#xD;
&lt;p&gt;ssss&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td width="20%"&gt;&#xD;
&lt;p&gt;s&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td width="41%"&gt;&#xD;
&lt;p&gt;计算底数为2&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&#xD;
&lt;tr&gt;&#xD;
&lt;td width="12%"&gt;&#xD;
&lt;p&gt;EXP&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td width="25%"&gt;&#xD;
&lt;p&gt;v&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td width="20%"&gt;&#xD;
&lt;p&gt;s&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td width="41%"&gt;&#xD;
&lt;p&gt;计算底数为2&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&#xD;
&lt;tr&gt;&#xD;
&lt;td width="12%"&gt;&#xD;
&lt;p&gt;FLR&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td width="25%"&gt;&#xD;
&lt;p&gt;v&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td width="20%"&gt;&#xD;
&lt;p&gt;v&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td width="41%"&gt;&#xD;
&lt;p&gt;计算比&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&#xD;
&lt;tr&gt;&#xD;
&lt;td width="12%"&gt;&#xD;
&lt;p&gt;FRC&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td width="25%"&gt;&#xD;
&lt;p&gt;v&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td width="20%"&gt;&#xD;
&lt;p&gt;v&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td width="41%"&gt;&#xD;
&lt;p&gt;计算&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&#xD;
&lt;tr&gt;&#xD;
&lt;td width="12%"&gt;&#xD;
&lt;p&gt;LG2&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td width="25%"&gt;&#xD;
&lt;p&gt;ssss&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td width="20%"&gt;&#xD;
&lt;p&gt;s&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td width="41%"&gt;&#xD;
&lt;p&gt;计算底数为2&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&#xD;
&lt;tr&gt;&#xD;
&lt;td width="12%"&gt;&#xD;
&lt;p&gt;LIT&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td width="25%"&gt;&#xD;
&lt;p&gt;v&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td width="20%"&gt;&#xD;
&lt;p&gt;v&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td width="41%"&gt;&#xD;
&lt;p&gt;计算光照计算系数&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&#xD;
&lt;tr&gt;&#xD;
&lt;td width="12%"&gt;&#xD;
&lt;p&gt;LOG&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td width="25%"&gt;&#xD;
&lt;p&gt;v&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td width="20%"&gt;&#xD;
&lt;p&gt;s&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td width="41%"&gt;&#xD;
&lt;p&gt;计算底数为2&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&#xD;
&lt;tr&gt;&#xD;
&lt;td width="12%"&gt;&#xD;
&lt;p&gt;MAD&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td width="25%"&gt;&#xD;
&lt;p&gt;v&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td width="20%"&gt;&#xD;
&lt;p&gt;v,&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td width="41%"&gt;&#xD;
&lt;p&gt;v,&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&#xD;
&lt;tr&gt;&#xD;
&lt;td width="12%"&gt;&#xD;
&lt;p&gt;MAX&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td width="25%"&gt;&#xD;
&lt;p&gt;v&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td width="20%"&gt;&#xD;
&lt;p&gt;v,&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td width="41%"&gt;&#xD;
&lt;p&gt;v&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&#xD;
&lt;tr&gt;&#xD;
&lt;td width="12%"&gt;&#xD;
&lt;p&gt;MIN&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td width="25%"&gt;&#xD;
&lt;p&gt;v&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td width="20%"&gt;&#xD;
&lt;p&gt;v,&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td width="41%"&gt;&#xD;
&lt;p&gt;v&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&#xD;
&lt;tr&gt;&#xD;
&lt;td width="12%"&gt;&#xD;
&lt;p&gt;MOV&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td width="25%"&gt;&#xD;
&lt;p&gt;v&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td width="20%"&gt;&#xD;
&lt;p&gt;v&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td width="41%"&gt;&#xD;
&lt;p&gt;赋值&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&#xD;
&lt;tr&gt;&#xD;
&lt;td width="12%"&gt;&#xD;
&lt;p&gt;MUL&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td width="25%"&gt;&#xD;
&lt;p&gt;v&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td width="20%"&gt;&#xD;
&lt;p&gt;v,&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td width="41%"&gt;&#xD;
&lt;p&gt;v&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&#xD;
&lt;tr&gt;&#xD;
&lt;td width="12%"&gt;&#xD;
&lt;p&gt;POW&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td width="25%"&gt;&#xD;
&lt;p&gt;ssss&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td width="20%"&gt;&#xD;
&lt;p&gt;s,&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td width="41%"&gt;&#xD;
&lt;p&gt;s&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&#xD;
&lt;tr&gt;&#xD;
&lt;td width="12%"&gt;&#xD;
&lt;p&gt;RCP&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td width="25%"&gt;&#xD;
&lt;p&gt;ssss&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td width="20%"&gt;&#xD;
&lt;p&gt;S&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td width="41%"&gt;&#xD;
&lt;p&gt;计算倒数&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&#xD;
&lt;tr&gt;&#xD;
&lt;td width="12%"&gt;&#xD;
&lt;p&gt;RSQ&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td width="25%"&gt;&#xD;
&lt;p&gt;ssss&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td width="20%"&gt;&#xD;
&lt;p&gt;S&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td width="41%"&gt;&#xD;
&lt;p&gt;计算平方根的倒数&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&#xD;
&lt;tr&gt;&#xD;
&lt;td width="12%"&gt;&#xD;
&lt;p&gt;SGE&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td width="25%"&gt;&#xD;
&lt;p&gt;v&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td width="20%"&gt;&#xD;
&lt;p&gt;v,&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td width="41%"&gt;&#xD;
&lt;p&gt;v&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&#xD;
&lt;tr&gt;&#xD;
&lt;td width="12%"&gt;&#xD;
&lt;p&gt;SLT&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td width="25%"&gt;&#xD;
&lt;p&gt;v&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td width="20%"&gt;&#xD;
&lt;p&gt;v,&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td width="41%"&gt;&#xD;
&lt;p&gt;v&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&#xD;
&lt;tr&gt;&#xD;
&lt;td width="12%"&gt;&#xD;
&lt;p&gt;SUB&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td width="25%"&gt;&#xD;
&lt;p&gt;v&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td width="20%"&gt;&#xD;
&lt;p&gt;v,&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td width="41%"&gt;&#xD;
&lt;p&gt;v&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&#xD;
&lt;tr&gt;&#xD;
&lt;td width="12%"&gt;&#xD;
&lt;p&gt;SWZ&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td width="25%"&gt;&#xD;
&lt;p&gt;v&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td width="20%"&gt;&#xD;
&lt;p&gt;V&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td width="41%"&gt;&#xD;
&lt;p&gt;扩展的分量下标置换&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&#xD;
&lt;tr&gt;&#xD;
&lt;td width="12%"&gt;&#xD;
&lt;p&gt;XPD&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td width="25%"&gt;&#xD;
&lt;p&gt;v&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td width="20%"&gt;&#xD;
&lt;p&gt;v,&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td width="41%"&gt;&#xD;
&lt;p&gt;v&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/p&gt;&#xD;
&lt;p&gt;Vertex Shader中的复杂指令： &#xD;
&lt;table border="1" cellspacing="0" cellpadding="0"&gt;&#xD;
&lt;tbody&gt;&#xD;
&lt;tr&gt;&#xD;
&lt;td&gt;&#xD;
&lt;p&gt;宏&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td&gt;&#xD;
&lt;p&gt;参数&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td&gt;&#xD;
&lt;p&gt;行为&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td&gt;&#xD;
&lt;p&gt;时钟数&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&#xD;
&lt;tr&gt;&#xD;
&lt;td&gt;&#xD;
&lt;p&gt;exp&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td&gt;&#xD;
&lt;p&gt;dest, src1&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td&gt;&#xD;
&lt;p&gt;提供精度至少在1/2&lt;sup&gt;20&lt;/sup&gt; 的2的幂计算&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td&gt;&#xD;
&lt;p&gt;12&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&#xD;
&lt;tr&gt;&#xD;
&lt;td&gt;&#xD;
&lt;p&gt;frc&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td&gt;&#xD;
&lt;p&gt;dest, src1&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td&gt;&#xD;
&lt;p&gt;返回每一个输入部分的小数&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td&gt;&#xD;
&lt;p&gt;3&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&#xD;
&lt;tr&gt;&#xD;
&lt;td&gt;&#xD;
&lt;p&gt;log&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td&gt;&#xD;
&lt;p&gt;dest, src1&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td&gt;&#xD;
&lt;p&gt;提供精度至少在1/2&lt;sup&gt;20&lt;/sup&gt; 的log2(x)计算&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td&gt;&#xD;
&lt;p&gt;12&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&#xD;
&lt;tr&gt;&#xD;
&lt;td&gt;&#xD;
&lt;p&gt;m3x2&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td&gt;&#xD;
&lt;p&gt;dest, src1, src2&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td&gt;&#xD;
&lt;p&gt;计算输入向量和一个3x2矩阵的乘积&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td&gt;&#xD;
&lt;p&gt;2&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&#xD;
&lt;tr&gt;&#xD;
&lt;td&gt;&#xD;
&lt;p&gt;m3x3&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td&gt;&#xD;
&lt;p&gt;dest, src1, src2&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td&gt;&#xD;
&lt;p&gt;计算输入向量和一个3x3矩阵的乘积&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td&gt;&#xD;
&lt;p&gt;3&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&#xD;
&lt;tr&gt;&#xD;
&lt;td&gt;&#xD;
&lt;p&gt;m3x4&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td&gt;&#xD;
&lt;p&gt;dest, src1, src2&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td&gt;&#xD;
&lt;p&gt;计算输入向量和一个3x4矩阵的乘积&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td&gt;&#xD;
&lt;p&gt;4&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&#xD;
&lt;tr&gt;&#xD;
&lt;td&gt;&#xD;
&lt;p&gt;m4x3&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td&gt;&#xD;
&lt;p&gt;dest, src1, src2&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td&gt;&#xD;
&lt;p&gt;计算输入向量和一个4x3矩阵的乘积&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td&gt;&#xD;
&lt;p&gt;3&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&#xD;
&lt;tr&gt;&#xD;
&lt;td&gt;&#xD;
&lt;p&gt;m4x4&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td&gt;&#xD;
&lt;p&gt;dest, src1, src2&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td&gt;&#xD;
&lt;p&gt;计算输入向量和一个4x4矩阵的乘积&lt;/p&gt;&lt;/td&gt;&#xD;
&lt;td&gt;&#xD;
&lt;p&gt;4&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/p&gt;&lt;/div&gt;&#xD;
&lt;div id="blog_post_info_block"&gt;&#xD;
&lt;div id="BlogPostCategory"&gt;&lt;/div&gt;&#xD;
&lt;div id="EntryTag"&gt;&lt;/div&gt;&#xD;
&lt;div id="green_channel"&gt;绿色通道：&lt;a id="green_channel_digg" onclick=";green_channel_success(this,'谢谢推荐！');" href="http://www.cnblogs.com/mazhenyu/admin/javascript:void(0);"&gt;好文要顶&lt;/a&gt;&lt;a id="green_channel_follow" onclick=";" href="http://www.cnblogs.com/mazhenyu/admin/javascript:void(0);"&gt;关注我&lt;/a&gt;&lt;a id="green_channel_favorite" onclick="AddToWz(2171727);return false;" href="http://www.cnblogs.com/mazhenyu/admin/javascript:void(0);"&gt;收藏该文&lt;/a&gt;&lt;a id="green_channel_contact" href="http://space.cnblogs.com/msg/send/%ef%bd%9e%e5%93%87%e5%93%87%ef%bd%9e" target="_blank"&gt;与我联系&lt;/a&gt; &lt;a id="green_channel_weibo" title="分享至新浪微博" onclick="ShareToTsina()" href="http://www.cnblogs.com/mazhenyu/admin/javascript:void(0);"&gt;&lt;img alt="" src="http://static.cnblogs.com/images/icon_sina.gif" /&gt;&lt;/a&gt; &lt;/div&gt;&#xD;
&lt;div id="digg_block"&gt;&#xD;
&lt;div id="author_profile"&gt;&#xD;
&lt;div id="author_profile_info" &gt;&#xD;
&lt;div id="author_profile_detail" &gt;&lt;a href="http://home.cnblogs.com/u/javazjh/"&gt;～哇哇～&lt;/a&gt;&lt;br /&gt;&lt;a href="http://home.cnblogs.com/u/javazjh/followees"&gt;关注 - 0&lt;/a&gt;&lt;br /&gt;&lt;a href="http://home.cnblogs.com/u/javazjh/followers"&gt;粉丝 - 1&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;&#xD;
&lt;div &gt;&lt;/div&gt;&#xD;
&lt;div id="author_profile_honor"&gt;&lt;/div&gt;&#xD;
&lt;div id="author_profile_follow"&gt;&lt;a onclick=";return false;" href="http://www.cnblogs.com/mazhenyu/admin/javascript:void(0);"&gt;+加关注&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;&#xD;
&lt;div id="div_digg"&gt;&#xD;
&lt;div  onclick=""&gt;&lt;span id="digg_count" &gt;0&lt;/span&gt;&lt;/div&gt;&#xD;
&lt;div  onclick=""&gt;&lt;span id="bury_count" &gt;0&lt;/span&gt;&lt;/div&gt;&#xD;
&lt;div &gt;&lt;/div&gt;&#xD;
&lt;div id="digg_tips" &gt;(请您对文章做出评价)&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&#xD;
&lt;div &gt;&lt;/div&gt;&#xD;
&lt;div id="post_next_prev"&gt;&lt;a  href="http://www.cnblogs.com/javazjh/archive/2011/09/08/2171725.html"&gt;&amp;#171; &lt;/a&gt;博主前一篇：&lt;a title="发布于2011-09-08 18:23" href="http://www.cnblogs.com/javazjh/archive/2011/09/08/2171725.html"&gt;细分曲面的GPU完全实现&lt;/a&gt;&lt;br /&gt;&lt;a  href="http://www.cnblogs.com/javazjh/archive/2011/09/08/2171729.html"&gt;&amp;#187; &lt;/a&gt;博主后一篇：&lt;a title="发布于2011-09-08 18:32" href="http://www.cnblogs.com/javazjh/archive/2011/09/08/2171729.html"&gt;基于需求驱动和OL-System的大规模城市建模&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&#xD;
&lt;div &gt;posted @ 2011-09-08 18:30 &lt;a href="http://www.cnblogs.com/javazjh/"&gt;～哇哇～&lt;/a&gt; 阅读(87) &lt;a href="http://www.cnblogs.com/javazjh/archive/2011/09/08/2171727.html#commentform"&gt;评论(0)&lt;/a&gt; &lt;a onclick="open_link('http://www.cnblogs.com/javazjh/admin/EditPosts.aspx?postid=2171727')" href="http://www.cnblogs.com/javazjh/archive/2011/09/08/2171727.html#" rel="nofollow"&gt;编辑&lt;/a&gt; &lt;a onclick="AddToWz(2171727);return false;" href="http://www.cnblogs.com/javazjh/archive/2011/09/08/2171727.html#"&gt;收藏&lt;/a&gt;&lt;/div&gt;&lt;img alt="" src="http://www.cnblogs.com/javazjh/aggbug/2171727.html?type=1&amp;amp;webview=1" width="1" height="1" /&gt; &lt;img src="http://www.cnblogs.com/mazhenyu/aggbug/2294458.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/mazhenyu/archive/2011/12/20/2294458.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/mazhenyu/archive/2011/12/08/2280660.html</id><title type="text">OpenGL: 3D坐标到屏幕坐标的转换逻辑（gluProject的实现）(转)</title><summary type="text">OpenGL:3D坐标到屏幕坐标的转换逻辑（gluProject的实现）遇到需要将3D坐标转换到屏幕坐标的问题，在网上很多朋友也在寻找答案，下面是glu中gluProject函数的实现。（实际上就是mesa的OpenGL实现版本）// 矩阵按行优先存储首先说一下opengl中的矩阵表示， 一般在c/c++中定义的矩阵和opengl中的矩阵分别是： /***************************************************************************** We define a 4x4 matrix array, OpenGL linear ma</summary><published>2011-12-08T05:57:00Z</published><updated>2011-12-08T05:57:00Z</updated><author><name>3D入魔</name><uri>http://www.cnblogs.com/mazhenyu/</uri></author><link rel="alternate" href="http://www.cnblogs.com/mazhenyu/archive/2011/12/08/2280660.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/mazhenyu/archive/2011/12/08/2280660.html"/><content type="html">&lt;p&gt;&lt;strong&gt;OpenGL:&amp;nbsp;3D坐标到屏幕坐标的转换逻辑（gluProject的实现）&#xD;
&lt;p &gt;&lt;/p&gt;遇到需要将3D坐标转换到屏幕坐标的问题，在网上很多朋友也在寻找答案，下面是glu中gluProject函数的实现。（实际上就是mesa的OpenGL实现版本）&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;div id="content"&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;// 矩阵按行优先存储&lt;/p&gt;&#xD;
&lt;p&gt;&lt;span style="font-family: 宋体; color: black; font-size: 9pt; mso-ascii-font-family: "  AR-SA??? mso-bidi-language: ZH-CN; mso-fareast-language: EN-US; mso-ansi-language: 1.0pt; mso-font-kerning: Roman?; New ?Times mso-bidi-font-family: mso-hansi-font-family: Times&gt;首先说一下&lt;/span&gt;&lt;span style="font-family: ; color: black; font-size: 9pt" lang="EN-US" mso-bidi-language: ZH-CN; mso-fareast-language: EN-US; mso-ansi-language: 1.0pt; mso-font-kerning: Roman?; New Times 宋体??? mso-fareast-font-family: AR-SA;&gt;opengl&lt;/span&gt;&lt;span style="font-family: 宋体; color: black; font-size: 9pt; mso-ascii-font-family: "  AR-SA??? mso-bidi-language: ZH-CN; mso-fareast-language: EN-US; mso-ansi-language: 1.0pt; mso-font-kerning: Roman?; New ?Times mso-bidi-font-family: mso-hansi-font-family: Times&gt;中的矩阵表示，&lt;/span&gt;&lt;span style="font-family: ; color: black; font-size: 9pt"  mso-bidi-language: ZH-CN; mso-fareast-language: EN-US; mso-ansi-language: 1.0pt; mso-font-kerning: Roman?; New Times 宋体??? mso-fareast-font-family: AR-SA;&gt; &lt;/span&gt;&lt;span style="font-family: 宋体; color: black; font-size: 9pt; mso-ascii-font-family: "  AR-SA??? mso-bidi-language: ZH-CN; mso-fareast-language: EN-US; mso-ansi-language: 1.0pt; mso-font-kerning: Roman?; New ?Times mso-bidi-font-family: mso-hansi-font-family: Times&gt;一般在&lt;/span&gt;&lt;span style="font-family: ; color: black; font-size: 9pt" lang="EN-US" mso-bidi-language: ZH-CN; mso-fareast-language: EN-US; mso-ansi-language: 1.0pt; mso-font-kerning: Roman?; New Times 宋体??? mso-fareast-font-family: AR-SA;&gt;c/c++&lt;/span&gt;&lt;span style="font-family: 宋体; color: black; font-size: 9pt; mso-ascii-font-family: "  AR-SA??? mso-bidi-language: ZH-CN; mso-fareast-language: EN-US; mso-ansi-language: 1.0pt; mso-font-kerning: Roman?; New ?Times mso-bidi-font-family: mso-hansi-font-family: Times&gt;中定义的矩阵和&lt;/span&gt;&lt;span style="font-family: ; color: black; font-size: 9pt" lang="EN-US" mso-bidi-language: ZH-CN; mso-fareast-language: EN-US; mso-ansi-language: 1.0pt; mso-font-kerning: Roman?; New Times 宋体??? mso-fareast-font-family: AR-SA;&gt;opengl&lt;/span&gt;&lt;span style="font-family: 宋体; color: black; font-size: 9pt; mso-ascii-font-family: "  AR-SA??? mso-bidi-language: ZH-CN; mso-fareast-language: EN-US; mso-ansi-language: 1.0pt; mso-font-kerning: Roman?; New ?Times mso-bidi-font-family: mso-hansi-font-family: Times&gt;中的矩阵分别是：&lt;/span&gt;&lt;span style="font-family: ; color: black; font-size: 9pt" lang="EN-US" mso-bidi-language: ZH-CN; mso-fareast-language: EN-US; mso-ansi-language: 1.0pt; mso-font-kerning: Roman?; New Times 宋体??? mso-fareast-font-family: AR-SA;&gt; &lt;br /&gt;/***************************************************************************** &lt;br /&gt;We define a 4x4 matrix array, OpenGL linear matrix format: &lt;br /&gt;referenced as Row,Column as: &lt;br /&gt;&lt;br /&gt;&lt;span style="background-color: #add5fe"&gt;| 0,0&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="background-color: #add5fe"&gt;0,1&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="background-color: #add5fe"&gt;0,2&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="background-color: #add5fe"&gt;0,3 |&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="background-color: #add5fe"&gt;|a0 a4 a8 a12| &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="background-color: #add5fe"&gt;| 1,0&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="background-color: #add5fe"&gt;1,1&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="background-color: #add5fe"&gt;1,2&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="background-color: #add5fe"&gt;1,3 |&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="background-color: #add5fe"&gt;|a1 a5 a9 a13| &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="background-color: #add5fe"&gt;| 2,0&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="background-color: #add5fe"&gt;2,1&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="background-color: #add5fe"&gt;2,2&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="background-color: #add5fe"&gt;2,3 |&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="background-color: #add5fe"&gt;|a2 a6 a10 a14| &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="background-color: #add5fe"&gt;| 3,0&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="background-color: #add5fe"&gt;3,1&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="background-color: #add5fe"&gt;3,2&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="background-color: #add5fe"&gt;3,3 |&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="background-color: #add5fe"&gt;|a3 a7 a11 a15| &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;span style="font-family: ; color: black; font-size: 9pt" lang="EN-US" mso-bidi-language: ZH-CN; mso-fareast-language: EN-US; mso-ansi-language: 1.0pt; mso-font-kerning: Roman?; New Times 宋体??? mso-fareast-font-family: AR-SA;&gt;*/ &lt;span style="font-family: 宋体; color: black; font-size: 9pt; mso-ascii-font-family: "  AR-SA??? mso-bidi-language: ZH-CN; mso-fareast-language: EN-US; mso-ansi-language: 1.0pt; mso-font-kerning: Roman?; New ?Times mso-bidi-font-family: mso-hansi-font-family: Times&gt;两者行和列正好相反，因此，对于一个&lt;/span&gt;&lt;span style="font-family: ; color: black; font-size: 9pt" lang="EN-US" mso-bidi-language: ZH-CN; mso-fareast-language: EN-US; mso-ansi-language: 1.0pt; mso-font-kerning: Roman?; New Times 宋体??? mso-fareast-font-family: AR-SA;&gt;4&amp;#215;4&lt;/span&gt;&lt;span style="font-family: 宋体; color: black; font-size: 9pt; mso-ascii-font-family: "  AR-SA??? mso-bidi-language: ZH-CN; mso-fareast-language: EN-US; mso-ansi-language: 1.0pt; mso-font-kerning: Roman?; New ?Times mso-bidi-font-family: mso-hansi-font-family: Times&gt;的矩阵&lt;/span&gt;&lt;span style="font-family: ; color: black; font-size: 9pt" lang="EN-US" mso-bidi-language: ZH-CN; mso-fareast-language: EN-US; mso-ansi-language: 1.0pt; mso-font-kerning: Roman?; New Times 宋体??? mso-fareast-font-family: AR-SA;&gt;GLdouble m[16], &lt;/span&gt;&lt;span style="font-family: 宋体; color: black; font-size: 9pt; mso-ascii-font-family: "  AR-SA??? mso-bidi-language: ZH-CN; mso-fareast-language: EN-US; mso-ansi-language: 1.0pt; mso-font-kerning: Roman?; New ?Times mso-bidi-font-family: mso-hansi-font-family: Times&gt;那么在操作这个矩阵时必须小心&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;span style="font-family: ; color: black; font-size: 9pt" lang="EN-US" mso-bidi-language: ZH-CN; mso-fareast-language: EN-US; mso-ansi-language: 1.0pt; mso-font-kerning: Roman?; New Times 宋体??? mso-fareast-font-family: AR-SA;&gt;&lt;span style="font-family: 宋体; color: black; font-size: 9pt; mso-ascii-font-family: "  AR-SA??? mso-bidi-language: ZH-CN; mso-fareast-language: EN-US; mso-ansi-language: 1.0pt; mso-font-kerning: Roman?; New ?Times mso-bidi-font-family: mso-hansi-font-family: Times&gt;&lt;/span&gt;&lt;/span&gt;&amp;nbsp;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;span style="font-family: ; color: black; font-size: 9pt" lang="EN-US" mso-bidi-language: ZH-CN; mso-fareast-language: EN-US; mso-ansi-language: 1.0pt; mso-font-kerning: Roman?; New Times 宋体??? mso-fareast-font-family: AR-SA;&gt;&lt;span style="font-family: 宋体; color: black; font-size: 9pt; mso-ascii-font-family: "  AR-SA??? mso-bidi-language: ZH-CN; mso-fareast-language: EN-US; mso-ansi-language: 1.0pt; mso-font-kerning: Roman?; New ?Times mso-bidi-font-family: mso-hansi-font-family: Times&gt;&lt;/span&gt;&lt;/span&gt;&amp;nbsp;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;span style="background-color: #fef4c4"&gt;GLint gluProject(GLdouble objx, GLdouble objy, GLdouble objz,&lt;/span&gt;&lt;br /&gt;&lt;span style="background-color: #fef4c4"&gt;const GLdouble model[16], const GLdouble proj[16],&lt;/span&gt;&lt;br /&gt;&lt;span style="background-color: #fef4c4"&gt;const GLint viewport[4],&lt;/span&gt;&lt;br /&gt;&lt;span style="background-color: #fef4c4"&gt;GLdouble * winx, GLdouble * winy, GLdouble * winz)&lt;/span&gt;&lt;br /&gt;{&lt;br /&gt;/* matrice de transformation */&lt;br /&gt;GLdouble in[4], out[4];&lt;br /&gt;/* initilise la matrice et le vecteur a transformer */&lt;br /&gt;in[0] = objx;&lt;br /&gt;in[1] = objy;&lt;br /&gt;in[2] = objz;&lt;br /&gt;in[3] = 1.0;&lt;br /&gt;transform_point(out, model, in);&lt;br /&gt;transform_point(in, proj, out);&lt;br /&gt;/* d&amp;#8217;ou le resultat normalise entre -1 et 1 */&lt;br /&gt;if (in[3] == 0.0)&lt;br /&gt;return GL_FALSE;&lt;br /&gt;in[0] /= in[3];&lt;br /&gt;in[1] /= in[3];&lt;br /&gt;in[2] /= in[3];&lt;br /&gt;/* en coordonnees ecran */&lt;br /&gt;*winx = viewport[0] + (1 + in[0]) * viewport[2] / 2;&lt;br /&gt;*winy = viewport[1] + (1 + in[1]) * viewport[3] / 2;&lt;br /&gt;/* entre 0 et 1 suivant z */&lt;br /&gt;*winz = (1 + in[2]) / 2;&lt;br /&gt;return GL_TRUE;&lt;br /&gt;}&lt;br /&gt;/*&lt;br /&gt;* Transform a point (column vector) by a 4x4 matrix. I.e. out = m * in&lt;br /&gt;* Input: m - the 4x4 matrix&lt;br /&gt;* in - the 4x1 vector&lt;br /&gt;* Output: out - the resulting 4x1 vector.&lt;br /&gt;*/&lt;/p&gt;&#xD;
&lt;p&gt;&lt;br /&gt;&lt;span style="background-color: #fef4c4"&gt;static void&lt;/span&gt;&lt;br /&gt;&lt;span style="background-color: #fef4c4"&gt;transform_point(GLdouble out[4], const GLdouble m[16], const GLdouble in[4])&lt;/span&gt;&lt;br /&gt;{&lt;br /&gt;#define M(row,col) m[col*4+row]&lt;br /&gt;out[0] =&lt;br /&gt;M(0, 0) * in[0] + M(0, 1) * in[1] + M(0, 2) * in[2] + M(0, 3) * in[3];&lt;br /&gt;out[1] =&lt;br /&gt;M(1, 0) * in[0] + M(1, 1) * in[1] + M(1, 2) * in[2] + M(1, 3) * in[3];&lt;br /&gt;out[2] =&lt;br /&gt;M(2, 0) * in[0] + M(2, 1) * in[1] + M(2, 2) * in[2] + M(2, 3) * in[3];&lt;br /&gt;out[3] =&lt;br /&gt;M(3, 0) * in[0] + M(3, 1) * in[1] + M(3, 2) * in[2] + M(3, 3) * in[3];&lt;br /&gt;#undef M&lt;br /&gt;}&lt;/p&gt;&#xD;
&lt;p&gt;&lt;br /&gt;参考：&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://www.soidc.net/articles/1215485053486/20081129/1215945559526_1.html"&gt;http://www.soidc.net/articles/1215485053486/20081129/1215945559526_1.html&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://sutiany.itpub.net/post/6261/33673"&gt;http://sutiany.itpub.net/post/6261/33673&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://www.opengl.org/wiki/GluProject_and_gluUnProject_code"&gt;http://www.opengl.org/wiki/GluProject_and_gluUnProject_code&lt;/a&gt;&lt;/p&gt;&lt;/div&gt;&lt;img src="http://www.cnblogs.com/mazhenyu/aggbug/2280660.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/mazhenyu/archive/2011/12/08/2280660.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry></feed>
