OSG編程指南<十>:OSG幾何體的繪制

1、場景基本繪圖類

??在 OSG 中創建幾何體的方法比較簡單,通常有 3 種處理幾何體的手段:

  • 使用松散封裝的OpenGL 繪圖基元;
  • 使用 OSG 中的基本幾何體;
  • 從文件中導入場景模型。

??使用松散封裝的OpenGL 繪圖基元繪制幾何體具有很強的靈活性,但工作量通常非常大,當面對大型場景時,繪制幾何體將是一項非常艱巨而富有挑戰的工作,因此,通常還是采用讀入外部模型的方法。

1.1 向量與數組類

??在 OSG 中定義了大量的類來保存數據,數據通常是以向量的形式來表示的,向量數據主要包括頂點坐標、紋理坐標、顏色和法線等。例如,定義 osg::Vec2 來保存紋理坐標;定義 osg::Vec3 來保存頂點坐標和法線坐標;定義 osg::Vec4 保存顏色的 RGBA 值。osg::Vec2、osg::Vec3 和 osg::Vec4 是分別用來保存向量的二維數組、三維數組和四維數組,這些類不僅能夠保存各種數據,還提供了向量的基本運算機制,如加、減、乘、除四則元算、點積和單位化等相關的操作。
??在 OSG 中還定義了模板數組用來保存對象,例如,可以用頂點索引對象(osg::DrawElementsUInt)來保存頂點索引,用顏色索引(osg::TemplateIndexeArray)來保存顏色。但最常用的還是保存向量數據,如 osg::Vec3Array 來保存眾多頂點坐標、osg::Vec2Array 保存紋理坐標等,這些模板數組都繼承自 std::Vector,因此,它們具有向量的基本操作方法,例如,可以利用 push_back()添加一個元素,可以利用pop_back()刪除一個元素,同樣也可以使用 clear()刪除所有的元素。

1.2 Drawable 類

??Drawable 類是一個純基類,無法實例化。作為可繪制對象基類的 osg::Drawable 類,它派生了很多類,它的繼承關系圖如圖 4-1 所示。
在這里插入圖片描述
??從圖 4-1 可以看出,由 osg::Drawable 派生的類有 9 個,分別是 osg::DrawPixels、osg::Geometry、osg::ShapeDrawable、osgParticle::ParticleSystem、osgParticle::PrecipitationEffect::PrecipitationDrawable、osgShadow::OccluderGeometry、osgShadow::ShadowVolumeGeometry、osgSim::ImpostorSprite 和 osgText::TextBase,其中,從 OSG 核心庫派生出了 3 個類,分別是 osg::DrawPiexels 類(主要封裝了 OpenGL中 glDrawPixels()的功能)、osg::Geometry 類(繪制幾何體的類,應用比較靈活)和 osg::ShapeDrawable類(主要封裝了一些已經定義好的幾何體,不需要設置坐標即可直接調用,如長方體、正方體、球體
等)。其他的類中,有兩個派生自粒子系統庫,有兩個派生自陰影庫,還有兩個分別派生自 osgSim 庫和 osgText 文字庫。

1.3 PrimitiveSet 類

??osg::PrimitiveSet 類繼承自 osg::Object 虛基類,但它不具備一般場景中的特性。osg::PrimitiveSet 類的繼承關系圖如圖 4-2 所示。
在這里插入圖片描述
??該類主要松散封裝了 OpenGL 的繪圖基元,通過指定繪圖基元來指定幾何體頂點將采用哪一種或幾種基元繪制。常用的繪圖基元包括如下幾種:

POINTS = GL_POINTS //繪制點
LINES = GL_LINES //繪制線
LINE_STRIP = GL_LINE_STRIP //繪制多段線
LINE_LOOP = GL_LINE_LOOP //繪制封閉線
TRIANGLES = GL_TRIANGLES //繪制一系列的三角形(不共用頂點)
TRIANGLE_STRIP = GL_TRIANGLE_STRIP //繪制一系列三角形(共用后面的兩個頂點)
TRIANGLE_FAN = GL_TRIANGLE_FAN //繪制一系列三角形,頂點順序與上一條語句繪制的三角形不同
QUADS = GL_QUADS //繪制四邊形
QUAD_STRIP = GL_QUAD_STRIP //繪制一系列四邊形
POLYGON = GL_POLYGON //繪制多邊形

從 osg::PrimitiveSet 類的繼承關系圖可以看出,它的派生類主要有如下 3 個:

  • osg::DrawArrays 類。繼承自 osg::PrimitiveSet,它封裝了glDrawArrays()頂點數組繪圖命令,用于指定頂點和繪圖基元。
  • osg::DrawElements 類。它又派生出 3 個子類,分別是 osg::DrawElementsUByte、osg::DrawElementsUShort和osg::DrawElementsUInt,封裝了 glDrawElements()的指令,可以起索引的作用,在后面的示例中會用到。
  • osg::DrawArrayLengths 類。它的主要作用是多次繪制,即多次調用glDrawArrays(),且每次均使用不同的長度和索引范圍,在繪制過程中用得不是很多。

DrawArrays 的基本用法如下:

osg::DrawArrays::DrawArrays( GLenum mode, GLint first,GLsizei count );
/*參數說明:第一個參數是指定的繪圖基元,即前面所列舉的常見繪圖基元;第二個參數是指繪制幾何體的第一個
頂點數在指定頂點的位置數;第三個參數是使用的頂點的總數*/

??還有一點值得注意的是,雖然 osg::PrimitiveSet 類提供與 OpenGL 一樣的頂點機制,但是在內部渲染上還是有一定區別的。根據渲染環境的不同,渲染的方式也是不一樣的,可能會采用頂點、頂點數組、顯示列表或者 glBegin()/glEnd()來渲染幾何體,繼承自 Drawable 類的對象(如 Geometry)在默認條件下將使用顯示列表。其中,osg::Drawable::setUseDisplayList(false)用于手動禁止使用顯示列表。還有一種比較特殊的情況,如果設置BIND_PER_PRIMITIVE 綁定方式,那么OSG將采用glBegin()/glEnd()函數進行渲染。因為在設置使用綁定方式為 BIND_PER_PRIMITIVE 后,它就為每個獨立的幾何圖元設置一種綁定屬性。

2、基本幾何體的繪制

??OSG 創建的場景和對象是由簡單的圖元(我們把構成 3D 對象的構件稱為圖元)按照一定的方式排列和組合而成的,OSG 中的所有圖元都是一維或二維對象,包括單個的點、直線和復雜的多邊形。

2.1 幾何體類 osg::Geometry

??它的主要作用是對指定繪制幾何體的頂點數及對數據的解析,主要提供了如下 3大類方法:

1)指定向量數據。就是以前所涉及的頂點數據、紋理坐標及顏色等一系列向量數據,可以通過下面的幾個函數來實現:

void setVertexArray(Array*array) //設置頂點數組
void setVertexData(const ArrayData&arrayData) //設置頂點數組數據
void setVertexIndices(IndexArray*array) //設置頂點索引數組
void setNormalArray(Array*array) //設置法線數組
void setNormalData(const ArrayData&arrayData) //設置法線數組數據
void setNormalIndices(IndexArray*array) //設置法線索引數組
void setColorArray(Array*array) //設置顏色數組
void setColorData(const ArrayData&arrayData) //設置顏色數組數據
void setColorIndices(IndexArray*array) //設置顏色索引數組
void setTexCoordArray(unsigned int unit,Array*)
//設置紋理坐標數組,第一個參數是紋理單元,第二個是紋理坐標數組
void setTexCoordData(unsigned int index, const ArrayData &arrayData)
//設置紋理坐標數組數據,第一個參數是紋理單元,第二個是紋理坐標數組數據
void setTexCoordIndices(unsigned int unit, IndexArray *)
//設置紋理坐標索引數組,第一個參數是紋理單元,第二個是紋理索引坐標數組

2)設置綁定方式。數據綁定主要有兩項,即法線及顏色,可以通過下面的兩個函數來實現:

void setNormalBinding(AttributeBinding ab) //設置法線綁定方式
void setColorBinding(AttributeBinding ab) //設置顏色綁定方式

綁定方式主要有下面幾種:

BIND_OFF //不啟用綁定
BIND_OVERALL //綁定全部的頂點
BIND_PER_PRIMITIVE_SET //單個繪圖基元綁定
BIND_PER_PRIMITIVE //單個獨立的繪圖基元綁定
BIND_PER_VERTEX //單個頂點綁定

3)數據解析。當在指定了各種向量數據和綁定方式之后,采用何種方式來渲染幾何體就是最為關鍵的。不同的方式下,渲染出來的圖形是不一樣的,即使效果一樣,可能面數或內部機制等也是有區別的。數據解析主要通過如下函數來指定:

bool addPrimitiveSet(PrimitiveSet*primitiveset)
/*參數說明:osg::PrimitiveSet 是無法初始化的虛基類,因此這里主要是調用它的子類來指定數據渲染,最常用的就是
前面介紹的 osg::DrawArrays,用法比較簡單,初始化一個對象實例,參數說明見前面 osg::DrawArrays 類*/

通過前面的講述可知,繪制并渲染幾何體主要有如下 3 大步驟:
1)創建各種向量數據,如頂點、紋理坐標、顏色和法線等。需要注意的是,添加頂點數據時主要按照逆時針順序添加,以確保背面剔除(backface culling)的正確(后面還會有介紹)。
2)實例化一個幾何體對象(osg::Geometry),設置頂點坐標數組、紋理坐標數組、顏色數組、法線數組、綁定方式及數據解析。
3)加入葉節點繪制并渲染。

2.2 示例

在這里插入圖片描述

2.3 示例源碼

#include <osgViewer/Viewer>#include <osg/Node>
#include <osg/Geode>
#include <osg/Group>#include <osgDB/ReadFile>
#include <osgDB/WriteFile>#include <osgUtil/Optimizer>#include <osgViewer/ViewerEventHandlers> //事件監聽
#include <osgGA/StateSetManipulator> //事件響應類,對渲染狀態進行控制#pragma comment(lib, "OpenThreadsd.lib")
#pragma comment(lib, "osgd.lib")
#pragma comment(lib, "osgDBd.lib")
#pragma comment(lib, "osgUtild.lib")
#pragma comment(lib, "osgGAd.lib")
#pragma comment(lib, "osgViewerd.lib")
#pragma comment(lib, "osgTextd.lib")//創建一個四邊形節點
osg::ref_ptr<osg::Node> createQuad()
{//創建一個葉節點對象osg::ref_ptr<osg::Geode> geode = new osg::Geode();//創建一個幾何體對象osg::ref_ptr<osg::Geometry> geom = new osg::Geometry();//創建頂點數組osg::ref_ptr<osg::Vec3Array> aryVertex = new osg::Vec3Array();//添加數據aryVertex->push_back(osg::Vec3(0.0f, 0.0f, 0.0f));aryVertex->push_back(osg::Vec3(1.0f, 0.0f, 0.0f));aryVertex->push_back(osg::Vec3(1.0f, 0.0f, 1.0f));aryVertex->push_back(osg::Vec3(0.0f, 0.0f, 1.0f));aryVertex->push_back(osg::Vec3(0.0f, -1.0f, 0.0f));//設置頂點數據geom->setVertexArray(aryVertex.get());//創建四邊形頂點索引數組,指定繪圖基元為四邊形,注意添加順序osg::ref_ptr<osg::DrawElementsUInt> quad = new osg::DrawElementsUInt(osg::PrimitiveSet::QUADS, 0);//添加數據quad->push_back(0);quad->push_back(1);quad->push_back(2);quad->push_back(3);//添加到幾何體geom->addPrimitiveSet(quad.get());//創建三角形頂點索引數組,指定繪圖基元為三角形,注意添加順序osg::ref_ptr<osg::DrawElementsUInt> triangle = new osg::DrawElementsUInt(osg::PrimitiveSet::TRIANGLES, 0);//添加數據triangle->push_back(4);triangle->push_back(0);triangle->push_back(3);//添加到幾何體geom->addPrimitiveSet(triangle.get());//創建顏色數組osg::ref_ptr<osg::Vec4Array> vecColor = new osg::Vec4Array();//添加數據vecColor->push_back(osg::Vec4(1.0f, 0.0f, 0.0f, 1.0f));vecColor->push_back(osg::Vec4(0.0f, 1.0f, 0.0f, 1.0f));vecColor->push_back(osg::Vec4(0.0f, 0.0f, 1.0f, 1.0f));vecColor->push_back(osg::Vec4(1.0f, 1.0f, 0.0f, 1.0f));vecColor->push_back(osg::Vec4(1.0f, 1.0f, 1.0f, 1.0f));//設置顏色數組geom->setColorArray(vecColor.get());//創建顏色索引數組//osg::TemplateIndexArray<unsigned int ,osg::Array::UIntArrayType,4,4>* colorIndex = new osg::TemplateIndexArray<unsigned int ,osg::Array::UIntArrayType,4,4>();//添加數據,注意添加數據順序與頂點一一對應//colorIndex->push_back(0);//colorIndex->push_back(1);//colorIndex->push_back(2);//colorIndex->push_back(3);//colorIndex->push_back(2);//設置顏色索引數組//geom->setColorIndices(colorIndex);//設置顏色的綁定方式為單個頂點geom->setColorBinding(osg::Geometry::BIND_PER_VERTEX);//創建法線數組osg::ref_ptr<osg::Vec3Array> vecNormal = new osg::Vec3Array();//添加法線vecNormal->push_back(osg::Vec3(0.0f, -1.0f, 0.0f));//設置法線數組geom->setNormalArray(vecNormal.get());//設置法線的綁定方式為全部頂點geom->setNormalBinding(osg::Geometry::BIND_OVERALL);//添加到葉節點geode->addDrawable(geom.get());return geode.get();
}int main()
{//創建Viewer對象,場景瀏覽器osg::ref_ptr<osgViewer::Viewer> viewer = new osgViewer::Viewer();osg::ref_ptr<osg::Group> root = new osg::Group();//添加到場景root->addChild(createQuad());//優化場景數據osgUtil::Optimizer optimizer;optimizer.optimize(root.get());viewer->setSceneData(root.get());//切換網格模式,方便比較viewer->addEventHandler(new osgGA::StateSetManipulator(viewer->getCamera()->getOrCreateStateSet()));viewer->addEventHandler(new osgViewer::StatsHandler());//實現狀態信息統計viewer->addEventHandler(new osgViewer::WindowSizeHandler());viewer->setUpViewInWindow(400,400,1000,800);viewer->run();return 0;
}

3、OSG預定義幾何體

3.1 osg::Shape 類

??osg::Shape 類直接繼承自 osg::Object 基類,繼承關系圖如圖 4-6 所示。
在這里插入圖片描述
??osg::Shape 類是各種內嵌幾何體的基類,它不但可用于剔除和碰撞檢測,還可用于生成預定義的幾何體對象。常用的內嵌幾何體包括如下幾種:

osg::Box //正方體
osg::Capsule //太空艙
osg::Cone //椎體
osg::Cylinder //柱體
osg::HeightField //高度圖
osg::InfinitePlane //無限平面
osg::Sphere //球體
osg::TriangleMesh //三角片

3.2 osg::ShapeDrawable 類

??在 OSG 中內嵌預定義的幾何體,如果渲染這些內嵌的幾何體,就必須將其與 osg::Drawable 關聯。實際應用中,可以使用 osg::Drawable 類的派生類 osg::ShapeDrawable來完成這個功能。osg::ShapeDrawable 類在前面已經講到,它派生自osg::Drawable 類。由于它繼承自 osg::Drawable 類,所以它的實例需要被添加到葉節點中才能被實例繪制。
在 osg::ShapeDrawable 類的構造函數中提供了關聯 osg::Shape 的方法:

ShapeDrawable(Shape*shape, TessellationHints *hints=0)
//第一個參數為 shape,第二個參數默認下不細化

3.3 網格化類

??網格化類(osg::TessellationHints)直接繼承自 osg::Object 基類。osg::TessellationHints 類的主要作用是設置預定義幾何體對象的精細程度,精細程度越高,表示其細分越詳細,但對于不同的預定義幾何體對象它的作用是不一樣的,例如:

 Box(四棱柱):網格化類對于四棱柱沒有意義。Capsule(太空艙):太空艙分 3 個部分,上下半球部分和圓柱側面部分,默認圓柱側面被細分。Cone(圓錐):直接細分。Cylinder(柱體):直接細分。Sphere(球):直接細分。

目前,osg::TessellationHints 類并不完整,部分類成員函數還沒有實現,具體可以參看源碼。在內嵌幾何體對象中,默認的情況下,網格化類的精細度為 0,表示預定義的幾何體此時按照原頂點默認繪制,不做任何細化處理。

3.4 示例

在這里插入圖片描述

3.5 示例源碼

#include <windows.h>#include <osgViewer/Viewer>
#include <osg/Node>
#include <osg/Geode>
#include <osg/Geometry>
#include <osg/Group>
#include <osg/Switch>
#include <osg/Billboard>
#include <osg/Texture2D>
#include <osg/Image>
#include <osg/Vec3>
#include <osg/Vec2>
#include <osg/PositionAttitudeTransform>
#include <osg/MatrixTransform>
#include <osgDB/ReadFile>
#include <osgDB/WriteFile>
#include <osgUtil/Optimizer>
#include <osg/PagedLOD>
#include <osgSim/Impostor>
#include <osgViewer/ViewerEventHandlers> //事件監聽
#include <osgGA/StateSetManipulator> //事件響應類,對渲染狀態進行控制
#include <osgUtil/Simplifier> //簡化幾何體
#include <osg/OccluderNode>
#include <osg/StateSet>
#include <osg/ConvexPlanarOccluder>
#include <osg/BoundingBox>
#include <osg/BoundingSphere>
#include <osgUtil/Optimizer>
#include <iostream>
#include <osg/ShapeDrawable>#pragma comment(lib, "OpenThreadsd.lib")
#pragma comment(lib, "osgd.lib")
#pragma comment(lib, "osgDBd.lib")
#pragma comment(lib, "osgUtild.lib")
#pragma comment(lib, "osgGAd.lib")
#pragma comment(lib, "osgViewerd.lib")
#pragma comment(lib, "osgTextd.lib")
#pragma comment(lib, "osgSimd.lib")
#pragma comment(lib, "osgFXd.lib")//繪制多個預定義的幾何體
osg::ref_ptr<osg::Geode> createShape()
{//創建一個葉節點osg::ref_ptr<osg::Geode> geode = new osg::Geode();//設置半徑和高度float radius = 0.8f;float height = 1.0f;//創建精細度對象,精細度越高,細分就越多osg::ref_ptr<osg::TessellationHints> hints = new osg::TessellationHints;//設置精細度為 0.5fhints->setDetailRatio(0.5f);//添加一個球體,第一個參數是預定義幾何體對象,第二個是精細度,默認為 0geode->addDrawable(new osg::ShapeDrawable(new osg::Sphere(osg::Vec3(0.0f, 0.0f, 0.0f), radius), hints.get()));//添加一個正方體geode->addDrawable(new osg::ShapeDrawable(new osg::Box(osg::Vec3(2.0f, 0.0f, 0.0f), 2 * radius), hints.get()));//添加一個圓錐geode->addDrawable(new osg::ShapeDrawable(new osg::Cone(osg::Vec3(4.0f, 0.0f, 0.0f), radius, height), hints.get()));//添加一個圓柱體geode->addDrawable(new osg::ShapeDrawable(new osg::Cylinder(osg::Vec3(6.0f, 0.0f, 0.0f), radius, height),hints.get()));//添加一個太空艙geode->addDrawable(new osg::ShapeDrawable(new osg::Capsule(osg::Vec3(8.0f, 0.0f, 0.0f), radius, height),hints.get()));return geode.get();
}int main()
{//創建Viewer對象,場景瀏覽器osg::ref_ptr<osgViewer::Viewer> viewer = new osgViewer::Viewer();osg::ref_ptr<osg::Group> root = new osg::Group();//添加到場景root->addChild(createShape());//優化場景數據osgUtil::Optimizer optimizer;optimizer.optimize(root.get());viewer->setSceneData(root.get());//切換網格模式,方便比較viewer->addEventHandler(new osgGA::StateSetManipulator(viewer->getCamera()->getOrCreateStateSet()));viewer->addEventHandler(new osgViewer::StatsHandler());//實現狀態信息統計viewer->addEventHandler(new osgViewer::WindowSizeHandler());viewer->setUpViewInWindow(400,400,1000,800);viewer->run();return 0;
}

4、多邊形分格化

4.1 定義

??如果讀者對 OpenGL 有一定了解的話,應該知道 OpenGL 為了快速渲染多邊形,只能直接顯示簡單的凸多邊形。所謂簡單的凸多邊形,就是多邊形上任意兩點的連線上的點依屬于該多邊形。對凹多邊形或者自交叉多邊形的渲染結果將不確定。下面列舉一些需要分格化的多邊形,如圖 4-10 所示。
在這里插入圖片描述

??為了正確顯示凹多邊形或者自交叉多邊形,就必須把它們分解為簡單的凸多邊形,這種做法就稱為多邊形的分格化。OSG 是對底層 OpenGL API 的封裝,所以它同樣只能直接顯示簡單的凸多邊形,對于凹多邊形或者自交叉多邊形,渲染也是不確定的。
??在 OSG 中提供了一個多邊形分格化的類 osgUtil::Tessellator,它繼承自 osg::Referenced 類,繼承關系圖如圖 4-11 所示。
在 OSG 中進行多邊形分格化渲染需要如下 3 個步驟:
(1)創建多邊形分格化對象。
(2)設置分格化對象的類型,通常有下面 3 種類型:

TESS_TYPE_GEOMETRY, //分格化幾何體
TESS_TYPE_DRAWABLE, //分格化幾何體中的 Drawable(如多邊形、三角形、四邊形等)
TESS_TYPE_POLYGONS //只分格化幾何體中的多邊形

(3)根據計算的環繞數指定相應的環繞規則。

1.環繞數
在《OpenGL 編程指南》第 5 版中曾指出“對于一條簡單的輪廓線,每個點的環繞數就是環繞這個點的所有輪廓線的代數和(用一個有符號的整數表示,求和規則是:逆時針環繞的輪廓線為正,順時針環繞的輪廓線為負)。這個過程把一個有符號的整數數值與平面上的每個頂點相關聯。注意,對于區域中的所有點,它們的環繞數都是相同的”。圖 4-12 為輪廓線與環繞數的計算方法,讀者可以通過此圖理解環繞數及如何計算環繞數。
在這里插入圖片描述

2.環繞規則
如果一個區域的環繞數屬于環繞規則所選擇的類型,那么它就是它的內部區域。通常,環繞規則把具有奇數和非零環繞數的區域定義為內部區域。環繞規則主要是針對環繞數來確定的。
幾種常用的環繞規則如下:

TESS_WINDING_ODD=GLU_TESS_WINDING_ODD //環繞數為奇數
TESS_WINDING_NONZERO=GLU_TESS_WINDING_NONZERO //環繞數為非零數
TESS_WINDING_POSITIVE=GLU_TESS_WINDING_POSITIVE //環繞數為正數
TESS_WINDING_NEGATIVE=GLU_TESS_WINDING_NEGATIVE //環繞數為負數
TESS_WINDING_ABS_GEQ_TWO=GLU_TESS_WINDING_ABS_GEQ_TWO //環繞數為絕對值大于或等于 2

4.2 示例

在這里插入圖片描述

4.3 示例源碼

#include <windows.h>#include <osgViewer/Viewer>
#include <osg/Node>
#include <osg/Geode>
#include <osg/Geometry>
#include <osg/Group>
#include <osg/Switch>
#include <osg/Billboard>
#include <osg/Texture2D>
#include <osg/Image>
#include <osg/Vec3>
#include <osg/Vec2>
#include <osg/PositionAttitudeTransform>
#include <osg/MatrixTransform>
#include <osgDB/ReadFile>
#include <osgDB/WriteFile>
#include <osgUtil/Optimizer>
#include <osg/PagedLOD>
#include <osgSim/Impostor>
#include <osgViewer/ViewerEventHandlers> //事件監聽
#include <osgGA/StateSetManipulator> //事件響應類,對渲染狀態進行控制
#include <osgUtil/Simplifier> //簡化幾何體
#include <osg/OccluderNode>
#include <osg/StateSet>
#include <osg/ConvexPlanarOccluder>
#include <osg/BoundingBox>
#include <osg/BoundingSphere>
#include <osgUtil/Optimizer>
#include <iostream>
#include <osg/ShapeDrawable>
#include <osgUtil/Tessellator>#pragma comment(lib, "OpenThreadsd.lib")
#pragma comment(lib, "osgd.lib")
#pragma comment(lib, "osgDBd.lib")
#pragma comment(lib, "osgUtild.lib")
#pragma comment(lib, "osgGAd.lib")
#pragma comment(lib, "osgViewerd.lib")
#pragma comment(lib, "osgTextd.lib")
#pragma comment(lib, "osgSimd.lib")
#pragma comment(lib, "osgFXd.lib")//使用分格化繪制凹多邊形
osg::ref_ptr<osg::Geode> tesslatorGeometry()
{osg::ref_ptr<osg::Geode> geode = new osg::Geode();osg::ref_ptr<osg::Geometry> geom = new osg::Geometry();geode->addDrawable(geom.get());//以下是一些頂點數據//墻const float wall[5][3] ={ { 2200.0f, 0.0f, 1130.0f },{ 2600.0f, 0.0f, 1130.0f },{ 2600.0f, 0.0f, 1340.0f },{ 2400.0f, 0.0f, 1440.0f },{ 2200.0f, 0.0f, 1340.0f } };//門const float door[4][3] ={ { 2360.0f, 0.0f, 1130.0f },{ 2440.0f, 0.0f, 1130.0f },{ 2440.0f, 0.0f, 1230.0f },{ 2360.0f, 0.0f, 1230.0f } };//四扇窗戶const float windows[16][3] ={ { 2240.0f, 0.0f, 1180.0f },{ 2330.0f, 0.0f,1180.0f },{ 2330.0f, 0.0f, 1220.0f },{ 2240.0f, 0.0f, 1220.0f },{ 2460.0f, 0.0f, 1180.0f },{ 2560.0f, 0.0f, 1180.0f },{ 2560.0f, 0.0f, 1220.0f },{ 2460.0f, 0.0f, 1220.0f },{ 2240.0f, 0.0f, 1280.0f },{ 2330.0f, 0.0f, 1280.0f },{ 2330.0f, 0.0f, 1320.0f },{ 2240.0f, 0.0f, 1320.0f },{ 2460.0f, 0.0f, 1280.0f },{ 2560.0f, 0.0f, 1280.0f },{ 2560.0f, 0.0f, 1320.0f },{ 2460.0f, 0.0f, 1320.0f } };//設置頂點數據osg::ref_ptr<osg::Vec3Array> coords = new osg::Vec3Array();geom->setVertexArray(coords.get());//設置法線osg::ref_ptr<osg::Vec3Array> normal = new osg::Vec3Array();normal->push_back(osg::Vec3(0.0f, -1.0f, 0.0f));geom->setNormalArray(normal.get());geom->setNormalBinding(osg::Geometry::BIND_OVERALL);//添加墻for (int i = 0; i < 5; i++){coords->push_back(osg::Vec3(wall[i][0], wall[i][1], wall[i][2]));}geom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::POLYGON, 0, 5));//添加門for (int i = 0; i < 4; i++){coords->push_back(osg::Vec3(door[i][0], door[i][1], door[i][2]));}//添加窗for (int i = 0; i < 16; i++){coords->push_back(osg::Vec3(windows[i][0], windows[i][1], windows[i][2]));}geom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS, 5, 20));//創建分格化對象osg::ref_ptr<osgUtil::Tessellator> tscx = new osgUtil::Tessellator();//設置分格類型為幾何體tscx->setTessellationType(osgUtil::Tessellator::TESS_TYPE_GEOMETRY);//設置只顯示輪廓線為 false,這里還需要填充tscx->setBoundaryOnly(false);//設置環繞規則tscx->setWindingType(osgUtil::Tessellator::TESS_WINDING_ODD);//使用分格化tscx->retessellatePolygons(*(geom.get()));return geode.get();
}int main()
{//創建Viewer對象,場景瀏覽器osg::ref_ptr<osgViewer::Viewer> viewer = new osgViewer::Viewer();osg::ref_ptr<osg::Group> root = new osg::Group();//添加到場景root->addChild(tesslatorGeometry());//優化場景數據osgUtil::Optimizer optimizer;optimizer.optimize(root.get());viewer->setSceneData(root.get());//切換網格模式,方便比較viewer->addEventHandler(new osgGA::StateSetManipulator(viewer->getCamera()->getOrCreateStateSet()));viewer->addEventHandler(new osgViewer::StatsHandler());//實現狀態信息統計viewer->addEventHandler(new osgViewer::WindowSizeHandler());viewer->setUpViewInWindow(400,400,1000,800);viewer->run();return 0;
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/165928.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/165928.shtml
英文地址,請注明出處:http://en.pswp.cn/news/165928.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

牛氣霸屏-快抖云推獨立版V1.6.7

介紹 快抖云推全插件獨立版是最近很火的牛氣霸屏系統獨立版&#xff0c;牛氣霸屏系統就是商家通過系統在線創建抖音或快手霸屏活動&#xff0c;并生成該活動的爆客二維碼&#xff0c;用戶通過掃二維碼即可參加活動&#xff08;活動可以是領取卡劵&#xff0c;抽獎等&#xff0…

DevExpress中文教程 - 如何在macOS和Linux (CTP)上創建、修改報表(下)

DevExpress Reporting是.NET Framework下功能完善的報表平臺&#xff0c;它附帶了易于使用的Visual Studio報表設計器和豐富的報表控件集&#xff0c;包括數據透視表、圖表&#xff0c;因此您可以構建無與倫比、信息清晰的報表。 DevExpress Reports — 跨平臺報表組件&#x…

linux(1)之build構建系統基礎(一)

Linux(1)之buildroot構建系統(一) Author&#xff1a;Onceday Date&#xff1a;2023年11月12日 漫漫長路&#xff0c;才剛剛開始… 參考文檔&#xff1a; The Yocto ProjectBuildroot - Making Embedded Linux Easy 文章目錄 Linux(1)之buildroot構建系統(一)1. 概述1.1 如…

企業數字化轉型轉什么?怎么轉?這份攻略請收好

目錄 -01-數字化轉型“是什么” -02-數據驅動推動企業數字化轉型 -03-企業數字化轉型的行動路線圖 數字化轉型&#xff0c;轉什么&#xff1f;怎么轉&#xff1f;這些問題仍在困擾不少企業&#xff0c;也是每個企業轉型升級不得不思考的重要問題。對此&#xff0c;中關村數字…

Python潮流周刊#1:如何系統地自學Python?

這里記錄每周值得分享的 Python 及通用技術內容&#xff0c;部分內容為英文&#xff0c;已在小標題注明。&#xff08;本期標題取自其中一則分享&#xff0c;不代表全部內容都是該主題&#xff0c;特此聲明。&#xff09; 文章&教程 1、編程語言的錯誤處理模式 文章討論…

requests請求django接口跨域問題處理

參考&#xff1a; https://zhuanlan.zhihu.com/p/416978320 https://blog.csdn.net/SweetHeartHuaZai/article/details/130983179 使用httpx代替requests import httpxheaders {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.3…

銷售為什么會選擇使用電銷這種方式 ?

在網絡經濟時代的大環境下&#xff0c;網絡營銷作為一種新型營銷模式和營銷理念&#xff0c;已經搶占了大部分市場。 網絡營銷&#xff0c;是指利用互聯網技術和現代信息技術&#xff0c;以及社交媒體平臺&#xff0c;進行產品宣傳、銷售、服務、品牌傳播等活動的一種營銷模式。…

MySQL-進階

存儲引擎 MySQL體系結構 連接層&#xff1a; 最上層是一些客戶端和連接服務&#xff0c;主要完成一些類似于連接處理、授權認證、及相關的安全方案。服務器也會為安全接入的每個客戶端驗證它所具有的操作權限。服務層&#xff1a; 第二層架構主要完成大多數的核心服務功能&…

財報解讀:三季度的美國零售,“沃爾瑪效應”仍在持續

經濟學中常用“沃爾瑪效應”來指代“消費者減少消費時&#xff0c;會選擇每種類別中價格最低的商品”這一現象。作為全球最大的零售商&#xff0c;沃爾瑪一定程度上成為了消費市場的風向標。 近日&#xff0c;沃爾瑪發布的2024財年第三季度財報顯示&#xff0c;其相較去年同期…

虛擬機(Linux)系統知識普及:什么是Linux發行版 以及各發行版的區別

什么是Linux發行版 以及各發行版的區別 一. 什么是linux發行版簡單來說正式定義區別資料1區別資料2區別資料3區別資料4注意事項二. Linux發行版:CentOS、Ubuntu、RedHat、Android、Tizen、MeeGoLinux 發行版:RedhatDebianUbuntuGentooFreeBSD

22款奔馳S400L升級主動式氛圍燈 光影彰顯奔馳的完美

新款奔馳S級原車自帶64色氛圍燈&#xff0c;還可以升級原廠的主動式氛圍燈&#xff0c;增加車內的氛圍效果。主動式環境氛圍燈包含263個LED光源&#xff0c;每隔1.6厘米就有一個LED光源&#xff0c;照明效果較過去明亮10倍&#xff0c;視覺效果更加絢麗&#xff0c;它還可結合智…

Python中的下劃線使用教程:單下劃線、雙下劃線和頭尾雙下劃線詳解

概要 Python是一種簡單、易學、功能強大的編程語言&#xff0c;被廣泛應用于各種領域。在Python中&#xff0c;下劃線的使用有其特殊的含義和用途。本文將詳細介紹Python中的單下劃線、雙下劃線和頭尾雙下劃線的使用教程&#xff0c;幫助讀者更好地理解和應用這些特性。 一、單…

干貨!ERP軟件如何幫助企業實現信息化管理?

ERP即企業資源規劃&#xff08;Enterprise Resource Planning&#xff09;系統&#xff0c;其核心是物料的追蹤流轉。而在物料追蹤流轉的基礎上&#xff0c;又衍生出一系列各類資源計劃的管理和追蹤。因此ERP發展成為一款集成各類資源計劃&#xff0c;也就是集成企業核心業務流…

化學氣相沉積(CVD)中的TEOS

在半導體制程中&#xff0c;薄膜的沉積是核心的步驟之一&#xff0c;有接觸過CVD的小伙伴應該或多或少聽過TEOS這種物質&#xff0c;TEOS作為一種重要的沉積源&#xff0c;尤其在低溫氧化硅的生成過程中&#xff0c;發揮了無可替代的角色。今天我們就來聊聊這種物質。 什么是TE…

ES開啟安全認證

elasticsearch開啟安全認證步驟 1.創建證書 進入到es主目錄下執行 ./bin/elasticsearch-certutil ca Elasticsearch開啟安全認證詳細步驟 第一個證書名稱默認&#xff0c;直接回車 第二個輸入密碼&#xff0c;直接回車 完成后會生成一個文件&#xff1a;elastic-stack-ca.p12…

創新研報|順應全球數字化,能源企業以“雙碳”為目標的轉型迫在眉睫

能源行業現狀及痛點分析 挑戰一&#xff1a;數字感知能力較弱 挑戰二&#xff1a;與業務的融合度低 挑戰三&#xff1a;決策響應速度滯后 挑戰四&#xff1a;價值創造有待提升 挑戰五&#xff1a;安全風險如影隨形 能源數字化轉型定義及架構 能源行業數字化轉型體系大體…

windows電腦定時開關機設置

設置流程 右擊【此電腦】>【管理】 【任務計劃程序】>【創建基本任務】 gina 命令 查看 已經添加的定時任務從哪看&#xff1f;這里&#xff1a; 往下滑啦&#xff0c;看你剛才添加的任務&#xff1a;

2015年8月19日 Go生態洞察:Go 1.5版本發布

&#x1f337;&#x1f341; 博主貓頭虎&#xff08;&#x1f405;&#x1f43e;&#xff09;帶您 Go to New World?&#x1f341; &#x1f984; 博客首頁——&#x1f405;&#x1f43e;貓頭虎的博客&#x1f390; &#x1f433; 《面試題大全專欄》 &#x1f995; 文章圖文…

C++學習之路(二)C++如何實現一個超簡單的學生信息管理系統?C++示例和小項目實例

這個示例實現了一個簡單的學生信息管理系統。它包括了學生類的定義&#xff0c;可以添加學生信息、顯示所有學生信息&#xff0c;將學生信息保存到文件并從文件加載信息。通過這個示例&#xff0c;你可以了解到如何使用類、函數和文件操作來構建一個基本的信息管理系統。 一個簡…

【數據結構/C++】棧和隊列_鏈隊列

#include <iostream> using namespace std; // 鏈隊列 typedef int ElemType; typedef struct LinkNode {ElemType data;struct LinkNode *next; } LinkNode; typedef struct {LinkNode *front, *rear; } LinkQueue; // 初始化 void InitQueue(LinkQueue &Q) {Q.fron…