33#include <Standard_Failure.hxx>
34#include <Standard_Handle.hxx>
35#include <Standard_Version.hxx>
37#include <XCAFDoc_DocumentTool.hxx>
38#include <XCAFDoc_ShapeTool.hxx>
39#include <XCAFDoc_ColorTool.hxx>
40#include <XCAFDoc_MaterialTool.hxx>
41#include <XCAFDoc_VisMaterialTool.hxx>
42#include <XCAFDoc_VisMaterialPBR.hxx>
43#include <TDocStd_Document.hxx>
44#include <TopoDS_Compound.hxx>
45#include <XCAFPrs_DocumentExplorer.hxx>
46#include <RWMesh_FaceIterator.hxx>
47#include <TDataStd_Name.hxx>
48#include <TDF_Tool.hxx>
50#include <BRepBndLib.hxx>
53#include <wx/mstream.h>
54#include <wx/datstrm.h>
59#define TRACE_MASK "U3D"
61#define MODEL_PARENT_BOARD_NAME "Board"
62#define MODEL_PARENT_COMPONENTS_NAME "Components"
89 constexpr uint32_t
MESH = 0x00000001;
90 constexpr uint32_t
LINE = 0x00000002;
91 constexpr uint32_t
POINT = 0x00000004;
92 constexpr uint32_t
GLYPH = 0x00000008;
106 [[maybe_unused]]
constexpr uint32_t
AMBIENT = 0x00000001;
109 [[maybe_unused]]
constexpr uint32_t
EMISSIVE = 0x00000008;
119 if( !aLabel.IsNull() && aLabel.FindAttribute( TDataStd_Name::GetID(),
name ) )
121 TCollection_ExtendedString extstr =
name->Get();
122 char* str =
new char[extstr.LengthOfCString() + 1];
123 extstr.ToUTF8CString( str );
125 txt = wxString::FromUTF8( str );
137 case TopAbs_COMPOUND:
return "COMPOUND";
138 case TopAbs_COMPSOLID:
return "COMPSOLID";
139 case TopAbs_SOLID:
return "SOLID";
140 case TopAbs_SHELL:
return "SHELL";
141 case TopAbs_FACE:
return "FACE";
142 case TopAbs_WIRE:
return "WIRE";
143 case TopAbs_EDGE:
return "EDGE";
144 case TopAbs_VERTEX:
return "VERTEX";
145 case TopAbs_SHAPE:
return "SHAPE";
158static inline std::ostream&
operator<<( std::ostream& aOStream,
const Quantity_ColorRGBA& aColor )
160 Quantity_Color rgb = aColor.GetRGB();
170 Handle( XCAFDoc_ColorTool ) aColorTool,
const char* aPreMsg =
nullptr )
172 if( aLabel.IsNull() )
178 TCollection_AsciiString entry;
179 TDF_Tool::Entry( aLabel, entry );
180 std::ostringstream ss;
181 ss << aPreMsg << entry <<
", " <<
getLabelName( aLabel )
182 << ( aShapeTool->IsShape( aLabel ) ?
", shape" :
"" )
183 << ( aShapeTool->IsTopLevel( aLabel ) ?
", topLevel" :
"" )
184 << ( aShapeTool->IsFree( aLabel ) ?
", free" :
"" )
185 << ( aShapeTool->IsAssembly( aLabel ) ?
", assembly" :
"" )
186 << ( aShapeTool->IsSimpleShape( aLabel ) ?
", simple" :
"" )
187 << ( aShapeTool->IsCompound( aLabel ) ?
", compound" :
"" )
188 << ( aShapeTool->IsReference( aLabel ) ?
", reference" :
"" )
189 << ( aShapeTool->IsComponent( aLabel ) ?
", component" :
"" )
190 << ( aShapeTool->IsSubShape( aLabel ) ?
", subshape" :
"" );
192 if( aShapeTool->IsSubShape( aLabel ) )
194 auto shape = aShapeTool->GetShape( aLabel );
195 if( !shape.IsNull() )
199 if( aShapeTool->IsShape( aLabel ) )
201 Quantity_ColorRGBA c;
202 if( aColorTool->GetColor( aLabel, XCAFDoc_ColorGen, c ) )
204 if( aColorTool->GetColor( aLabel, XCAFDoc_ColorSurf, c ) )
206 if( aColorTool->GetColor( aLabel, XCAFDoc_ColorCurv, c ) )
222[[maybe_unused]]
static void dumpLabels( TDF_Label aLabel,
Handle( XCAFDoc_ShapeTool ) aShapeTool,
223 Handle( XCAFDoc_ColorTool ) aColorTool,
int aDepth = 0 )
225 std::string indent( aDepth * 2,
' ' );
226 printLabel( aLabel, aShapeTool, aColorTool, indent.c_str() );
227 TDF_ChildIterator it;
228 for( it.Initialize( aLabel ); it.More(); it.Next() )
229 dumpLabels( it.Value(), aShapeTool, aColorTool, aDepth + 1 );
247 Handle( TDataStd_Name ) n;
252 mesh->
name = wxGetTranslation( c->GetDisplayName() );
256 if( label.FindAttribute( TDataStd_Name::GetID(), n ) )
258 mesh->
name = TCollection_AsciiString( n->Get() ).ToCString();
265 if( mesh->
name.empty() )
267 mesh->
name =
"NoName";
286 const Handle( XCAFDoc_ColorTool ) & colorTool,
287 const Handle( XCAFDoc_VisMaterialTool ) & visMatTool,
288 const gp_Trsf& cumulativeTransform,
289 const std::string& baseName,
290 std::unordered_map<NCollection_Vec4<float>,
MESH*>& meshesByColor )
295 if( shapeTool->IsAssembly( label ) || shapeTool->IsReference( label ) )
297 NCollection_Sequence<TDF_Label> childrenOrComponents;
298 TDF_Label referencedLabel;
299 gp_Trsf currentTransform = cumulativeTransform;
300 bool isRef = shapeTool->IsReference( label );
304 if( shapeTool->GetReferredShape( label, referencedLabel ) )
306 if( cumulativeTransform.Form() == gp_Identity )
308 TopLoc_Location instanceLocation;
309 instanceLocation = shapeTool->GetLocation( label );
310 currentTransform = cumulativeTransform * instanceLocation.Transformation();
314 baseName, meshesByColor );
319 shapeTool->GetComponents( label, childrenOrComponents );
320 for(
int i = 1; i <= childrenOrComponents.Length(); ++i )
322 TDF_Label compLabel = childrenOrComponents.Value( i );
323 TopLoc_Location compLocation;
324 gp_Trsf childTransform = currentTransform;
326 compLocation = shapeTool->GetLocation( compLabel );
327 childTransform = currentTransform * compLocation.Transformation();
334 else if( shapeTool->IsShape( label ) )
337 if( shapeTool->GetShape( label, shape ) && !shape.IsNull() )
340 location = shapeTool->GetLocation( label );
343 for( RWMesh_FaceIterator faceIter( label,
location,
true ); faceIter.More(); faceIter.Next() )
345 if( faceIter.IsEmptyMesh() )
348 Handle( Poly_Triangulation ) triangulation = faceIter.Triangulation();
349 if( triangulation.IsNull() )
352 NCollection_Vec4<float> aColorF = faceIter.FaceColor();
353 NCollection_Vec4<float> specularColor( 0.2f );
355 MESH* mesh =
nullptr;
356 auto it = meshesByColor.find( aColorF );
357 if( it == meshesByColor.end() )
359 auto newMesh = std::make_unique<MESH>();
360 newMesh->name = baseName +
"_" + std::to_string( meshesByColor.size() );
361 newMesh->parentName = baseName;
362 newMesh->diffuse_color = aColorF;
363 newMesh->specular_color = specularColor.rgb();
364 mesh = newMesh.get();
365 meshesByColor.emplace( aColorF, mesh );
366 m_meshes.emplace_back( std::move( newMesh ) );
373 uint32_t nodesExistingSum = mesh->
coords.size();
374 uint32_t numberTriangles = 0;
375 uint32_t numberNodes = 0;
377 const int aNodeUpper = faceIter.NodeUpper();
378 numberNodes += faceIter.NbNodes();
379 numberTriangles += faceIter.NbTriangles();
381 mesh->
coords.reserve( mesh->
coords.size() + numberNodes );
390 for(
int aNodeIter = faceIter.NodeLower(); aNodeIter <= aNodeUpper; ++aNodeIter )
392 const gp_Dir aNormal = faceIter.NormalTransformed( aNodeIter );
393 gp_XYZ vertex = faceIter.NodeTransformed( aNodeIter ).XYZ();
395 mesh->
coords.emplace_back( vertex.X(), vertex.Y(), vertex.Z() );
398 mesh->
normals.emplace_back( aNormal.X(), aNormal.Y(), aNormal.Z() );
404 const int anElemLower = faceIter.ElemLower();
405 const int anElemUpper = faceIter.ElemUpper();
406 for(
int anElemIter = anElemLower; anElemIter <= anElemUpper; ++anElemIter )
408 const Poly_Triangle aTri = faceIter.TriangleOriented( anElemIter );
410 NCollection_Vec3<int> vec =
411 NCollection_Vec3<int>( aTri( 1 ), aTri( 2 ), aTri( 3 ) ) - NCollection_Vec3<int>( anElemLower );
413 mesh->
coordIndices.emplace_back( vec.x() + nodesExistingSum );
414 mesh->
coordIndices.emplace_back( vec.y() + nodesExistingSum );
415 mesh->
coordIndices.emplace_back( vec.z() + nodesExistingSum );
419 mesh->
normalIndices.emplace_back( vec.x() + nodesExistingSum );
420 mesh->
normalIndices.emplace_back( vec.y() + nodesExistingSum );
421 mesh->
normalIndices.emplace_back( vec.z() + nodesExistingSum );
441 Handle( XCAFDoc_ShapeTool ) shapeTool = XCAFDoc_DocumentTool::ShapeTool( doc->Main() );
442 Handle( XCAFDoc_ColorTool ) colorTool = XCAFDoc_DocumentTool::ColorTool( doc->Main() );
443 Handle( XCAFDoc_VisMaterialTool ) visMatTool = XCAFDoc_DocumentTool::VisMaterialTool( doc->Main() );
445 if( shapeTool.IsNull() )
450 NCollection_Sequence<TDF_Label> meshableLabels;
451 NCollection_Sequence<TDF_Label> rootLabels;
452 shapeTool->GetFreeShapes( rootLabels );
458 std::function<void(
const TDF_Label& )> recurseFindKiCadElements;
459 recurseFindKiCadElements = [&](
const TDF_Label& label ) ->
void
464 meshableLabels.Append( label );
468 NCollection_Sequence<TDF_Label> childrenOrComponents;
469 shapeTool->GetComponents( label, childrenOrComponents );
470 for(
int i = 1; i <= childrenOrComponents.Length(); ++i )
471 recurseFindKiCadElements( childrenOrComponents.Value( i ) );
474 for(
int i = 1; i <= rootLabels.Length(); ++i )
475 recurseFindKiCadElements( rootLabels.Value( i ) );
477 for(
int i = 1; i <= meshableLabels.Length(); ++i )
479 TDF_Label meshLabel = meshableLabels.Value( i );
480 if( !( shapeTool->IsAssembly( meshLabel ) || shapeTool->IsShape( meshLabel ) ) )
483 std::string rootGroupName;
493 std::unique_ptr<MESH> dummyNameMesh = std::make_unique<MESH>();
494 getMeshName( meshLabel, shapeTool, dummyNameMesh.get() );
495 std::string topName = dummyNameMesh->name;
499 if( !rootGroupName.empty() && topName != rootGroupName )
501 PARENT_NODE pn; pn.
name = rootGroupName; pn.
mat = { 1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1 };
506 std::unordered_map<NCollection_Vec4<float>,
MESH*> meshesByColor;
507 gp_Trsf initialTransform;
509 topName, meshesByColor );
513 [](
const std::unique_ptr<MESH>& a,
const std::unique_ptr<MESH>& b )
515 return a->name < b->name;
532 for(
size_t i = 0; i < aMat.size(); i++ )
533 aBitStreamWriter.
WriteF32( aMat[i] );
541 uint32_t parentNodeCount = aParentNode ==
nullptr ? 0 : 1;
546 if( parentNodeCount > 0 )
559 const std::string& aParentNodeName,
560 const std::string& aModelResourceName,
561 const std::vector<float>& aMat )
566 uint32_t parentNodecount = aParentNodeName.empty() ? 0 : 1;
568 if( parentNodecount )
584 const std::string& aShaderName )
603 const MESH* aMesh,
const std::string& aMeshname )
624 const std::vector<GROUP_NODE>& aGroupNodes )
634 for(
const auto& groupNode : aGroupNodes )
636 const PARENT_NODE* parent = groupNode.parentNodes.empty() ? nullptr : &groupNode.parentNodes[0];
647 const std::string& aModelNodeName,
648 const std::string& aParentNodeName,
649 const std::string& aModelResourceName,
650 const std::string& aShaderName,
651 const std::vector<float>& aMat )
672 const uint32_t headerBlockSize = 36;
678 w.
WriteU32( headerBlockSize + aDeclSize );
679 w.
WriteU64( headerBlockSize + aDeclSize + aContSize );
691 const std::string& aMaterialName )
715 const NCollection_Vec4<float>& aDiffuseColor,
716 const NCollection_Vec3<float>& aSpecularColor )
748 const std::string& aMeshName )
768 uint32_t shadingAttributes = 0;
772 shadingAttributes |= 0x01;
777 shadingAttributes |= 0x02;
808 const std::string& aMeshname )
822 for(
size_t i = 0; i < aMesh->
coords.size(); i++ )
829 for(
size_t i = 0; i < aMesh->
normals.size(); i++ )
852 for(
size_t i = 0; i < aMesh->
coordIndices.size(); i += 3 )
855 for(
int j = 0; j < 3; j++ )
858 if( aMesh->
normals.size() > 0 )
879 const std::string& aLightResourceName )
898 const std::string& aLightResourceName )
900 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 };
938 uint32_t dataSize = (uint32_t) ceil( aBlock->GetDataSize() / 4.0 );
939 uint32_t metaDataSize = (uint32_t) ceil( aBlock->GetMetaDataSize() / 4.0 );
942 uint32_t blockLength = ( 4 + 4 + 4 + 4 * ( dataSize + metaDataSize ) );
944 wxDataOutputStream workWriter( aStream );
946 workWriter.Write32( aBlock->GetBlockType() );
947 workWriter.Write32( aBlock->GetDataSize() );
948 workWriter.Write32( aBlock->GetMetaDataSize() );
949 for( uint32_t i = 0; i < dataSize; i++ )
951 workWriter.Write32( aBlock->GetData()[i] );
954 for( uint32_t i = 0; i < metaDataSize; i++ )
956 workWriter.Write32( aBlock->GetMetaData()[i] );
968 std::vector<float> matrix = { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 };
975 double xMin, yMin, zMin, xMax, yMax, zMax;
978 double centerX = ( xMin + xMax ) / 2.0;
979 double centerY = ( yMin + yMax ) / 2.0;
980 double centerZ = ( zMin + zMax ) / 2.0;
986 wxMemoryOutputStream decStream;
987 wxMemoryOutputStream contStream;
988 wxMemoryOutputStream outStream;
990 uint32_t decSize = 0;
991 uint32_t contSize = 0;
993 std::vector<GROUP_NODE> baseGroupNodes;
998 std::vector<GROUP_NODE> allGroups = baseGroupNodes;
1003 for(
const std::unique_ptr<MESH>& mesh :
m_meshes )
1005 if( mesh->IsEmpty() )
1008 std::string meshName =
"n_" + mesh->name;
1010 std::string modelResourceName =
"n_" + mesh->name;
1011 std::string matName =
"m_" + mesh->name;
1012 std::string shaderName =
"s_" + mesh->name;
1013 std::string modelModifierChainName =
"n_" + mesh->name;
1016 modelResourceName, shaderName, matrix ),
1033 wxStreamBuffer* buffer = outStream.GetOutputStreamBuffer();
1035 std::ofstream u3dFile(
m_filename, std::ios::binary );
1037 if( !u3dFile.is_open() )
1043 u3dFile.write(
static_cast<const char*
>( buffer->GetBufferStart() ), buffer->GetBufferSize() );
1045 wxStreamBuffer* decBuffer = decStream.GetOutputStreamBuffer();
1046 u3dFile.write(
static_cast<const char*
>( decBuffer->GetBufferStart() ), decBuffer->GetBufferSize() );
1048 wxStreamBuffer* contBuffer = contStream.GetOutputStreamBuffer();
1049 u3dFile.write(
static_cast<const char*
>( contBuffer->GetBufferStart() ), 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< NCollection_Vec4< float > > diffuse_colors
List of all unique diffuse colors.
std::vector< uint32_t > coordIndices
Coordinate indices, maps vertex positions to triangles.
std::vector< NCollection_Vec4< float > > specular_colors
List of all unique specular colors.
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< 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)
std::shared_ptr< DATA_BLOCK > getMaterialResourceBlock(const std::string &aMaterialName, const NCollection_Vec4< float > &aDiffuseColor, const NCollection_Vec3< float > &aSpecularColor)
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 > 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)
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
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< NCollection_Vec4< float >, MESH * > &meshesByColor)
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)