A-6 2023/1/13
OCCT/Qt/VulkanSceneGraph(VSG)
- stp文件的读取
- occ的离散化
- CAD模型添加vsg的渲染管线
- 欢迎交流,QQ:963385291
- 开源项目:https://blog.csdn.net/qq_46348003/article/details/139995406?spm=1001.2014.3001.5502
stp文件读取
市面上常见的开源CAD查看软件,都是用OpenCascade来读取stp模型的,读取stp模型有两种方式STEPControl_Reader和STEPCAFControl_Reader。
- STEPControl_Reader是读取一整个模型,读不出来模型的树状结构
- STEPCAFControl_Reader读到的信息才是全的。occ用XDE框架组织了一棵树,也提供了广度优先遍历的接口
- 要是想要生成像CAD软件中那样的树形结构,需要深度优先遍历
以下是对比,这里参考了潇湘散客的博客
- 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);
}