1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-06-05 11:24:17 +03:00

Data Exchange, GLTF - fix saving edges when Merge Faces is enabled #554

Removed check for LineStrip mode to force use of Lines for merged faces
Updated primitive mode checks by removing LineStrip references
Added getShapeType to correctly determine the underlying shape type from compounds and updated index calculation logic
This commit is contained in:
Elias Cohenca 2025-05-23 14:24:13 +03:00 committed by GitHub
parent 7ed396b0eb
commit 4f2d4c1f4b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 63 additions and 32 deletions

View File

@ -278,6 +278,23 @@ TCollection_AsciiString RWGltf_CafWriter::formatName(RWMesh_NameFormat theFormat
//=================================================================================================
TopAbs_ShapeEnum RWGltf_CafWriter::getShapeType(const TopoDS_Shape& theShape) const
{
TopAbs_ShapeEnum aShapeType = theShape.ShapeType();
if (aShapeType == TopAbs_COMPOUND)
{
// Compounds are created in the case of merged faces.
// Assuming that all shapes in the compound are of the same type
TopoDS_Iterator it(theShape);
Standard_ProgramError_Raise_if(!it.More(), "Empty compound");
aShapeType = it.Value().ShapeType();
}
return aShapeType;
}
//=================================================================================================
Standard_Boolean RWGltf_CafWriter::toSkipShape(const RWMesh_ShapeIterator& theShapeIter) const
{
return theShapeIter.IsEmpty();
@ -287,19 +304,17 @@ Standard_Boolean RWGltf_CafWriter::toSkipShape(const RWMesh_ShapeIterator& theSh
Standard_Boolean RWGltf_CafWriter::hasTriangulation(const RWGltf_GltfFace& theGltfFace) const
{
switch (theGltfFace.Shape.ShapeType())
TopAbs_ShapeEnum shapeType = getShapeType(theGltfFace.Shape);
switch (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;
default:
throw Standard_ProgramError("Unsupported shape type");
}
}
@ -499,21 +514,29 @@ void RWGltf_CafWriter::saveTriangleIndices(RWGltf_GltfFace& theGltfFac
void RWGltf_CafWriter::saveEdgeIndices(RWGltf_GltfFace& theGltfFace,
std::ostream& theBinFile,
const RWMesh_EdgeIterator& theFaceIter)
const RWMesh_EdgeIterator& theEdgeIter)
{
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)
const Standard_Integer aNodeFirst = theGltfFace.NbIndexedNodes;
theGltfFace.NbIndexedNodes += theEdgeIter.NbNodes();
const Standard_Integer numSegments = Max(0, theEdgeIter.NbNodes() - 1);
// each segment writes two indices
theGltfFace.Indices.Count += numSegments * 2;
for (Standard_Integer i = 0; i < numSegments; ++i)
{
Standard_Integer i0 = aNodeFirst + i;
Standard_Integer i1 = aNodeFirst + i + 1;
if (theGltfFace.Indices.ComponentType == RWGltf_GltfAccessorCompType_UInt16)
{
writeVertex(theBinFile, (uint16_t)(anElemIter + aNodeFirst));
writeVertex(theBinFile, (uint16_t)i0);
writeVertex(theBinFile, (uint16_t)i1);
}
else
{
writeVertex(theBinFile, anElemIter + aNodeFirst);
writeVertex(theBinFile, i0);
writeVertex(theBinFile, i1);
}
}
}
@ -522,12 +545,13 @@ void RWGltf_CafWriter::saveEdgeIndices(RWGltf_GltfFace& theGltfFace,
void RWGltf_CafWriter::saveVertexIndices(RWGltf_GltfFace& theGltfFace,
std::ostream& theBinFile,
const RWMesh_VertexIterator& theFaceIter)
const RWMesh_VertexIterator& theVertexIter)
{
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();
const Standard_Integer aNodeFirst = theGltfFace.NbIndexedNodes - theVertexIter.ElemLower();
theGltfFace.NbIndexedNodes += theVertexIter.NbNodes();
theGltfFace.Indices.Count += theVertexIter.NbNodes();
for (Standard_Integer anElemIter = theVertexIter.ElemLower();
anElemIter <= theVertexIter.ElemUpper();
++anElemIter)
{
if (theGltfFace.Indices.ComponentType == RWGltf_GltfAccessorCompType_UInt16)
@ -545,7 +569,7 @@ void RWGltf_CafWriter::saveVertexIndices(RWGltf_GltfFace& theGltfFac
void RWGltf_CafWriter::saveIndices(RWGltf_GltfFace& theGltfFace,
std::ostream& theBinFile,
const RWMesh_ShapeIterator& theFaceIter,
const RWMesh_ShapeIterator& theShapeIter,
Standard_Integer& theAccessorNb,
const std::shared_ptr<RWGltf_CafWriter::Mesh>& theMesh)
{
@ -574,17 +598,18 @@ void RWGltf_CafWriter::saveIndices(RWGltf_GltfFace&
}
}
if (const RWMesh_FaceIterator* aFaceIter = dynamic_cast<const RWMesh_FaceIterator*>(&theFaceIter))
if (const RWMesh_FaceIterator* aFaceIter =
dynamic_cast<const RWMesh_FaceIterator*>(&theShapeIter))
{
saveTriangleIndices(theGltfFace, theBinFile, *aFaceIter, theMesh);
}
else if (const RWMesh_EdgeIterator* anEdgeIter =
dynamic_cast<const RWMesh_EdgeIterator*>(&theFaceIter))
dynamic_cast<const RWMesh_EdgeIterator*>(&theShapeIter))
{
saveEdgeIndices(theGltfFace, theBinFile, *anEdgeIter);
}
else if (const RWMesh_VertexIterator* aVertexIter =
dynamic_cast<const RWMesh_VertexIterator*>(&theFaceIter))
dynamic_cast<const RWMesh_VertexIterator*>(&theShapeIter))
{
saveVertexIndices(theGltfFace, theBinFile, *aVertexIter);
}
@ -963,7 +988,9 @@ bool RWGltf_CafWriter::writeBinData(const Handle(TDocStd_Document)& theDocument,
aWrittenPrimData.Bind(aGltfFace->Shape, aGltfFace);
Standard_Boolean wasWrittenNonFace = Standard_False;
switch (aGltfFace->Shape.ShapeType())
TopAbs_ShapeEnum shapeType = getShapeType(aGltfFace->Shape);
switch (shapeType)
{
case TopAbs_EDGE: {
RWMesh_EdgeIterator anIter(aGltfFace->Shape, aGltfFace->Style);
@ -2027,10 +2054,13 @@ void RWGltf_CafWriter::writePrimArray(const RWGltf_GltfFace& theGltfFace
}
myWriter->Key("mode");
switch (theGltfFace.Shape.ShapeType())
TopAbs_ShapeEnum shapeType = getShapeType(theGltfFace.Shape);
switch (shapeType)
{
case TopAbs_EDGE:
myWriter->Int(RWGltf_GltfPrimitiveMode_LineStrip);
myWriter->Int(RWGltf_GltfPrimitiveMode_Lines);
break;
case TopAbs_VERTEX:
myWriter->Int(RWGltf_GltfPrimitiveMode_Points);

View File

@ -209,6 +209,9 @@ protected:
const Message_ProgressRange& theProgress);
protected:
//! Returns the underlying shape in case of a compound.
Standard_EXPORT virtual TopAbs_ShapeEnum getShapeType(const TopoDS_Shape& theShape) const;
//! 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;

View File

@ -1808,7 +1808,7 @@ bool RWGltf_GltfJsonParser::gltfParsePrimArray(TopoDS_Shape& th
}
}
if (aMode != RWGltf_GltfPrimitiveMode_Triangles && aMode != RWGltf_GltfPrimitiveMode_Lines
&& aMode != RWGltf_GltfPrimitiveMode_LineStrip && aMode != RWGltf_GltfPrimitiveMode_Points)
&& aMode != RWGltf_GltfPrimitiveMode_Points)
{
Message::SendWarning(TCollection_AsciiString() + "Primitive array within Mesh '" + theMeshId
+ "' skipped due to unsupported mode");
@ -1976,8 +1976,7 @@ bool RWGltf_GltfJsonParser::gltfParsePrimArray(TopoDS_Shape& th
aShape = aVertices;
break;
}
case RWGltf_GltfPrimitiveMode_Lines:
case RWGltf_GltfPrimitiveMode_LineStrip: {
case RWGltf_GltfPrimitiveMode_Lines: {
TColgp_Array1OfPnt aNodes(1, aMeshData->NbEdges());
for (Standard_Integer anEdgeIdx = 1; anEdgeIdx <= aMeshData->NbEdges(); ++anEdgeIdx)
{
@ -2012,7 +2011,7 @@ bool RWGltf_GltfJsonParser::gltfParsePrimArray(TopoDS_Shape& th
aShapeAttribs.RawName = theMeshName;
// assign material and not color
if (aMode == RWGltf_GltfPrimitiveMode_Lines || aMode == RWGltf_GltfPrimitiveMode_LineStrip)
if (aMode == RWGltf_GltfPrimitiveMode_Lines)
{
aShapeAttribs.Style.SetColorCurv(aMeshData->BaseColor().GetRGB());
}

View File

@ -579,7 +579,6 @@ bool RWGltf_TriangulationReader::ReadStream(
const TCollection_AsciiString& aName = theSourceMesh->Id();
const RWGltf_GltfPrimitiveMode aPrimMode = theSourceMesh->PrimitiveMode();
if (aPrimMode != RWGltf_GltfPrimitiveMode_Triangles && aPrimMode != RWGltf_GltfPrimitiveMode_Lines
&& aPrimMode != RWGltf_GltfPrimitiveMode_LineStrip
&& aPrimMode != RWGltf_GltfPrimitiveMode_Points)
{
Message::SendWarning(TCollection_AsciiString("Buffer '") + aName