4

我正在尝试使用 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);
}

我究竟做错了什么?为什么物体是双倍的?

4

0 回答 0