#include <gp_Quaternion.hxx>
#include <Message.hxx>
#include <Message_Messenger.hxx>
-#include <Message_ProgressScope.hxx>
-#include <NCollection_DataMap.hxx>
#include <OSD_FileSystem.hxx>
#include <OSD_File.hxx>
#include <OSD_Parallel.hxx>
#include <OSD_Path.hxx>
#include <OSD_Timer.hxx>
#include <RWGltf_GltfAccessorLayout.hxx>
-#include <RWGltf_GltfArrayType.hxx>
#include <RWGltf_GltfMaterialMap.hxx>
#include <RWGltf_GltfPrimitiveMode.hxx>
#include <RWGltf_GltfRootElement.hxx>
#include <RWGltf_GltfSceneNodeMap.hxx>
#include <RWMesh.hxx>
+#include <RWMesh_EdgeIterator.hxx>
+#include <RWMesh_ShapeIterator.hxx>
#include <RWMesh_FaceIterator.hxx>
+#include <RWMesh_VertexIterator.hxx>
#include <Standard_Version.hxx>
#include <TDataStd_Name.hxx>
#include <TDF_Tool.hxx>
theStream.write((const char*)aVec2.GetData(), sizeof(aVec2));
}
-//! Write triangle indices.
-static void writeTriangle32(std::ostream& theStream, const Graphic3d_Vec3i& theTri)
+//! General function to write triangle indices.
+template <typename VecType>
+static void writeTriangle(std::ostream& theStream, const VecType& theTri)
{
- theStream.write((const char*)theTri.GetData(), sizeof(theTri));
+ theStream.write(reinterpret_cast<const char*>(theTri.GetData()), sizeof(theTri));
}
-//! Write triangle indices.
-static void writeTriangle16(std::ostream& theStream, const NCollection_Vec3<uint16_t>& theTri)
+//! General function to write vertex index.
+template <typename T>
+static void writeVertex(std::ostream& theStream, const T& theVertex)
{
- theStream.write((const char*)theTri.GetData(), sizeof(theTri));
+ theStream.write(reinterpret_cast<const char*>(&theVertex), sizeof(T));
}
#ifdef HAVE_DRACO
//=================================================================================================
-Standard_Boolean RWGltf_CafWriter::toSkipFaceMesh(const RWMesh_FaceIterator& theFaceIter)
+Standard_Boolean RWGltf_CafWriter::toSkipShape(const RWMesh_ShapeIterator& theShapeIter) const
{
- return theFaceIter.IsEmptyMesh();
+ return theShapeIter.IsEmpty();
+}
+
+//=================================================================================================
+
+Standard_Boolean RWGltf_CafWriter::hasTriangulation(const RWGltf_GltfFace& theGltfFace) const
+{
+ switch (theGltfFace.Shape.ShapeType())
+ {
+ case TopAbs_COMPOUND:
+ case TopAbs_COMPSOLID:
+ case TopAbs_SOLID:
+ case TopAbs_SHELL:
+ case TopAbs_FACE:
+ return true;
+ case TopAbs_WIRE:
+ case TopAbs_EDGE:
+ case TopAbs_VERTEX:
+ default:
+ return false;
+ }
}
// =======================================================================
// =======================================================================
void RWGltf_CafWriter::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
{
Standard_ASSERT_RAISE(aPos == (int64_t)theBinFile.tellp(), "wrong offset");
}
}
- theGltfFace.NodePos.Count += theFaceIter.NbNodes();
+ theGltfFace.NodePos.Count += theShapeIter.NbNodes();
- const Standard_Integer aNodeUpper = theFaceIter.NodeUpper();
- for (Standard_Integer aNodeIter = theFaceIter.NodeLower(); aNodeIter <= aNodeUpper; ++aNodeIter)
+ const Standard_Integer aNodeUpper = theShapeIter.NodeUpper();
+ for (Standard_Integer aNodeIter = theShapeIter.NodeLower(); aNodeIter <= aNodeUpper; ++aNodeIter)
{
- gp_XYZ aNode = theFaceIter.NodeTransformed(aNodeIter).XYZ();
+ gp_XYZ aNode = theShapeIter.NodeTransformed(aNodeIter).XYZ();
myCSTrsf.TransformPosition(aNode);
theGltfFace.NodePos.BndBox.Add(Graphic3d_Vec3d(aNode.X(), aNode.Y(), aNode.Z()));
- if (theMesh.get() != nullptr)
+ if (theMesh.get() != nullptr && hasTriangulation(theGltfFace))
{
theMesh->NodesVec.push_back(
Graphic3d_Vec3(float(aNode.X()), float(aNode.Y()), float(aNode.Z())));
// =======================================================================
void RWGltf_CafWriter::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
{
}
if (!myIsForcedUVExport)
{
- if (theFaceIter.FaceStyle().Material().IsNull())
+ if (theFaceIter.Style().Material().IsNull())
{
return;
}
- if (RWGltf_GltfMaterialMap::baseColorTexture(theFaceIter.FaceStyle().Material()).IsNull()
- && theFaceIter.FaceStyle().Material()->PbrMaterial().MetallicRoughnessTexture.IsNull()
- && theFaceIter.FaceStyle().Material()->PbrMaterial().EmissiveTexture.IsNull()
- && theFaceIter.FaceStyle().Material()->PbrMaterial().OcclusionTexture.IsNull()
- && theFaceIter.FaceStyle().Material()->PbrMaterial().NormalTexture.IsNull())
+ if (RWGltf_GltfMaterialMap::baseColorTexture(theFaceIter.Style().Material()).IsNull()
+ && theFaceIter.Style().Material()->PbrMaterial().MetallicRoughnessTexture.IsNull()
+ && theFaceIter.Style().Material()->PbrMaterial().EmissiveTexture.IsNull()
+ && theFaceIter.Style().Material()->PbrMaterial().OcclusionTexture.IsNull()
+ && theFaceIter.Style().Material()->PbrMaterial().NormalTexture.IsNull())
{
return;
}
}
}
+// =======================================================================
+// function : saveTriangleIndices
+// purpose :
+// =======================================================================
+void RWGltf_CafWriter::saveTriangleIndices(RWGltf_GltfFace& theGltfFace,
+ std::ostream& theBinFile,
+ const RWMesh_FaceIterator& theFaceIter,
+ const std::shared_ptr<RWGltf_CafWriter::Mesh>& theMesh)
+{
+ const Standard_Integer aNodeFirst = theGltfFace.NbIndexedNodes - theFaceIter.ElemLower();
+ theGltfFace.NbIndexedNodes += theFaceIter.NbNodes();
+ theGltfFace.Indices.Count += theFaceIter.NbTriangles() * 3;
+ for (Standard_Integer anElemIter = theFaceIter.ElemLower(); anElemIter <= theFaceIter.ElemUpper();
+ ++anElemIter)
+ {
+ Poly_Triangle aTri = theFaceIter.TriangleOriented(anElemIter);
+ aTri(1) += aNodeFirst;
+ aTri(2) += aNodeFirst;
+ aTri(3) += aNodeFirst;
+ if (theMesh.get() != nullptr)
+ {
+ theMesh->IndicesVec.push_back(aTri);
+ }
+ else
+ {
+ if (theGltfFace.Indices.ComponentType == RWGltf_GltfAccessorCompType_UInt16)
+ {
+ writeTriangle(
+ theBinFile,
+ NCollection_Vec3<uint16_t>((uint16_t)aTri(1), (uint16_t)aTri(2), (uint16_t)aTri(3)));
+ }
+ else
+ {
+ writeTriangle(theBinFile, Graphic3d_Vec3i(aTri(1), aTri(2), aTri(3)));
+ }
+ }
+ }
+}
+
+// =======================================================================
+// function : saveEdgeIndices
+// purpose :
+// =======================================================================
+void RWGltf_CafWriter::saveEdgeIndices(RWGltf_GltfFace& theGltfFace,
+ std::ostream& theBinFile,
+ const RWMesh_EdgeIterator& theFaceIter)
+{
+ const Standard_Integer aNodeFirst = theGltfFace.NbIndexedNodes - theFaceIter.ElemLower();
+ theGltfFace.NbIndexedNodes += theFaceIter.NbNodes();
+ theGltfFace.Indices.Count += theFaceIter.NbNodes();
+ for (Standard_Integer anElemIter = theFaceIter.ElemLower(); anElemIter <= theFaceIter.ElemUpper();
+ ++anElemIter)
+ {
+ if (theGltfFace.Indices.ComponentType == RWGltf_GltfAccessorCompType_UInt16)
+ {
+ writeVertex(theBinFile, (uint16_t)(anElemIter + aNodeFirst));
+ }
+ else
+ {
+ writeVertex(theBinFile, anElemIter + aNodeFirst);
+ }
+ }
+}
+
+// =======================================================================
+// function : saveVertexIndices
+// purpose :
+// =======================================================================
+void RWGltf_CafWriter::saveVertexIndices(RWGltf_GltfFace& theGltfFace,
+ std::ostream& theBinFile,
+ const RWMesh_VertexIterator& theFaceIter)
+{
+ const Standard_Integer aNodeFirst = theGltfFace.NbIndexedNodes - theFaceIter.ElemLower();
+ theGltfFace.NbIndexedNodes += theFaceIter.NbNodes();
+ theGltfFace.Indices.Count += theFaceIter.NbNodes();
+ for (Standard_Integer anElemIter = theFaceIter.ElemLower(); anElemIter <= theFaceIter.ElemUpper();
+ ++anElemIter)
+ {
+ if (theGltfFace.Indices.ComponentType == RWGltf_GltfAccessorCompType_UInt16)
+ {
+ writeVertex(theBinFile, (uint16_t)(anElemIter + aNodeFirst));
+ }
+ else
+ {
+ writeVertex(theBinFile, anElemIter + aNodeFirst);
+ }
+ }
+}
+
// =======================================================================
// function : saveIndices
// purpose :
// =======================================================================
void RWGltf_CafWriter::saveIndices(RWGltf_GltfFace& theGltfFace,
std::ostream& theBinFile,
- const RWMesh_FaceIterator& theFaceIter,
+ const RWMesh_ShapeIterator& theFaceIter,
Standard_Integer& theAccessorNb,
const std::shared_ptr<RWGltf_CafWriter::Mesh>& theMesh)
{
}
}
- const Standard_Integer aNodeFirst = theGltfFace.NbIndexedNodes - theFaceIter.ElemLower();
- theGltfFace.NbIndexedNodes += theFaceIter.NbNodes();
- theGltfFace.Indices.Count += theFaceIter.NbTriangles() * 3;
-
- const Standard_Integer anElemLower = theFaceIter.ElemLower();
- const Standard_Integer anElemUpper = theFaceIter.ElemUpper();
- for (Standard_Integer anElemIter = anElemLower; anElemIter <= anElemUpper; ++anElemIter)
+ if (const RWMesh_FaceIterator* aFaceIter = dynamic_cast<const RWMesh_FaceIterator*>(&theFaceIter))
{
- Poly_Triangle aTri = theFaceIter.TriangleOriented(anElemIter);
- aTri(1) += aNodeFirst;
- aTri(2) += aNodeFirst;
- aTri(3) += aNodeFirst;
- if (theMesh.get() != nullptr)
- {
- theMesh->IndicesVec.push_back(aTri);
- }
- else
- {
- if (theGltfFace.Indices.ComponentType == RWGltf_GltfAccessorCompType_UInt16)
- {
- writeTriangle16(
- theBinFile,
- NCollection_Vec3<uint16_t>((uint16_t)aTri(1), (uint16_t)aTri(2), (uint16_t)aTri(3)));
- }
- else
- {
- writeTriangle32(theBinFile, Graphic3d_Vec3i(aTri(1), aTri(2), aTri(3)));
- }
- }
+ saveTriangleIndices(theGltfFace, theBinFile, *aFaceIter, theMesh);
+ }
+ else if (const RWMesh_EdgeIterator* anEdgeIter =
+ dynamic_cast<const RWMesh_EdgeIterator*>(&theFaceIter))
+ {
+ saveEdgeIndices(theGltfFace, theBinFile, *anEdgeIter);
+ }
+ else if (const RWMesh_VertexIterator* aVertexIter =
+ dynamic_cast<const RWMesh_VertexIterator*>(&theFaceIter))
+ {
+ saveVertexIndices(theGltfFace, theBinFile, *aVertexIter);
}
}
return writeJson(theDocument, theRootLabels, theLabelFilter, theFileInfo, aPSentry.Next());
}
+// =======================================================================
+// function : dispatchShapes
+// purpose :
+// =======================================================================
+void RWGltf_CafWriter::dispatchShapes(
+ const XCAFPrs_DocumentNode& theDocNode,
+ const Message_ProgressScope& thePSentryBin,
+ NCollection_DataMap<XCAFPrs_Style, Handle(RWGltf_GltfFace)>& theMergedFaces,
+ RWMesh_ShapeIterator& theShapeIter)
+{
+ if (myToMergeFaces && theShapeIter.More())
+ {
+ RWGltf_StyledShape aStyledShape(theShapeIter.ExploredShape(), theDocNode.Style);
+ if (myBinDataMap.Contains(aStyledShape))
+ {
+ return;
+ }
+
+ Handle(RWGltf_GltfFaceList) aGltfFaceList = new RWGltf_GltfFaceList();
+ myBinDataMap.Add(aStyledShape, aGltfFaceList);
+ for (; theShapeIter.More() && thePSentryBin.More(); theShapeIter.Next())
+ {
+ if (toSkipShape(theShapeIter))
+ {
+ continue;
+ }
+
+ Handle(RWGltf_GltfFace) aGltfFace;
+ if (!theMergedFaces.Find(theShapeIter.Style(), aGltfFace))
+ {
+ aGltfFace = new RWGltf_GltfFace();
+ aGltfFaceList->Append(aGltfFace);
+ aGltfFace->Shape = theShapeIter.Shape();
+ aGltfFace->Style = theShapeIter.Style();
+ aGltfFace->NbIndexedNodes = theShapeIter.NbNodes();
+ theMergedFaces.Bind(theShapeIter.Style(), aGltfFace);
+ }
+ else if (myToSplitIndices16
+ && aGltfFace->NbIndexedNodes < std::numeric_limits<uint16_t>::max()
+ && (aGltfFace->NbIndexedNodes + theShapeIter.NbNodes())
+ >= std::numeric_limits<uint16_t>::max())
+ {
+ theMergedFaces.UnBind(theShapeIter.Style());
+ aGltfFace = new RWGltf_GltfFace();
+ aGltfFaceList->Append(aGltfFace);
+ aGltfFace->Shape = theShapeIter.Shape();
+ aGltfFace->Style = theShapeIter.Style();
+ aGltfFace->NbIndexedNodes = theShapeIter.NbNodes();
+ theMergedFaces.Bind(theShapeIter.Style(), aGltfFace);
+ }
+ else
+ {
+ if (aGltfFace->Shape.ShapeType() != TopAbs_COMPOUND)
+ {
+ TopoDS_Shape anOldShape = aGltfFace->Shape;
+ TopoDS_Compound aComp;
+ BRep_Builder().MakeCompound(aComp);
+ BRep_Builder().Add(aComp, anOldShape);
+ aGltfFace->Shape = aComp;
+ }
+ BRep_Builder().Add(aGltfFace->Shape, theShapeIter.Shape());
+ aGltfFace->NbIndexedNodes += theShapeIter.NbNodes();
+ }
+ }
+ }
+ else
+ {
+ for (; theShapeIter.More() && thePSentryBin.More(); theShapeIter.Next())
+ {
+ RWGltf_StyledShape aStyledShape(theShapeIter.Shape(), theShapeIter.Style());
+ if (toSkipShape(theShapeIter) || myBinDataMap.Contains(aStyledShape))
+ {
+ continue;
+ }
+
+ Handle(RWGltf_GltfFaceList) aGltfFaceList = new RWGltf_GltfFaceList();
+ Handle(RWGltf_GltfFace) aGltfFace = new RWGltf_GltfFace();
+ aGltfFace->Shape = theShapeIter.Shape();
+ aGltfFace->Style = theShapeIter.Style();
+ aGltfFaceList->Append(aGltfFace);
+ myBinDataMap.Add(aStyledShape, aGltfFaceList);
+ }
+ }
+}
+
+// =======================================================================
+// function : saveShapes
+// purpose :
+// =======================================================================
+Standard_Boolean RWGltf_CafWriter::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)
+{
+ for (; theShapeIter.More() && thePSentryBin.More(); theShapeIter.Next())
+ {
+ switch (theArrType)
+ {
+ case RWGltf_GltfArrayType_Position: {
+ // clang-format off
+ theGltfFace.NbIndexedNodes = 0; // reset to zero before RWGltf_GltfArrayType_Indices step
+ // clang-format on
+ saveNodes(theGltfFace, theBinFile, theShapeIter, theAccessorNb, theMesh);
+ break;
+ }
+ case RWGltf_GltfArrayType_Normal: {
+ if (const RWMesh_FaceIterator* aFaceIter =
+ dynamic_cast<const RWMesh_FaceIterator*>(&theShapeIter))
+ {
+ saveNormals(theGltfFace, theBinFile, *aFaceIter, theAccessorNb, theMesh);
+ }
+ break;
+ }
+ case RWGltf_GltfArrayType_TCoord0: {
+ if (const RWMesh_FaceIterator* aFaceIter =
+ dynamic_cast<const RWMesh_FaceIterator*>(&theShapeIter))
+ {
+ saveTextCoords(theGltfFace, theBinFile, *aFaceIter, theAccessorNb, theMesh);
+ }
+ break;
+ }
+ case RWGltf_GltfArrayType_Indices: {
+ saveIndices(theGltfFace, theBinFile, theShapeIter, theAccessorNb, theMesh);
+ break;
+ }
+ default: {
+ break;
+ }
+ }
+
+ if (!theBinFile.good())
+ {
+ Message::SendFail(TCollection_AsciiString("File '") + myBinFileNameFull
+ + "' cannot be written");
+ return false;
+ }
+ }
+ return true;
+}
+
// =======================================================================
// function : writeBinData
// purpose :
RWGltf_GltfArrayType_TCoord0,
RWGltf_GltfArrayType_Indices};
- // dispatch faces
+ // dispatch shapes
NCollection_DataMap<XCAFPrs_Style, Handle(RWGltf_GltfFace)> aMergedFaces;
for (XCAFPrs_DocumentExplorer aDocExplorer(theDocument,
theRootLabels,
// transformation will be stored at scene nodes
aMergedFaces.Clear(false);
- RWMesh_FaceIterator aFaceIter(aDocNode.RefLabel, TopLoc_Location(), true, aDocNode.Style);
- if (myToMergeFaces)
+ Standard_Integer aBinDataSize = myBinDataMap.Size();
{
- RWGltf_StyledShape aStyledShape(aFaceIter.ExploredShape(), aDocNode.Style);
- if (myBinDataMap.Contains(aStyledShape))
- {
- continue;
- }
-
- Handle(RWGltf_GltfFaceList) aGltfFaceList = new RWGltf_GltfFaceList();
- myBinDataMap.Add(aStyledShape, aGltfFaceList);
- for (; aFaceIter.More() && aPSentryBin.More(); aFaceIter.Next())
- {
- if (toSkipFaceMesh(aFaceIter))
- {
- continue;
- }
-
- Handle(RWGltf_GltfFace) aGltfFace;
- if (!aMergedFaces.Find(aFaceIter.FaceStyle(), aGltfFace))
- {
- aGltfFace = new RWGltf_GltfFace();
- aGltfFaceList->Append(aGltfFace);
- aGltfFace->Shape = aFaceIter.Face();
- aGltfFace->Style = aFaceIter.FaceStyle();
- aGltfFace->NbIndexedNodes = aFaceIter.NbNodes();
- aMergedFaces.Bind(aFaceIter.FaceStyle(), aGltfFace);
- }
- else if (myToSplitIndices16
- && aGltfFace->NbIndexedNodes < std::numeric_limits<uint16_t>::max()
- && (aGltfFace->NbIndexedNodes + aFaceIter.NbNodes())
- >= std::numeric_limits<uint16_t>::max())
- {
- aMergedFaces.UnBind(aFaceIter.FaceStyle());
- aGltfFace = new RWGltf_GltfFace();
- aGltfFaceList->Append(aGltfFace);
- aGltfFace->Shape = aFaceIter.Face();
- aGltfFace->Style = aFaceIter.FaceStyle();
- aGltfFace->NbIndexedNodes = aFaceIter.NbNodes();
- aMergedFaces.Bind(aFaceIter.FaceStyle(), aGltfFace);
- }
- else
- {
- if (aGltfFace->Shape.ShapeType() != TopAbs_COMPOUND)
- {
- TopoDS_Shape anOldShape = aGltfFace->Shape;
- TopoDS_Compound aComp;
- BRep_Builder().MakeCompound(aComp);
- BRep_Builder().Add(aComp, anOldShape);
- aGltfFace->Shape = aComp;
- }
- BRep_Builder().Add(aGltfFace->Shape, aFaceIter.Face());
- aGltfFace->NbIndexedNodes += aFaceIter.NbNodes();
- }
- }
+ RWMesh_FaceIterator aFaceIter(aDocNode.RefLabel, TopLoc_Location(), true, aDocNode.Style);
+ dispatchShapes(aDocNode, aPSentryBin, aMergedFaces, aFaceIter);
}
- else
+ if (aBinDataSize == myBinDataMap.Size())
{
- for (; aFaceIter.More() && aPSentryBin.More(); aFaceIter.Next())
- {
- RWGltf_StyledShape aStyledShape(aFaceIter.Face(), aFaceIter.FaceStyle());
- if (toSkipFaceMesh(aFaceIter) || myBinDataMap.Contains(aStyledShape))
- {
- continue;
- }
-
- Handle(RWGltf_GltfFaceList) aGltfFaceList = new RWGltf_GltfFaceList();
- Handle(RWGltf_GltfFace) aGltfFace = new RWGltf_GltfFace();
- aGltfFace->Shape = aFaceIter.Face();
- aGltfFace->Style = aFaceIter.FaceStyle();
- aGltfFaceList->Append(aGltfFace);
- myBinDataMap.Add(aStyledShape, aGltfFaceList);
- }
+ RWMesh_EdgeIterator anEdgeIter(aDocNode.RefLabel, TopLoc_Location(), true, aDocNode.Style);
+ dispatchShapes(aDocNode, aPSentryBin, aMergedFaces, anEdgeIter);
+ }
+ if (aBinDataSize == myBinDataMap.Size())
+ {
+ RWMesh_VertexIterator aVertexIter(aDocNode.RefLabel, TopLoc_Location(), true, aDocNode.Style);
+ dispatchShapes(aDocNode, aPSentryBin, aMergedFaces, aVertexIter);
}
}
#ifdef HAVE_DRACO
size_t aMeshIndex = 0;
#endif
+
+ Standard_Boolean isFacesOnly = Standard_True;
for (ShapeToGltfFaceMap::Iterator aBinDataIter(myBinDataMap);
aBinDataIter.More() && aPSentryBin.More();
aBinDataIter.Next())
}
aWrittenPrimData.Bind(aGltfFace->Shape, aGltfFace);
- for (RWMesh_FaceIterator aFaceIter(aGltfFace->Shape, aGltfFace->Style);
- aFaceIter.More() && aPSentryBin.More();
- aFaceIter.Next())
+ Standard_Boolean wasWrittenNonFace = Standard_False;
+ switch (aGltfFace->Shape.ShapeType())
{
- switch (anArrType)
- {
- case RWGltf_GltfArrayType_Position: {
- // clang-format off
- aGltfFace->NbIndexedNodes = 0; // reset to zero before RWGltf_GltfArrayType_Indices step
- // clang-format on
- saveNodes(*aGltfFace, *aBinFile, aFaceIter, aNbAccessors, aMeshPtr);
- break;
- }
- case RWGltf_GltfArrayType_Normal: {
- saveNormals(*aGltfFace, *aBinFile, aFaceIter, aNbAccessors, aMeshPtr);
- break;
- }
- case RWGltf_GltfArrayType_TCoord0: {
- saveTextCoords(*aGltfFace, *aBinFile, aFaceIter, aNbAccessors, aMeshPtr);
- break;
- }
- case RWGltf_GltfArrayType_Indices: {
- saveIndices(*aGltfFace, *aBinFile, aFaceIter, aNbAccessors, aMeshPtr);
- break;
+ case TopAbs_EDGE: {
+ RWMesh_EdgeIterator anIter(aGltfFace->Shape, aGltfFace->Style);
+ if (!writeShapesToBin(*aGltfFace,
+ *aBinFile,
+ anIter,
+ aNbAccessors,
+ aMeshPtr,
+ anArrType,
+ aPSentryBin))
+ {
+ return false;
}
- default: {
- break;
+ wasWrittenNonFace = Standard_True;
+ break;
+ }
+ case TopAbs_VERTEX: {
+ RWMesh_VertexIterator anIter(aGltfFace->Shape, aGltfFace->Style);
+ if (!writeShapesToBin(*aGltfFace,
+ *aBinFile,
+ anIter,
+ aNbAccessors,
+ aMeshPtr,
+ anArrType,
+ aPSentryBin))
+ {
+ return false;
}
+ wasWrittenNonFace = Standard_True;
+ break;
}
-
- if (!aBinFile->good())
- {
- Message::SendFail(TCollection_AsciiString("File '") + myBinFileNameFull
- + "' cannot be written");
- return false;
+ default: {
+ RWMesh_FaceIterator anIter(aGltfFace->Shape, aGltfFace->Style);
+ if (!writeShapesToBin(*aGltfFace,
+ *aBinFile,
+ anIter,
+ aNbAccessors,
+ aMeshPtr,
+ anArrType,
+ aPSentryBin))
+ {
+ return false;
+ }
+ break;
}
}
// add alignment by 4 bytes (might happen on RWGltf_GltfAccessorCompType_UInt16 indices)
- if (!myDracoParameters.DracoCompression)
+ if (!myDracoParameters.DracoCompression || wasWrittenNonFace)
{
+ isFacesOnly = Standard_False;
int64_t aContentLen64 = (int64_t)aBinFile->tellp();
while (aContentLen64 % 4 != 0)
{
}
}
- if (!myDracoParameters.DracoCompression)
+ if (!myDracoParameters.DracoCompression || !isFacesOnly)
{
aBuffView->ByteLength = (int64_t)aBinFile->tellp() - aBuffView->ByteOffset;
}
aPSentryBin.Next();
}
+ int aBuffViewId = 0;
+ if (myBuffViewPos.ByteLength > 0)
+ {
+ myBuffViewPos.Id = aBuffViewId++;
+ }
+ if (myBuffViewNorm.ByteLength > 0)
+ {
+ myBuffViewNorm.Id = aBuffViewId++;
+ }
+ if (myBuffViewTextCoord.ByteLength > 0)
+ {
+ myBuffViewTextCoord.Id = aBuffViewId++;
+ }
+ if (myBuffViewInd.ByteLength > 0)
+ {
+ myBuffViewInd.Id = aBuffViewId++;
+ }
+
if (myDracoParameters.DracoCompression)
{
#ifdef HAVE_DRACO
DracoEncodingFunctor aFunctor(aScope.Next(), aDracoEncoder, aMeshes, anEncoderBuffers);
OSD_Parallel::For(0, int(aMeshes.size()), aFunctor, !myToParallel);
+ int aNbSkippedBuffers = 0;
for (size_t aBuffInd = 0; aBuffInd != anEncoderBuffers.size(); ++aBuffInd)
{
if (anEncoderBuffers.at(aBuffInd).get() == nullptr)
{
- Message::SendFail(TCollection_AsciiString("Error: mesh not encoded in draco buffer."));
- return false;
+ if (aBuffViewId == 0)
+ {
+ Message::SendFail() << "Error: mesh not encoded in draco buffer.";
+ return false;
+ }
+ Message::SendWarning() << "Warning: mesh is not encoded as a Draco buffer and has been "
+ "loaded into a regular buffer.";
+ aNbSkippedBuffers++;
+ continue;
}
RWGltf_GltfBufferView aBuffViewDraco;
- aBuffViewDraco.Id = (int)aBuffInd;
+ aBuffViewDraco.Id = (int)aBuffInd + aBuffViewId - aNbSkippedBuffers;
aBuffViewDraco.ByteOffset = aBinFile->tellp();
const draco::EncoderBuffer& anEncoderBuff = *anEncoderBuffers.at(aBuffInd);
aBinFile->write(anEncoderBuff.data(), std::streamsize(anEncoderBuff.size()));
aFaceIter.More();
aFaceIter.Next())
{
- if (toSkipFaceMesh(aFaceIter))
+ if (toSkipShape(aFaceIter))
{
continue;
}
- myMaterialMap->AddGlbImages(*aBinFile, aFaceIter.FaceStyle());
+ myMaterialMap->AddGlbImages(*aBinFile, aFaceIter.Style());
}
}
}
-
- int aBuffViewId = 0;
- if (myBuffViewPos.ByteLength > 0)
- {
- myBuffViewPos.Id = aBuffViewId++;
- }
- if (myBuffViewNorm.ByteLength > 0)
- {
- myBuffViewNorm.Id = aBuffViewId++;
- }
- if (myBuffViewTextCoord.ByteLength > 0)
- {
- myBuffViewTextCoord.Id = aBuffViewId++;
- }
- if (myBuffViewInd.ByteLength > 0)
- {
- myBuffViewInd.Id = aBuffViewId++;
- }
// myMaterialMap->FlushGlbBufferViews() will put image bufferView's IDs at the end of list
myBinDataLen64 = aBinFile->tellp();
continue;
}
- bool hasMeshData = false;
+ bool hasShapeData = false;
if (!aDocNode.IsAssembly)
{
- for (RWMesh_FaceIterator aFaceIter(aDocNode.RefLabel,
- TopLoc_Location(),
- true,
- aDocNode.Style);
- aFaceIter.More();
- aFaceIter.Next())
- {
- if (!toSkipFaceMesh(aFaceIter))
+ auto checkShapeData = [&](RWMesh_ShapeIterator& anIter) {
+ for (; anIter.More(); anIter.Next())
{
- hasMeshData = true;
- break;
+ if (!toSkipShape(anIter))
+ {
+ return true;
+ }
}
+ return false;
+ };
+ {
+ RWMesh_FaceIterator aFaceIter(aDocNode.RefLabel, TopLoc_Location(), true, aDocNode.Style);
+ hasShapeData = checkShapeData(aFaceIter);
+ }
+ if (!hasShapeData)
+ {
+ RWMesh_EdgeIterator anEdgeIter(aDocNode.RefLabel, TopLoc_Location(), true, aDocNode.Style);
+ hasShapeData = checkShapeData(anEdgeIter);
+ }
+ if (!hasShapeData)
+ {
+ RWMesh_VertexIterator aVertIter(aDocNode.RefLabel, TopLoc_Location(), true, aDocNode.Style);
+ hasShapeData = checkShapeData(aVertIter);
}
}
- if (hasMeshData)
+
+ if (hasShapeData)
{
aSceneNodeMap.Add(aDocNode);
}
else
{
- // glTF disallows empty meshes / primitive arrays
+ // glTF disallows empty shapes / primitive arrays
const TCollection_AsciiString aNodeName =
formatName(RWMesh_NameFormat_ProductOrInstance, aDocNode.Label, aDocNode.RefLabel);
Message::SendWarning(TCollection_AsciiString("RWGltf_CafWriter skipped node '") + aNodeName
- + "' without triangulation data");
+ + "' without geometry data");
}
}
}
myWriter->StartObject();
- if (!myDracoParameters.DracoCompression)
+ if (!myDracoParameters.DracoCompression || !hasTriangulation(theGltfFace))
{
myWriter->Key("bufferView");
myWriter->Int(myBuffViewPos.Id);
}
myWriter->StartObject();
- if (!myDracoParameters.DracoCompression)
+ if (!myDracoParameters.DracoCompression || !hasTriangulation(theGltfFace))
{
myWriter->Key("bufferView");
myWriter->Int(myBuffViewInd.Id);
aFaceIter.More();
aFaceIter.Next())
{
- myMaterialMap->AddImages(myWriter.get(), aFaceIter.FaceStyle(), anIsStarted);
+ myMaterialMap->AddImages(myWriter.get(), aFaceIter.Style(), anIsStarted);
}
}
if (anIsStarted)
aFaceIter.More();
aFaceIter.Next())
{
- myMaterialMap->AddMaterial(myWriter.get(), aFaceIter.FaceStyle(), anIsStarted);
+ myMaterialMap->AddMaterial(myWriter.get(), aFaceIter.Style(), anIsStarted);
}
}
if (anIsStarted)
myWriter->Key("material");
myWriter->Int(aMatId.IntegerValue());
}
+
myWriter->Key("mode");
- myWriter->Int(RWGltf_GltfPrimitiveMode_Triangles);
+ switch (theGltfFace.Shape.ShapeType())
+ {
+ case TopAbs_EDGE:
+ myWriter->Int(RWGltf_GltfPrimitiveMode_Lines);
+ break;
+ case TopAbs_VERTEX:
+ myWriter->Int(RWGltf_GltfPrimitiveMode_Points);
+ break;
+ default:
+ myWriter->Int(RWGltf_GltfPrimitiveMode_Triangles);
+ break;
+ }
- if (myDracoParameters.DracoCompression)
+ if (myDracoParameters.DracoCompression && hasTriangulation(theGltfFace))
{
myWriter->Key("extensions");
myWriter->StartObject();
#endif
}
+// =======================================================================
+// function : writeShapes
+// purpose :
+// =======================================================================
+void RWGltf_CafWriter::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)
+{
+ for (; theShapeIter.More(); theShapeIter.Next(), ++theNbFacesInNode)
+ {
+ if (toSkipShape(theShapeIter))
+ {
+ continue;
+ }
+
+ RWGltf_StyledShape aStyledShape(theShapeIter.Shape(), theShapeIter.Style());
+ const Handle(RWGltf_GltfFaceList)& aGltfShapeList = myBinDataMap.FindFromKey(aStyledShape);
+ if (!theWrittenShapes.Add(aGltfShapeList))
+ {
+ continue;
+ }
+
+ const Handle(RWGltf_GltfFace)& aGltfShape = aGltfShapeList->First();
+ int aCurrentDracoBufInd = 0;
+
+ if (myDracoParameters.DracoCompression && hasTriangulation(*aGltfShape))
+ {
+ // Check if we've seen this NodePos.Id before
+ if (!theDracoBufIndMap.FindFromKey(aGltfShape->NodePos.Id, aCurrentDracoBufInd))
+ {
+ // New Draco buffer entry needed
+ aCurrentDracoBufInd = theDracoBufInd;
+ theDracoBufIndMap.Add(aGltfShape->NodePos.Id, aCurrentDracoBufInd);
+ ++theDracoBufInd;
+ }
+ }
+
+ writePrimArray(*aGltfShape, theNodeName, aCurrentDracoBufInd, theToStartPrims);
+ }
+}
+
// =======================================================================
// function : writeMeshes
// purpose :
myWriter->StartArray();
int aDracoBufInd = 0;
- NCollection_IndexedDataMap<int, int> aDracoBufIndMap;
- NCollection_Map<Handle(RWGltf_GltfFaceList)> aWrittenFaces;
+ NCollection_IndexedDataMap<int, int> aDracoBufMap;
+ NCollection_Map<Handle(RWGltf_GltfFaceList)> aWrittenShapes;
for (RWGltf_GltfSceneNodeMap::Iterator aSceneNodeIter(theSceneNodeMap); aSceneNodeIter.More();
aSceneNodeIter.Next())
{
const TCollection_AsciiString aNodeName =
formatName(myMeshNameFormat, aDocNode.Label, aDocNode.RefLabel);
- bool toStartPrims = true;
- Standard_Integer aNbFacesInNode = 0;
- aWrittenFaces.Clear(false);
+ bool toStartPrims = true;
+ Standard_Integer aNbShapes = 0;
+ aWrittenShapes.Clear(false);
if (myToMergeFaces)
{
TopoDS_Shape aShape;
aShape.Location(TopLoc_Location());
RWGltf_StyledShape aStyledShape(aShape, aDocNode.Style);
myBinDataMap.FindFromKey(aStyledShape, aGltfFaceList);
- if (!aWrittenFaces.Add(aGltfFaceList))
+ if (!aWrittenShapes.Add(aGltfFaceList))
{
continue;
}
const Handle(RWGltf_GltfFace)& aGltfFace = aFaceGroupIter.Value();
int aCurrentDracoBufInd = 0;
- if (myDracoParameters.DracoCompression)
+ if (myDracoParameters.DracoCompression && hasTriangulation(*aGltfFace))
{
// Check if we've seen this NodePos.Id before
- if (!aDracoBufIndMap.FindFromKey(aGltfFace->NodePos.Id, aCurrentDracoBufInd))
+ if (!aDracoBufMap.FindFromKey(aGltfFace->NodePos.Id, aCurrentDracoBufInd))
{
// New Draco buffer entry needed
aCurrentDracoBufInd = aDracoBufInd;
- aDracoBufIndMap.Add(aGltfFace->NodePos.Id, aCurrentDracoBufInd);
+ aDracoBufMap.Add(aGltfFace->NodePos.Id, aCurrentDracoBufInd);
++aDracoBufInd;
}
}
-
writePrimArray(*aGltfFace, aNodeName, aCurrentDracoBufInd, toStartPrims);
}
}
else
{
- for (RWMesh_FaceIterator aFaceIter(aDocNode.RefLabel,
- TopLoc_Location(),
- true,
- aDocNode.Style);
- aFaceIter.More();
- aFaceIter.Next(), ++aNbFacesInNode)
{
- if (toSkipFaceMesh(aFaceIter))
- {
- continue;
- }
-
- RWGltf_StyledShape aStyledShape(aFaceIter.Face(), aFaceIter.FaceStyle());
- const Handle(RWGltf_GltfFaceList)& aGltfFaceList = myBinDataMap.FindFromKey(aStyledShape);
- if (!aWrittenFaces.Add(aGltfFaceList))
- {
- continue;
- }
-
- const Handle(RWGltf_GltfFace)& aGltfFace = aGltfFaceList->First();
- int aCurrentDracoBufInd = 0;
-
- if (myDracoParameters.DracoCompression)
- {
- // Check if we've seen this NodePos.Id before
- if (!aDracoBufIndMap.FindFromKey(aGltfFace->NodePos.Id, aCurrentDracoBufInd))
- {
- // New Draco buffer entry needed
- aCurrentDracoBufInd = aDracoBufInd;
- aDracoBufIndMap.Add(aGltfFace->NodePos.Id, aCurrentDracoBufInd);
- ++aDracoBufInd;
- }
- }
-
- writePrimArray(*aGltfFace, aNodeName, aCurrentDracoBufInd, toStartPrims);
+ RWMesh_FaceIterator anIter(aDocNode.RefLabel, TopLoc_Location(), true, aDocNode.Style);
+ writeShapes(anIter,
+ aNbShapes,
+ aDracoBufInd,
+ toStartPrims,
+ aNodeName,
+ aWrittenShapes,
+ aDracoBufMap);
+ }
+ if (aNbShapes == 0)
+ {
+ RWMesh_EdgeIterator anIter(aDocNode.RefLabel, TopLoc_Location(), true, aDocNode.Style);
+ writeShapes(anIter,
+ aNbShapes,
+ aDracoBufInd,
+ toStartPrims,
+ aNodeName,
+ aWrittenShapes,
+ aDracoBufMap);
+ }
+ if (aNbShapes == 0)
+ {
+ RWMesh_VertexIterator anIter(aDocNode.RefLabel, TopLoc_Location(), true, aDocNode.Style);
+ writeShapes(anIter,
+ aNbShapes,
+ aDracoBufInd,
+ toStartPrims,
+ aNodeName,
+ aWrittenShapes,
+ aDracoBufMap);
}
}
aFaceIter.More();
aFaceIter.Next())
{
- myMaterialMap->AddTextures(myWriter.get(), aFaceIter.FaceStyle(), anIsStarted);
+ myMaterialMap->AddTextures(myWriter.get(), aFaceIter.Style(), anIsStarted);
}
}
if (anIsStarted)
#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;
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
//! 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;
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;
//! 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
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
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
--- /dev/null
+// 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();
+}
--- /dev/null
+// 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
const TopLoc_Location& theLocation,
const Standard_Boolean theToMapColors,
const XCAFPrs_Style& theStyle)
- : myDefStyle(theStyle),
- myToMapColors(theToMapColors),
+ : RWMesh_ShapeIterator(theLabel, theLocation, TopAbs_FACE, theToMapColors, theStyle),
mySLTool(1, 1e-12),
myHasNormals(false),
- myIsMirrored(false),
- myHasFaceColor(false)
+ myIsMirrored(false)
{
- TopoDS_Shape aShape;
- if (!XCAFDoc_ShapeTool::GetShape(theLabel, aShape) || aShape.IsNull())
- {
- return;
- }
-
- aShape.Location(theLocation, false);
- myFaceIter.Init(aShape, TopAbs_FACE);
-
- if (theToMapColors)
- {
- dispatchStyles(theLabel, theLocation, theStyle);
- myStyles.Bind(aShape, theStyle);
- }
-
Next();
}
// =======================================================================
RWMesh_FaceIterator::RWMesh_FaceIterator(const TopoDS_Shape& theShape,
const XCAFPrs_Style& theStyle)
- : myDefStyle(theStyle),
- myToMapColors(true),
+ : RWMesh_ShapeIterator(theShape, TopAbs_FACE, theStyle),
mySLTool(1, 1e-12),
myHasNormals(false),
- myIsMirrored(false),
- myHasFaceColor(false)
+ myIsMirrored(false)
{
- if (theShape.IsNull())
- {
- return;
- }
-
- myFaceIter.Init(theShape, TopAbs_FACE);
Next();
}
-// =======================================================================
-// function : dispatchStyles
-// purpose :
-// =======================================================================
-void RWMesh_FaceIterator::dispatchStyles(const TDF_Label& theLabel,
- const TopLoc_Location& theLocation,
- const XCAFPrs_Style& theStyle)
-{
- TopLoc_Location aDummyLoc;
- XCAFPrs_IndexedDataMapOfShapeStyle aStyles;
- XCAFPrs::CollectStyleSettings(theLabel, aDummyLoc, aStyles);
-
- Standard_Integer aNbTypes[TopAbs_SHAPE] = {};
- for (Standard_Integer aTypeIter = TopAbs_FACE; aTypeIter >= TopAbs_COMPOUND; --aTypeIter)
- {
- if (aTypeIter != TopAbs_FACE && aNbTypes[aTypeIter] == 0)
- {
- continue;
- }
-
- for (XCAFPrs_IndexedDataMapOfShapeStyle::Iterator aStyleIter(aStyles); aStyleIter.More();
- aStyleIter.Next())
- {
- const TopoDS_Shape& aKeyShape = aStyleIter.Key();
- const TopAbs_ShapeEnum aKeyShapeType = aKeyShape.ShapeType();
- if (aTypeIter == TopAbs_FACE)
- {
- ++aNbTypes[aKeyShapeType];
- }
- if (aTypeIter != aKeyShapeType)
- {
- continue;
- }
-
- XCAFPrs_Style aCafStyle = aStyleIter.Value();
- if (!aCafStyle.IsSetColorCurv() && theStyle.IsSetColorCurv())
- {
- aCafStyle.SetColorCurv(theStyle.GetColorCurv());
- }
- if (!aCafStyle.IsSetColorSurf() && theStyle.IsSetColorSurf())
- {
- aCafStyle.SetColorSurf(theStyle.GetColorSurfRGBA());
- }
- if (aCafStyle.Material().IsNull() && !theStyle.Material().IsNull())
- {
- aCafStyle.SetMaterial(theStyle.Material());
- }
-
- TopoDS_Shape aKeyShapeLocated = aKeyShape.Located(theLocation);
- if (aKeyShapeType == TopAbs_FACE)
- {
- myStyles.Bind(aKeyShapeLocated, aCafStyle);
- }
- else
- {
- for (TopExp_Explorer aFaceIter(aKeyShapeLocated, TopAbs_FACE); aFaceIter.More();
- aFaceIter.Next())
- {
- if (!myStyles.IsBound(aFaceIter.Current()))
- {
- myStyles.Bind(aFaceIter.Current(), aCafStyle);
- }
- }
- }
- }
- }
-}
-
// =======================================================================
// function : normal
// purpose :
// =======================================================================
void RWMesh_FaceIterator::Next()
{
- for (; myFaceIter.More(); myFaceIter.Next())
+ for (; myIter.More(); myIter.Next())
{
- myFace = TopoDS::Face(myFaceIter.Current());
- myPolyTriang = BRep_Tool::Triangulation(myFace, myFaceLocation);
- myTrsf = myFaceLocation.Transformation();
+ myFace = TopoDS::Face(myIter.Current());
+ myPolyTriang = BRep_Tool::Triangulation(myFace, myLocation);
+ myTrsf = myLocation.Transformation();
if (myPolyTriang.IsNull() || myPolyTriang->NbTriangles() == 0)
{
resetFace();
}
initFace();
- myFaceIter.Next();
+ myIter.Next();
return;
}
// =======================================================================
void RWMesh_FaceIterator::initFace()
{
- myHasNormals = false;
- myHasFaceColor = false;
- myIsMirrored = myTrsf.VectorialPart().Determinant() < 0.0;
+ myHasNormals = false;
+ myIsMirrored = myTrsf.VectorialPart().Determinant() < 0.0;
if (myPolyTriang->HasNormals())
{
myHasNormals = true;
myHasNormals = true;
}
}
- if (!myToMapColors)
- {
- return;
- }
-
- if (!myStyles.Find(myFace, myFaceStyle))
- {
- myFaceStyle = myDefStyle;
- }
- if (!myFaceStyle.Material().IsNull())
- {
- myHasFaceColor = true;
- myFaceColor = myFaceStyle.Material()->BaseColor();
- }
- else if (myFaceStyle.IsSetColorSurf())
- {
- myHasFaceColor = true;
- myFaceColor = myFaceStyle.GetColorSurfRGBA();
- }
+ initShape();
}
#ifndef _RWMesh_FaceIterator_HeaderFile
#define _RWMesh_FaceIterator_HeaderFile
+#include <RWMesh_ShapeIterator.hxx>
+
#include <BRepLProp_SLProps.hxx>
-#include <gp_Trsf.hxx>
-#include <NCollection_DataMap.hxx>
#include <Poly_Triangulation.hxx>
-#include <TopExp_Explorer.hxx>
#include <TopoDS_Face.hxx>
-#include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
-#include <XCAFPrs_Style.hxx>
#include <algorithm>
class TDF_Label;
//! Auxiliary class to iterate through triangulated faces.
-class RWMesh_FaceIterator
+//! Class is designed to provide an interface for iterating over the faces
+//! of a shape, specifically focusing on triangulated faces.
+//! It inherits from the `RWMesh_ShapeIterator` base class and
+//! extends its functionality to handle faces with triangulation data.
+class RWMesh_FaceIterator : public RWMesh_ShapeIterator
{
public:
//! Main constructor.
+ //! @param[in] theLabel Label containing the face data
+ //! @param[in] theLocation Location of the face
+ //! @param[in] theToMapColors Flag to indicate if colors should be mapped
+ //! @param[in] theStyle Style information for the face
Standard_EXPORT RWMesh_FaceIterator(const TDF_Label& theLabel,
const TopLoc_Location& theLocation,
const Standard_Boolean theToMapColors = false,
const XCAFPrs_Style& theStyle = XCAFPrs_Style());
//! Auxiliary constructor.
+ //! @param[in] theShape Shape containing the face data
+ //! @param[in] theStyle Style information for the face
Standard_EXPORT RWMesh_FaceIterator(const TopoDS_Shape& theShape,
const XCAFPrs_Style& theStyle = XCAFPrs_Style());
- //! Return explored shape.
- const TopoDS_Shape& ExploredShape() const { return myFaceIter.ExploredShape(); }
-
//! Return true if iterator points to the valid triangulation.
- bool More() const { return !myPolyTriang.IsNull(); }
+ bool More() const Standard_OVERRIDE { return !myPolyTriang.IsNull(); }
//! Find next value.
- Standard_EXPORT void Next();
+ Standard_EXPORT void Next() Standard_OVERRIDE;
//! Return current face.
const TopoDS_Face& Face() const { return myFace; }
+ //! Return current face.
+ const TopoDS_Shape& Shape() const Standard_OVERRIDE { return myFace; }
+
//! Return current face triangulation.
const Handle(Poly_Triangulation)& Triangulation() const { return myPolyTriang; }
//! Return true if mesh data is defined.
- bool IsEmptyMesh() const
+ bool IsEmptyMesh() const { return IsEmpty(); }
+
+ //! Return true if mesh data is defined.
+ bool IsEmpty() const Standard_OVERRIDE
{
return myPolyTriang.IsNull()
|| (myPolyTriang->NbNodes() < 1 && myPolyTriang->NbTriangles() < 1);
public:
//! Return face material.
- const XCAFPrs_Style& FaceStyle() const { return myFaceStyle; }
+ const XCAFPrs_Style& FaceStyle() const { return myStyle; }
//! Return TRUE if face color is set.
- bool HasFaceColor() const { return myHasFaceColor; }
+ bool HasFaceColor() const { return myHasColor; }
//! Return face color.
- const Quantity_ColorRGBA& FaceColor() const { return myFaceColor; }
+ const Quantity_ColorRGBA& FaceColor() const { return myColor; }
public:
//! Return number of elements of specific type for the current face.
Standard_Integer NbTriangles() const { return myPolyTriang->NbTriangles(); }
//! Lower element index in current triangulation.
- Standard_Integer ElemLower() const { return 1; }
+ Standard_Integer ElemLower() const Standard_OVERRIDE { return 1; }
//! Upper element index in current triangulation.
- Standard_Integer ElemUpper() const { return myPolyTriang->NbTriangles(); }
+ Standard_Integer ElemUpper() const Standard_OVERRIDE { return myPolyTriang->NbTriangles(); }
//! Return triangle with specified index with applied Face orientation.
Poly_Triangle TriangleOriented(Standard_Integer theElemIndex) const
}
//! Return number of nodes for the current face.
- Standard_Integer NbNodes() const { return !myPolyTriang.IsNull() ? myPolyTriang->NbNodes() : 0; }
+ Standard_Integer NbNodes() const Standard_OVERRIDE
+ {
+ return !myPolyTriang.IsNull() ? myPolyTriang->NbNodes() : 0;
+ }
//! Lower node index in current triangulation.
- Standard_Integer NodeLower() const { return 1; }
+ Standard_Integer NodeLower() const Standard_OVERRIDE { return 1; }
//! Upper node index in current triangulation.
- Standard_Integer NodeUpper() const { return myPolyTriang->NbNodes(); }
-
- //! Return the node with specified index with applied transformation.
- gp_Pnt NodeTransformed(const Standard_Integer theNode) const
- {
- gp_Pnt aNode = node(theNode);
- aNode.Transform(myTrsf);
- return aNode;
- }
+ Standard_Integer NodeUpper() const Standard_OVERRIDE { return myPolyTriang->NbNodes(); }
//! Return texture coordinates for the node.
gp_Pnt2d NodeTexCoord(const Standard_Integer theNode) const
public:
//! Return the node with specified index with applied transformation.
- gp_Pnt node(const Standard_Integer theNode) const { return myPolyTriang->Node(theNode); }
+ gp_Pnt node(const Standard_Integer theNode) const Standard_OVERRIDE
+ {
+ return myPolyTriang->Node(theNode);
+ }
//! Return normal at specified node index without face transformation applied.
Standard_EXPORT gp_Dir normal(Standard_Integer theNode) const;
}
private:
- //! Dispatch face styles.
- void dispatchStyles(const TDF_Label& theLabel,
- const TopLoc_Location& theLocation,
- const XCAFPrs_Style& theStyle);
-
//! Reset information for current face.
void resetFace()
{
myPolyTriang.Nullify();
myFace.Nullify();
- myHasNormals = false;
- myHasFaceColor = false;
- myFaceColor = Quantity_ColorRGBA();
- myFaceStyle = XCAFPrs_Style();
+ myHasNormals = false;
+ resetShape();
}
//! Initialize face properties.
void initFace();
private:
- NCollection_DataMap<TopoDS_Shape, XCAFPrs_Style, TopTools_ShapeMapHasher>
- myStyles; //!< Face -> Style map
// clang-format off
- XCAFPrs_Style myDefStyle; //!< default style for faces without dedicated style
- Standard_Boolean myToMapColors; //!< flag to dispatch styles
-
- TopExp_Explorer myFaceIter; //!< face explorer
- TopoDS_Face myFace; //!< current face
- Handle(Poly_Triangulation) myPolyTriang; //!< triangulation of current face
- TopLoc_Location myFaceLocation; //!< current face location
- mutable BRepLProp_SLProps mySLTool; //!< auxiliary tool for fetching normals from surface
- BRepAdaptor_Surface myFaceAdaptor; //!< surface adaptor for fetching normals from surface
- Standard_Boolean myHasNormals; //!< flag indicating that current face has normals
- gp_Trsf myTrsf; //!< current face transformation
- Standard_Boolean myIsMirrored; //!< flag indicating that face triangles should be mirrored
- XCAFPrs_Style myFaceStyle; //!< current face style
- Quantity_ColorRGBA myFaceColor; //!< current face color
- Standard_Boolean myHasFaceColor; //!< flag indicating that current face has assigned color
+ TopoDS_Face myFace; //!< current face
+ Handle(Poly_Triangulation) myPolyTriang; //!< triangulation of current face
+ mutable BRepLProp_SLProps mySLTool; //!< auxiliary tool for fetching normals from surface
+ BRepAdaptor_Surface myFaceAdaptor; //!< surface adaptor for fetching normals from surface
+ Standard_Boolean myHasNormals; //!< flag indicating that current face has normals
+ Standard_Boolean myIsMirrored; //!< flag indicating that face triangles should be mirrored
// clang-format on
};
--- /dev/null
+// 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_ShapeIterator.hxx>
+
+#include <TopExp.hxx>
+#include <TopoDS.hxx>
+#include <XCAFDoc_ShapeTool.hxx>
+#include <XCAFPrs.hxx>
+
+// =======================================================================
+// function : RWMesh_ShapeIterator
+// purpose :
+// =======================================================================
+RWMesh_ShapeIterator::RWMesh_ShapeIterator(const TDF_Label& theLabel,
+ const TopLoc_Location& theLocation,
+ const TopAbs_ShapeEnum theShapeType,
+ const Standard_Boolean theToMapColors,
+ const XCAFPrs_Style& theStyle)
+ : myDefStyle(theStyle),
+ myToMapColors(theToMapColors),
+ myShapeType(theShapeType),
+ myHasColor(false)
+{
+ TopoDS_Shape aShape;
+ if (!XCAFDoc_ShapeTool::GetShape(theLabel, aShape) || aShape.IsNull())
+ {
+ return;
+ }
+
+ aShape.Location(theLocation, false);
+ myIter.Init(aShape, myShapeType);
+
+ if (theToMapColors)
+ {
+ dispatchStyles(theLabel, theLocation, theStyle);
+ myStyles.Bind(aShape, theStyle);
+ }
+}
+
+// =======================================================================
+// function : RWMesh_ShapeIterator
+// purpose :
+// =======================================================================
+RWMesh_ShapeIterator::RWMesh_ShapeIterator(const TopoDS_Shape& theShape,
+ const TopAbs_ShapeEnum theShapeType,
+ const XCAFPrs_Style& theStyle)
+ : myDefStyle(theStyle),
+ myToMapColors(true),
+ myShapeType(theShapeType),
+ myHasColor(false)
+{
+ if (theShape.IsNull())
+ {
+ return;
+ }
+ myIter.Init(theShape, myShapeType);
+}
+
+// =======================================================================
+// function : dispatchStyles
+// purpose :
+// =======================================================================
+void RWMesh_ShapeIterator::dispatchStyles(const TDF_Label& theLabel,
+ const TopLoc_Location& theLocation,
+ const XCAFPrs_Style& theStyle)
+{
+ TopLoc_Location aDummyLoc;
+ XCAFPrs_IndexedDataMapOfShapeStyle aStyles;
+ XCAFPrs::CollectStyleSettings(theLabel, aDummyLoc, aStyles);
+
+ Standard_Integer aNbTypes[TopAbs_SHAPE] = {};
+ for (Standard_Integer aTypeIter = myShapeType; aTypeIter >= TopAbs_COMPOUND; --aTypeIter)
+ {
+ if (aTypeIter != myShapeType && aNbTypes[aTypeIter] == 0)
+ {
+ continue;
+ }
+
+ for (XCAFPrs_IndexedDataMapOfShapeStyle::Iterator aStyleIter(aStyles); aStyleIter.More();
+ aStyleIter.Next())
+ {
+ const TopoDS_Shape& aKeyShape = aStyleIter.Key();
+ const TopAbs_ShapeEnum aKeyShapeType = aKeyShape.ShapeType();
+ if (aTypeIter == myShapeType)
+ {
+ ++aNbTypes[aKeyShapeType];
+ }
+ if (aTypeIter != aKeyShapeType)
+ {
+ continue;
+ }
+
+ XCAFPrs_Style aCafStyle = aStyleIter.Value();
+ if (!aCafStyle.IsSetColorCurv() && theStyle.IsSetColorCurv())
+ {
+ aCafStyle.SetColorCurv(theStyle.GetColorCurv());
+ }
+ if (!aCafStyle.IsSetColorSurf() && theStyle.IsSetColorSurf())
+ {
+ aCafStyle.SetColorSurf(theStyle.GetColorSurfRGBA());
+ }
+ if (aCafStyle.Material().IsNull() && !theStyle.Material().IsNull())
+ {
+ aCafStyle.SetMaterial(theStyle.Material());
+ }
+
+ TopoDS_Shape aKeyShapeLocated = aKeyShape.Located(theLocation);
+ if (aKeyShapeType == myShapeType)
+ {
+ myStyles.Bind(aKeyShapeLocated, aCafStyle);
+ }
+ else
+ {
+ for (TopExp_Explorer aShapeIter(aKeyShapeLocated, myShapeType); aShapeIter.More();
+ aShapeIter.Next())
+ {
+ if (!myStyles.IsBound(aShapeIter.Current()))
+ {
+ myStyles.Bind(aShapeIter.Current(), aCafStyle);
+ }
+ }
+ }
+ }
+ }
+}
+
+// =======================================================================
+// function : initEdge
+// purpose :
+// =======================================================================
+void RWMesh_ShapeIterator::initShape()
+{
+ myHasColor = false;
+ if (!myToMapColors)
+ {
+ return;
+ }
+ if (!myStyles.Find(Shape(), myStyle))
+ {
+ myStyle = myDefStyle;
+ }
+ if (!myStyle.Material().IsNull())
+ {
+ myHasColor = true;
+ myColor = myStyle.Material()->BaseColor();
+ }
+ else if (myStyle.IsSetColorSurf())
+ {
+ myHasColor = true;
+ myColor = myStyle.GetColorSurfRGBA();
+ }
+}
\ No newline at end of file
--- /dev/null
+// 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_ShapeIterator_HeaderFile
+#define _RWMesh_ShapeIterator_HeaderFile
+
+#include <BRepLProp_SLProps.hxx>
+#include <NCollection_DataMap.hxx>
+#include <Poly_Triangulation.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;
+
+//! This is a virtual base class for other shape iterators.
+//! Provides an abstract interface for iterating over the elements of a shape.
+//! It defines a set of pure virtual methods that must be implemented by
+//! derived classes to handle specific types of shapes and their elements.
+class RWMesh_ShapeIterator
+{
+public:
+ //! Return explored shape.
+ const TopoDS_Shape& ExploredShape() const { return myIter.ExploredShape(); }
+
+ //! Return shape.
+ Standard_EXPORT virtual const TopoDS_Shape& Shape() const = 0;
+
+ //! Return true if iterator points to the valid triangulation.
+ Standard_EXPORT virtual bool More() const = 0;
+
+ //! Find next value.
+ Standard_EXPORT virtual void Next() = 0;
+
+ //! Return true if mesh data is defined.
+ Standard_EXPORT virtual bool IsEmpty() const = 0;
+
+ //! Return shape material.
+ const XCAFPrs_Style& Style() const { return myStyle; }
+
+ //! Return TRUE if shape color is set.
+ bool HasColor() const { return myHasColor; }
+
+ //! Return shape color.
+ const Quantity_ColorRGBA& Color() const { return myColor; }
+
+ //! Lower element index in current triangulation.
+ Standard_EXPORT virtual Standard_Integer ElemLower() const = 0;
+
+ //! Upper element index in current triangulation.
+ Standard_EXPORT virtual Standard_Integer ElemUpper() const = 0;
+
+ //! Return number of nodes for the current shape.
+ Standard_EXPORT virtual Standard_Integer NbNodes() const = 0;
+
+ //! Lower node index in current shape.
+ Standard_EXPORT virtual Standard_Integer NodeLower() const = 0;
+
+ //! Upper node index in current shape.
+ Standard_EXPORT virtual Standard_Integer NodeUpper() const = 0;
+
+ //! Return the node with specified index with applied transformation.
+ gp_Pnt NodeTransformed(const Standard_Integer theNode) const
+ {
+ gp_Pnt aNode = node(theNode);
+ aNode.Transform(myTrsf);
+ return aNode;
+ }
+
+protected:
+ //! Return the node with specified index with applied transformation.
+ virtual gp_Pnt node(const Standard_Integer theNode) const = 0;
+
+ //! Main constructor.
+ RWMesh_ShapeIterator(const TDF_Label& theLabel,
+ const TopLoc_Location& theLocation,
+ const TopAbs_ShapeEnum theShapeType,
+ const Standard_Boolean theToMapColors = false,
+ const XCAFPrs_Style& theStyle = XCAFPrs_Style());
+
+ //! Auxiliary constructor.
+ RWMesh_ShapeIterator(const TopoDS_Shape& theShape,
+ const TopAbs_ShapeEnum theShapeType,
+ const XCAFPrs_Style& theStyle = XCAFPrs_Style());
+
+ //! Dispatch shape styles.
+ void dispatchStyles(const TDF_Label& theLabel,
+ const TopLoc_Location& theLocation,
+ const XCAFPrs_Style& theStyle);
+
+ //! Reset information for current shape.
+ void resetShape()
+ {
+ myHasColor = false;
+ myColor = Quantity_ColorRGBA();
+ myStyle = XCAFPrs_Style();
+ }
+
+ //! Initialize shape properties.
+ void initShape();
+
+protected:
+ NCollection_DataMap<TopoDS_Shape, XCAFPrs_Style, TopTools_ShapeMapHasher>
+ myStyles; //!< Shape -> Style map
+ XCAFPrs_Style myDefStyle; //!< default style for shapes without dedicated style
+ Standard_Boolean myToMapColors; //!< flag to dispatch styles
+
+ TopExp_Explorer myIter; //!< shape explorer
+ TopLoc_Location myLocation; //!< current shape location
+ gp_Trsf myTrsf; //!< current shape transformation
+ XCAFPrs_Style myStyle; //!< current shape style
+ Quantity_ColorRGBA myColor; //!< current shape color
+ TopAbs_ShapeEnum myShapeType; //!< type of shape
+ Standard_Boolean myHasColor; //!< flag indicating that current shape has assigned color
+};
+
+#endif // _RWMesh_ShapeIterator_HeaderFile
--- /dev/null
+// 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_VertexIterator.hxx>
+
+#include <BRep_Tool.hxx>
+#include <TopExp.hxx>
+#include <TopoDS.hxx>
+#include <XCAFDoc_ShapeTool.hxx>
+#include <XCAFPrs.hxx>
+
+// =======================================================================
+// function : RWMesh_VertexIterator
+// purpose :
+// =======================================================================
+RWMesh_VertexIterator::RWMesh_VertexIterator(const TDF_Label& theLabel,
+ const TopLoc_Location& theLocation,
+ const Standard_Boolean theToMapColors,
+ const XCAFPrs_Style& theStyle)
+ : RWMesh_ShapeIterator(theLabel, theLocation, TopAbs_VERTEX, theToMapColors, theStyle)
+{
+ Next();
+}
+
+// =======================================================================
+// function : RWMesh_VertexIterator
+// purpose :
+// =======================================================================
+RWMesh_VertexIterator::RWMesh_VertexIterator(const TopoDS_Shape& theShape,
+ const XCAFPrs_Style& theStyle)
+ : RWMesh_ShapeIterator(theShape, TopAbs_VERTEX, theStyle)
+{
+ Next();
+}
+
+// =======================================================================
+// function : Next
+// purpose :
+// =======================================================================
+void RWMesh_VertexIterator::Next()
+{
+ for (; myIter.More(); myIter.Next())
+ {
+ myVertex = TopoDS::Vertex(myIter.Current());
+ myPoint = BRep_Tool::Pnt(myVertex);
+ myTrsf = myLocation.Transformation();
+ if (myVertex.IsNull())
+ {
+ resetVertex();
+ continue;
+ }
+
+ initVertex();
+ myIter.Next();
+ return;
+ }
+
+ resetVertex();
+}
+
+// =======================================================================
+// function : initEdge
+// purpose :
+// =======================================================================
+void RWMesh_VertexIterator::initVertex()
+{
+ initShape();
+}
--- /dev/null
+// 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_VertexIterator_HeaderFile
+#define _RWMesh_VertexIterator_HeaderFile
+
+#include <NCollection_DataMap.hxx>
+#include <Poly_Polygon3D.hxx>
+#include <RWMesh_ShapeIterator.hxx>
+#include <TopExp_Explorer.hxx>
+#include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
+#include <TopoDS_Vertex.hxx>
+#include <XCAFPrs_Style.hxx>
+#include <gp_Trsf.hxx>
+
+#include <algorithm>
+
+class TDF_Label;
+
+//! Auxiliary class to iterate through vertices.
+//! Provides functionality to iterate through the vertices of a shape.
+//! It inherits from `RWMesh_ShapeIterator` and implements
+//! methods to access and manipulate vertex data.
+class RWMesh_VertexIterator : 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_VertexIterator(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_VertexIterator(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 !myVertex.IsNull(); }
+
+ //! Find next value.
+ Standard_EXPORT void Next() Standard_OVERRIDE;
+
+ //! Return current edge.
+ const TopoDS_Vertex& Vertex() const { return myVertex; }
+
+ //! Return current vertex.
+ const TopoDS_Shape& Shape() const Standard_OVERRIDE { return myVertex; }
+
+ //! Return current vertex data.
+ const gp_Pnt& Point() const { return myPoint; }
+
+ //! Return true if geometry data is defined.
+ bool IsEmpty() const Standard_OVERRIDE { return myVertex.IsNull(); }
+
+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 1; }
+
+public:
+ //! Return number of nodes for the current edge.
+ Standard_Integer NbNodes() const Standard_OVERRIDE { return 1; }
+
+ //! 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 1; }
+
+public:
+ //! Return the node with specified index with applied transformation.
+ gp_Pnt node(const Standard_Integer /*theNode*/) const Standard_OVERRIDE { return myPoint; }
+
+private:
+ //! Reset information for current vertex.
+ void resetVertex()
+ {
+ myVertex.Nullify();
+ resetShape();
+ }
+
+ //! Initialize vertex properties.
+ void initVertex();
+
+private:
+ TopoDS_Vertex myVertex; //!< current vertex
+ gp_Pnt myPoint; //!< geometry of current vertex
+};
+
+#endif // _RWMesh_VertexIterator_HeaderFile
--- /dev/null
+puts "========"
+puts "278: Data Exchange, Fail to export to GLTF with draco buffer index out of bounds"
+puts "========"
+
+vclear
+vclose ALL
+Close *
+
+set aTmpGltf "${imagedir}/${casename}_tmp.glb"
+
+ReadStep D [locate_data_file "bug31670_russian.stp"]
+XGetOneShape s D
+incmesh s 0.1
+
+XNewDoc D
+XAddShape D s
+
+WriteGltf D "$aTmpGltf" -draco -mergefaces
+
+ReadGltf D1 "$aTmpGltf"
+XGetOneShape s1 D1
+checknbshapes s1 -face 11 -compound 10 -shape 21