1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-08-14 13:30:48 +03:00

0030953: Data Exchange - implement export of mesh data into glTF 2.0 format

Added new class RWGltf_CafWriter for exporting XCAF document into glTF file
as well as Draw Harness command WriteGltf.

Added auxiliary method OSD_Path::FileNameAndExtension() splitting file name into Name and Extension.
This commit is contained in:
kgv
2019-11-19 02:09:09 +03:00
committed by bugmaster
parent df8c7e3e18
commit 01b2f506d6
26 changed files with 3620 additions and 12 deletions

View File

@@ -0,0 +1,461 @@
// Copyright (c) 2017-2019 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 <RWGltf_GltfMaterialMap.hxx>
#include <RWGltf_GltfRootElement.hxx>
#ifdef HAVE_RAPIDJSON
#include <RWGltf_GltfOStreamWriter.hxx>
#endif
// =======================================================================
// function : baseColorTexture
// purpose :
// =======================================================================
const Handle(Image_Texture)& RWGltf_GltfMaterialMap::baseColorTexture (const Handle(XCAFDoc_VisMaterial)& theMat)
{
static const Handle(Image_Texture) THE_NULL_TEXTURE;
if (theMat.IsNull())
{
return THE_NULL_TEXTURE;
}
else if (theMat->HasPbrMaterial()
&& !theMat->PbrMaterial().BaseColorTexture.IsNull())
{
return theMat->PbrMaterial().BaseColorTexture;
}
else if (theMat->HasCommonMaterial()
&& !theMat->CommonMaterial().DiffuseTexture.IsNull())
{
return theMat->CommonMaterial().DiffuseTexture;
}
return THE_NULL_TEXTURE;
}
// =======================================================================
// function : RWGltf_GltfMaterialMap
// purpose :
// =======================================================================
RWGltf_GltfMaterialMap::RWGltf_GltfMaterialMap (const TCollection_AsciiString& theFile,
const Standard_Integer theDefSamplerId)
: RWMesh_MaterialMap (theFile),
myWriter (NULL),
myDefSamplerId (theDefSamplerId),
myNbImages (0)
{
myMatNameAsKey = false;
}
// =======================================================================
// function : ~RWGltf_GltfMaterialMap
// purpose :
// =======================================================================
RWGltf_GltfMaterialMap::~RWGltf_GltfMaterialMap()
{
//
}
// =======================================================================
// function : AddImages
// purpose :
// =======================================================================
void RWGltf_GltfMaterialMap::AddImages (RWGltf_GltfOStreamWriter* theWriter,
const XCAFPrs_Style& theStyle,
Standard_Boolean& theIsStarted)
{
if (theWriter == NULL
|| theStyle.Material().IsNull()
|| theStyle.Material()->IsEmpty())
{
return;
}
addImage (theWriter, baseColorTexture (theStyle.Material()), theIsStarted);
addImage (theWriter, theStyle.Material()->PbrMaterial().MetallicRoughnessTexture, theIsStarted);
addImage (theWriter, theStyle.Material()->PbrMaterial().NormalTexture, theIsStarted);
addImage (theWriter, theStyle.Material()->PbrMaterial().EmissiveTexture, theIsStarted);
addImage (theWriter, theStyle.Material()->PbrMaterial().OcclusionTexture, theIsStarted);
}
// =======================================================================
// function : addImage
// purpose :
// =======================================================================
void RWGltf_GltfMaterialMap::addImage (RWGltf_GltfOStreamWriter* theWriter,
const Handle(Image_Texture)& theTexture,
Standard_Boolean& theIsStarted)
{
#ifdef HAVE_RAPIDJSON
if (theTexture.IsNull()
|| myImageMap.IsBound1 (theTexture)
|| myImageFailMap.Contains (theTexture))
{
return;
}
TCollection_AsciiString aGltfImgKey = myNbImages;
++myNbImages;
for (; myImageMap.IsBound2 (aGltfImgKey); ++myNbImages)
{
aGltfImgKey = myNbImages;
}
TCollection_AsciiString aTextureUri;
if (!CopyTexture (aTextureUri, theTexture, aGltfImgKey))
{
myImageFailMap.Add (theTexture);
return;
}
myImageMap.Bind (theTexture, aGltfImgKey);
if (!theIsStarted)
{
theWriter->Key (RWGltf_GltfRootElementName (RWGltf_GltfRootElement_Images));
theWriter->StartArray();
theIsStarted = true;
}
theWriter->StartObject();
{
theWriter->Key ("uri");
theWriter->String (aTextureUri.ToCString());
}
theWriter->EndObject();
#else
(void )theWriter;
(void )theTexture;
(void )theIsStarted;
#endif
}
// =======================================================================
// function : AddMaterial
// purpose :
// =======================================================================
void RWGltf_GltfMaterialMap::AddMaterial (RWGltf_GltfOStreamWriter* theWriter,
const XCAFPrs_Style& theStyle,
Standard_Boolean& theIsStarted)
{
#ifdef HAVE_RAPIDJSON
if (theWriter == NULL
|| ((theStyle.Material().IsNull() || theStyle.Material()->IsEmpty())
&& !theStyle.IsSetColorSurf()))
{
return;
}
if (!theIsStarted)
{
theWriter->Key (RWGltf_GltfRootElementName (RWGltf_GltfRootElement_Materials));
theWriter->StartArray();
theIsStarted = true;
}
myWriter = theWriter;
AddMaterial (theStyle);
myWriter = NULL;
#else
(void )theWriter;
(void )theStyle;
(void )theIsStarted;
#endif
}
// =======================================================================
// function : AddTextures
// purpose :
// =======================================================================
void RWGltf_GltfMaterialMap::AddTextures (RWGltf_GltfOStreamWriter* theWriter,
const XCAFPrs_Style& theStyle,
Standard_Boolean& theIsStarted)
{
if (theWriter == NULL
|| theStyle.Material().IsNull()
|| theStyle.Material()->IsEmpty())
{
return;
}
addTexture (theWriter, baseColorTexture (theStyle.Material()), theIsStarted);
addTexture (theWriter, theStyle.Material()->PbrMaterial().MetallicRoughnessTexture, theIsStarted);
addTexture (theWriter, theStyle.Material()->PbrMaterial().NormalTexture, theIsStarted);
addTexture (theWriter, theStyle.Material()->PbrMaterial().EmissiveTexture, theIsStarted);
addTexture (theWriter, theStyle.Material()->PbrMaterial().OcclusionTexture, theIsStarted);
}
// =======================================================================
// function : addTexture
// purpose :
// =======================================================================
void RWGltf_GltfMaterialMap::addTexture (RWGltf_GltfOStreamWriter* theWriter,
const Handle(Image_Texture)& theTexture,
Standard_Boolean& theIsStarted)
{
#ifdef HAVE_RAPIDJSON
if (theTexture.IsNull()
|| myTextureMap.Contains (theTexture)
|| !myImageMap .IsBound1 (theTexture))
{
return;
}
const TCollection_AsciiString anImgKey = myImageMap.Find1 (theTexture);
myTextureMap.Add (theTexture);
if (anImgKey.IsEmpty())
{
return;
}
if (!theIsStarted)
{
theWriter->Key (RWGltf_GltfRootElementName (RWGltf_GltfRootElement_Textures));
theWriter->StartArray();
theIsStarted = true;
}
theWriter->StartObject();
{
theWriter->Key ("sampler");
theWriter->Int (myDefSamplerId); // mandatory field by specs
theWriter->Key ("source");
theWriter->Int (anImgKey.IntegerValue());
}
theWriter->EndObject();
#else
(void )theWriter;
(void )theTexture;
(void )theIsStarted;
#endif
}
// =======================================================================
// function : AddMaterial
// purpose :
// =======================================================================
TCollection_AsciiString RWGltf_GltfMaterialMap::AddMaterial (const XCAFPrs_Style& theStyle)
{
return RWMesh_MaterialMap::AddMaterial (theStyle);
}
// =======================================================================
// function : DefineMaterial
// purpose :
// =======================================================================
void RWGltf_GltfMaterialMap::DefineMaterial (const XCAFPrs_Style& theStyle,
const TCollection_AsciiString& /*theKey*/,
const TCollection_AsciiString& theName)
{
#ifdef HAVE_RAPIDJSON
if (myWriter == NULL)
{
Standard_ProgramError::Raise ("RWGltf_GltfMaterialMap::DefineMaterial() should be called with JSON Writer");
return;
}
XCAFDoc_VisMaterialPBR aPbrMat;
const bool hasMaterial = !theStyle.Material().IsNull()
&& !theStyle.Material()->IsEmpty();
if (hasMaterial)
{
aPbrMat = theStyle.Material()->ConvertToPbrMaterial();
}
else if (!myDefaultStyle.Material().IsNull()
&& myDefaultStyle.Material()->HasPbrMaterial())
{
aPbrMat = myDefaultStyle.Material()->PbrMaterial();
}
if (theStyle.IsSetColorSurf())
{
aPbrMat.BaseColor.SetRGB (theStyle.GetColorSurf());
if (theStyle.GetColorSurfRGBA().Alpha() < 1.0f)
{
aPbrMat.BaseColor.SetAlpha (theStyle.GetColorSurfRGBA().Alpha());
}
}
myWriter->StartObject();
{
myWriter->Key ("name");
myWriter->String (theName.ToCString());
myWriter->Key ("pbrMetallicRoughness");
myWriter->StartObject();
{
myWriter->Key ("baseColorFactor");
myWriter->StartArray();
{
myWriter->Double (aPbrMat.BaseColor.GetRGB().Red());
myWriter->Double (aPbrMat.BaseColor.GetRGB().Green());
myWriter->Double (aPbrMat.BaseColor.GetRGB().Blue());
myWriter->Double (aPbrMat.BaseColor.Alpha());
}
myWriter->EndArray();
if (const Handle(Image_Texture)& aBaseTexture = baseColorTexture (theStyle.Material()))
{
if (myImageMap.IsBound1 (aBaseTexture))
{
myWriter->Key ("baseColorTexture");
myWriter->StartObject();
{
myWriter->Key ("index");
const TCollection_AsciiString& anImageIdx = myImageMap.Find1 (aBaseTexture);
if (!anImageIdx.IsEmpty())
{
myWriter->Int (anImageIdx.IntegerValue());
}
}
myWriter->EndObject();
}
}
if (hasMaterial
|| aPbrMat.Metallic != 1.0f)
{
myWriter->Key ("metallicFactor");
myWriter->Double (aPbrMat.Metallic);
}
if (!aPbrMat.MetallicRoughnessTexture.IsNull()
&& myImageMap.IsBound1 (aPbrMat.MetallicRoughnessTexture))
{
myWriter->Key ("metallicRoughnessTexture");
myWriter->StartObject();
{
myWriter->Key ("index");
const TCollection_AsciiString& anImageIdx = myImageMap.Find1 (aPbrMat.MetallicRoughnessTexture);
if (!anImageIdx.IsEmpty())
{
myWriter->Int (anImageIdx.IntegerValue());
}
}
myWriter->EndObject();
}
if (hasMaterial
|| aPbrMat.Roughness != 1.0f)
{
myWriter->Key ("roughnessFactor");
myWriter->Double (aPbrMat.Roughness);
}
}
myWriter->EndObject();
if (theStyle.Material().IsNull()
|| theStyle.Material()->IsDoubleSided())
{
myWriter->Key ("doubleSided");
myWriter->Bool (true);
}
const Graphic3d_AlphaMode anAlphaMode = !theStyle.Material().IsNull() ? theStyle.Material()->AlphaMode() : Graphic3d_AlphaMode_BlendAuto;
switch (anAlphaMode)
{
case Graphic3d_AlphaMode_BlendAuto:
{
if (aPbrMat.BaseColor.Alpha() < 1.0f)
{
myWriter->Key ("alphaMode");
myWriter->String ("BLEND");
}
break;
}
case Graphic3d_AlphaMode_Opaque:
{
break;
}
case Graphic3d_AlphaMode_Mask:
{
myWriter->Key ("alphaMode");
myWriter->String ("MASK");
break;
}
case Graphic3d_AlphaMode_Blend:
{
myWriter->Key ("alphaMode");
myWriter->String ("BLEND");
break;
}
}
if (!theStyle.Material().IsNull()
&& theStyle.Material()->AlphaCutOff() != 0.5f)
{
myWriter->Key ("alphaCutoff");
myWriter->Double (theStyle.Material()->AlphaCutOff());
}
if (aPbrMat.EmissiveFactor != Graphic3d_Vec3 (0.0f, 0.0f, 0.0f))
{
myWriter->Key ("emissiveFactor");
myWriter->StartArray();
{
myWriter->Double (aPbrMat.EmissiveFactor.r());
myWriter->Double (aPbrMat.EmissiveFactor.g());
myWriter->Double (aPbrMat.EmissiveFactor.b());
}
myWriter->EndArray();
}
if (!aPbrMat.EmissiveTexture.IsNull()
&& myImageMap.IsBound1 (aPbrMat.EmissiveTexture))
{
myWriter->Key ("emissiveTexture");
myWriter->StartObject();
{
myWriter->Key ("index");
const TCollection_AsciiString& anImageIdx = myImageMap.Find1 (aPbrMat.EmissiveTexture);
if (!anImageIdx.IsEmpty())
{
myWriter->Int (anImageIdx.IntegerValue());
}
}
myWriter->EndObject();
}
if (!aPbrMat.NormalTexture.IsNull()
&& myImageMap.IsBound1 (aPbrMat.NormalTexture))
{
myWriter->Key ("normalTexture");
myWriter->StartObject();
{
myWriter->Key ("index");
const TCollection_AsciiString& anImageIdx = myImageMap.Find1 (aPbrMat.NormalTexture);
if (!anImageIdx.IsEmpty())
{
myWriter->Int (anImageIdx.IntegerValue());
}
}
myWriter->EndObject();
}
if (!aPbrMat.OcclusionTexture.IsNull()
&& myImageMap.IsBound1 (aPbrMat.OcclusionTexture))
{
myWriter->Key ("occlusionTexture");
myWriter->StartObject();
{
myWriter->Key ("index");
const TCollection_AsciiString& anImageIdx = myImageMap.Find1 (aPbrMat.OcclusionTexture);
if (!anImageIdx.IsEmpty())
{
myWriter->Int (anImageIdx.IntegerValue());
}
}
myWriter->EndObject();
}
}
myWriter->EndObject();
#else
(void )theStyle;
(void )theName;
#endif
}