virtual void apply(osg::Geode& node) {for (int i = 0; i < node.getNumDrawables(); i++){osg::Geometry* geometry = dynamic_cast<osg::Geometry*>(node.getDrawable(i));if (geometry){//apply(*g);//***********************************************//解析頂點osg::Array* vertexArray = geometry->getVertexArray();if (vertexArray == NULL)return;//頂點數組osg::Vec3Array* verts = dynamic_cast<osg::Vec3Array*>(vertexArray);long lVertNum = verts->size();std::vector<osg::Vec3 >::iterator iter_ver = verts->begin();//遍歷頂點值for (; iter_ver != verts->end(); iter_ver++){double x = iter_ver->x();double y = iter_ver->y();double z = iter_ver->z(); }//紋理osg::Texture2D* tex2D = dynamic_cast<osg::Texture2D*>(geometry->getStateSet()->getTextureAttribute(0, osg::StateAttribute::TEXTURE));osg::Image* image = tex2D->getImage();osgDB::writeImageFile(*image, "abc.jpg");int width = image->s();int height = image->t();/*osg::Vec2 color;osg::Vec4 c = image->getColor(color);*///UVosg::Array* uvArry = geometry->getTexCoordArray(0);osg::Vec2Array* vertsUV = dynamic_cast<osg::Vec2Array*>(uvArry);std::vector<osg::Vec2 >::iterator iter_verUV = vertsUV->begin();std::vector<int> greenPointIndices;int i = 0;for (; iter_verUV != vertsUV->end(); iter_verUV++){double u = iter_verUV->x();double v = iter_verUV->y();osg::Vec2 color(u, v);osg::Vec4 c = image->getColor(color);float r = c.r() * 255;float g = c.g() * 255;float b = c.b() * 255;if (r < 100 && g < 100 && b < 100 )greenPointIndices.push_back(i);i++;}//索引int numP = geometry->getNumPrimitiveSets();osg::ref_ptr<osg::DrawElementsUInt> drawElemUInt = new osg::DrawElementsUInt(GL_TRIANGLES);for (unsigned int ipr = 0; ipr < numP; ipr++){osg::PrimitiveSet* prset = geometry->getPrimitiveSet(ipr);unsigned int ncnt = prset->getNumIndices();for (unsigned int ic = 0; ic * 3 < prset->getNumIndices(); ic++){unsigned int iIndex0 = prset->index(ic * 3);unsigned int iIndex1 = prset->index(ic * 3 + 1);unsigned int iIndex2 = prset->index(ic * 3 + 2);bool find = false;for (int i = 0; i < greenPointIndices.size(); i++){if (greenPointIndices[i] == iIndex0 || greenPointIndices[i] == iIndex1 || greenPointIndices[i] == iIndex2){find = true;break;}}if (find)continue;else{drawElemUInt->push_back(prset->index(ic * 3));drawElemUInt->push_back(prset->index(ic * 3 + 1));drawElemUInt->push_back(prset->index(ic * 3 + 2));}}}osg::ref_ptr<osg::Geometry> geometry_new = new osg::Geometry();geometry_new->setVertexArray(verts);geometry_new->getOrCreateStateSet()->setTextureAttributeAndModes(0, tex2D, osg::StateAttribute::ON);geometry_new->setTexCoordArray(0, uvArry);geometry_new->addPrimitiveSet(drawElemUInt);osg::Geode* pGeode_new = new osg::Geode;pGeode_new->removeDrawables(0, pGeode_new->getNumDrawables());pGeode_new->addDrawable(geometry_new);osgDB::writeNodeFile(*pGeode_new, "test.osgb", new osgDB::Options("WriteImageHint=IncludeData Compressor=zlib"));//***********************************************}}}
參考博主:osgb的頂點,紋理,索引,UV讀取與存儲_osgb獲取頂點-CSDN博客
作為C++小白看這段代碼的詳細解讀
這段代碼是用 C++ 編寫的,并使用了 OpenSceneGraph (OSG) —— 一個開源的高性能 3D 圖形引擎,廣泛用于地理信息系統、仿真、可視化等領域。
這段代碼定義了一個虛函數 apply(osg::Geode& node)
,該函數的作用是:遍歷一個三維模型,識別紋理上顏色較暗的區域,剔除那些區域對應的三角形網格,然后將剩余的“亮色”區域導出為一個新的 3D 模型文件。
一、逐行詳細解析
開始遍歷Geode下的Drawable對象(通常是Geometry)
for (int i = 0; i < node.getNumDrawables(); i++)
遍歷Geode中所有的Drawable(通常是osg::Geometry類型)
處理每個Geometry
osg::Geometry* geometry = dynamic_cast<osg::Geometry*>(node.getDrawable(i));
嘗試將 Drawable
轉為 osg::Geometry
類型,如果轉換成功,表示該對象是幾何體。
解析頂點信息
osg::Array* vertexArray = geometry->getVertexArray();
osg::Vec3Array* verts = dynamic_cast<osg::Vec3Array*>(vertexArray);
獲取頂點數組并強制轉換為三維坐標數組(Vec3Array)
vert存儲所有頂點坐標
for (; iter_ver != verts->end(); iter_ver++)
{double x = iter_ver->x();double y = iter_ver->y();double z = iter_ver->z();
}
遍歷每個頂點,獲取其三維坐標(這里沒做實際操作)
提取紋理圖像
osg::Texture2D* tex2D = dynamic_cast<osg::Texture2D*>(geometry->getStateSet()->getTextureAttribute(0, ...));
osg::Image* image = tex2D->getImage();
osgDB::writeImageFile(*image, "abc.jpg");
獲取貼在模型上的紋理(Texture2D)
提取出其中的圖像(osg::Image)
保存圖像為JPG文件(調試用途)
讀取UV坐標+獲取紋理顏色
osg::Array* uvArry = geometry->getTexCoordArray(0);
osg::Vec2Array* vertsUV = dynamic_cast<osg::Vec2Array*>(uvArry);
獲取紋理坐標(UV)數組
for (; iter_verUV != vertsUV->end(); iter_verUV++)
{double u = iter_verUV->x();double v = iter_verUV->y();osg::Vec2 color(u, v);osg::Vec4 c = image->getColor(color);...
}
遍歷每個頂點對應的紋理坐標(u,v)
從image圖像中獲取對應像素顏色c
判斷顏色是否“偏暗”,若R、G、B分量都小于100(即為暗色或黑色點)
if (r < 100 && g < 100 && b < 100)greenPointIndices.push_back(i);
這些“暗黑點”會被記錄到greenPointIndices中
處理索引,剔除包含暗黑點的三角面
osg::DrawElementsUInt* drawElemUInt = new osg::DrawElementsUInt(GL_TRIANGLES);
新建一個DrawElementsUInt類型的三角形集合,保存有效三角面索引。
for (ipr ...)
{for (ic ...){unsigned int iIndex0 = prset->index(ic * 3);...if (任意一個頂點是暗色點)continue;elsedrawElemUInt->push_back(三個頂點索引);}
}
遍歷所有原始三角形
若三角形中有任意一個頂點在greenPointIndices中(即暗點),跳過不加入新網格。
其他三角面則加入drawElemUInt
構建新Geometry并導出為OSGB文件
osg::Geometry* geometry_new = new osg::Geometry();
geometry_new->setVertexArray(verts);
...
geometry_new->addPrimitiveSet(drawElemUInt);
構建一個新幾何體,復用原始頂點和紋理坐標,僅替換三角面為“亮色區域”
osg::Geode* pGeode_new = new osg::Geode;
pGeode_new->addDrawable(geometry_new);
osgDB::writeNodeFile(*pGeode_new, "test.osgb", ...);
將新的幾何體寫入.osgb文件(OpenSceneGraph二進制模式格式)