37#include <Standard_Failure.hxx>
38#include <Standard_Handle.hxx>
39#include <Standard_Version.hxx>
41#include <XCAFDoc_DocumentTool.hxx>
42#include <XCAFDoc_ShapeTool.hxx>
43#include <XCAFDoc_ColorTool.hxx>
44#include <XCAFDoc_MaterialTool.hxx>
45#include <XCAFDoc_VisMaterialTool.hxx>
46#include <XCAFDoc_VisMaterialPBR.hxx>
47#include <TDocStd_Document.hxx>
48#include <TopoDS_Compound.hxx>
49#include <XCAFPrs_DocumentExplorer.hxx>
50#include <RWMesh_FaceIterator.hxx>
51#include <TDataStd_Name.hxx>
52#include <TDF_Tool.hxx>
54#include <BRepBndLib.hxx>
57#include <wx/mstream.h>
58#include <wx/datstrm.h>
63#define TRACE_MASK "U3D"
65#define MODEL_PARENT_BOARD_NAME "Board"
66#define MODEL_PARENT_COMPONENTS_NAME "Components"
93 constexpr uint32_t
MESH = 0x00000001;
94 constexpr uint32_t
LINE = 0x00000002;
95 constexpr uint32_t
POINT = 0x00000004;
96 constexpr uint32_t
GLYPH = 0x00000008;
123 if( !aLabel.IsNull() && aLabel.FindAttribute( TDataStd_Name::GetID(),
name ) )
125 TCollection_ExtendedString extstr =
name->Get();
126 char* str =
new char[extstr.LengthOfCString() + 1];
127 extstr.ToUTF8CString( str );
129 txt = wxString::FromUTF8( str );
141 case TopAbs_COMPOUND:
return "COMPOUND";
142 case TopAbs_COMPSOLID:
return "COMPSOLID";
143 case TopAbs_SOLID:
return "SOLID";
144 case TopAbs_SHELL:
return "SHELL";
145 case TopAbs_FACE:
return "FACE";
146 case TopAbs_WIRE:
return "WIRE";
147 case TopAbs_EDGE:
return "EDGE";
148 case TopAbs_VERTEX:
return "VERTEX";
149 case TopAbs_SHAPE:
return "SHAPE";
162static inline std::ostream&
operator<<( std::ostream& aOStream,
const Quantity_ColorRGBA& aColor )
164 Quantity_Color rgb = aColor.GetRGB();
174 Handle( XCAFDoc_ColorTool ) aColorTool,
const char* aPreMsg =
nullptr )
176 if( aLabel.IsNull() )
182 TCollection_AsciiString entry;
183 TDF_Tool::Entry( aLabel, entry );
184 std::ostringstream ss;
185 ss << aPreMsg << entry <<
", " <<
getLabelName( aLabel )
186 << ( aShapeTool->IsShape( aLabel ) ?
", shape" :
"" )
187 << ( aShapeTool->IsTopLevel( aLabel ) ?
", topLevel" :
"" )
188 << ( aShapeTool->IsFree( aLabel ) ?
", free" :
"" )
189 << ( aShapeTool->IsAssembly( aLabel ) ?
", assembly" :
"" )
190 << ( aShapeTool->IsSimpleShape( aLabel ) ?
", simple" :
"" )
191 << ( aShapeTool->IsCompound( aLabel ) ?
", compound" :
"" )
192 << ( aShapeTool->IsReference( aLabel ) ?
", reference" :
"" )
193 << ( aShapeTool->IsComponent( aLabel ) ?
", component" :
"" )
194 << ( aShapeTool->IsSubShape( aLabel ) ?
", subshape" :
"" );
196 if( aShapeTool->IsSubShape( aLabel ) )
198 auto shape = aShapeTool->GetShape( aLabel );
199 if( !shape.IsNull() )
203 if( aShapeTool->IsShape( aLabel ) )
205 Quantity_ColorRGBA c;
206 if( aColorTool->GetColor( aLabel, XCAFDoc_ColorGen, c ) )
208 if( aColorTool->GetColor( aLabel, XCAFDoc_ColorSurf, c ) )
210 if( aColorTool->GetColor( aLabel, XCAFDoc_ColorCurv, c ) )
227 Handle( XCAFDoc_ColorTool ) aColorTool,
int aDepth = 0 )
229 std::string indent( aDepth * 2,
' ' );
230 printLabel( aLabel, aShapeTool, aColorTool, indent.c_str() );
231 TDF_ChildIterator it;
232 for( it.Initialize( aLabel ); it.More(); it.Next() )
233 dumpLabels( it.Value(), aShapeTool, aColorTool, aDepth + 1 );
251 Handle( TDataStd_Name ) n;
256 mesh->
name = wxGetTranslation( c->GetDisplayName() );
260 if( label.FindAttribute( TDataStd_Name::GetID(), n ) )
262 mesh->
name = TCollection_AsciiString( n->Get() ).ToCString();
269 if( mesh->
name.empty() )
271 mesh->
name =
"NoName";
290 const Handle( XCAFDoc_ColorTool ) & colorTool,
291 const Handle( XCAFDoc_VisMaterialTool ) & visMatTool,
292 const gp_Trsf& cumulativeTransform,
293 const std::string& baseName,
294 std::unordered_map<Graphic3d_Vec4, MESH*>& meshesByColor )
299 if( shapeTool->IsAssembly( label ) || shapeTool->IsReference( label ) )
301 TDF_LabelSequence childrenOrComponents;
302 TDF_Label referencedLabel;
303 gp_Trsf currentTransform = cumulativeTransform;
304 bool isRef = shapeTool->IsReference( label );
308 if( shapeTool->GetReferredShape( label, referencedLabel ) )
310 if( cumulativeTransform.Form() == gp_Identity )
312 TopLoc_Location instanceLocation;
313 instanceLocation = shapeTool->GetLocation( label );
314 currentTransform = cumulativeTransform * instanceLocation.Transformation();
318 baseName, meshesByColor );
323 shapeTool->GetComponents( label, childrenOrComponents );
324 for( Standard_Integer i = 1; i <= childrenOrComponents.Length(); ++i )
326 TDF_Label compLabel = childrenOrComponents.Value( i );
327 TopLoc_Location compLocation;
328 gp_Trsf childTransform = currentTransform;
330 compLocation = shapeTool->GetLocation( compLabel );
331 childTransform = currentTransform * compLocation.Transformation();
338 else if( shapeTool->IsShape( label ) )
341 if( shapeTool->GetShape( label, shape ) && !shape.IsNull() )
344 location = shapeTool->GetLocation( label );
347 for( RWMesh_FaceIterator faceIter( label,
location,
true ); faceIter.More(); faceIter.Next() )
349 if( faceIter.IsEmptyMesh() )
352 Handle( Poly_Triangulation ) triangulation = faceIter.Triangulation();
353 if( triangulation.IsNull() )
356 Graphic3d_Vec4 aColorF = faceIter.FaceColor();
357 Graphic3d_Vec4 specularColor( 0.2f );
359 MESH* mesh =
nullptr;
360 auto it = meshesByColor.find( aColorF );
361 if( it == meshesByColor.end() )
363 auto newMesh = std::make_unique<MESH>();
364 newMesh->name = baseName +
"_" + std::to_string( meshesByColor.size() );
365 newMesh->parentName = baseName;
366 newMesh->diffuse_color = aColorF;
367 newMesh->specular_color = specularColor.rgb();
368 mesh = newMesh.get();
369 meshesByColor.emplace( aColorF, mesh );
370 m_meshes.emplace_back( std::move( newMesh ) );
377 uint32_t nodesExistingSum = mesh->
coords.size();
378 uint32_t numberTriangles = 0;
379 uint32_t numberNodes = 0;
381 const Standard_Integer aNodeUpper = faceIter.NodeUpper();
382 numberNodes += faceIter.NbNodes();
383 numberTriangles += faceIter.NbTriangles();
385 mesh->
coords.reserve( mesh->
coords.size() + numberNodes );
394 for( Standard_Integer aNodeIter = faceIter.NodeLower(); aNodeIter <= aNodeUpper; ++aNodeIter )
396 const gp_Dir aNormal = faceIter.NormalTransformed( aNodeIter );
397 gp_XYZ vertex = faceIter.NodeTransformed( aNodeIter ).XYZ();
399 mesh->
coords.emplace_back( vertex.X(), vertex.Y(), vertex.Z() );
402 mesh->
normals.emplace_back( aNormal.X(), aNormal.Y(), aNormal.Z() );
408 const Standard_Integer anElemLower = faceIter.ElemLower();
409 const Standard_Integer anElemUpper = faceIter.ElemUpper();
410 for( Standard_Integer anElemIter = anElemLower; anElemIter <= anElemUpper; ++anElemIter )
412 const Poly_Triangle aTri = faceIter.TriangleOriented( anElemIter );
414 Graphic3d_Vec3i vec =
415 Graphic3d_Vec3i( aTri( 1 ), aTri( 2 ), aTri( 3 ) ) - Graphic3d_Vec3i( anElemLower );
417 mesh->
coordIndices.emplace_back( vec.x() + nodesExistingSum );
418 mesh->
coordIndices.emplace_back( vec.y() + nodesExistingSum );
419 mesh->
coordIndices.emplace_back( vec.z() + nodesExistingSum );
423 mesh->
normalIndices.emplace_back( vec.x() + nodesExistingSum );
424 mesh->
normalIndices.emplace_back( vec.y() + nodesExistingSum );
425 mesh->
normalIndices.emplace_back( vec.z() + nodesExistingSum );
445 Handle( XCAFDoc_ShapeTool ) shapeTool = XCAFDoc_DocumentTool::ShapeTool( doc->Main() );
446 Handle( XCAFDoc_ColorTool ) colorTool = XCAFDoc_DocumentTool::ColorTool( doc->Main() );
447 Handle( XCAFDoc_VisMaterialTool ) visMatTool = XCAFDoc_DocumentTool::VisMaterialTool( doc->Main() );
449 if( shapeTool.IsNull() )
454 TDF_LabelSequence meshableLabels;
455 TDF_LabelSequence rootLabels;
456 shapeTool->GetFreeShapes( rootLabels );
462 std::function<void(
const TDF_Label& )> recurseFindKiCadElements;
463 recurseFindKiCadElements = [&](
const TDF_Label& label ) ->
void
468 meshableLabels.Append( label );
472 TDF_LabelSequence childrenOrComponents;
473 shapeTool->GetComponents( label, childrenOrComponents );
474 for( Standard_Integer i = 1; i <= childrenOrComponents.Length(); ++i )
475 recurseFindKiCadElements( childrenOrComponents.Value( i ) );
478 for( Standard_Integer i = 1; i <= rootLabels.Length(); ++i )
479 recurseFindKiCadElements( rootLabels.Value( i ) );
481 for( Standard_Integer i = 1; i <= meshableLabels.Length(); ++i )
483 TDF_Label meshLabel = meshableLabels.Value( i );
484 if( !( shapeTool->IsAssembly( meshLabel ) || shapeTool->IsShape( meshLabel ) ) )
487 std::string rootGroupName;
497 std::unique_ptr<MESH> dummyNameMesh = std::make_unique<MESH>();
498 getMeshName( meshLabel, shapeTool, dummyNameMesh.get() );
499 std::string topName = dummyNameMesh->name;
503 if( !rootGroupName.empty() && topName != rootGroupName )
505 PARENT_NODE pn; pn.
name = rootGroupName; pn.
mat = { 1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1 };
510 std::unordered_map<Graphic3d_Vec4, MESH*> meshesByColor;
511 gp_Trsf initialTransform;
513 topName, meshesByColor );
517 [](
const std::unique_ptr<MESH>& a,
const std::unique_ptr<MESH>& b )
519 return a->name < b->name;
536 for(
size_t i = 0; i < aMat.size(); i++ )
537 aBitStreamWriter.
WriteF32( aMat[i] );
545 uint32_t parentNodeCount = aParentNode ==
nullptr ? 0 : 1;
550 if( parentNodeCount > 0 )
563 const std::string& aParentNodeName,
564 const std::string& aModelResourceName,
565 const std::vector<float>& aMat )
570 uint32_t parentNodecount = aParentNodeName.empty() ? 0 : 1;
572 if( parentNodecount )
588 const std::string& aShaderName )
607 const MESH* aMesh,
const std::string& aMeshname )
628 const std::vector<GROUP_NODE>& aGroupNodes )
638 for(
const auto& groupNode : aGroupNodes )
640 const PARENT_NODE* parent = groupNode.parentNodes.empty() ? nullptr : &groupNode.parentNodes[0];
651 const std::string& aModelNodeName,
652 const std::string& aParentNodeName,
653 const std::string& aModelResourceName,
654 const std::string& aShaderName,
655 const std::vector<float>& aMat )
676 const uint32_t headerBlockSize = 36;
682 w.
WriteU32( headerBlockSize + aDeclSize );
683 w.
WriteU64( headerBlockSize + aDeclSize + aContSize );
695 const std::string& aMaterialName )
719 const Graphic3d_Vec4& aDiffuseColor,
720 const Graphic3d_Vec3& aSpecularColor )
752 const std::string& aMeshName )
772 uint32_t shadingAttributes = 0;
776 shadingAttributes |= 0x01;
781 shadingAttributes |= 0x02;
812 const std::string& aMeshname )
826 for(
size_t i = 0; i < aMesh->
coords.size(); i++ )
833 for(
size_t i = 0; i < aMesh->
normals.size(); i++ )
856 for(
size_t i = 0; i < aMesh->
coordIndices.size(); i += 3 )
859 for(
int j = 0; j < 3; j++ )
862 if( aMesh->
normals.size() > 0 )
883 const std::string& aLightResourceName )
902 const std::string& aLightResourceName )
904 std::vector<float> matrix = std::vector<float>{ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 6.f, -20.0f, 4.0f, 1.0f };
942 uint32_t dataSize = (uint32_t) ceil( aBlock->GetDataSize() / 4.0 );
943 uint32_t metaDataSize = (uint32_t) ceil( aBlock->GetMetaDataSize() / 4.0 );
946 uint32_t blockLength = ( 4 + 4 + 4 + 4 * ( dataSize + metaDataSize ) );
948 wxDataOutputStream workWriter( aStream );
950 workWriter.Write32( aBlock->GetBlockType() );
951 workWriter.Write32( aBlock->GetDataSize() );
952 workWriter.Write32( aBlock->GetMetaDataSize() );
953 for( uint32_t i = 0; i < dataSize; i++ )
955 workWriter.Write32( aBlock->GetData()[i] );
958 for( uint32_t i = 0; i < metaDataSize; i++ )
960 workWriter.Write32( aBlock->GetMetaData()[i] );
972 std::vector<float> matrix = { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 };
979 Standard_Real xMin, yMin, zMin, xMax, yMax, zMax;
982 Standard_Real centerX = ( xMin + xMax ) / 2.0;
983 Standard_Real centerY = ( yMin + yMax ) / 2.0;
984 Standard_Real centerZ = ( zMin + zMax ) / 2.0;
990 wxMemoryOutputStream decStream;
991 wxMemoryOutputStream contStream;
992 wxMemoryOutputStream outStream;
994 uint32_t decSize = 0;
995 uint32_t contSize = 0;
997 std::vector<GROUP_NODE> baseGroupNodes;
1002 std::vector<GROUP_NODE> allGroups = baseGroupNodes;
1009 if( mesh->IsEmpty() )
1012 std::string meshName =
"n_" + mesh->name;
1014 std::string modelResourceName =
"n_" + mesh->name;
1015 std::string matName =
"m_" + mesh->name;
1016 std::string shaderName =
"s_" + mesh->name;
1017 std::string modelModifierChainName =
"n_" + mesh->name;
1019 std::shared_ptr<DATA_BLOCK> block =
1020 getNodeModifierChain( meshName, mesh->name, mesh->parentName, modelResourceName, shaderName, matrix );
1039 wxStreamBuffer* buffer = outStream.GetOutputStreamBuffer();
1041 std::ofstream u3dFile(
m_filename, std::ios::binary );
1042 if( !u3dFile.is_open() )
1048 u3dFile.write(
static_cast<const char*
>( buffer->GetBufferStart() ), buffer->GetBufferSize() );
1050 wxStreamBuffer* decBuffer = decStream.GetOutputStreamBuffer();
1051 u3dFile.write(
static_cast<const char*
>( decBuffer->GetBufferStart() ),
1052 decBuffer->GetBufferSize() );
1054 wxStreamBuffer* contBuffer = contStream.GetOutputStreamBuffer();
1055 u3dFile.write(
static_cast<const char*
>( contBuffer->GetBufferStart() ),
1056 contBuffer->GetBufferSize() );
This is an internal KiCad use attribute to add additional markup to a opencascade document for intern...
static const Standard_GUID & GetID()
Get the GUID of this attribute.
Implements the bit stream writer functionality.
void WriteF64(double aValue)
void WriteU8(uint8_t aValue)
void WriteU16(uint16_t uValue)
void WriteU32(uint32_t uValue)
std::shared_ptr< DATA_BLOCK > GetDataBlock()
void WriteDataBlock(std::shared_ptr< DATA_BLOCK > b)
void WriteF32(float fValue)
void WriteString(const std::string &aStr)
void WriteU64(uint64_t uValue)
void WriteCompressedU32(uint32_t aContext, uint32_t uValue)
static const uint32_t StaticFull
Contexts greater than this are static contexts.
std::vector< uint32_t > normalIndices
Coordinate indices, maps vertex normal positions to triangles.
std::vector< uint32_t > specularColorIndices
Coordinate indices, maps each vertex to a specular color.
std::vector< VECTOR3D > normals
std::vector< Graphic3d_Vec4 > diffuse_colors
List of all unique diffuse colors.
std::vector< uint32_t > coordIndices
Coordinate indices, maps vertex positions to triangles.
std::vector< uint32_t > diffuseColorIndices
Coordinate indices, maps each vertex to a diffuse color.
std::string name
The name of the mesh, this will be visible in U3D viewers.
std::vector< VECTOR3D > coords
std::vector< Graphic3d_Vec4 > specular_colors
List of all unique specular colors.
std::vector< GROUP_NODE > m_groupNodes
std::shared_ptr< DATA_BLOCK > getHeaderBlock(uint32_t aDeclSize, uint32_t aContSize)
std::shared_ptr< DATA_BLOCK > getShadingModifierBlock(const std::string &aShadingModName, const std::string &aShaderName)
std::shared_ptr< DATA_BLOCK > getLitTextureShaderBlock(const std::string &aShaderName, const std::string &aMaterialName)
void writeMatrix(BIT_STREAM_WRITER &aBitStreamWriter, const std::vector< float > &aMat)
bool Perform(const Handle(TDocStd_Document) &aDocument)
std::shared_ptr< DATA_BLOCK > getModelNodeBlock(const std::string &aModelNodeName, const std::string &aParentNodeName, const std::string &aModelResourceName, const std::vector< float > &aMat)
void getMeshName(const TDF_Label &label, Handle(XCAFDoc_ShapeTool) shapeTool, MESH *mesh)
WRITER(const std::string &aFilename)
const uint32_t m_contextBaseShadingID
std::shared_ptr< DATA_BLOCK > getMeshContinuationBlock(const MESH *aMesh, const std::string &aMeshName)
void generateMeshesByAssembly(const Handle(TDocStd_Document) &doc)
std::shared_ptr< DATA_BLOCK > getLightNodeBlock(const std::string &aLightNodeName, const std::string &aLightResourceName)
std::shared_ptr< DATA_BLOCK > getModelResourceModifierChain(const std::string &aModifierChainName, const MESH *aMesh, const std::string &aMeshname)
std::shared_ptr< DATA_BLOCK > getMaterialResourceBlock(const std::string &aMaterialName, const Graphic3d_Vec4 &aDiffuseColor, const Graphic3d_Vec3 &aSpecularColor)
std::shared_ptr< DATA_BLOCK > getGroupNodeModifierChain(const std::string &aModifierChainName, const std::vector< GROUP_NODE > &aGroupNodes)
std::vector< std::unique_ptr< MESH > > m_meshes
std::shared_ptr< DATA_BLOCK > getLightModifierChain(const std::string &aModifierChainName, const std::string &aLightResourceName)
void collectGeometryRecursive(const TDF_Label &label, const Handle(XCAFDoc_ShapeTool) &shapeTool, const Handle(XCAFDoc_ColorTool) &colorTool, const Handle(XCAFDoc_VisMaterialTool) &visMatTool, const gp_Trsf &cumulativeTransform, const std::string &baseName, std::unordered_map< Graphic3d_Vec4, MESH * > &meshesByColor)
std::shared_ptr< DATA_BLOCK > getLightResourceBlock(const std::string &aLightResourceName)
uint32_t writeDataBlock(std::shared_ptr< DATA_BLOCK > b, wxMemoryOutputStream &aStream)
std::map< std::string, int > m_meshDedupMap
std::shared_ptr< DATA_BLOCK > getNodeModifierChain(const std::string &aModifierChainName, const std::string &aModelNodeName, const std::string &aParentNodeName, const std::string &aModelResourceName, const std::string &aShaderName, const std::vector< float > &aMat)
std::shared_ptr< DATA_BLOCK > getGroupNodeBlock(const std::string &aGroupNodeName, const PARENT_NODE *aParentNode)
Bnd_Box m_meshBoundingBox
std::shared_ptr< DATA_BLOCK > getMeshDeclarationBlock(const MESH *aMesh, const std::string &aMeshName)
Handle(KICAD3D_INFO) KICAD3D_INFO
constexpr uint32_t LIGHTING_ENABLED
constexpr uint32_t USE_VERTEX_COLOR
constexpr uint32_t ALPHA_TEST_ENABLED
constexpr uint32_t EMISSIVE
constexpr uint32_t REFLECTIVITY
constexpr uint32_t DIFFUSE
constexpr uint32_t SPECULAR
constexpr uint32_t AMBIENT
constexpr uint32_t OPACITY
constexpr uint32_t MODIFIER_CHAIN
constexpr uint32_t MESH_DECLARATION
constexpr uint32_t MATERIAL_RESOURCE
constexpr uint32_t MESH_CONTINUATION
constexpr uint32_t LIGHT_NODE
constexpr uint32_t GROUP_NODE
constexpr uint32_t SHADING_MODIFIER
constexpr uint32_t LIGHT_RESOURCE
constexpr uint32_t MODEL_NODE
constexpr uint32_t LIT_TEXTURE_SHADER
constexpr uint32_t FILE_HEADER
std::vector< PARENT_NODE > parentNodes
List of parent nodes this group node belongs to.
std::string name
Name of this group node.
std::vector< float > mat
Transform matrix, 4x4, row major.
std::string name
Name of the parent node to link to.
VECTOR3< double > VECTOR3D
static bool isLabelABoardMesh(const TDF_Label &aLabel)
#define MODEL_PARENT_BOARD_NAME
static int colorFloatToDecimal(float aVal)
std::string getShapeName(TopAbs_ShapeEnum aShape)
static void printLabel(TDF_Label aLabel, Handle(XCAFDoc_ShapeTool) aShapeTool, Handle(XCAFDoc_ColorTool) aColorTool, const char *aPreMsg=nullptr)
static void dumpLabels(TDF_Label aLabel, Handle(XCAFDoc_ShapeTool) aShapeTool, Handle(XCAFDoc_ColorTool) aColorTool, int aDepth=0)
Dumps a label and the entire tree underneath it.
#define MODEL_PARENT_COMPONENTS_NAME
static std::ostream & operator<<(std::ostream &aOStream, const Quantity_ColorRGBA &aColor)
static wxString getLabelName(const TDF_Label &aLabel)