A-6 利用occ读取stp模型并离散化生成三角面片

A-6 2023/1/13

OCCT/Qt/VulkanSceneGraph(VSG)

  • stp文件的读取
  • occ的离散化
  • CAD模型添加vsg的渲染管线
  • 欢迎交流,QQ:963385291

stp文件读取

市面上常见的开源CAD查看软件,都是用OpenCascade来读取stp模型的,读取stp模型有两种方式STEPControl_Reader和STEPCAFControl_Reader。

  • STEPControl_Reader是读取一整个模型,读不出来模型的树状结构
  • STEPCAFControl_Reader读到的信息才是全的。occ用XDE框架组织了一棵树,也提供了广度优先遍历的接口
  • 要是想要生成像CAD软件中那样的树形结构,需要深度优先遍历

以下是对比,这里参考了潇湘散客的博客

A-6-1

A-6-0

  • STEPControl_Reader读取stp文件的代码
void readStep()
{
STEPControl_Reader reader;
reader.ReadFile(“E:\t3.step”);
// Loads file MyFile.stp
Standard_Integer NbRoots = reader.NbRootsForTransfer();
// gets the number of transferable roots
Standard_Integer NbTrans = reader.TransferRoots();
// translates all transferable roots, and returns the number of //successful translations
TopoDS_Shape aShape = reader.OneShape();
}

  • STEPCAFControl_Reader读取stp文件的代码
 Handle(TDocStd_Document) aDoc;
    XCAFApp_Application::GetApplication()->NewDocument("MDTV-XCAF", aDoc);
    STEPCAFControl_Reader myReader;
    if (myReader.ReadFile(path)) {
        myReader.SetColorMode(true);
        myReader.SetNameMode(true);
        myReader.SetLayerMode(true);
        myReader.SetPropsMode(true);
        myReader.SetGDTMode(true);
        myReader.SetMatMode(true);
        myReader.SetViewMode(true);
        Handle_Message_ProgressIndicator indicator;


        myReader.Transfer(aDoc);
    }

    TDF_Label mainLabel = aDoc->Main();
    Handle(XCAFDoc_ShapeTool) myAssembly = XCAFDoc_DocumentTool::ShapeTool(mainLabel);
    TDF_Label aLabel = myAssembly->NewShape();

    aColorTool = XCAFDoc_DocumentTool::ColorTool(mainLabel);
    TDF_LabelSequence FreeShape;
    myAssembly->GetFreeShapes(FreeShape);

    int Roots = FreeShape.Length();
    for (int index = 1; index <= Roots; index++)
    {
        TDF_Label Label = FreeShape.Value(index);
        
        //vsg节点
        vsg::ref_ptr<vsg::Group> rootTreeNode = vsg::Group::create();
        stateGroup->addChild(rootTreeNode);

        MakeTree(myAssembly, aColorTool, Label, TopLoc_Location(), father, rootTreeNode)  
    }
 
   
  • 以上代码是包含在读取文件的函数中的,里面有一个MakeTree函数,这是用来读取stp模型中的树形结构的,我就没有放上去。

OCC离散化

  • 如何将一个TopoDS_Shape类离散化为三角面片

  • 调用 BRepMesh_IncrementalMesh (shape ,Standard_True);进行离散化

  • 然后按面遍历,读取每一面的三角形个数和顶点

  • 获取每个三角形的顶点索引,根据顶点索引找到对应的顶点,然后读取对应顶点的坐标和法向

  • 没有法向就自己计算法向

  • 填充索引数组

以下是两个离散化代码,效果是一样的:

void CADMesh::buildnode(TopoDS_Shape shape, TopLoc_Location aLoc, vsg::ref_ptr<vsg::Group> TreeNode) {
    BRepMesh_IncrementalMesh (shape ,Standard_True);
    Standard_Integer aNbTriangles(0);
    
    shape.Location(aLoc);
    TopTools_IndexedMapOfShape faceMap;
    TopExp::MapShapes(shape, TopAbs_FACE, faceMap);
    int Triangnumber = 0;
    int Nodenumber = 0;
    TopLoc_Location faceLoc;
    //这一个循环是统计顶点和三角面片的个数的,其实有别的写法
    for (int i = 1; i <= faceMap.Extent(); i++) {
        
        Handle(Poly_Triangulation) aTriangulation = BRep_Tool::Triangulation(TopoDS::Face(faceMap(i)), faceLoc);
        if (!aTriangulation.IsNull())
        {
            Nodenumber += aTriangulation->NbNodes();
            Triangnumber += aTriangulation->NbTriangles();
        }
    }

    auto vertices = vsg::vec3Array::create(Nodenumber);
   
    //normals = vsg::vec3Array::create(Nodenumber,vsg::vec3{0.0f,0.0f,1.0f});
    auto coordinates = vsg::vec2Array::create(Nodenumber);
    auto normals = vsg::vec3Array::create(Triangnumber * 3);
    auto indexes = vsg::uintArray::create(Triangnumber * 3);
    int verticesnumber = 0;
    int indexesnumber = 0;
    
    for (int i = 1; i <= faceMap.Extent(); i++) {
        
       //获取面
        Handle(Poly_Triangulation) aTriangulation = BRep_Tool::Triangulation(TopoDS::Face(faceMap(i)), faceLoc);

        
        if (!aTriangulation.IsNull())
        {
            int number = aTriangulation->NbNodes();

            for (int k = 1; k <= number; k++) {
               //填顶点坐标
               //尤其需要注意要加上这个变换矩阵,不然最后画出来的几何体位置可能不对
               vertices->at(verticesnumber) = vsg::vec3(float(aTriangulation->Node(k).Transformed(faceLoc).X()),
                    float( aTriangulation->Node(k).Transformed(faceLoc).Y()),
                    float( aTriangulation->Node(k).Transformed(faceLoc).Z()));

                verticesnumber++;
               
            }

            for (Standard_Integer j = 1; j <= aTriangulation->NbTriangles(); j++)
            {

                gp_Pnt  Vertex;
                const Poly_Triangle trian = aTriangulation->Triangle(j); // 获取第i个三角形
                Standard_Integer index1, index2, index3;
                trian.Get(index1, index2, index3);
                int finallindex1 = verticesnumber + index1 - number - 1;
                int finallindex2 = verticesnumber + index2 - number - 1;
                int finallindex3 = verticesnumber + index3 - number - 1;




                indexes->at(indexesnumber++) = verticesnumber + index1 - number - 1;
                indexes->at(indexesnumber++) = verticesnumber + index2 - number - 1;
                indexes->at(indexesnumber++) = verticesnumber + index3 - number - 1;
                

                //计算法向   
                vsg::vec3 n = vsg::normalize(vsg::cross(vertices->at(finallindex2) - vertices->at(finallindex3), vertices->at(finallindex1) - vertices->at(finallindex3)));
                
                //添加法向
                normals->at(indexesnumber - 3) = n;
                normals->at(indexesnumber - 2) = n;
                normals->at(indexesnumber - 1) = n;
        
            }
        }
        
    }

  //添加管线
    auto vid = vsg::VertexIndexDraw::create();
    auto vid2 = vsg::VertexIndexDraw::create();
    
    vsg::DataList arrays;
    arrays.push_back(vertices);
    arrays.push_back(normals);

    vid->assignArrays(arrays);
    vid->assignIndices(indexes);
    vid->indexCount = indexes->size();

    vid->instanceCount = 1;
	TreeNode->addChild(vid);
       

}

这是用DX12渲染代码的离散化。

OCCGeomerty::OCCGeomerty(RenderDevice* renderCore) {
	std::vector<MeshVertex>vertexsData;
	std::vector<uint32_t>indexsData;
	TopoDS_Shape theShape = BRepPrimAPI_MakeBox(6,8,10);
	BRepMesh_IncrementalMesh(theShape,1);
	Standard_Integer aNbTriangles(0);
	for (TopExp_Explorer anExplorer(theShape, TopAbs_FACE); anExplorer.More(); anExplorer.Next()) // 对于每个面
	{
		TopoDS_Face aFace = TopoDS::Face(anExplorer.Current());
		TopLoc_Location aLocation;
		//取出面的三角化数据,三角化过程在上面的BRepMesh_IncrementalMesh实现的
		Handle(Poly_Triangulation) aTriangulation = BRep_Tool::Triangulation(aFace, aLocation);
		int number = aTriangulation->NbNodes();

		for (Standard_Integer i = 1; i <= aTriangulation->NbTriangles(); i++)
		{
			MeshVertex Vertex;
			const Poly_Triangle trian = aTriangulation->Triangle(i); // 获取第i个三角形
			Standard_Integer index1, index2, index3;
			trian.Get(index1, index2, index3);
			
			Vertex.Position.x = float(aTriangulation->Node(index1).X());
			Vertex.Position.y = float(aTriangulation->Node(index1).Y());
			Vertex.Position.z = float(aTriangulation->Node(index1).Z());
			Vertex.Normal = { 0.0f, +1.0f, 0.0f };
			vertexsData.push_back(Vertex);

			Vertex.Position.x = float(aTriangulation->Node(index2).X());
			Vertex.Position.y = float(aTriangulation->Node(index2).Y());
			Vertex.Position.z = float(aTriangulation->Node(index2).Z());
			Vertex.Normal = { 0.0f, +1.0f, 0.0f };
			vertexsData.push_back(Vertex);

			Vertex.Position.x = float(aTriangulation->Node(index3).X());
			Vertex.Position.y = float(aTriangulation->Node(index3).Y());
			Vertex.Position.z = float(aTriangulation->Node(index3).Z());
			Vertex.Normal = { 0.0f, +1.0f, 0.0f };
			vertexsData.push_back(Vertex);
		}
	}

	
	for (uint32_t i = 1; i <= vertexsData.size(); ++i)
	{
		indexsData.push_back(i-1);
	}

	meshs.reserve(1);
	meshs.emplace_back(renderCore, vertexsData, indexsData);
}


  • 12
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值