Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GLTF Export - Edge and Vertex support #243

Open
wants to merge 1 commit into
base: IR
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
756 changes: 511 additions & 245 deletions src/RWGltf/RWGltf_CafWriter.cxx

Large diffs are not rendered by default.

103 changes: 93 additions & 10 deletions src/RWGltf/RWGltf_CafWriter.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -14,23 +14,30 @@
#ifndef _RWGltf_CafWriter_HeaderFiler
#define _RWGltf_CafWriter_HeaderFiler

#include <Message_ProgressScope.hxx>
#include <NCollection_DataMap.hxx>
#include <TColStd_IndexedDataMapOfStringString.hxx>
#include <TColStd_MapOfAsciiString.hxx>
#include <TDF_LabelSequence.hxx>
#include <TopTools_ShapeMapHasher.hxx>
#include <RWGltf_DracoParameters.hxx>
#include <RWGltf_GltfArrayType.hxx>
#include <RWGltf_GltfBufferView.hxx>
#include <RWGltf_GltfFace.hxx>
#include <RWGltf_WriterTrsfFormat.hxx>
#include <RWMesh_CoordinateSystemConverter.hxx>
#include <RWMesh_NameFormat.hxx>
#include <XCAFPrs_DocumentNode.hxx>
#include <XCAFPrs_Style.hxx>
#include <Poly_Triangle.hxx>

#include <memory>

class Message_ProgressRange;
class RWMesh_ShapeIterator;
class RWMesh_FaceIterator;
class RWMesh_EdgeIterator;
class RWMesh_VertexIterator;
class RWGltf_GltfOStreamWriter;
class RWGltf_GltfMaterialMap;
class RWGltf_GltfSceneNodeMap;
Expand Down Expand Up @@ -202,8 +209,12 @@ protected:
const Message_ProgressRange& theProgress);

protected:
//! Return TRUE if face mesh should be skipped (e.g. because it is invalid or empty).
Standard_EXPORT virtual Standard_Boolean toSkipFaceMesh(const RWMesh_FaceIterator& theFaceIter);
//! Return TRUE if face shape should be skipped (e.g. because it is invalid or empty).
Standard_EXPORT virtual Standard_Boolean toSkipShape(
const RWMesh_ShapeIterator& theShapeIter) const;

//! Return TRUE if shape has triangulation (not vertex or edge).
Standard_EXPORT virtual Standard_Boolean hasTriangulation(const RWGltf_GltfFace& theShape) const;

//! Generate name for specified labels.
//! @param[in] theFormat name format to apply
Expand All @@ -216,13 +227,13 @@ protected:
//! Write mesh nodes into binary file.
//! @param[out] theGltfFace glTF face definition
//! @param[out] theBinFile output file to write into
//! @param[in] theFaceIter current face to write
//! @param[in] theShapeIter current shape to write
//! @param[in][out] theAccessorNb last accessor index
//! @param[in][out] theMesh mesh
Standard_EXPORT virtual void saveNodes(
RWGltf_GltfFace& theGltfFace,
std::ostream& theBinFile,
const RWMesh_FaceIterator& theFaceIter,
const RWMesh_ShapeIterator& theShapeIter,
Standard_Integer& theAccessorNb,
const std::shared_ptr<RWGltf_CafWriter::Mesh>& theMesh) const;

Expand All @@ -235,7 +246,7 @@ protected:
Standard_EXPORT virtual void saveNormals(
RWGltf_GltfFace& theGltfFace,
std::ostream& theBinFile,
RWMesh_FaceIterator& theFaceIter,
const RWMesh_FaceIterator& theFaceIter,
Standard_Integer& theAccessorNb,
const std::shared_ptr<RWGltf_CafWriter::Mesh>& theMesh) const;

Expand All @@ -255,15 +266,42 @@ protected:
//! Write mesh indexes into binary file.
//! @param[out] theGltfFace glTF face definition
//! @param[out] theBinFile output file to write into
//! @param[in] theFaceIter current face to write
//! @param[in] theShapeIter current shape to write
//! @param[in][out] theAccessorNb last accessor index
//! @param[in][out] theMesh mesh
Standard_EXPORT virtual void saveIndices(RWGltf_GltfFace& theGltfFace,
std::ostream& theBinFile,
const RWMesh_FaceIterator& theFaceIter,
Standard_Integer& theAccessorNb,
Standard_EXPORT virtual void saveIndices(RWGltf_GltfFace& theGltfFace,
std::ostream& theBinFile,
const RWMesh_ShapeIterator& theShapeIter,
Standard_Integer& theAccessorNb,
const std::shared_ptr<RWGltf_CafWriter::Mesh>& theMesh);

//! Write triangle indexes into binary file.
//! @param[out] theGltfFace glTF face definition
//! @param[out] theBinFile output file to write into
//! @param[in] theFaceIter current face to write
//! @param[in][out] theMesh mesh
Standard_EXPORT virtual void saveTriangleIndices(
RWGltf_GltfFace& theGltfFace,
std::ostream& theBinFile,
const RWMesh_FaceIterator& theFaceIter,
const std::shared_ptr<RWGltf_CafWriter::Mesh>& theMesh);

//! Write edge indexes into binary file.
//! @param[out] theGltfFace glTF face definition
//! @param[out] theBinFile output file to write into
//! @param[in] theEdgeIter current edge to write
Standard_EXPORT virtual void saveEdgeIndices(RWGltf_GltfFace& theGltfFace,
std::ostream& theBinFile,
const RWMesh_EdgeIterator& theEdgeIter);

//! Write vertex indexes into binary file.
//! @param[out] theGltfFace glTF face definition
//! @param[out] theBinFile output file to write into
//! @param[in] theVertexIter current vertex to write
Standard_EXPORT virtual void saveVertexIndices(RWGltf_GltfFace& theGltfFace,
std::ostream& theBinFile,
const RWMesh_VertexIterator& theVertexIter);

protected:
//! Write bufferView for vertex positions within RWGltf_GltfRootElement_Accessors section
//! @param[in] theGltfFace face definition to write
Expand Down Expand Up @@ -369,6 +407,51 @@ protected:
Standard_EXPORT virtual void writeExtrasAttributes(
const Handle(TDataStd_NamedData)& theNamedData);

//! Dispatch shapes
//! @param[in] theDocNode Document node containing shape data
//! @param[in] thePSentryBin Progress scope for the operation
//! @param[in,out] theMergedFaces Data map to store merged faces
//! @param[in,out] theShapeIter Shape iterator to traverse shapes
Standard_EXPORT virtual void dispatchShapes(
const XCAFPrs_DocumentNode& theDocNode,
const Message_ProgressScope& thePSentryBin,
NCollection_DataMap<XCAFPrs_Style, Handle(RWGltf_GltfFace)>& theMergedFaces,
RWMesh_ShapeIterator& theShapeIter);

//! Write shape into binary file
//! @param[out] theGltfFace glTF face definition
//! @param[out] theBinFile Output file to write into
//! @param[in] theShapeIter Current shape iterator
//! @param[in,out] theAccessorNb Last accessor index
//! @param[in,out] theMesh Mesh data
//! @param[in] theArrType Array type for glTF
//! @param[in] thePSentryBin Progress scope for the operation
//! @return True if shapes were successfully written to the binary file, false otherwise
Standard_EXPORT bool writeShapesToBin(RWGltf_GltfFace& theGltfFace,
std::ostream& theBinFile,
RWMesh_ShapeIterator& theShapeIter,
Standard_Integer& theAccessorNb,
const std::shared_ptr<RWGltf_CafWriter::Mesh>& theMesh,
const RWGltf_GltfArrayType theArrType,
const Message_ProgressScope& thePSentryBin);

//! Write shapes to RWGltf_GltfRootElement_Meshes section
//! @param[in] theShapeIter Shape iterator to traverse shapes
//! @param[in,out] theNbFacesInNode Number of faces in the current node
//! @param[in,out] theDracoBufInd Draco buffer index
//! @param[in,out] theToStartPrims Flag to indicate if primitives should be started
//! @param[in] theNodeName Name of the current node
//! @param[in,out] theWrittenShapes Map to store written shapes
//! @param[in,out] theDracoBufIndMap Map to store Draco buffer indices
Standard_EXPORT virtual void writeShapes(
RWMesh_ShapeIterator& theShapeIter,
Standard_Integer& theNbFacesInNode,
Standard_Integer& theDracoBufInd,
Standard_Boolean& theToStartPrims,
const TCollection_AsciiString& theNodeName,
NCollection_Map<Handle(RWGltf_GltfFaceList)>& theWrittenShapes,
NCollection_IndexedDataMap<int, int>& theDracoBufIndMap);

protected:
//! Shape + Style pair.
struct RWGltf_StyledShape
Expand Down
6 changes: 6 additions & 0 deletions src/RWMesh/FILES
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,19 @@ RWMesh_CafReader.hxx
RWMesh_CoordinateSystem.hxx
RWMesh_CoordinateSystemConverter.cxx
RWMesh_CoordinateSystemConverter.hxx
RWMesh_EdgeIterator.cxx
RWMesh_EdgeIterator.hxx
RWMesh_FaceIterator.cxx
RWMesh_FaceIterator.hxx
RWMesh_MaterialMap.cxx
RWMesh_MaterialMap.hxx
RWMesh_NameFormat.hxx
RWMesh_NodeAttributes.hxx
RWMesh_ShapeIterator.cxx
RWMesh_ShapeIterator.hxx
RWMesh_TriangulationReader.cxx
RWMesh_TriangulationReader.hxx
RWMesh_TriangulationSource.cxx
RWMesh_TriangulationSource.hxx
RWMesh_VertexIterator.cxx
RWMesh_VertexIterator.hxx
78 changes: 78 additions & 0 deletions src/RWMesh/RWMesh_EdgeIterator.cxx
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
// Copyright (c) 2025 OPEN CASCADE SAS
//
// This file is part of Open CASCADE Technology software library.
//
// This library is free software; you can redistribute it and/or modify it under
// the terms of the GNU Lesser General Public License version 2.1 as published
// by the Free Software Foundation, with special exception defined in the file
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
// distribution for complete text of the license and disclaimer of any warranty.
//
// Alternatively, this file may be used under the terms of Open CASCADE
// commercial license or contractual agreement.

#include <RWMesh_EdgeIterator.hxx>

#include <BRep_Tool.hxx>
#include <TopExp.hxx>
#include <TopoDS.hxx>
#include <XCAFDoc_ShapeTool.hxx>
#include <XCAFPrs.hxx>

// =======================================================================
// function : RWMesh_EdgeIterator
// purpose :
// =======================================================================
RWMesh_EdgeIterator::RWMesh_EdgeIterator(const TDF_Label& theLabel,
const TopLoc_Location& theLocation,
const Standard_Boolean theToMapColors,
const XCAFPrs_Style& theStyle)
: RWMesh_ShapeIterator(theLabel, theLocation, TopAbs_EDGE, theToMapColors, theStyle)
{
Next();
}

// =======================================================================
// function : RWMesh_EdgeIterator
// purpose :
// =======================================================================
RWMesh_EdgeIterator::RWMesh_EdgeIterator(const TopoDS_Shape& theShape,
const XCAFPrs_Style& theStyle)
: RWMesh_ShapeIterator(theShape, TopAbs_EDGE, theStyle)
{
Next();
}

// =======================================================================
// function : Next
// purpose :
// =======================================================================
void RWMesh_EdgeIterator::Next()
{
for (; myIter.More(); myIter.Next())
{
myEdge = TopoDS::Edge(myIter.Current());
myPolygon3D = BRep_Tool::Polygon3D(myEdge, myLocation);
myTrsf = myLocation.Transformation();
if (myPolygon3D.IsNull() || myPolygon3D->NbNodes() == 0)
{
resetEdge();
continue;
}

initEdge();
myIter.Next();
return;
}

resetEdge();
}

// =======================================================================
// function : initEdge
// purpose :
// =======================================================================
void RWMesh_EdgeIterator::initEdge()
{
initShape();
}
118 changes: 118 additions & 0 deletions src/RWMesh/RWMesh_EdgeIterator.hxx
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
// Copyright (c) 2025 OPEN CASCADE SAS
//
// This file is part of Open CASCADE Technology software library.
//
// This library is free software; you can redistribute it and/or modify it under
// the terms of the GNU Lesser General Public License version 2.1 as published
// by the Free Software Foundation, with special exception defined in the file
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
// distribution for complete text of the license and disclaimer of any warranty.
//
// Alternatively, this file may be used under the terms of Open CASCADE
// commercial license or contractual agreement.

#ifndef _RWMesh_EdgeIterator_HeaderFile
#define _RWMesh_EdgeIterator_HeaderFile

#include <NCollection_DataMap.hxx>
#include <Poly_Polygon3D.hxx>
#include <RWMesh_ShapeIterator.hxx>
#include <TopExp_Explorer.hxx>
#include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
#include <TopoDS_Edge.hxx>
#include <XCAFPrs_Style.hxx>
#include <gp_Trsf.hxx>

#include <algorithm>

class TDF_Label;

//! Auxiliary class to iterate through edges.
//! Provides functionality to iterate through the edges of a shape.
//! It inherits from `RWMesh_ShapeIterator` and implements
//! methods to access and manipulate edge data.
class RWMesh_EdgeIterator : public RWMesh_ShapeIterator
{
public:
//! Main constructor.
//! @param[in] theLabel The label of the shape.
//! @param[in] theLocation The location of the shape.
//! @param[in] theToMapColors Flag to indicate if colors should be mapped.
//! @param[in] theStyle The style of the shape.
Standard_EXPORT RWMesh_EdgeIterator(const TDF_Label& theLabel,
const TopLoc_Location& theLocation,
const Standard_Boolean theToMapColors = false,
const XCAFPrs_Style& theStyle = XCAFPrs_Style());

//! Auxiliary constructor.
//! @param[in] theShape The shape to iterate.
//! @param[in] theStyle The style of the shape.
Standard_EXPORT RWMesh_EdgeIterator(const TopoDS_Shape& theShape,
const XCAFPrs_Style& theStyle = XCAFPrs_Style());

//! Return true if iterator points to the valid triangulation.
bool More() const Standard_OVERRIDE { return !myPolygon3D.IsNull(); }

//! Find next value.
Standard_EXPORT void Next() Standard_OVERRIDE;

//! Return current edge.
const TopoDS_Edge& Edge() const { return myEdge; }

//! Return current edge.
const TopoDS_Shape& Shape() const Standard_OVERRIDE { return myEdge; }

//! Return current edge data.
const Handle(Poly_Polygon3D)& Polygon3D() const { return myPolygon3D; }

//! Return true if geometry data is defined.
bool IsEmpty() const Standard_OVERRIDE
{
return myPolygon3D.IsNull() || myPolygon3D->NbNodes() < 1;
}

public:
//! Lower element index in current triangulation.
Standard_Integer ElemLower() const Standard_OVERRIDE { return 1; }

//! Upper element index in current triangulation.
Standard_Integer ElemUpper() const Standard_OVERRIDE { return myPolygon3D->NbNodes(); }

public:
//! Return number of nodes for the current edge.
Standard_Integer NbNodes() const Standard_OVERRIDE
{
return !myPolygon3D.IsNull() ? myPolygon3D->NbNodes() : 0;
}

//! Lower node index in current triangulation.
Standard_Integer NodeLower() const Standard_OVERRIDE { return 1; }

//! Upper node index in current triangulation.
Standard_Integer NodeUpper() const Standard_OVERRIDE { return myPolygon3D->NbNodes(); }

public:
//! Return the node with specified index with applied transformation.
gp_Pnt node(const Standard_Integer theNode) const Standard_OVERRIDE
{
return myPolygon3D->Nodes().Value(theNode);
}

private:
//! Reset information for current edge.
void resetEdge()
{
myPolygon3D.Nullify();
myEdge.Nullify();
resetShape();
}

//! Initialize edge properties.
void initEdge();

private:
TopoDS_Edge myEdge; //!< current edge
Handle(Poly_Polygon3D) myPolygon3D; //!< geometry of current edge
};

#endif // _RWMesh_EdgeIterator_HeaderFile
Loading
Loading