4

i am trying to import STEP files with OpenCascade and display them on Screen with the Open Inventor compatible coin3d library. Unfortunately i always end up with either the colors working, or the geometry being correct, having correctly positioned parts with correct colors seems not to work.

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);
            }
        }
    }
}

I also tried to make a compound shape in case there is more than 1 shape, as i found it in the OpenCascade forum, but makes no difference.

In general, simple STEP files found on the net import fine (i assume they only have one part), but more complex multi part objects exported from solid works come either with correct geometry, or with correct colors, but never both.

The problematic part is here:

if (Assembly->IsFree(aLabel) ) {
    loadShape(scene, S, noPerVertexNormals, qualityNormals);                }

If i use the IsFree(aLabel) all geometry is correct, but there are almost no colors imported.

If i negate it, by using if (!Assembly->IsFree(aLabel) ) ... imported geometry is all over the place, rotated, transformed, but with correct colors.

If i remove the if completely, both situations are active, it imports everything double, once with correct geo, without colors, and a second time, translated and rotated somewhere, with correct colors.

My thought was, that the translated/rotatet colored objects just may have translation/rotation information that is ignored where they are converted, but when i output the shapes Transformation() information, Location and Rotation are all 0.

Heres the rest of the code, actually transforming the imported shapes to polygon objects for display:

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);
}

What am i doing wrong? Why are the objects doubled?

Hellagot
  • 235
  • 2
  • 13

0 Answers0