HOOPS3D可视化入门教程三大体概念和数据结构.docx

上传人:b****7 文档编号:8720557 上传时间:2023-02-01 格式:DOCX 页数:9 大小:49.15KB
下载 相关 举报
HOOPS3D可视化入门教程三大体概念和数据结构.docx_第1页
第1页 / 共9页
HOOPS3D可视化入门教程三大体概念和数据结构.docx_第2页
第2页 / 共9页
HOOPS3D可视化入门教程三大体概念和数据结构.docx_第3页
第3页 / 共9页
HOOPS3D可视化入门教程三大体概念和数据结构.docx_第4页
第4页 / 共9页
HOOPS3D可视化入门教程三大体概念和数据结构.docx_第5页
第5页 / 共9页
点击查看更多>>
下载资源
资源描述

HOOPS3D可视化入门教程三大体概念和数据结构.docx

《HOOPS3D可视化入门教程三大体概念和数据结构.docx》由会员分享,可在线阅读,更多相关《HOOPS3D可视化入门教程三大体概念和数据结构.docx(9页珍藏版)》请在冰豆网上搜索。

HOOPS3D可视化入门教程三大体概念和数据结构.docx

HOOPS3D可视化入门教程三大体概念和数据结构

HOOPS3D可视化入门教程三:

大体概念和数据结构

上篇文章介绍了HOOPS的要紧模块,这篇文章将要向大伙儿介绍HOOPS的数据结构和穿插其中的一些大体概念。

这些内容要紧包括在3dGS模块内。

一、保留模式

HOOPS采纳保留画图模式(retained mode)。

所谓保留模式是相关于传统的非保留模式而言的。

做过OpenGL编程的人都知道,OpenGL的绘制都是通过挪用一系列画图命令来实现的,一般是在一个叫updateGL的函数里。

除非你自己把相关画图信息保留起来,不然出了那个函数OpenGL就不认帐了,也确实是说你无法从OpenGL里面再获取你曾经绘制的一些图元信息。

而保留模式那么不如此,它把绘制过的命令和图形会保留起来,放在特定的数据结构中,从而使得咱们能够事后随时读取这些数据。

相较于非保留模式,保留模式能够提供更高的效率(因为数据都在内部,下次绘制时不需要再读取),更快的交互(通过特定的基于数据结构的算法,能够加速选取、高亮等等交互操作),还有更方便的编程接口。

固然凡事都有两面性,保留模式也有它的缺点,其中之一确实是它增加了程序的内存消耗(用于存储那个数据结构)。

但咱们以为如此的代价是完全值得的。

二、基于段的数据结构

HOOPS的数据结构简单讲是基于段(segment)的树状结构。

最上层是根段,为“/”。

该数据结构和Linux文件系统有着一曲同工之妙,有Linux利用体会的同窗将会很容易明白得。

Linux的根目录的符号也是“/”,所有文件系统中的文件或文件夹的途径都以该符号开头。

文件夹出名字,段也出名字。

犹如文件夹内能够有文件和子文件夹,segment下能够有sub segment。

如此的层次结构能够专门好地构建咱们想要的图形。

打开一个段的HOOPS函数是HC_Open_Segment,它有一个参数,确实是那个段的名字。

咱们能够传一个空字符串给它,从而创建一个匿名段。

若是已经存在那个名字的段,那么该函数会打开那个段,不然就自动创建一个新段。

打开后,咱们就能够够在该段内做任何咱们想要做的操作。

操作终止,记得用HC_Close_Segment来关闭那个段。

HOOPS采纳和OpenGL一样的上下文机制,那确实是“状态机(State Machine)”。

所谓状态机,形象地讲确实是一旦改变了状态,那么接下去不论程序运行到哪里,该状态将一直保留,直到下次改变状态。

在HOOPS中,打开一个段事实上就意味着进入了一个状态机,直到你关闭那个段,你所有的操作都将在如此一个上下文中进行。

具体来讲确实是,打开一个段,然后你能够跳转到任意的程序位置完成具体的绘制任务,然后关闭段,这一系列操作没有必要在一个函数中完成。

这无疑大大增加了咱们编程的灵活性。

举个例子,咱们想要绘制一所屋子,屋子有房顶、窗户还有门,咱们能够用如下代码:

HC_Open_Segment (“/”);

HC_Open_Segment (“house”);

HC_Open_Segment (“roof”);

HC_Close_Segment ();

HC_Open_Segment (“door”);

HC_Open_Segment (“windows”);

HC_Open_Segment (“window1”);

HC_Close_Segment ();

HC_Open_Segment (“window2”);

HC_Close_Segment ();

HC_Open_Segment (“window3”);

HC_Close_Segment ();

HC_Close_Segment ();

HC_Close_Segment ();

HC_Close_Segment ();

事实上咱们创建了如下的树状结构:

 

创建了段以后,咱们需要有相应的方式能够找到那个段,这时就会用到段的途径。

和Linux上的文件途径类似,段的途径也分为两种:

相对途径和绝对路径。

咱们打开一个段,进入该段的状态机,若是要打开它下面的子段,就能够够用相对途径。

HOOPS会自动地在该段下面找给出的段名,若是找不到,那么会报错。

绝对途径那么是从根段名“/”开始,慢慢地把段名添加上去,直到咱们想要找的段为止,完整的途径确实是绝对途径。

例如咱们要找第三扇窗户,相关于house的相对途径是:

”windows/window3”,而绝对途径是:

”/house/windows/window3。

咱们能够用“.”和“..”来别离指代当前目录和父目录,这又跟Linux上的途径利用适应是一致的。

这种简称只能用于相对途径中。

为了能够更方便地提供段的途径,HOOPS中还有一套特有的符号,叫做“wildcards”,能够同时指代多个不同的途径,有以下几种:

1. 逗号wildcard。

那个是最简单的一种。

有时候咱们需要同时对多个可列举的段进行统一处置,例如咱们想用同一种颜色来装饰roof和door(尽管这种做法很少见……),咱们就能够够用如此的一个途径来同时指代这两个段:

/house/(door,roof)。

2. 通配符。

能够用“*”来匹配0个或多个字符,“%”来匹配单个字符,那个跟咱们用Windows系统搜索功能是一样的,也和正那么表达式相一致。

3. 递归wildcards。

其实上面两个并非是HOOPS所特有的,在其他也有见到。

可是HOOPS还有一个它特有的符号,那确实是“…”,该符号能够指代一个段名或一串途径上的段名。

例如咱们能够用/house/…/window1来指代第一扇窗户,而不用去管当中到底隔了多少个段。

该种方式超级长适合于咱们不清楚house到window1之间到底存在着如何的父子结构。

尽管方面,可是若是咱们确切地明白window1的完整途径,那就不要这么写了,因为HOOPS是通过自顶向下的方式搜索取得window1,因此需要消耗必然的计算量。

另外,该符号还能够递归地表示一个段的所有子段和子段的子段。

若是咱们要对一个段内的所有子段进行某项修改,那么那个wildcards真是再适合只是了。

三、几何信息(Geometry)

segment像文件夹一样,它本身并无实质的东西,而只是一个容器。

真正绘制出车的形状,还需要具体的几何信息。

因此,段内部除能够存储子段外,还能够存储Geometry。

HOOPS中的Geometry丰硕多样,囊括了点、边、面、壳(shell)、网络(mesh)等等大体上大伙儿能够想到的图元。

这些大体几何通过彼此组合,能够组成加倍复杂的图像信息,这是一个自底向上的组建进程。

例如咱们能够通过下面的方式插入一个点和一条直线:

HC_Open_Segment (“myseg”);

HC_Insert_Marker (0, 1, 1);

HC_Insert_Line (-1, -1, -1, 2, 2, 2);

HC_Close_Segment ();

HC_Insert_Marker需要传入三个浮点参数,也确实是一个点的三维坐标。

HC_Insert_Line需要传入六个参数,为一个线段的起始点和终止点的三维坐标。

咱们能够用下面的代码插入一个多边形的面:

HC_POINT pts[4] = 

{HC_POINT(0, 0, 0), HC_POINT(1, 0, 0), HC_POINT(1, 1, 0), HC_POINT(0, 1, 0)};

HC_Open_Segment (“mypolygon”);

HC_Insert_Polygon (4, pts);

HC_Close_Segment ();

HC_Insert_Polygon需要传入两个参数,别离是多边形极点个数和寄存极点三维坐标的数组。

该函数代表了HOOPS中一类参数,确实是对一群点进行操作。

需要注意的是,这种函数在内部会对传入的三维坐标数组进行拷贝,因此若是你传入的坐标数组是动态申请出来的,在挪用完该类函数以后,必须手动地将其释放掉。

除大体的点、线、多边形等,HOOPS还提供了两个相对高级的图元,别离是Shell和Mesh。

在进行大型场景构建时,这两个图元是超级经常使用的,例如咱们用三角网格构建一个人的模型,那么那个三角模型确实是一个shell。

shell有三个层次的图元组成,别离是node(点)、edge(边)和face(面),这三部份彼此连接形成一个整体。

mesh和shell超级类似,一样由点边面三部份组成,唯一的区别是mesh它不能形成一个封锁的类似于人如此的模型,它只能是一张面,而且只能是一张四边形面,例如一张四边形纸。

如此的区别使得在处置特定的模型时,若是mesh能够知足应用需要,那么mesh将会比shell表现得高效得多。

下面举例创建一个立方体,并在它的一个面上接一个金字塔体:

HC_POINT pts[] = {

HC_POINT (0, 0, 1), HC_POINT (1, 0, 1),

HC_POINT (1, 1, 1), HC_POINT (0, 1, 1),

HC_POINT (0, 0, 2), HC_POINT (1, 0, 2), 

HC_POINT (1, 1, 2), HC_POINT (0, 1, 2),

HC_POINT (0.5, 0.5, 2.5)

};

int flist[] = {

4, 0, 3, 2, 1,

4, 0, 1, 5, 4,

4, 1, 2, 6, 5,

4, 2, 3, 7, 6,

4, 3, 0, 4, 7,

3, 4, 5, 8,

3, 5, 6, 8,

3, 6, 7, 8,

3, 7, 4, 8

};

HC_Open_Segment ("mymodel");

HC_Insert_Shell (9, pts, 41, flist);

HC_Close_Segment ();

HC_Insert_Shell需要四个参数,别离是shell的极点个数,极点数组,面列表数组的长度,面列表数组指针。

极点个数和数组专门好理解,确实是具体的各个极点的三维坐标。

面列表是如此的格式:

面极点个数n, 第一个极点序号,第二个极点序号,…,第n个极点序号。

例如flist第一行,4表示该面由四个极点组成,也确实是一个四边形。

然后,0,3,2,1表示由pts那个数组中的第0、3、二、1号点组成那个面。

需要注意的是HC_Insert_Shell的第三个参数实质flist那个数组本身的长度,而不是将要构建的shell上面的个数。

例如那个例子中面的个数为9,但flist的长度为41。

成效如以下图所示:

 

四、段的属性

上文中,咱们在HOOPS中创建了一个屋子,假设咱们此刻已经用几何图元将屋子给绘制出来了,可是光有结构还不行,至少咱们还需要给它上色,或许我们还会通过贴上不同的纹理来表示不同的材料。

HOOPS的段结构中除能够寄存Geometry,还能够寄存属性Attribute。

咱们经常使用的属性包括:

可见性(Visibility),颜色(Color),可选择性(Selectability),点、边、字体的大小,光照(light),渲染属性(rendition)等等。

乃至能够添加咱们自概念的属性(User defined attribution)。

能够说,HOOPS的属性功能是超级全面而壮大的。

和插入几何一样,要修改一个segment的属性,咱们需要进入该segment的状态机,亦即要第一打开那个段。

下面以house模型为例:

HC_Open_Segment (“house”);

HC_Open_Segment (“roof”);

//add roof geometry here...

HC_Set_Color (“geometry=red”);

HC_Close_Segment ();

HC_Open_Segment (“door”);

//add door geometry here...

HC_Set_Color (“geometry=grey”);

HC_Close_Segment ();

HC_Close_Segment ();

如此,咱们将屋顶和门别离设置成了红色和灰色。

又比如适才咱们自创的那个集合模型,这回,咱们要让它再也不空白一片了,咱们给它点颜色看看(J):

HC_Open_Segment ("mymodel");

HC_Set_Color ("faces=grey,edges=green");

HC_Set_Visibility ("edges=on");

HC_Insert_Shell (9, pts, 41, flist);

HC_Close_Segment ();

咱们设置了mymodel那个段的两个属性,颜色和可见性。

在设置颜色中,咱们设置面为灰色,而设置边为绿色;在设置可见性上,咱们设置边为可见。

什么缘故不设置面为可见呢?

因为在HOOPS中,有些是默许可见的,而有些是默许不可兼得;而shell的面是默许可见的,edges那么恰好是默许不可见的。

下面是新的成效图,怎么样,和之前不一样了吧?

记住那个模型,往后的教程中咱们还会多次用到,比如给它贴上漂亮的纹理、光照等等,还有动画。

上面在设置颜色时,咱们用一个字符串命令同时设置了面和边的颜色。

这种格式化的字符串在HOOPS中被大量应用,几乎同意字符串作为参数的HOOPS函数中都有如此的格式化命令。

faces和edges关于HC_Set_Color函数来讲,是能够设置颜色的对象,而等号后面是具体的值,中间用逗号分隔。

若是没有显式地说明设置对象,那么确实是everything,也确实是所有对象。

该格式化字符串有很多相关利用技术,具体能够参看HOOPS的帮忙文档,下面仅举几个例子来讲明格式化字符串的大体用法:

1. “red,faces=green”,设置所有几何图元为红色,只有面为绿色;

2. “markers=edges=black”,点和边为黑色;

3. “!

edges=(r=0.5 g=0.5 b=0.5)”,非边的图元颜色都设置为灰色。

至于设置对象是复数仍是单数是无所谓的,即edges和edge的作用成效完全一样。

五、属性的继承

属性(Attribute)是能够被继承的,就像面向对象的编程语言里面类的继承一样。

关于绝大多数属性来讲,继承的方向是子段从父段中继承属性。

这种特性有时候对咱们来讲能够提供极大的方便。

回忆咱们之前创建的house,它有三扇窗户,一样来讲,一座屋子的窗户颜色都是一样的,若是没有属性的继承,那么咱们可能就需要针对每一个窗户段设置它的颜色属性。

关于咱们这座小屋子来讲,这还能够同意,可是某天你发达了,让你构建一桩拥有成千上万扇窗户的摩天大楼,那恐怕确实是场灾难了。

有了属性的继承,世界仍是美好的。

咱们能够在windows那个段设置颜色,那么所有该段下面的子段都自动继承了该颜色属性,再不用咱们单独去设置了。

但是,问题也随之显现。

整幢大楼里毕竟有些窗户所在的房间住着不寻常的人,而这些窗户咱们希望显示出不一样的颜色,以彰显这些人的显赫身份。

那如何幸免这些窗户继承父段的颜色呢?

咱们能够单独设置这些窗户的颜色,HOOPS在绘制这些窗时,会优先利用单独设置在这些段上的颜色;若是没有单独设置(如同绝大多数窗户),那么HOOPS才会自动地去读取父段的该属性,直到最上层的根节点“/”。

若是根节点也没有设置该属性,HOOPS就会报错。

关于绝大多数的属性来讲,HOOPS正是遵循这种“追根溯源”的方式来确信一个属性的值的。

尽管这种直接覆盖的属性占大多数,可是有些属性不是直接覆盖取得的,例如旋转矩阵。

要计算一个图元最终活着界坐标上的位置,咱们需要从根节点开始,慢慢地累加旋转矩阵,一直到该段,如此计算所得的旋转矩阵才是最后真正的旋转矩阵。

尽管咱们能够操纵一个特定的段的属性,可是有时候咱们仍是想要强制整个段表现为同一种属性,而不管底下各个子段是不是单独设置了该属性。

有些属性就提供了如此的功能,其中之一确实是颜色属性。

当咱们用鼠标选中了某一个segment以后,咱们希望整个段都显示一种高亮色,而不管该段内部子段的单独颜色。

这时,咱们需要用到颜色的属性锁。

能够通过挪用下面的代码来对颜色加锁:

    HC_Open_Segment(“myseg”);    

      HC_Set_Color("red"); 

      HC_Set_Rendering_Options("attribute lock = color"); 

    HC_Close_Segment();

如此,myseg那个段的颜色就被锁定为红色。

若是后续操作中咱们再也不需要对颜色进行锁定,那么能够利用HC_UnSet_Rendering_Option (“attribute lock”)。

六、特殊的段——包括段和样式段

上面介绍的段都是HOOPS中的一般类型的段。

另外,HOOPS还有包括段(included segment)和样式段(style segment)。

这些段的功能事实上都能够用一般段来实现,可是正因为引入了这些特殊类型的段,咱们能够将HOOPS的数据结构设计得更为精致和高效,咱们的程序结构性也更好。

再回忆咱们之前给的house模型。

咱们在屋子上添加了三扇窗户。

一样来讲,一幢屋子上的窗户长得都是差不多的,因此咱们想到是不是能够只设计窗户一次,而三次重复利用呢?

能够的,HOOPS里面利用的确实是包括段(included segment)。

包括段事实上确实是一次概念,多次重复利用,它提高了代码的利用率,也提高了内存利用率。

事实上包括段和C/C++语言中的头文件是很像的,咱们编写一次头文件,然后在需要用到的地址通过#include就能够够将其包括进来,而不需要另外再写。

包括机制除提高效率之外,还能够方便后续的保护,例如当咱们想要更新窗户的样式时,只需要在概念处修改一次,由于三处窗户都是包括该窗户的,因此这三处就自动加载了新的样式。

咱们再也不需要一个个地别离去修改,既提高了效率,又减少了犯错的可能。

包括段一般是针对含有几何信息的段(固然,由于包括段本质上仍是一般的段,因此它能够包括属性),而样式段那么仅包括属性。

有些时候,咱们需要重用的可能仅仅是一套样式,例如颜色、大小、光照等,关于具体的几何图元咱们却爱好不大,那个时候就能够够用到HOOPS的样式段。

下面的代码演示了如何利用Style segment:

HC_Open_Segment (“mystyle”);

HC_Set_Color (“edges=red,faces=(diffuse=(r=0.5 g=0.2 b=0.3))”);

HC_Close_Segment ();

 

HC_Open_Segment (“myseg1”);

HC_Style_Segment (“mystyle”);

//Insert my geometry...

HC_Close_Segment ();

HC_Open_Segment (“myseg2”);

HC_Style_Segment (“mystyle”);

//Insert my another geometry...

HC_Close_Segment ();

这段创建了一个样式段,两个一般段,这两个一般段插入了不同的几何图元,可是利用了一样的样式段,因此它们显示出来后都是红色的边,紫色的面。

七、键值

键值(一般是HC_KEY类型)是HOOPS中一个超级重要的概念。

HC_KEY本质上是一个32位带符号的整型。

前文中咱们说,能够通过段的名字和途径(相对途径或绝对途径)来索引一个段,于此同时咱们也能够用键值来索引段。

HC_Open_Segment会返回一个long型的整数,确实是打开的那个段的键值。

注意,新版本的HOOPS取消了在API谓词前的K变形,而因此之前这些K变形函数都返回键值了。

19版本之前的HOOPS,HC_Open_Segment返回是void类型的,而要返回段的键值,那么必需显示地挪用HC_KOpen_Segment。

在新版本中这样的函数已经去掉了,HC_Open_Segment直接返回键值。

除段能够有键值,几何图元也能够有键值。

HC_Insert_Line、HC_Insert_Polygon等插入图元的函数都会返回一个键值,该键值唯一的指代新插入的几何图元。

HOOPS中大部份的API函数都有By_Key结尾的变形,这一类的变形函数实现和它们原型函数一样的功能,唯一的区别是它们的入口参数是要操作的段的键值,而不是字符形式的名字了。

既然此刻咱们有两种方式来找到一个段,那么咱们就需要详细地比较一下这两种方式各自的好坏。

1. 存储键值只需要一个32位整数,存储段名那么需要一个字符数组,而且长度不定;

2. 用键值来找到一个段速度要比用字符途径快;

3. 段名比较直观,便于调试的时候肉眼判定正误,键值那么比较抽象,一眼看上去不太容易分辨对错;

4. 段名还有途径支持之前提到的wildcards,因此能够同时指代多个不同的段,可是键值是唯一的,它只能指代一个段或几何图元;

5. 关于几何图元来讲,咱们只能够用键值去找到它们,因为它们是没有字符形式的名字的;

6. 关于匿名段来讲,由于咱们没有赋给它任何段名(应该说是空的段名),因此也就无法用段名来索引它,而只能用键值。

以上只是我目前发觉并整理的不同的地方,如后续有新发觉,那么会继续补充。

一样来讲,系统返回的键值是负数。

咱们能够通过HC_Renumber_Key来修改系统给咱们的键值。

若是咱们调试的时候发觉一个键值为0或正数,那么要么是咱们修改了,要么是程序在哪个地址犯错了。

那个概念虽小,可是在实际操作中却是超级有效的。

另外,为了确保某些HOOPS API操作成功,咱们能够在操作终止后将取得的键值跟INVALID_KEY进行比较。

INVALID_KEY是HOOPS预概念的一个值,它表示若是API执行失败返回的错误键值。

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 人文社科 > 文化宗教

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1