osg:Geode*pyramidGeode createPyramid(); root->addChild(pyramidGeode); 现在,准备加纹理。这里我们会声明一个纹理实例并将它的数据不一致性设为‘DYNAMIC'。(如 果不把纹理声明为dynamic,osg的一些优化程序会删除它。)这个texture类包装了OpenGL纹理 模式(wrap,filter,等等)和一个osg:Image.。下面的代码说明了如何从文件里读取osg:Image 实例并把这个图像和纹理关联起来。 osg:Texture2D*KLN89FaceTexture new osg:Texture2D: /protect from being optimized away as static state: KLN89FaceTexture->setDataVariance(osg:Object:DYNAMIC): /load an image by reading a file: osg:Image*kInFace osgDB:readImageFile("KLN89FaceB.tga"); if (!klnFace) { std:cout <<couldn't find texture,quiting."<<std:endl; return -1; /Assign the texture to the image we read from file: KLN89FaceTexture->setImage (klnFace); 纹理可以和渲染StateSet关联起来。下一步就产生一个StateSet,关联并启动我们的纹理,并 将这个StateSet附加到我们的geometry上。 //Create a new StateSet with default settings: osg:StateSet*stateOne new osg:StateSet () /Assign texture unit 0 of our new StateSet to the texture /we just created and enable the texture. stateOne->setTextureAttributeAndModes(0,KLN89FaceTexture, osg:StateAttribute:ON); /Associate this state set with the Geode that contains /the pyramid: pyramidGeode->setStateSet(stateOne); 最后一步是仿真循环: //The final step is to set up and enter a simulation loop. viewer.setUpViewer(osgProducer::Viewer::STANDARD_SETTINGS): viewer.setSceneData(root ) viewer.realize(); while(!viewer.done()) { viewer.sync(); viewer.update(); viewer.frame(); return 0: >
7 osg::Geode* pyramidGeode = createPyramid(); root->addChild(pyramidGeode); 现在,准备加纹理。这里我们会声明一个纹理实例并将它的数据不一致性设为‘DYNAMIC'。(如 果不把纹理声明为 dynamic,osg 的一些优化程序会删除它。)这个 texture 类包装了 OpenGL 纹理 模式(wrap,filter,等等)和一个 osg::Image。下面的代码说明了如何从文件里读取 osg::Image 实例并把这个图像和纹理关联起来。 osg::Texture2D* KLN89FaceTexture = new osg::Texture2D; // protect from being optimized away as static state: KLN89FaceTexture->setDataVariance(osg::Object::DYNAMIC); // load an image by reading a file: osg::Image* klnFace = osgDB::readImageFile("KLN89FaceB.tga"); if (!klnFace) { std::cout << " couldn't find texture, quiting." << std::endl; return -1; } // Assign the texture to the image we read from file: KLN89FaceTexture->setImage(klnFace); 纹理可以和渲染 StateSet 关联起来。下一步就产生一个 StateSet,关联并启动我们的纹理,并 将这个 StateSet 附加到我们的 geometry 上。 // Create a new StateSet with default settings: osg::StateSet* stateOne = new osg::StateSet(); // Assign texture unit 0 of our new StateSet to the texture // we just created and enable the texture. stateOne->setTextureAttributeAndModes(0,KLN89FaceTexture, osg::StateAttribute::ON); // Associate this state set with the Geode that contains // the pyramid: pyramidGeode->setStateSet(stateOne); 最后一步是仿真循环: //The final step is to set up and enter a simulation loop. viewer.setUpViewer(osgProducer::Viewer::STANDARD_SETTINGS); viewer.setSceneData( root ); viewer.realize(); while( !viewer.done() ) { viewer.sync(); viewer.update(); viewer.frame(); } return 0; }
3.使用Shape,改变state 3.1本章目标 用osg:Shape实例构建场景。使用osg:StateSet控制shape的渲染。 3.2使用Shape类 Shape类是所有形状类别的基类。Shape既可用于剪裁和碰撞检测也可用于定义程序性地产生几 何体的那些基本形状。下面的类继承自Shape类: TriangleMesh Sphere InfinitePlane HeightField Cylinder Cone CompositeShape Box 为了使这些形状可以被渲染,我们需要把他们和Drawable类的实例关联起来。ShapeDrawable类 提供了这样的功能。这个类继承自Drawable并允许我们把Shape实例附加到可以被渲染的东西上。 既然ShapeDrawable类继承自Drawable,ShapDrawable实例就可以被加到Geode类实例上。下面 的步骤演示了将一个单位立方体加到空场景中时是如何做到这些的。 /Declare a group to act as root node of a scene: osg:Group*root new osg:Group(); /Declare a box class (derived from shape class)instance /This constructor takes an osg:Vec3 to define the center /and a float to define the height,width and depth. //(an overloaded constructor allows you to specify unique /height,width and height values.) osg:Box*unitCube new osg:Box(osg:Vec3(0,0,0),1.0f); /Declare an instance of the shape drawable class and initialize /it with the unitCube shape we created above. /This class is derived from'drawable'so instances of this /class can be added to Geode instances. osg:ShapeDrawable*unitCubeDrawable new osg:ShapeDrawable(unitCube); /Declare a instance of the geode class: osg:Geode*basicShapesGeode new osg:Geode(); /Add the unit cube drawable to the geode: basicShapesGeode->addDrawable(unitCubeDrawable); /Add the goede to the scene: root->addChild(basicShapesGeode):
8 3.使用 Shape,改变 state 3.1 本章目标 用 osg::Shape 实例构建场景。使用 osg::StateSet 控制 shape 的渲染。 3.2 使用 Shape 类 Shape 类是所有形状类别的基类。Shape 既可用于剪裁和碰撞检测也可用于定义程序性地产生几 何体的那些基本形状。下面的类继承自 Shape 类: TriangleMesh Sphere InfinitePlane HeightField Cylinder Cone CompositeShape Box 为了使这些形状可以被渲染,我们需要把他们和 Drawable 类的实例关联起来。ShapeDrawable 类 提供了这样的功能。这个类继承自 Drawable 并允许我们把 Shape 实例附加到可以被渲染的东西上。 既然 ShapeDrawable 类继承自 Drawable,ShapDrawable 实例就可以被加到 Geode 类实例上。下面 的步骤演示了将一个单位立方体加到空场景中时是如何做到这些的。 // Declare a group to act as root node of a scene: osg::Group* root = new osg::Group(); // Declare a box class (derived from shape class) instance // This constructor takes an osg::Vec3 to define the center // and a float to define the height, width and depth. // (an overloaded constructor allows you to specify unique // height, width and height values.) osg::Box* unitCube = new osg::Box( osg::Vec3(0,0,0), 1.0f); // Declare an instance of the shape drawable class and initialize // it with the unitCube shape we created above. // This class is derived from 'drawable' so instances of this // class can be added to Geode instances. osg::ShapeDrawable* unitCubeDrawable = new osg::ShapeDrawable(unitCube); // Declare a instance of the geode class: osg::Geode* basicShapesGeode = new osg::Geode(); // Add the unit cube drawable to the geode: basicShapesGeode->addDrawable(unitCubeDrawable); // Add the goede to the scene: root->addChild(basicShapesGeode);
产生一个球体和上面的代码基本相似。没有太多的注释的代码看起来是这个样子: /Create a sphere centered at the origin,unit radius: osg:Sphere*unitSphere new osg:Sphere(osg:Vec3(0,0,0),1.0); osg:ShapeDrawable*unitSphereDrawable=new osg:ShapeDrawable(unitSphere); 现在,我们可以使用transform节点将这个球体加到场景中,以便让它离开原点。 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); 3.3设置状态 前面的教程讲解了如何生成纹理,将其指定为从文件加载的图像,生成一个带纹理的StateSet。. 下面的代码建立了两个状态集合一一一个是BLEND纹理模式,另一个是DECAL纹理模式。BLEND模 式: /Declare a state set for 'BLEND'texture mode osg:StateSet*blendStateSet new osg:StateSet(); /Declare a TexEnv instance,set the mode to 'BLEND' osg:TexEnv*blendTexEnv new osg:TexEnv; blendTexEnv->setMode(osg:TexEnv:BLEND); /Turn the attribute of texture 0-the texture we loaded above -'ON' blendStateSet->setTextureAttributeAndModes(0,KLN89FaceTexture, osg:StateAttribute:ON); /Set the texture texture environment for texture 0 to the /texture envirnoment we declared above: 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); 产生了状态集合后我们就可以把它们应用在场景中的节点上。在scene graph的绘制遍历 (root->leaf)中状态是积累的。除非这个节点有一个它自己的状态,否则它会继承其父节点的状态。 (如果一个节点有一个以上的父节点,它会使用一个以上的状态渲染。) 9
9 产生一个球体和上面的代码基本相似。没有太多的注释的代码看起来是这个样子: // Create a sphere centered at the origin, unit radius: osg::Sphere* unitSphere = new osg::Sphere( osg::Vec3(0,0,0), 1.0); osg::ShapeDrawable* unitSphereDrawable=new osg::ShapeDrawable(unitSphere); 现 在 , 我 们 可 以 使 用 transform 节 点 将 这 个 球 体 加 到 场 景 中 , 以 便 让 它 离 开 原 点 。 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); 3.3 设置状态 前面的教程讲解了如何生成纹理,将其指定为从文件加载的图像,生成一个带纹理的 StateSet。 下面的代码建立了两个状态集合——一个是 BLEND 纹理模式,另一个是 DECAL 纹理模式。BLEND 模 式: // Declare a state set for 'BLEND' texture mode osg::StateSet* blendStateSet = new osg::StateSet(); // Declare a TexEnv instance, set the mode to 'BLEND' osg::TexEnv* blendTexEnv = new osg::TexEnv; blendTexEnv->setMode(osg::TexEnv::BLEND); // Turn the attribute of texture 0 - the texture we loaded above - 'ON' blendStateSet->setTextureAttributeAndModes(0,KLN89FaceTexture, osg::StateAttribute::ON); // Set the texture texture environment for texture 0 to the // texture envirnoment we declared above: 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); 产生了状态集合后我们就可以把它们应用在场景中的节点上。在 scene graph 的绘制遍历 (root->leaf)中状态是积累的。除非这个节点有一个它自己的状态,否则它会继承其父节点的状态。 (如果一个节点有一个以上的父节点,它会使用一个以上的状态渲染。)
root->setStateSet(blendStateSet): unitSphereGeode->setStateSet(decalStateSet); 最后一步是进入仿真循环。 viewer.setUpViewer(osgProducer:Viewer:STANDARD SETTINGS); viewer.setSceneData(root ) viewer.realize(): while(!viewer.done()) { viewer.sync(); viewer.update(); viewer.frame(: } return 0: 4.更多的StateSet 4.1 StateSet如何工作 场景图管理器遍历scene graph,.决定哪些几何体需要送到图形管道渲染。在遍历的过程中, 场景图管理器也搜集几何体如何被渲染的信息。这些信息存在osg:StateSet实例中。StateSet包 含OpenGL的属性/数值对列表。这些StateSet可以和scenegraph中的节点关联起来。在预渲染的 遍历中,StateSet从根节点到叶子节点是积累的。一个节点的没有变化的状态属性也是简单的遗传 自父节点。 几个附加的特性允许更多的控制和弹性。一个状态的属性值可以被设为OVERRIDE。这意味着这 个节点的所有孩子节点一一不管其属性值是什么一一会遗传其父节点的属性值。OVERRIDE意味着可 以被覆盖。如果一个孩子节点把那个属性设为PROTECTED,那么它就可以设置自己的属性值,而不 用理会父节点的设置。 4.2例子及代码 下面的场景示范了state如何影响scene graph。根节点有一个BLEND模式纹理的基本状态。 这个基本状态会被所有子节点继承,除非这个状态的参数改变。根节点的右子树就是这样的。右孩 子没有被指定任何状态,所以它使用和根节点一样的状态来渲染。对于节点6,纹理的混合模式没 有改变但是使用了一个新纹理。 根节点的左子树的纹理模式被设为DECL。其他的参数是一样的,所以它们从根节点继承。在 节点3中,FOG被打开了并设置为OVERRIDE。这个节点一一节点3一一的左孩子将FOG设为了OFF。 既然它没有设置PROTECTED并且它父节点设置了OVERRIDE,所以就像父节点一样FOG仍然是ON。 右孩子4设置FOG属性值为PROTECTED,因此可以覆盖其父节点的设置。 o
10 root->setStateSet(blendStateSet); unitSphereGeode->setStateSet(decalStateSet); 最后一步是进入仿真循环。 viewer.setUpViewer(osgProducer::Viewer::STANDARD_SETTINGS); viewer.setSceneData( root ); viewer.realize(); while( !viewer.done() ) { viewer.sync(); viewer.update(); viewer.frame(); } return 0; 4.更多的 StateSet 4.1StateSet 如何工作 场景图管理器遍历 scene graph,决定哪些几何体需要送到图形管道渲染。在遍历的过程中, 场景图管理器也搜集几何体如何被渲染的信息。这些信息存在 osg::StateSet 实例中。StateSet 包 含 OpenGL 的属性/数值对列表。这些 StateSet 可以和 scenegraph 中的节点关联起来。在预渲染的 遍历中,StateSet 从根节点到叶子节点是积累的。一个节点的没有变化的状态属性也是简单的遗传 自父节点。 几个附加的特性允许更多的控制和弹性。一个状态的属性值可以被设为 OVERRIDE。这意味着这 个节点的所有孩子节点——不管其属性值是什么——会遗传其父节点的属性值。OVERRIDE 意味着可 以被覆盖。如果一个孩子节点把那个属性设为 PROTECTED,那么它就可以设置自己的属性值,而不 用理会父节点的设置。 4.2 例子及代码 下面的场景示范了 state 如何影响 scene graph。根节点有一个 BLEND 模式纹理的基本状态。 这个基本状态会被所有子节点继承,除非这个状态的参数改变。根节点的右子树就是这样的。右孩 子没有被指定任何状态,所以它使用和根节点一样的状态来渲染。对于节点 6,纹理的混合模式没 有改变但是使用了一个新纹理。 根节点的左子树的纹理模式被设为 DECAL。其他的参数是一样的,所以它们从根节点继承。在 节点 3 中,FOG 被打开了并设置为 OVERRIDE。这个节点——节点 3——的左孩子将 FOG 设为了 OFF。 既然它没有设置 PROTECTED 并且它父节点设置了 OVERRIDE,所以就像父节点一样 FOG 仍然是 ON。 右孩子 4 设置 FOG 属性值为 PROTECTED,因此可以覆盖其父节点的设置
Screen BLEND Texture Mode (1)DECAL Texture Mode (no change) (2)FOG,ON,OVERRIDE (5)Change Texture (3)FOG,OFF (4)FOG,OFF,PROTECTED 虚拟现实中国社区 下面是操作状态配置并用节点将这些状态关联起来的代码。 /Set an osg:TexEnv instance's mode to BLEND, /make this TexEnv current for texture unit 0 and assign //a valid texture to texture unit 0 blendTexEnv->setMode(osg:TexEnv:BLEND): stateRootBlend->setTextureAttribute(0,blendTexEnv,osg:StateAttribute:ON): stateRootBlend->setTextureAttributeAndModes(0,ocotilloTexture, osg:StateAttribute:ON); /For state five,change the texture associated with texture unit 0 //all other attributes will remain unchanged as inherited from above. //(texture mode will still be BLEND) stateFiveDustTexture->setTextureAttributeAndModes(0,dustTexture. osg:StateAttribute:ON): /Set the mode of an osg:TexEnv instance to DECAL //Use this mode for stateOneDecal. decalTexEnv->setMode(osg:TexEnv:DECAL); stateOneDecal->setTextureAttribute(0,decalTexEnv,osg::StateAttribute::ON): W
11 下面是操作状态配置并用节点将这些状态关联起来的代码。 // Set an osg::TexEnv instance's mode to BLEND, // make this TexEnv current for texture unit 0 and assign // a valid texture to texture unit 0 blendTexEnv->setMode(osg::TexEnv::BLEND); stateRootBlend->setTextureAttribute(0,blendTexEnv,osg::StateAttribute::ON); stateRootBlend->setTextureAttributeAndModes(0,ocotilloTexture, osg::StateAttribute::ON); // For state five, change the texture associated with texture unit 0 //all other attributes will remain unchanged as inherited from above. // (texture mode will still be BLEND) stateFiveDustTexture->setTextureAttributeAndModes(0,dustTexture, osg::StateAttribute::ON); // Set the mode of an osg::TexEnv instance to DECAL //Use this mode for stateOneDecal. decalTexEnv->setMode(osg::TexEnv::DECAL); stateOneDecal->setTextureAttribute(0,decalTexEnv,osg::StateAttribute::ON);