我正在尝试使用 OpenCascade 导入 STEP 文件,并使用 Open Inventor 兼容的 coin3d 库将它们显示在屏幕上。不幸的是,我总是以颜色工作或几何形状正确而结束,正确定位具有正确颜色的零件似乎不起作用。
Handle(XCAFDoc_ShapeTool) Assembly;
Assembly = XCAFDoc_DocumentTool::ShapeTool(scene->document->Main());
STEPCAFControl_Reader stepReader;
stepReader.SetColorMode(true);
stepReader.SetNameMode(true);
stepReader.SetLayerMode(true);
const auto stepStat = stepReader.ReadFile(fn.c_str());
if(stepStat != IFSelect_ReturnStatus::IFSelect_RetDone) {
return false;
}
stepReader.Transfer(scene->document);
TDF_LabelSequence frshapes;
Assembly->GetShapes(frshapes);
if (frshapes.Length() == 0) {
return false;
} else if (frshapes.Length() == 1) {
TopoDS_Shape shape = Assembly->GetShape(frshapes.Value(1));
loadShape(scene, shape, noPerVertexNormals, qualityNormals);
} else {
for (Standard_Integer i=1; i<frshapes.Length(); i++) {
TopoDS_Shape S = Assembly->GetShape(frshapes.Value(i));
TDF_Label aLabel = Assembly->FindShape(S, Standard_False);
if ( (!aLabel.IsNull()) && (Assembly->IsShape(aLabel)) ) {
if (Assembly->IsFree(aLabel) ) {
loadShape(scene, S, noPerVertexNormals, qualityNormals);
}
}
}
}
我还尝试制作一个复合形状,以防有超过 1 个形状,正如我在 OpenCascade 论坛中找到的那样,但没有区别。
一般来说,在网上找到的简单 STEP 文件导入很好(我假设它们只有一个部分),但从实体作品导出的更复杂的多部分对象要么具有正确的几何形状,要么具有正确的颜色,但绝不会两者兼而有之。
有问题的部分在这里:
if (Assembly->IsFree(aLabel) ) {
loadShape(scene, S, noPerVertexNormals, qualityNormals); }
如果我使用 IsFree(aLabel) 所有几何图形都是正确的,但几乎没有导入颜色。
如果我否定它,通过使用 if (!Assembly->IsFree(aLabel) ) ... 导入的几何图形到处都是,旋转,变换,但颜色正确。
如果我完全删除 if ,两种情况都处于活动状态,它会导入所有内容,一次是正确的地理,没有颜色,第二次是在某处翻译和旋转,颜色正确。
我的想法是,平移/旋转的彩色对象可能只有平移/旋转信息,在它们被转换的地方被忽略,但是当我输出形状 Transformation() 信息时,位置和旋转都是 0。
下面是其余代码,实际上将导入的形状转换为多边形对象以进行显示:
void loadShape(const std::shared_ptr<Scene> &scene, const TopoDS_Shape &shape, bool noPerVertexNormals, bool qualityNormals)
{
TopExp_Explorer ex;
Handle(XCAFDoc_ColorTool) Colors;
Colors = XCAFDoc_DocumentTool::ColorTool(scene->document->Main());
SceneShape * so = new SceneShape;
so->setShape(shape);
// this is all zero
gp_XYZ aggi = shape.Location().Transformation().TranslationPart();
std::cout << aggi.X() << "," << aggi.Y() << "," << aggi.Z() << std::endl;
gp_Quaternion aggiaggi = shape.Location().Transformation().GetRotation();
std::cout << aggiaggi.X() << "," << aggiaggi.Y() << "," << aggiaggi.Z() << "," << aggiaggi.W() << std::endl << std::endl;
BRepMesh_IncrementalMesh bMesh(so->shape(), 1 /* ? */,Standard_False, 0.5, Standard_True);
SoMaterial *fallBackMat = new SoMaterial;
fallBackMat->ref();
fallBackMat->diffuseColor.setValue(0.64f, 0.64f, 0.64f);
Quantity_Color fbColor;
if (Colors->GetColor(so->shape(), XCAFDoc_ColorGen, fbColor) || Colors->GetColor(so->shape(), XCAFDoc_ColorSurf, fbColor) || Colors->GetColor(so->shape(), XCAFDoc_ColorCurv, fbColor)) {
fallBackMat->diffuseColor.setValue(static_cast<float>(fbColor.Red()), static_cast<float>(fbColor.Green()), static_cast<float>(fbColor.Blue()));
}
so->root()->addChild(fallBackMat);
SoMaterial *selectionMat = new SoMaterial;
selectionMat->emissiveColor.setValue(.9f, .9f, .6f);
int i = 1;
for (ex.Init(so->shape(), TopAbs_FACE); ex.More(); ex.Next(),i++) {
const TopoDS_Face& aFace = TopoDS::Face(ex.Current());
ObjectPart *part = new ObjectPart;
part->setFace(aFace);
selectionMat->ref();
part->selectedRoot()->addChild(selectionMat);
Quantity_Color color;
if (
Colors->GetColor(aFace, XCAFDoc_ColorGen, color) ||
Colors->GetColor(aFace, XCAFDoc_ColorSurf, color) ||
Colors->GetColor(aFace, XCAFDoc_ColorCurv, color)
) {
SoMaterial *myMaterial = new SoMaterial;
myMaterial->ref();
myMaterial->diffuseColor.setValue(static_cast<float>(color.Red()), static_cast<float>(color.Green()), static_cast<float>(color.Blue()));
part->unselectedRoot()->addChild(myMaterial);
} else {
fallBackMat->ref();
part->unselectedRoot()->addChild(fallBackMat);
}
Standard_Integer nbNodesInFace,nbTriInFace;
SbVec3f* vertices=0;
SbVec3f* vertexnormals=0;
int32_t* cons=0;
// this subroutine is taken from FreeCAD which can import the models correctly, so i assume it is not the problem
transferToArray(aFace, &vertices, &vertexnormals, &cons, nbNodesInFace, nbTriInFace, noPerVertexNormals, qualityNormals);
if (!vertices)
continue;
part->selectedRoot()->addChild(part->selectedPolygonRoot());
part->unselectedRoot()->addChild(part->unselectedPolygonRoot());
if (!noPerVertexNormals) {
SoNormal * norm = new SoNormal;
norm->vector.setValues(0, nbNodesInFace, vertexnormals);
part->selectedPolygonRoot()->addChild(norm);
part->unselectedPolygonRoot()->addChild(norm);
SoNormalBinding * normb = new SoNormalBinding;
normb->value = SoNormalBinding::PER_VERTEX_INDEXED;
part->selectedPolygonRoot()->addChild(normb);
part->unselectedPolygonRoot()->addChild(normb);
}
SoCoordinate3 * coords = new SoCoordinate3;
coords->point.setValues(0,nbNodesInFace, vertices);
part->selectedPolygonRoot()->addChild(coords);
part->unselectedPolygonRoot()->addChild(coords);
SoIndexedFaceSet * faceset = new SoIndexedFaceSet;
faceset->coordIndex.setValues(0,4*nbTriInFace,(const int32_t*) cons);
faceset->setUserData((void *) part);
part->selectedPolygonRoot()->addChild(faceset);
part->unselectedPolygonRoot()->addChild(faceset);
so->addPart(part);
delete [] vertexnormals;
delete [] vertices;
delete [] cons;
}
scene->addShape(so);
}
我究竟做错了什么?为什么物体是双倍的?