How to export gltf with right texture UV

I have two qustions here

  1. I have set the UV for the shape, but it didnt work in the final glb file

  2. Is there any way to set textureMap for gltf, like what I do in Compute() by Graphic3d_Texture2Dplane. such as set texture Rotaion

export gltf

#include <AIS_TexturedShape.hxx>
#include <RWGltf_CafWriter.hxx>
#include <TDocStd_Application.hxx>
#include <BinXCAFDrivers.hxx>
#include <XCAFDoc_DocumentTool.hxx>
#include <BRep_Builder.hxx>
#include <XCAFDoc_ShapeTool.hxx>
#include <TDocStd_Document.hxx>
#include <TDataStd_Name.hxx>
#include <BRepPrimAPI_MakeBox.hxx>
#include <BRepMesh_IncrementalMesh.hxx>
#include <Prs3d.hxx>
#include <XCAFDoc_VisMaterialTool.hxx>
#include <Poly_Connect.hxx>
#include <Poly.hxx>
#include <BRepTools.hxx>
#include <Poly_Triangulation.hxx>
#include <BRepBuilderAPI_Copy.hxx>
#include <GeomLib.hxx>
#include <Poly_MeshPurpose.hxx>
#include <TopoDS.hxx>
#include <TopExp_Explorer.hxx>
#include <XBRepMesh.hxx>
#include <StdPrs_ShadedShape.hxx>
static void ComputeNormals(const TopoDS_Face& aFace, const Handle(Poly_Triangulation)& aTris)
{
    Poly_Connect thePolyConnect;
    if (aTris.IsNull()
        /*|| aTris->HasNormals()*/)
    {
        return;
    }

    // take in face the surface location
    const TopoDS_Face    aZeroFace = TopoDS::Face(aFace.Located(TopLoc_Location()));
    Handle(Geom_Surface) aSurf = BRep_Tool::Surface(aZeroFace);
    if (!aTris->HasUVNodes() || aSurf.IsNull())
    {
        // compute normals by averaging triangulation normals sharing the same vertex
        Poly::ComputeNormals(aTris);
        return;
    }

    const Standard_Real aTol = Precision::Confusion();
    Standard_Integer aTri[3];
    gp_Dir aNorm;
    aTris->AddNormals();
    for (Standard_Integer aNodeIter = 1; aNodeIter <= aTris->NbNodes(); ++aNodeIter)
    {
        // try to retrieve normal from real surface first, when UV coordinates are available
        if (GeomLib::NormEstim(aSurf, aTris->UVNode(aNodeIter), aTol, aNorm) > 1)
        {
            if (thePolyConnect.Triangulation() != aTris)
            {
                thePolyConnect.Load(aTris);
            }

            // compute flat normals
            gp_XYZ eqPlan(0.0, 0.0, 0.0);
            for (thePolyConnect.Initialize(aNodeIter); thePolyConnect.More(); thePolyConnect.Next())
            {
                aTris->Triangle(thePolyConnect.Value()).Get(aTri[0], aTri[1], aTri[2]);
                const gp_XYZ v1(aTris->Node(aTri[1]).Coord() - aTris->Node(aTri[0]).Coord());
                const gp_XYZ v2(aTris->Node(aTri[2]).Coord() - aTris->Node(aTri[1]).Coord());
                const gp_XYZ vv = v1 ^ v2;
                const Standard_Real aMod = vv.Modulus();
                if (aMod >= aTol)
                {
                    eqPlan += vv / aMod;
                }
            }
            const Standard_Real aModMax = eqPlan.Modulus();
            aNorm = (aModMax > aTol) ? gp_Dir(eqPlan) : gp::DZ();
        }

        aTris->SetNormal(aNodeIter, aNorm);
    }
}

static TopoDS_Shape NormalizeUV(TopoDS_Shape& shape)
{
    BRepBuilderAPI_Copy copier(shape, true, true);
    const TopoDS_Shape& newShape = copier.Shape();

    TopLoc_Location aFaceLoc;
    for (TopExp_Explorer aFaceIter(newShape, TopAbs_FACE); aFaceIter.More(); aFaceIter.Next())
    {
        const TopoDS_Face& aFace = TopoDS::Face(aFaceIter.Current());
        if (aFace.IsNull()) continue;
        Handle(Poly_Triangulation) aTris = BRep_Tool::Triangulation(aFace, aFaceLoc);
        if (aTris.IsNull()) continue;

        // compute surface normals before UV parameters will be modified
        ComputeNormals(aFace, aTris);

        // normalize UV range in triangulation
        double aUMin = 0.0, aUMax = 0.0, aVMin = 0.0, aVMax = 0.0;
        BRepTools::UVBounds(aFace, aUMin, aUMax, aVMin, aVMax);

        auto size = aTris->NbNodes();

        for (int aNodeIter = 1; aNodeIter <= aTris->NbNodes(); ++aNodeIter)
        {
            gp_Pnt2d aUV = aTris->UVNode(aNodeIter);
            aUV.SetX((aUV.X() - aUMin) / (aUMax - aUMin));
            aUV.SetY((aUV.Y() - aVMin) / (aVMax - aVMin));
            aTris->SetUVNode(aNodeIter, aUV);
        }
    }
    return newShape;
}
void TexturedShapeTest(TopoDS_Shape& shape1)
{
    Handle(TDocStd_Application) app = new TDocStd_Application();
    BinXCAFDrivers::DefineFormat(app);
    Handle(TDocStd_Document) doc;
    app->NewDocument("CONVERTXCAF-DOC", doc);

    Handle(XCAFDoc_ShapeTool) m_ShapeTool = XCAFDoc_DocumentTool::ShapeTool(doc->Main());
    TopoDS_Shape shape = NormalizeUV(shape1);
    TDF_Label label = m_ShapeTool->AddShape(shape, false);
    TDataStd_Name::Set(label, "shape_name");

    // material
    Handle(XCAFDoc_VisMaterialTool)  m_VisMaterialTool = XCAFDoc_DocumentTool::VisMaterialTool(doc->Main());
    Handle(Image_Texture)  texture = new Image_Texture("C:\\Users\\shengshu_wang\\Desktop\\a.jpg");
    XCAFDoc_VisMaterialPBR pbrm;
    pbrm.BaseColorTexture = texture;
    pbrm.IsDefined = true;
    Handle(XCAFDoc_VisMaterial) floorMat = new XCAFDoc_VisMaterial();
    floorMat->SetPbrMaterial(pbrm);
    TDF_Label matLabel = m_VisMaterialTool->AddMaterial(floorMat, "name");
    m_VisMaterialTool->SetShapeMaterial(label, matLabel);

    Handle(Prs3d_Drawer) aDrawer = new Prs3d_Drawer(); // holds visualization defaults
    BRepMesh_IncrementalMesh anAlgo;
    //anAlgo.ChangeParameters().Deflection = Prs3d::GetDeflection(m_Compound, aDrawer);
    anAlgo.ChangeParameters().Angle = 20.0 * M_PI / 180.0; // 20 degrees
    anAlgo.ChangeParameters().InParallel = true;
    anAlgo.SetShape(shape);
    anAlgo.Perform();

    RWGltf_CafWriter aGltfWriter("C:\\Users\\shengshu_wang\\Desktop\\test.glb",true);
    aGltfWriter.ChangeCoordinateSystemConverter().SetInputLengthUnit(0.001);
    aGltfWriter.ChangeCoordinateSystemConverter().SetInputCoordinateSystem(RWMesh_CoordinateSystem_Zup);
    TColStd_IndexedDataMapOfStringString gltfMetaData;
    aGltfWriter.Perform(doc, gltfMetaData, Message_ProgressRange());
};

display in view

void AIS_TestShape::Compute(const Handle(PrsMgr_PresentationManager)& thePrsMgr,
    const Handle(Prs3d_Presentation)& thePrs,
    const Standard_Integer theMode)
{
    StdPrs_ShadedShape::Add(thePrs, myshape, myDrawer, Standard_True,
        gp_Pnt2d(0.0, 0.0),
        gp_Pnt2d(1, 1),
        gp_Pnt2d(1.0, 1.0));

    Handle(Graphic3d_Texture2Dplane) myTexture = new Graphic3d_Texture2Dplane("C:\\Users\\shengshu_wang\\Desktop\\a.jpg");
    if (!myTexture->IsDone())
    {
        return;
    }
    myTexture->SetScaleT(-1);
    myTexture->SetTranslateT(1.0);
    myTexture->SetRotation(90);
    myTexture->SetMipMaps(true);
    myTexture->SetAnisoFilter(Graphic3d_LevelOfTextureAnisotropy::Graphic3d_LOTA_FAST);
    myTexture->EnableRepeat();
    myTexture->EnableSmooth();
    myTexture->DisableModulate();
    myTexture->IsDone();
    Handle(Graphic3d_AspectFillArea3d) aAspect = new Graphic3d_AspectFillArea3d(*myDrawer->ShadingAspect()->Aspect());
    aAspect->SetTextureMap(myTexture);
    aAspect->SetFaceCulling(Graphic3d_TypeOfBackfacingModel_DoubleSided);
    aAspect->SetTextureMapOn();
    aAspect->SetAlphaMode(Graphic3d_AlphaMode_Opaque, 1);
    aAspect->SetColor(Quantity_NOC_YELLOW);
    Handle(Graphic3d_Group) aGroup = thePrs->CurrentGroup();
    aGroup->SetGroupPrimitivesAspect(aAspect);
}
Attachments: 
gkv311 n's picture

You're calling BRepMesh_IncrementalMesh after NormalizeUV, so I guess the mesh could be re-generated or modified. Logically these two steps should be swapped.

gkv311 n's picture

As for Graphic3d_Texture2Dplane - this tool relies on legacy OpenGL functionality.

You may try retrieving the math from OpenGL documentation to compute texture coordinates straight ahead and assing them to Poly_Triangulation.

song MR's picture

Have you solved this problem?