几何体的绘制
概述
本章将介绍一些创建几何体元素的方法。通常我们有这样几种处理几何体的手段:底层手段是使用松散封装的OpenGL基元;中级手段是使用 OpenSceneGraph的基本几何体;高级手段是从文件读入模型。本章教程将主要介绍底层手段的实现方法。这种实现具有很强的灵活性,相应的工作量也比较大。应用于场景图形级别的几何体通常是从文件读入的,因而顶点的跟踪和处理工作将由文件读取插件完成。
背景
下面将对几个常用的类作简要的介绍:
?Geode类
Geode类派生自Node节点类。节点类(包括Geode)可以作为场景图形的叶节点添加。Geode 类的实例可以与任意多个可绘制对象Drawable类相关联。
?Drawable类
作为可绘制对象基类的Drawable类是一个纯虚类,它有六个派生类。其中Geometry类中可以直接指定顶点数据,或者指定任意数目的几何基元PrimitiveSet类与其关联。
顶点和顶点属性数据(颜色,法线,纹理坐标)是保存在数组中的。多个顶点可以共享同一种颜色,法线和纹理坐标,同时我们还可以使用索引将顶点数组映射给颜色,法线或纹理坐标的数组。
?PrimitiveSet类
这个类松散地封装了OpenGL的绘图基元,包括点(POINTS),线(LINES),多段线(LINE_STRIP),封闭线(LINE_LOOP),四边形(QUADS),多边形(POLYGON)等。
代码
下面的代码将设置一个用于显示场景的视窗,一个作为场景图形根节点的Group类实例,一个用于记录可绘制对象(Drawable)的几何体节点(Geode),以及一个记录顶点和顶点相关数据的Geometry类实例。本例中我们将渲染一个金字塔的形状。
...
int main()
{
...
osg::Group* root = new osg::Group();
osg::Geode* pyramidGeode = new osg::Geode();
osg::Geometry* pyramidGeometry = new osg::Geometry();
现在我们将金字塔几何体与Geode关联,并将Geode叶节点添加到场景图形的根节点。
pyramidGeode->addDrawable(pyramidGeometry);
root->addChild(pyramidGeode);
声明一个顶点数组。每个顶点有三个坐标值,也就是一个Vec3类的实例。osg::Vec3Array 类的实例可以用来保存顶点数组。它派生自 STL库的vector模板,因此我们可以使用push_back方法向其中追加数组元素。该方法的作用是在向量数组的末尾添加一个元素,因此数组中第一个元素的索引值为0,紧随其后的第二个元素为1,以此类推。
我们使用Z轴向上的右手坐标系作为参照,数组元素0-4用于表达金字塔形体的五个顶点。
osg::Vec3Array* pyramidVertices = new osg::Vec3Array;
pyramidVertices->push_back( osg::Vec3( 0, 0, 0) ); // 左前
pyramidVertices->push_back( osg::Vec3(10, 0, 0) ); // 右前
pyramidVertices->push_back( osg::Vec3(10,10, 0) ); // 右后
pyramidVertices->push_back( osg::Vec3( 0,10, 0) ); // 左后
pyramidVertices->push_back( osg::Vec3( 5, 5,10) ); // 塔尖
将这一顶点集合关联到Geometry实例上,后者已经与场景的Geode叶节点相关联。
pyramidGeometry->setVertexArray( pyramidVertices );
现在我们创建几何基元类PrimitiveSet的实例并添加到金字塔几何体上。金字塔底部的四个点组成一个基面,可以使用 DrawElementsUint类来实现。这个类同样继承自STL库的vector模板,我们可以使用push_back顺序向其中添加元素。为了保证背面剔除(backface cullling)的正确,我们需要按照逆时针的顺序添加顶点数据。类的构造函数使用几何基元枚举类型(与OpenGL的几何基元枚举类型相同)作为输入参数,另一个输入参数是作为起始点的顶点索引值。
osg::DrawElementsUInt* pyramidBase =
new osg::DrawElementsUInt(osg::PrimitiveSet::QUADS, 0);
pyramidBase->push_back(3);
pyramidBase->push_back(2);
pyramidBase->push_back(1);
pyramidBase->push_back(0);
pyramidGeometry->addPrimitiveSet(pyramidBase);
重复这一过程,添加金字塔的每个面。再次注意,顶点是以逆时针为顺序添加的。
osg::DrawElementsUInt* pyramidFaceOne =
new osg::DrawElementsUInt(osg::PrimitiveSet::TRIANGLES, 0);
pyramidFaceOne->push_back(0);
pyramidFaceOne->push_back(1);
pyramidFaceOne->push_back(4);
pyramidGeometry->addPrimitiveSet(pyramidFaceOne);
osg::DrawElementsUInt* pyramidFaceTwo =
new osg::DrawElementsUInt(osg::PrimitiveSet::TRIANGLES, 0);
pyramidFaceTwo->push_back(1);
pyramidFaceTwo->push_back(2);
pyramidFaceTwo->push_back(4);
pyramidGeometry->addPrimitiveSet(pyramidFaceTwo);
osg::DrawElementsUInt* pyramidFaceThree =
new osg::DrawElementsUInt(osg::PrimitiveSet::TRIANGLES, 0);
pyramidFaceThree->push_back(2);
pyramidFaceThree->push_back(3);
pyramidFaceThree->push_back(4);
pyramidGeometry->addPrimitiveSet(pyramidFaceThree);
osg::DrawElementsUInt* pyramidFaceFour =
new osg::DrawElementsUInt(osg::PrimitiveSet::TRIANGLES, 0);
pyramidFaceFour->push_back(3);
pyramidFaceFour->push_back(0);
pyramidFaceFour->push_back(4);
pyramidGeometry->addPrimitiveSet(pyramidFaceFour)
定义一个Vec4的数组,用于保存颜色值。
osg::Vec4Array* colors = new osg::Vec4Array;
colors->push_back(osg::Vec4(1.0f, 0.0f, 0.0f, 1.0f) ); //索引0 红色
colors->push_back(osg::Vec4(0.0f, 1.0f, 0.0f, 1.0f) ); //索引1 绿色
colors->push_back(osg::Vec4(0.0f, 0.0f, 1.0f, 1.0f) ); //索引2 蓝色
colors->push_back(osg::Vec4(1.0f, 1.0f, 1.0f, 1.0f) ); //索引3 白色
下一步要将顶点数组的元素与颜色数组的元素对应起来。我们将声明一个与顶点数组有相同个数元素的向量组。它将负责连接各个顶点与颜色。该向量组的索引对应顶点数组的元素,其取值对应颜色数组的索引。如果需要将顶点数组与法线数组或者纹理坐标数组一一对应,那么还需重复这一步骤。
注意在本例中,我们需要将5个顶点对应到4种颜色上。因此顶点数组的元素0(左下)和元素4(塔尖)都需要对应到颜色数组元素0(红色)上。
osg::TemplateIndexArray
colorIndexArray =
new osg::TemplateIndexArray
colorIndexArray->push_back(1); // vertex 1 assigned color array element 1
colorIndexArray->push_back(2); // vertex 2 assigned color array element 2
colorIndexArray->push_back(3); // vertex 3 assigned color array element 3
colorIndexArray->push_back(0); // vertex 4 assigned color array element 0
下一步,我们将颜色数组以及刚才创建的颜色索引数组与几何体相关联,并设置绑定模式为“按顶点绑定”。
pyramidGeometry->setColorArray(colors);
pyramidGeometry->setColorIndices(colorIndexArray);
pyramidGeometry->setColorBinding(osg::Geometry::BIND_PER_VERTEX);
osg::Vec2Array* texcoords = new osg::Vec2Array(5);
(*texcoords)[0].set(0.00f,0.0f);
(*texcoords)[1].set(0.25f,0.0f);
(*texcoords)[2].set(0.50f,0.0f);
(*texcoords)[3].set(0.75f,0.0f);
(*texcoords)[4].set(0.50f,1.0f);
pyramidGeometry->setTexCoordArray(0,texcoords);
现在我们已经创建了一个几何体节点,并将其添加到场景中。其中的几何体是可以复用的,例如,如果我们希望在第一个金字塔右侧15个单位再放置第二个金字塔,那么我们可以将这个Geode节点作为位置变换节点的子节点,并再次添加到场景当中。
//初始化位置变换节点
osg::PositionAttitudeTransform* pyramidTwoXForm =
new osg::PositionAttitudeTransform();
//使用osg::Group的addChild方法,将位置变换节点添加到根节点的子节点上,并将金字塔节点作为变换节点的子节点
root->addChild(pyramidTwoXForm);
pyramidTwoXForm->addChild(pyramidGeode);
// 初始化一个Vec3实例,用于改变模型在场景中的位置
osg::Vec3 pyramidTwoPosition(15,0,0);
pyramidTwoXForm->setPosition( pyramidTwoPosition );
最后,设置视窗类并进入仿真循环。
osgViewer::Viewer viewer;
viewer.setSceneData( root );
viewer.run();
继续到下一节使用StateSet创建带有纹理的几何体
使用StateSet创建带有纹理的几何体
目标
向使用OpenGL基元绘制的基本几何体添加纹理。
背景
上一个教程介绍了使用OpenGL基元创建基本几何体并在视窗中浏览的方法。本章将介绍如何向几何体添加纹理。为了使代码易于阅读,我们将有关金字塔绘制的代码封装到一个函数中,并返回一个Geode指针。代码如下所示:
osg::Geode* createPyramid()
{
osg::Geode* pyramidGeode = new osg::Geode();
osg::Geometry* pyramidGeometry = new osg::Geometry();
pyramidGeode->addDrawable(pyramidGeometry);
// 指定顶点
osg::Vec3Array* pyramidVertices = new osg::Vec3Array;
pyramidVertices->push_back( osg::Vec3(0, 0, 0) ); // 左前
pyramidVertices->push_back( osg::Vec3(2, 0, 0) ); // 右前
pyramidVertices->push_back( osg::Vec3(2, 2, 0) ); // 右后
pyramidVertices->push_back( osg::Vec3( 0,2, 0) ); // 左后
pyramidVertices->push_back( osg::Vec3( 1, 1,2) ); // 塔尖
// 将顶点数组关联给几何体
pyramidGeometry->setVertexArray( pyramidVertices );
// 根据底面的四个顶点创建底面四边形(QUAD)
osg::DrawElementsUInt* pyramidBase =
new osg::DrawElementsUInt(osg::PrimitiveSet::QUADS, 0);
pyramidBase->push_back(3);
pyramidBase->push_back(2);
pyramidBase->push_back(1);
pyramidBase->push_back(0);
// 创建其他面的代码从略
osg::Vec4Array* colors = new osg::Vec4Array;
colors->push_back(osg::Vec4(1.0f, 0.0f, 0.0f, 1.0f) ); //索引0 红色
colors->push_back(osg::Vec4(0.0f, 1.0f, 0.0f, 1.0f) ); //索引1 绿色
colors->push_back(osg::Vec4(0.0f, 0.0f, 1.0f, 1.0f) ); //索引2 蓝色
colors->push_back(osg::Vec4(1.0f, 1.0f, 1.0f, 1.0f) ); //索引3 白色
osg::TemplateIndexArray
colorIndexArray =
new osg::TemplateIndexArray
colorIndexArray->push_back(1); // 顶点1对应颜色元素1
colorIndexArray->push_back(2); // 顶点2对应颜色元素2
colorIndexArray->push_back(3); // 顶点3对应颜色元素3
colorIndexArray->push_back(0); // 顶点4对应颜色元素0
pyramidGeometry->setColorArray(colors);
pyramidGeometry->setColorIndices(colorIndexArray);
pyramidGeometry->setColorBinding(osg::Geometry::BIND_PER_VERTEX);
//由于纹理坐标与顶点是一一对应的,因此不需要使用索引数组来进行映射。我们只需要直接使用setTexCoordArray方法即可. setTexCoordArray方法传递osg::Vec2的二维坐标数组作为参数,传递的二维坐标数与顶点数相同。数组中元素的位置与顶点数组中顶点的位置一一对应。
osg::Vec2Array* texcoords = new osg::Vec2Array(5);
(*texcoords)[0].set(0.00f,0.0f); // 顶点0的纹理坐标
(*texcoords)[1].set(0.25f,0.0f); // 顶点1的纹理坐标
(*texcoords)[2].set(0.50f,0.0f); // 顶点2的纹理坐标
(*texcoords)[3].set(0.75f,0.0f); // 顶点3的纹理坐标
(*texcoords)[4].set(0.50f,1.0f); // 顶点4的纹理坐标
pyramidGeometry->setTexCoordArray(0,texcoords);
return pyramidGeode;
}
加载纹理,创建渲染状态类,关联到节点
我们使用StateSet类来控制几何基元的渲染状态。下面的代码演示了从文件中读取纹理,创建StateSet类并设置纹理,以及关联StateSet到场景节点的方法。代码的前一部分与上一章教程相同。首先我们初始化视窗并创建只有单一金字塔的场景。
int main()
{
// 声明场景的根节点
osg::Group* root = new osg::Group();
osg::Geode* pyramidGeode = createPyramid();
root->addChild(pyramidGeode);
现在我们添加纹理。我们定义一个纹理实例并设置其数据变更类型为“DYNAMIC”(否则的话,OSG的优化过程中可能会自动去除这个纹理)。纹理类封装了OpenGL纹理模式
(GL_TEXTURE_WRAP,GL_TEXTURE_FILTER等),以及一个osg::Image对象。下面的代码将演示如何从文件读入osg::Image实例并将其关联到纹理。
osg::Texture2D* KLN89FaceTexture = new osg::Texture2D;
//避免在优化过程中出错
KLN89FaceTexture->setDataVariance(osg::Object::DYNAMIC);
// 从文件读取图片
osg::Image* klnFace = osgDB::readImageFile("KLN89FaceB.tga");
if (!klnFace)
{
std::cout << " couldn't find texture, quiting." << std::endl;
return -1;
}
// 将图片关联到纹理
KLN89FaceTexture->setImage(klnFace);
Texture类可以关联到渲染状态StateSet类。下一步我们将创建一个StateSet,将纹理关联到这个渲染状态实例并允许使用纹理,最后将StateSet关联到几何体节点上。
// 创建StateSet
osg::StateSet* stateOne = new osg::StateSet();
// 将纹理关联给StateSet的纹理单元0
stateOne->setTextureAttributeAndModes
(0,KLN89FaceTexture,osg::StateAttribute::ON);
// 将渲染状态关联给金字塔节点
pyramidGeode->setStateSet(stateOne);
osgViewer::Viewer viewer;
//最后我们进入仿真循环:
viewer.setSceneData( root );
return viewer.run();
}
使用内嵌几何形状(Shape)对象,改变渲染状态
目标
使用osg::Shape实例构建场景。使用osg::StateSet控制几何形状的渲染。
Shape类的使用
Shape类是各种内嵌几何形状的基类。它可以用于剔除和碰撞检测,或者设计并生成简单几何形体。下面这些类均派生自Shape类:
?TriangleMesh
?Sphere
?InfinitePlane
?HeightField
?Cylinder
?Cone
?CompositeShape
?Box
如果要渲染这些内嵌形体,我们需要首先将其与Drawable类的实例相关联。我们可以使用ShapeDrawable类来完成这一功能。它派生自 Drawable类,并提供了关联Shape实例的方法。正因为ShapeDrawable是继承自Drawable的,它的实例因而可以被添加到 Geode实例中。下面的代码演示了在场景中添加单位立方体的方法:
//创建场景的根节点
osg::Group* root = new osg::Group();
//声明Box类(派生自Shape)的实例。构造函数的参数为:osg::Vec3的中心位置,浮点数定义统一的高/宽/深度。
// (我们也可以分别输入不同的高度、宽度、深度值)
osg::Box* unitCube = new osg::Box( osg::Vec3(0,0,0), 1.0f);
//声明ShapeDrawable类的实例,使用刚才创建的unitCube作为传递参数。这个类派生自Drawable类,因此可以直接添加到Geode实例中。
osg::ShapeDrawable* unitCubeDrawable = new osg::ShapeDrawable(unitCube);
// 声明Geode类的实例
osg::Geode* basicShapesGeode = new osg::Geode();
// 将单位立方体添加到Geode中
basicShapesGeode->addDrawable(unitCubeDrawable);
// 将Geode添加到场景中
root->addChild(basicShapesGeode);
创建球的方法与此类同。如下面的代码所示:
// 在原点创建单位半径的球
osg::Sphere* unitSphere = new osg::Sphere( osg::Vec3(0,0,0), 1.0);
osg::ShapeDrawable* unitSphereDrawable = new osg::ShapeDrawable(unitSphere);
现在我们可以对球作位置变换后添加到场景中,以便将其与已经置于原点上的立方体区分开。注意unitSphereDrawable是不能直接添加到场景中的(它不是Node的派生类),因此我们需要为其创建一个新的Geode叶节点:
osg::PositionAttitudeTransform* sphereXForm =
new osg::PositionAttitudeTransform();
sphereXForm->setPosition(osg::Vec3(2.5,0,0));
osg::Geode* unitSphereGeode = new osg::Geode();
root->addChild(sphereXForm);
sphereXForm->addChild(unitSphereGeode);
unitSphereGeode->addDrawable(unitSphereDrawable);
设置渲染状态
前一个教程已经演示了创建纹理,从文件加载纹理图片,并关联纹理到StateSet对象的过程。下面的代码将设置两种不同的渲染状态:一个使用BLEND纹理模式,另一个使用DECAL 模式。首先是BLEND模式:
//创建使用BLEND模式的渲染状态对象
osg::StateSet* blendStateSet = new osg::StateSet();
//声明TexEnv实例,设置模式为BLEND
osg::TexEnv* blendTexEnv = new osg::TexEnv;
blendTexEnv->setMode(osg::TexEnv::BLEND);
// 使用纹理0,也就是上一章加载的纹理
blendStateSet->setTextureAttributeAndModes
(0,KLN89FaceTexture,osg::StateAttribute::ON);
// 设置纹理单元0所用的纹理环境
blendStateSet->setTextureAttribute(0,blendTexEnv);
现在我们重复刚才的过程,但是将纹理环境模式设置为DECAL:
osg::StateSet* decalStateSet = new osg::StateSet();
osg::TexEnv* decalTexEnv = new osg::TexEnv();
decalTexEnv->setMode(osg::TexEnv::DECAL);
decalStateSet->setTextureAttributeAndModes
(0,KLN89FaceTexture,osg::StateAttribute::ON);
decalStateSet->setTextureAttribute(0,decalTexEnv);
现在我们将刚才创建的渲染状态对象关联到场景图形的节点。当场景图形执行绘制遍历(根节点->叶节点)时,渲染状态会暂存起来。如果某个节点没有与之关联的渲染状态,那么它将继承其父节点的渲染状态(换句话说,对于有不止一个父节点的节点来说,它可能有多种不同的渲染状态)。
root->setStateSet(blendStateSet);
unitSphereGeode->setStateSet(decalStateSet);
最后我们进入仿真循环:
osgViewer::Viewer viewer;
viewer.setSceneData( root );
return viewer.run();
StateSet的工作流程
出自osgChina
跳转到:导航, 搜索
场景图形在遍历场景的过程中,会自动判断哪一些几何体要送入图形管道进行渲染。在遍历过程中,场景图形还要收集几何体渲染状态的信息。这些信息就保存在 osg::StateSet
实例中。StateSet包含了一个OpenGL属性/值的列表,它可以与场景中的节点相关联。在渲染之前的遍历过程中, StateSet会从根节点一直向叶节点进行积累。如果某个节点只是简单地继承上一节点的状态,那么与它关联的StateSet也不会发生改变。
我们可以使用一些附加的特性来提升工作的灵活性。渲染状态所保存的属性可以设置为OVERRIDE,也就是说,该节点的所有子节点,无论其渲染状态是什么,都将继承父节点的渲染属性。但是OVERRIDE也可能存在一种例外,如果某个子节点的渲染属性设置为PROTECTED,那么它将忽略父节点的相应属性,而使用自己设定的属性值。
示例
下面的例子演示了渲染状态对场景图形的影响。根节点使用BLEND模式。如果它的子节点没有改变任何渲染属性值,则子节点的渲染状态也不会发生改变,如根节点的右子树所示。右子树的节点没有指定渲染状态,因此它的渲染方式与根节点相同。而对于节点5来说,虽然纹理的混合模式没有改变,但是它已经关联了新的纹理。
根节点的左子树设置纹理模式为DECAL,其它的渲染属性与根节点相同。节点3将FOG属性设置为ON并指定为OVERRIDE。对于节点2的左子节点(节点3),其FOG属性设置为OFF,但是由于没有指定PROTECTED方式,且父节点为OVERRIDE方式,因此FOG属性依然为 ON。而对于右子节点(节点4),其FOG属性使用PROTECTED方式并设定为OFF,此时它将忽略父节点的相应设置。
代码
下面的代码用于控制渲染状态的设定并将其关联到节点。
//设置osg::TexEnv实例为BLEND模式,将TexEnv属性和一幅纹理关联到纹理单元0 blendTexEnv->setMode(osg::TexEnv::BLEND);
stateRootBlend->setTextureAttribute(0,blendTexEnv,osg::StateAttribute::ON); stateRootBlend->setTextureAttributeAndModes(0,ocotilloTexture,osg::StateAttribu te::ON);
// 对于节点5,重新设置其渲染单元0的纹理。其它的渲染属性将继承父节点的属性(渲染模式属性仍为BLEND)
stateFiveDustTexture->setTextureAttributeAndModes(0,dustTexture,osg::StateAttri bute::ON);
// 设置osg::TexEnv实例为DECAL模式,将其关联到stateOneDecal
decalTexEnv->setMode(osg::TexEnv::DECAL);
stateOneDecal->setTextureAttribute(0,decalTexEnv,osg::StateAttribute::ON);
// 对于stateTwo,设置FOG属性为ON并设置OVERRIDE,所有的子树将自动继承它的渲染状态,除非设置了PROTECTED标志
stateTwoFogON_OVRD->setAttribute(fog, osg::StateAttribute::ON); stateTwoFogON_OVRD->setMode(GL_FOG, osg::StateAttribute::ON |
osg::StateAttribute::OVERRIDE);
// stateThree试图关闭FOG属性,但是由于父节点的渲染状态设置为OVERRIDE,因此FOG 的设置没有发生变化(仍为ON)
stateThreeFogOFF->setMode(GL_FOG, osg::StateAttribute::OFF);
// stateFour设置了PROTECTED标志,因此它可以重载父节点的渲染状态了stateFourFogOFF_PROT->setMode(GL_FOG, osg::StateAttribute::OFF |
osg::StateAttribute::PROTECTED);
// 将上面的各个渲染状态实例应用到场景图形的节点上
root->setStateSet(stateRootBlend);
mtOne->setStateSet(stateOneDecal);
mtTwo->setStateSet(stateTwoFogON_OVRD);
mtThree->setStateSet(stateThreeFogOFF);
mtSix->setStateSet(stateFiveDustTexture);
mtFour->setStateSet(stateFourFogOFF_PROT);
HumanCAD? V1.2 入门教程 NexGen人机工程研究公司 6600 Trans 加拿大高速公路 750号公寓 蓬特克莱尔(蒙特利尔),魁北克H9R 4S2 加拿大 电话:5146858593 传真:5146858687 电子邮箱:techsupport@https://www.sodocs.net/doc/717072399.html, 网址:https://www.sodocs.net/doc/717072399.html, 最后修订:2008-10-30 未经NexGen人机工程研究公司许可,不得以任何形式任何手段(电子、机械、或其他方式),包括复印和录音与该资料或录音系统有关的文件。 NexGen人机工程研究公司2008保留所有权
导言 本教程提供给您一种快捷简单的资源来向您介绍HumanCAD?的各种功能。通过简化一步一步的指示、解释和说明,你将塑造属于你自己的三维人物,揭露你自己的各种人性化功能和CAD工具。HumanCAD ?可以提供给任何设计师,工程师或人为因素的专业。 第一步,通过本教程熟悉HumanCAD ?的主要功能,按键和屏幕的命令。第二个是介绍了一些应用程序和软件的功能。 本教程的第三步也就是最后一步,是以各种姿势、划线和导入不同的三维物体来创建自己的个性化三维人物,应用和编辑有外部负载的模特儿的身体和执行了一系列的生物力学分析,包括预测和NIOSH (美国职业安全及健康研究所)的计算和模拟。 首先,比如一个常见的被称为“举箱子”的动作(看下图),可以看出本教程是非常的简单。这个例子用一中简单的方法来理解了一些应用HumanCAD ?及其各职能。
目录 HumanCAD?的基本操作原理 (4) 主屏幕的所有相关信息 (5) 菜单选项 (6) HumanCAD?速成教程 (11) 1.1.达到量和视觉锥 (13) 1.2.分析模特儿的视野...................................................................... (14) 1.3.样本人机工程学问题 (16) 1.4. 让我们创建一个模特儿 (18) 1.5.让我们构造和操纵模特儿......................................................... . (19) 1.6. 现在让我们来绘制三维对象 (21) 1.7.将力作用在模特儿身上 (22) 1.8.分析模特儿身上的作用力 (23) 1.9.应该成载多大的重量 (24) 关于NexGen人机工程研究公司 (25)
最长的一帧 王锐(array) 这是一篇有关OpenSceneGraph源代码的拙劣教程,没有任何能赏心悦目的小例子,也不会贡献出什么企业级的绝密的商业代码,标题也只是个噱头(坏了,没人看了^_^)。 本文写作的目的说来很简单,无非就是想要深入地了解一下,OSG在一帧时间,也就是仿真循环的一个画面当中都做了什么。 对OSG有所了解之后,我们也许可以很快地回答这个问题,正如下面的代码所示:while (!viewer.done()) viewer.frame(); 就这样,用一个循环结构来反复地执行frame()函数,直到done()函数的返回值为true 为止。每一次执行frame()函数就相当于完成了OSG场景渲染的一帧,配置较好的计算机可以达到每秒钟一二百帧的速率,而通常仿真程序顺利运行的最低帧速在15~25帧/秒即可。 很好,看来笔者的机器运行frame()函数通常只需要8~10ms左右,比一眨眼的工夫都要短。那么本文就到此结束吗? 答案当然是否定的,恰恰相反,这篇繁琐且可能错误百出的文字,其目的正是要深入frame()函数,再深入函数中调用的函数……一直挖掘下去,直到我们期待的瑰宝出现;当然也可能是一无所获,只是乐在其中。 这样的探索要到什么时候结束呢?从这短短的10毫秒中引申出来的,无比冗长的一帧,又是多么丰富抑或无聊的内容呢?现在笔者也不知道,也许直到最后也不会明了,不过相信深入源代码的过程就是一种享受,希望读者您也可以同我一起享受这份辛苦与快乐。 源代码版本:OpenSceneGraph 2.6.0;操作系统环境假设为Win32平台。为了保证教程的篇幅不致被过多程序代码所占据,文中会适当地改写和缩编所列出的代码,仅保证其执行效果不变,因此可能与实际源文件的内容有所区别。 由于作者水平和精力所限,本文暂时仅对单视景器(即使用osgViewer::Viewer类)的情形作出介绍。 转载请注明作者和https://www.sodocs.net/doc/717072399.html, 本文在写作过程中将会用到一些专有名词,它们可能与读者阅读的其它文章中所述有所差异,现列举如下: 场景图形-SceneGraph;场景子树-Subgraph;节点-Node;摄像机-Camera;渲染器-Renderer;窗口-Window;视口-Viewport;场景-Scene;视图-View;视景器-Viewer;漫游器-Manipulator;访问器-Visitor;回调-Callback;事件-Event;更新-Update;筛选-Cull;绘制-Draw。 第一日 好了,在开始第一天的行程之前,请先打开您最惯用的编程工具吧:VisualStudio?CodeBlocks?UltraEdit?SourceInsight?Emacs?Vim?或者只是附件里那个制作低劣的记事本……总之请打开它们,打开OpenSceneGraph-2.6.0的源代码文件夹,打开
在编程开始前要认识一下*.tga后缀的文件: TGA格式(Tagged Graphics)是由美国Truevision公司为其显示卡开发的一种图像文件格式,文件后缀为“.tga”,已被国际上的图形、图像工业所接受。 TGA的结构比较简单,属于一种图形、图像数据的通用格式,在多媒体领域有很大影响,是计 算机生成图像向电视转换的一种首选格式。 TGA图像格式最大的特点是可以做出不规则形状的图形、图像文件,一般图形、图像文件都为四方形,若需要有圆形、菱形甚至是缕空的图像文件时,TGA可就派上用场了! TGA格式支持压缩,使用不失真的压缩算法。 在工业设计领域,使用三维软件制作出来的图像可以利用TGA格式的优势,在图像内部生成一个Alpha(通道),这个功能方便了在平面软件中的工作。 ========================================================================== ======== #include
Contextcapture建模流程 初学篇 1 新建工程 新建工程,设置工程路径 2 导入照片 导入本机照片。如需集群处理,则需要导入网络路径下的照片,详见6.2工程设置:
导入照片 Set downsampling(设置采样率):该参数只会在空三的过程中对照片进行重采样空三,建模时仍旧使用原始分辨率影像。 Check image files...(检查航片完整性):建模失败的时候可以用此功能进行数据完整性检查。 Import positions...(导入POS):导入POS格式如下, a.如果有多个照片组(Photogroup)则必须保证每个照片组中的照片名称唯一,否则会导入失败; b.POS路径必须为英文;
相机参数 每个照片组(Photogroup)都会有一个相机参数,可以在右键菜单中导入或导出相机检校参数(特别对CC4.4以后版本有用)。 3 空中三角测量 3.1常规空三流程 空三参数设置,如第一次使用,则建议直接按照默认参数,只需“下一步”即可,如欲了解其中参数意义则进入如下内容: (1)设置名称,最好根据飞行架次或项目信息进行设置
(2)参与空三的照片,默认使用全部照片。 (3)照片定位或地理参考设置
(4)空三参数设置,通常默认参数即可 a.对于地名拍摄照片,可能会修改“Keypoints density”、“Pair selection mode”、“Component construction mode”三个选项; b.对于航空拍摄照片,通常使用默认参数,如果多个架次且存在航高不一致的情况,则可能会修改“Pair selection mode”、“Component construction mode”两个 选项;(实例:百里峡漂流两个架次航高不一致)
FlightGear2016.4.1+VS2015编译指南 前言:本人之前也看了许多网上的教程,但编译一直出现各种问题(和操作系统位数,第三方库文件版本,VS版本,FlightGear版本都有一定的关系),花了两个星期终于编译成功了。因此整理了教程,希望能对大家有所帮助。 一、编译前准备工作 1、Cmake下载安装:上cmake官网https://https://www.sodocs.net/doc/717072399.html,/download/下载CMAkE并安装,我用的版本是cmake3.6.3 2、OSG二进制文件下载:(自己编译也可以,但是耗时不说,还容易出现不兼容的问题),可以从官方的编译教程里面下载https://www.sodocs.net/doc/717072399.html,/Building_using_CMake_-_Windows,如下图所示: 3、第三方库3rdParty及Boost下载:一样的也是从官方的编译教程里面下载(注意若要编译64位的程序要下载3rdParty.x64)https://www.sodocs.net/doc/717072399.html,/Building_using_CMake_-_Windows,如下图所示:
4、simgear2016.4.1、flightgear2016.4.1源码和fgdata(程序启动时加载的地形、机场、飞机模型文件等都在这里面)下载:链接https://https://www.sodocs.net/doc/717072399.html,/projects/flightgear/files/release-2016.4/,下载划线的三项,如下图所示: 5、构建编译目录:我在C盘下建立一个根文件夹FlightGear,然后把上面下载的编译所需文件的压缩包都解压到这个文件夹中,并新建两个文件夹:分别重命名为simgear-build和flightgear-build用来存放Cmake生成的可编译文件,如下图所示:(PS:plib和freeglut如果需要的话也可以自己去下载)
OSG虚拟可视化图形开发简介 OSG诞生于大概是1997年,可以在osgChina[https://www.sodocs.net/doc/717072399.html,]上查阅到关于OSG的来龙去脉。笔者使用OSG也已经有三到四年的时间了。当初偶然接触OSG到现在,OSG已经在国内外得到广泛的应用,国内已经有好几家专门使用OSG的公司,他们分布在杭州、西安、深圳以及还有一些我不知道的地方。然而,更让人兴慰的是国内的各重点院校与研究所都已经开始使用OSG。 我做为一直使用OSG做开发的图形工作者,感觉非常兴慰。当每一次在群里或论坛说OSG 又有什么什么消息时,看到很多人说:看来选OSG是选对了,OSG明天更好等等类似的话,我热泪盈框。OSG进入中国已经有七到八年了,在这期间,OSG经历了数次变迁,青丝变白发。使用OSG的开发者从无到有,从草根开发者到成立专门使用OSG的公司。 1.1 OSG简介 1.1.1 OSG的诞生 在1997年时,Don Burns由于喜欢滑翔机运动且对计算机图形学非常熟悉,在LINUX上写了一个控制滑翔机的小引擎,这便是OSG的最初雏形。后来在1998年,Don Burns在滑翔机爱好者邮件列表中遇到了Robert Osfield,对OSG的命运起到了决定性的改变。我们现在在邮件列表中也会经常看到Robert的名字,从98年至今,Robert一直担当OSG开发组长,权衡OSG的各种利弊。有很多人在刚开始接触OSG时感觉到非常痛苦,咋一看一点儿都看不懂,疑是什么鬼怪新语言。其实OSG是语法是标准C++的。您可以登录:https://www.sodocs.net/doc/717072399.html,/ 与https://www.sodocs.net/doc/717072399.html,查看关于OSG历史的更多信息。也可以查阅《OSG快速入门指南》[
Contextcapture保姆级使用教程 初学篇 1 新建工程 新建工程,设置工程路径 2 导入照片 导入本机照片。如需集群处理,则需要导入网络路径下的照片,详见6.2工程设置:
导入照片 Set downsampling(设置采样率):该参数只会在空三的过程中对照片进行重采样空三,建模时仍旧使用原始分辨率影像。 Check image files...(检查航片完整性):建模失败的时候可以用此功能进行数据完整性检查。 Import positions...(导入POS):导入POS格式如下, a.如果有多个照片组(Photogroup)则必须保证每个照片组中的照片名称唯一,否则会导入失败; b.POS路径必须为英文;
相机参数 每个照片组(Photogroup)都会有一个相机参数,可以在右键菜单中导入或导出相机检校参数(特别对CC4.4以后版本有用)。 3 空中三角测量 3.1常规空三流程 空三参数设置,如第一次使用,则建议直接按照默认参数,只需“下一步”即可,如欲了解其中参数意义则进入如下内容: (1)设置名称,最好根据飞行架次或项目信息进行设置
(2)参与空三的照片,默认使用全部照片。 (3)照片定位或地理参考设置
(4)空三参数设置,通常默认参数即可 a.对于地名拍摄照片,可能会修改“Keypoints density”、“Pair selection mode”、“Component construction mode”三个选项; b.对于航空拍摄照片,通常使用默认参数,如果多个架次且存在航高不一致的情况,则可能会修改“Pair selection mode”、“Component construction mode”两个选项;(实例:百里峡漂流两个架次航高不一致)
参考pdf,FlightGear2.10编译。但是尝试了两个多星期,并未成功,可能是各种版本不匹配问题。但上面这个pdf有指导性意义!!! 主要编译三大块OSG,simgear,flightgear。另外,需要的附加库有boost,3rdparty,openal,plib。 flightgear-data是在编译成功后启动项目时候用。 之后,在win10 64位系统下,下载了网友的3rdparty.x64 - vs2015和OSG-vs2015-x64-debug,然后自己在官网下载了2016.3.1版本的源码以及其他附加库。 环境变量的设置中OSG的路径要设到其文件夹下的/bin中,否则最后运行的时候会找不到某些.dll。环境变量修改后注销即可生效。 如果想完全重新编译,需从OSG源码开始!!!注意:先删除之前的其他Flightgear有关的环境变量。 最重要的事情是,附加的库既不能少也不能多!!!版本匹配,特别是和VS 文编译环境在win10 64位、VS2015 pro。 新建文件夹FlightGear将来放整个项目!我建在了C盘。 一、各种源码包准备 (1)先来准备第三方库 最好是下载附件提供的3rdparty.x64 - vs2015,想自己下也行。方法如下,下载出来的文件会多一点。文本教程写的命名是3rdparty.x64,这个无所谓,自己对应就好。 https://https://www.sodocs.net/doc/717072399.html,/p/flightgear/windows-3rd- party/ci/master/tree/msvc140/3rdParty.x64/ 这个网站直接下载不好下的话,用Git下载,安装Git,默认安装即可,各种下一步,然后自己建立一个空文件夹。准备clone上面网址的代码用。准备好后,在命令行用git clone 网址这条命令即可将源码克隆下来。目前可以用如下网址,之后可能有更改。 git clone git://https://www.sodocs.net/doc/717072399.html,/p/flightgear/windows-3rd-party flightgear-windows-3rd-party Windows键+R进入运行,输入cmd后回车,进入命令行,然后输入如下图东西: 自己建的文件夹名可以不命名为clone,随意。克隆出来的文件夹即flightgear-windows-3rd-party
几何体的绘制 概述 本章将介绍一些创建几何体元素的方法。通常我们有这样几种处理几何体的手段:底层手段是使用松散封装的OpenGL基元;中级手段是使用 OpenSceneGraph的基本几何体;高级手段是从文件读入模型。本章教程将主要介绍底层手段的实现方法。这种实现具有很强的灵活性,相应的工作量也比较大。应用于场景图形级别的几何体通常是从文件读入的,因而顶点的跟踪和处理工作将由文件读取插件完成。 背景 下面将对几个常用的类作简要的介绍: ?Geode类 Geode类派生自Node节点类。节点类(包括Geode)可以作为场景图形的叶节点添加。Geode 类的实例可以与任意多个可绘制对象Drawable类相关联。 ?Drawable类 作为可绘制对象基类的Drawable类是一个纯虚类,它有六个派生类。其中Geometry类中可以直接指定顶点数据,或者指定任意数目的几何基元PrimitiveSet类与其关联。 顶点和顶点属性数据(颜色,法线,纹理坐标)是保存在数组中的。多个顶点可以共享同一种颜色,法线和纹理坐标,同时我们还可以使用索引将顶点数组映射给颜色,法线或纹理坐标的数组。 ?PrimitiveSet类 这个类松散地封装了OpenGL的绘图基元,包括点(POINTS),线(LINES),多段线(LINE_STRIP),封闭线(LINE_LOOP),四边形(QUADS),多边形(POLYGON)等。 代码 下面的代码将设置一个用于显示场景的视窗,一个作为场景图形根节点的Group类实例,一个用于记录可绘制对象(Drawable)的几何体节点(Geode),以及一个记录顶点和顶点相关数据的Geometry类实例。本例中我们将渲染一个金字塔的形状。 ... int main() { ... osg::Group* root = new osg::Group(); osg::Geode* pyramidGeode = new osg::Geode(); osg::Geometry* pyramidGeometry = new osg::Geometry();
VTK教程之一可视化管线 VTK是一个基于面向对象的开源三维绘图软件包,和其它的的三维绘图引擎如OSG、OGRE不同之处在于,VTK可视化对象主要是各种数据,更加注重对数据分析处理后的可视化,可视化的内容是人们无法直接感受到的东西,如地质构造、地层分布、矿床分布、三维空间应力场的状态变化等等,而OSG、OGRE是基于场景的可视化,更强调视觉感官的感受,所以OSG主要应用于虚拟现实领域,而VTK主要应用于科学计算可视化领域,本教程主要介绍VTK的可视化应用。 VTK的可视化设计是基于管线流的设计模式,将要处理的数据作为流动介质在管线中流动,不同的阶段对数据有不同的处理方式,VTK的可视化管线主要由图形模型和可视化模型组成,如下图所示: 可视化模型主要对数据进行处理,生成可被绘制的几何体,而图形模型主要对生成的几何体进行绘制,在VTK的可视化管线中所包含的对象一般包括:源对象、过滤器对象(可选)、映射器对象、Props对象、绘制器对象、绘制窗口,其中源对象、过滤器对象(可选)、映射器对象、绘制器对象、绘制窗口为处理对象, Props对象为数据对象,映射器对象是可视化模型和图形模型的接口。 有了可视化管线,VTK的可视化过程就可以用数据在可视化管线流动的过程来描述(数据在管线中流动过程中,被管线不同的对象处理,最终以图形的方式表现数据信息),VTK的可视化管线具有如下特点: 1、变换 数据从原始的形式变换成图元的形式,最终以图形的形式显示。 2、表现 用VTK内部定义的数据结构描述数据,形成数据集,用图形的方式表现数据。 3、是基于面向对象的
用面向对象的观点描述可视化管线,表现是数据对象,变换是处理对象。 下面我们对VTK可视化管线的各个对象分别介绍,在可视化管线中,按对数据处理方式的不同,分为数据对象和处理对象,其中数据对象主要作用是表现数据信息,并对表现的信息进行维护(创建、访问、删除),处理对象主要是对输入的数据进行处理后生成输出新的数据,处理对象主要包括: 1、源对象 数据生成的源头,数据来源主要包括从磁盘读取数据文件,如VTK所支持的各种格式文件生成数据源对象,这种源对象被称为读源对象,或者利用数学方法生成源对象,如利用多个四边形构建一个圆柱体,这种对象被称为程序源对象。 2、过滤器对象 对源对象进行处理,生成新的数据集输出。 3、映射器对象 映射器对象主要作用是将可视化模型生成的数据转换到图形模型进行绘制,或者以磁盘文件的形式进行输出。 以上对VTK可视化管线做了一个简单的介绍,下面通过一个示例程序来说明数据是如何在可视化管线中流动的。 #include "stdafx.h" #include "vtkCamera.h" #include "vtkGenericRenderWindowInteractor.h" #include "vtkInteractorStyleJoystickCamera.h" #include "vtkInteractorStyleTrackballCamera.h" #include "vtkLODActor.h" #include "vtkLight.h" #include "vtkPolyData.h" #include "vtkPolyDataMapper.h" #include "vtkPropPicker.h" #include "vtkProperty.h" #include "vtkRenderWindow.h" #include "vtkRenderer.h" #include "vtkSTLReader.h" #include "vtkShrinkPolyData.h" int main( int argc, char *argv[] ) { //创建绘制器对象 vtkRenderer *ren1 = vtkRenderer::New(); //设置相机 ren1->GetActiveCamera()->SetClippingRange(0.294421 , 29.4421); ren1->GetActiveCamera()->SetDistance(7.94348); ren1->GetActiveCamera()->SetFocalPoint(-66.9367 , -49.4539 , 258.453); ren1->GetActiveCamera()->SetPosition(-67.8091 , -57.3489 , 258.377); ren1->GetActiveCamera()->SetViewAngle(20); ren1->GetActiveCamera()->SetViewUp(-0.82718 , 0.0860684 , 0.555306); ren1->GetActiveCamera()->SetParallelProjection(0);
#include
OSG中Dragger系统架构与算法分析(magicstone & Simbaforrest) 开放合作 很高兴能够和Simbaforrest筒子合作,让我们开放合作来把大家对于OSG的分析记录下来,对于OSG的在国内的普及和让OSG服务于国内的软件行业的发展敬一份微薄的力量。同时也在这里倡议大家能够一起来把OSG的分析合作整理出来,发挥各自的力量! Dragger系统作用论述 Dragger系统主要用来对模型空间位移信息的编辑,这个系统在3D空间的场景中给美术创作人员起到很大的帮助。 Dragger算法原理简述 Dragger主要是将用户在屏幕窗口的鼠标消息,通过对应的Projector算法来求出各种类型Projector对应的空间位置,这样记录用户的屏幕窗口消息的变化,求出3D空间中位移的变化,得出用户对3D模型在空间中位移变化的操作。 Dragger程序架构 主体架构 Dragger系统架构信息处理描述 聚合了所有的各种类型的Dragger,是Dragger系统的核心,其在Dragger系统中的作用是处理外设的输入消息。通过算法,将鼠标的窗口坐标信息转换到PointInfo结构信息。根
据鼠标的点击事件类型,转换到对应的Dragger事件类型,同时根据鼠标点击选择拣选出选中的Dragger来处理,根据多态的机制,对应有具体的类型Dragger来具体处理。每个Dragger 对应有自身的窗口屏幕鼠标位移到3D坐标空间的位移的Projector映射算法,通过Projector 算出来此次位移的3D空间位置或者旋转量,此后通过Command命令模式,将具体的Dragger 空间相对变换量,打包到具体的Command中去,然后由CommandManager来负责将各种类型的Command调用其执行命令接口,其实就是将其自身传递到Selection处Command接口处理。Selection中接受到各种不同命令时,根据命令不同获取命令空间的变化量信息,将Selection对象空间做位移。 上面大致描述了Dragger系统的运作,具体其实可以用动态图来具体呈现,但是其实这个系统挺简单的,所以也就简单描述下,相信有些程序经验的也都能明白^_^。 Selection架构与作用论述 从Selection类的继承层次关系我们就可以看出来,从Selection名字顾名思义也可以看出来,Selection是用来在场景中被选中并做3D空间位移与外部交互的类。该类还可以是一个场景图的组,可以加入和管理其他的子节点。 该类函数处理各种空间位移命令,也即把各种空间位移命令中记录的空间位移变化信息使用到该节点的空间变化中来。 Simbaforrest:啊,该讲selection了,要讲清楚这个,就不得不先搞清楚图形学中的变换,这个东西很让人头疼,我也是刚刚才弄明白滴,现买现卖吧:) 为了讲清楚Selection中间的变换,我们先要看这两个场景图例子:
OSG+VS2010+win7环境搭建 Win7下osg+vs2010环境搭建 一.相关准备 a) Osg源码 当前最新版:OpenSceneGraph的3.0.0.zip 下载链接: https://www.sodocs.net/doc/717072399.html,/downloads/stable_releases/OpenSceneGraph-3. 0/source/OpenSceneGraph-3.0.0.zip b) Osg第三方库 3rdParty_VC10_x86_x64.zip https://www.sodocs.net/doc/717072399.html,.au/~bchrist/3rdParty_VC10_x86_x64.zip c) 数据包 当前最新版:OpenSceneGraph-Data-3.0.0.zip 下载链接: https://www.sodocs.net/doc/717072399.html,/downloads/stable_releases/OpenSceneGraph-3. 0/data/OpenSceneGraph-Data-3.0.0.zip d) 安装源码工具 cmake-2.8.4-win32-x86.exe 至于这个文件的下载需要翻墙或者VPN代理,我使用的就是VPN代理的,如果不方便下载的 话我传一个吧 http://119.147.99.9/gdown_group255/M00/17/0A/d5NjCU-aQJMAAAAAAIssvk3uq Wk5209449/cmake-2.8.8-win32-x86.exe?k=61GUEkJXX2Buzr15ZSgafA&t=13466 93036&u=244400084-9477243-e7vfww1u&s=307200&file=cmake-2.8.8-win32-x 86.exe。 二、编译准备 为了编译的顺利进行,将下载的文件组织如下: 在E盘建立一个OSG的文件夹,然后其他文件如下放置: E:\OSG\OpenSceneGraph:源码解压后放于此 E:\OSG\3rdParty:第三方依赖库解压后放于此 注意这个里面的第三方库一般包含x64和x86的两个版本的,这里要根据你自己的电脑需要选择一个然后把里面的文件复制到3rdParty文件夹中。由于本人的电脑是64位的系统,所以我选择的留下了的是“x86”。之所以选择x86,也就是32位是因为64位的隐患很大,很多库没有64位的,而我也自己亲身实践过,在后面的VS批生成的时候导致ALL_INSTALL出现了2个失败,在后面的直接4个全失败。所以这里我建议选择使用32位的。 E:\OSG\data:数据包解压后放于此。 三.安装源码 a) 安装CMake之后,打开CMake -gui.exe
delta3d 2.0基本教程消息机制 (2008年4月28日星期一3时51分26秒) 作者:阿威 声明:如果有引用或借用他人文字会在文章末尾表明。本文章只是个人学习交流使用,如果转载请保持文章的完整性。 涉及到的主要类型 dtCore::Base dtCore::RefPtr< T > 概述 说到delta3d自然不能不讨论osg,毕竟osg是他的最重要的部分,没有osg其他的一切都是不存在的。但实际上在delta3d的使用中大部分情况下并不会感觉到osg的存在,所以osg 的一些特性和组织方式或者是对事件的处理方式在delta3d中是没有必然联系的。如果没有必要我尽量的不提osg的事情。 这里要提到的dtCore::Base 就是组成delta3d的最重要的一个类。从继承关系上看,几乎所有重要的类型都是从这里继承出来的。从dtCore::Base的定义上看我们知道他主要完成了两个功能:消息机制、实例的管理、智能指针。当然他也允许给对象设置名称和id,这也是为前三者服务的。 先说说消息机制,他并没有使用osg里的callback方式,为什么。因为callback方式只是在被调用的时候被执行,而我们不能有效的对他随意的调用。而且如果callback方式想对其他对象进行操作的时候,必须去得到对方的指针,每次初始化都要这么做,总是要用到Visitor 类型,总是很痛苦。最重要的原因是callback有很多个,你没办法把他们统一成一个简单的类型用来继承,也不能方便的扩展他。所以dtCore::Base 简单的解决了这个问题,只需要从他继承出来,就可以方便的处理任何你想让他处理的消息,谁是发送者,谁是接收者,都随你使用。(具体的使用方法参见下面的代码片段说明)。 实例的管理就是可以使用类的静态方法对一个类的所有实例进行添加删除和查找的管理功能。这样可以只知道类型和名称就轻松的得到一个实例对象的指针。这个功能是通过几个宏定义来完成的。(参见下面的代码片段说明) 智能指针的功能实现是和dtCore::RefPtr< T >有精密关系的,直接说dtCore::RefPtr< T >吧。现在说说dtCore::RefPtr< T > ,这个类是从osg::ref_ptr< T >继承出来的,但没有对其功能做
2、注音符号表 目前台湾使用的注音符号为37个,其中声母21个,韵母16个。另"万兀广"是拼写方言用的,故本贴不特别说明。具体见下表: 注音符号发音参考:[传送门] 2.2 注音符号与汉语拼音对照 注音符号和汉语拼音都能表示汉字的读音,因此它们是可以互相转换的。一般来说,从注音符号转换为汉语拼音,可以直接将每个注音符号转换为对应的汉语拼音符号即可,具体的对应可参见下表:
2.3 注音符号的来源
2.4 注音符号与汉语拼音拼写上的区别
3 注音输入法 3.1 繁体输入法的种类 在了解完了辅助汉字读音工具以后,进入本帖的重点。与简体输入法一样,繁体也分为字型输入和字音输入两类,字型输入法有:仓颉等,字音输入法有:注音输入法(台湾)、粤语拼音输入法(香港)。还有一些其他输入法,但使用范围较小故未提及(如无虾米等)。 3.2 注音输入法 注音输入法是一种以注音符号来输入汉字的中文输入法,主要使用地区为台湾。因为台湾小学基础教育就由注音符号教起,所以此输入法可被称为台湾电脑使用者最为熟悉的中文输入法,只要能读就能输入。 注音输入法的优点在于台湾人几乎懂得注音符号(就像大陆人懂拼音一样),不用特别学习也会使用。注音输入法的特色在于需要自己输入声调(由于注音最长3个符号,加上声调不过4个键,少有希望省略声调的意见),所以注音输入法相对拼音输入法的重码率要低不少。 因为大多数大陆人认识繁体字但不太会写,所以繁体录入不推荐考虑字型输入法,而在字音输入法里只有注音输入法与拼音相近,故推荐使用。在掌握本帖第二部分关于注音符号和它与拼音拼写上的区别后,使用注音输入法就简单很多,基本和拼音输入法一样。 4 微软新注音输入法 因为台湾使用微软新注音输入法的人数较多,所以本文以微软新注音输入法为例介绍。 [微软新注音输入法2003下载传送门]; 可以单独下载注音输入法。 [Microsoft Office 输入法2010下载传送门]; 整合了新注音输入法2010、新仓颉输入法2010、新速成输入法2010 与香港粵語输入法2010 微软新注音输入法有几种输入方式本文介绍其中两种:拼音方式及注音方式。 4.1 注音符号输入方式 4.1.1 注音方式的键盘排列布局 注音符号的键盘排列方式有多种方式,有大千式(Windows内称为标准式)、倚天式、精业式、IBM式等。鉴于手提电话或个人数码助理(PDA)的使用需要,诞生了以数字键盘输入的注音输入法。本帖介绍微软新注音输入法默认状态下的大千式,其他排列方法因使用较少故本帖不做介绍。其键盘排列如下图:
使用vc++ 9.0建立简单的场景图形一、创建vc++工程 打开vc++应用程序,在菜单栏中选择“文件”->“新建”->“项目”。出现新建项目对话框。在左侧的“项目类型”中,选择“Visual C++”->“win 32”,在右侧选择“win32 控制台应用程序”,在下面的“名称”编辑框内输入工程名,选择工程的位置,点击“确定”。如图所示: 在跳出的“win32 应用程序向导”中点击“完成”。 二、Osg源码的建立及分析 2.1 代码分析 此时生成的工程中,stdafx.h 、targetver.h、stdafx.cpp均是vc++程序自己创建的,我们自己的代码的主函数则是写在工程名同名的cpp文件中。 例程:绘制直线 #include "stdafx.h" #include
#include