17
17
#include " ../base/property.h"
18
18
#include " ../base/string_conv.h"
19
19
#include " ../base/task_progress.h"
20
+ #include " ../base/tkernel_utils.h"
20
21
#include " ../base/xcaf.h"
21
22
22
23
#include < assimp/scene.h>
29
30
#include < cassert>
30
31
#include < iostream>
31
32
33
+ #include < gp_Quaternion.hxx>
32
34
#include < gp_Trsf.hxx>
33
35
#include < BRep_Builder.hxx>
34
36
#include < Image_Texture.hxx>
@@ -52,21 +54,11 @@ struct AssimpReaderI18N {
52
54
// Retrieve the scaling component in assimp matrix 'trsf'
53
55
aiVector3D aiMatrixScaling (const aiMatrix4x4& trsf)
54
56
{
55
- const ai_real scalingX = aiVector3D (trsf.a1 , trsf.a2 , trsf.a3 ).Length ();
56
- const ai_real scalingY = aiVector3D (trsf.b1 , trsf.b2 , trsf.b3 ).Length ();
57
- const ai_real scalingZ = aiVector3D (trsf.c1 , trsf.c2 , trsf.c3 ).Length ();
58
- return aiVector3D (scalingX, scalingY, scalingZ);
59
- }
60
-
61
- bool hasScaleFactor (const gp_Trsf& trsf)
62
- {
63
- const double topLocationScalePrec =
64
- #if OCC_VERSION_HEX >= OCC_VERSION_CHECK(7, 6, 0)
65
- TopLoc_Location::ScalePrec ();
66
- #else
67
- 1 .e -14 ;
68
- #endif
69
- return (Abs (Abs (trsf.ScaleFactor ()) - 1 .) > topLocationScalePrec) || trsf.IsNegative ();
57
+ aiVector3D scaling;
58
+ aiQuaternion rotation;
59
+ aiVector3D position;
60
+ trsf.Decompose (scaling, rotation, position);
61
+ return scaling;
70
62
}
71
63
72
64
bool hasScaleFactor (const aiVector3D& scaling)
@@ -78,54 +70,142 @@ bool hasScaleFactor(const aiVector3D& scaling)
78
70
);
79
71
}
80
72
81
- [[maybe_unused]] bool hasScaleFactor (const aiMatrix4x4& trsf)
73
+ // Visit each node in Assimp tree and call 'fnCallback'
74
+ void deep_aiNodeVisit (
75
+ const aiNode* node,
76
+ const std::function<void (const aiNode*)>& fnPreCallback,
77
+ const std::function<void(const aiNode*)>& fnPostCallback = nullptr
78
+ )
82
79
{
83
- const aiVector3D scaling = aiMatrixScaling (trsf);
84
- return hasScaleFactor (scaling);
80
+ if (fnPreCallback)
81
+ fnPreCallback (node);
82
+
83
+ for (unsigned ichild = 0 ; ichild < node->mNumChildren ; ++ichild)
84
+ deep_aiNodeVisit (node->mChildren [ichild], fnPreCallback, fnPostCallback);
85
+
86
+ if (fnPostCallback)
87
+ fnPostCallback (node);
85
88
}
86
89
87
90
// Check if Assimp tree from 'node' contains a transformation having scale
88
91
bool deep_aiNodeTransformationHasScaling (const aiNode* node)
89
92
{
90
- const aiVector3D scaling = aiMatrixScaling (node->mTransformation );
91
- if (!MathUtils::fuzzyEqual (scaling.x , 1 )
92
- || !MathUtils::fuzzyEqual (scaling.y , 1 )
93
- || !MathUtils::fuzzyEqual (scaling.z , 1 )
94
- || scaling.x < 0 . || scaling.y < 0 . || scaling.z < 0 .
95
- )
96
- {
97
- // std::cout << "[TRACE] hasScaling: " << scaling.x << " " << scaling.y << " " << scaling.z << std::endl;
98
- return true ;
93
+ bool hasScaling = false ;
94
+ deep_aiNodeVisit (node, [&](const aiNode* node) {
95
+ if (!hasScaling) {
96
+ const aiVector3D scaling = aiMatrixScaling (node->mTransformation );
97
+ hasScaling =
98
+ !MathUtils::fuzzyEqual (scaling.x , 1 )
99
+ || !MathUtils::fuzzyEqual (scaling.y , 1 )
100
+ || !MathUtils::fuzzyEqual (scaling.z , 1 )
101
+ || scaling.x < 0 . || scaling.y < 0 . || scaling.z < 0 .
102
+ ;
103
+ }
104
+ });
105
+
106
+ return hasScaling;
107
+ }
108
+
109
+ void deep_aiScenePrint (std::ostream& outs, const aiScene* scene)
110
+ {
111
+ auto fnIndent = [](std::ostream& outs, int depth) -> std::ostream& {
112
+ for (int i = 0 ; i < depth * 4 ; ++i)
113
+ outs << ' ' ;
114
+ return outs;
115
+ };
116
+
117
+ outs << " #animation: " << scene->mNumAnimations << std::endl;
118
+ outs << " #camera: " << scene->mNumCameras << std::endl;
119
+ outs << " #light: " << scene->mNumLights << std::endl;
120
+ outs << " #mesh: " << scene->mNumMeshes << std::endl;
121
+ outs << " #material: " << scene->mNumMaterials << std::endl;
122
+ outs << " #skeleton: " << scene->mNumSkeletons << std::endl;
123
+ outs << " #texture: " << scene->mNumTextures << std::endl;
124
+ outs << std::endl;
125
+
126
+ for (unsigned ianim = 0 ; ianim < scene->mNumAnimations ; ++ianim) {
127
+ const aiAnimation* anim = scene->mAnimations [ianim];
128
+ outs << " Animation" << ianim << std::endl;
129
+ outs << " name: '" << anim->mName .C_Str () << " '\n " ;
130
+ outs << " duration: " << anim->mDuration << " \n " ;
131
+ outs << " ticksPerSecond: " << anim->mTicksPerSecond << " \n " ;
132
+ outs << " #channel: " << anim->mNumChannels << " \n " ;
133
+ outs << " #meshChannel: " << anim->mNumMeshChannels << " \n " ;
134
+ outs << " #morphMeshChannel: " << anim->mNumMorphMeshChannels << " \n " ;
135
+ for (unsigned ichannel = 0 ; ichannel < anim->mNumChannels ; ++ichannel) {
136
+ const aiNodeAnim* iNodeAnim = anim->mChannels [ichannel];
137
+ outs << " NodeAnim" << ichannel << " \n " ;
138
+ outs << " nodeName: '" << iNodeAnim->mNodeName .C_Str () << " '\n " ;
139
+ outs << " #posKey: " << iNodeAnim->mNumPositionKeys << " \n " ;
140
+ outs << " #rotKey: " << iNodeAnim->mNumRotationKeys << " \n " ;
141
+ outs << " #scaleKey: " << iNodeAnim->mNumScalingKeys << " \n " ;
142
+ #if 0
143
+ outs << " ScalingKeys" << "\n";
144
+ for (unsigned iKey = 0; iKey < iNodeAnim->mNumScalingKeys; ++iKey) {
145
+ const aiVector3D& vec = iNodeAnim->mScalingKeys[iKey].mValue;
146
+ outs << " " << vec.x << ", " << vec.y << ", " << vec.z << "\n";
147
+ }
148
+ #endif
149
+ }
150
+
151
+ outs << std::endl;
99
152
}
100
153
101
- for (unsigned ichild = 0 ; ichild < node->mNumChildren ; ++ichild) {
102
- if (deep_aiNodeTransformationHasScaling (node->mChildren [ichild]))
103
- return true ;
154
+ for (unsigned imesh = 0 ; imesh < scene->mNumMeshes ; ++imesh) {
155
+ const aiMesh* mesh = scene->mMeshes [imesh];
156
+ outs << " Mesh" << imesh << " \n "
157
+ << " name: '" << mesh->mName .C_Str () << " '\n "
158
+ << " materialid: " << mesh->mMaterialIndex << " \n "
159
+ << " #vert: " << mesh->mNumVertices << " \n "
160
+ << " #face: " << mesh->mNumFaces << " \n "
161
+ << " #bone: " << mesh->mNumBones << " \n " ;
162
+ for (unsigned ibone = 0 ; ibone < mesh->mNumBones ; ++ibone) {
163
+ const aiBone* bone = mesh->mBones [ibone];
164
+ outs << " Bone" << ibone << " \n "
165
+ << " name: '" << bone->mName .C_Str () << " '\n "
166
+ << " #weight: " << bone->mNumWeights
167
+ << " \n " ;
168
+ }
104
169
}
105
170
106
- return false ;
107
- }
171
+ outs << " \n Scene graph:\n " ;
172
+ int nodeDepth = 0 ;
173
+ deep_aiNodeVisit (
174
+ scene->mRootNode ,
175
+ [&](const aiNode* node) {
176
+ fnIndent (outs, nodeDepth);
177
+ outs << node->mName .C_Str () << " {" ;
178
+ if (node->mNumMeshes )
179
+ outs << " #mesh:" << node->mNumMeshes << " " ;
180
+
181
+ if (node->mNumChildren )
182
+ outs << " #child:" << node->mNumChildren ;
183
+
184
+ outs << " }\n " ;
185
+ if (node->mMetaData ) {
186
+ fnIndent (outs, nodeDepth) << " " ;
187
+ outs << " ->metada " << " #prop:" << node->mMetaData ->mNumProperties ;
188
+ for (unsigned ikey = 0 ; ikey < node->mMetaData ->mNumProperties ; ++ikey) {
189
+ outs << " key:'" << node->mMetaData ->mKeys [ikey].C_Str () << " '" ;
190
+ }
191
+
192
+ outs << " \n " ;
193
+ }
108
194
109
- // Visit each node in Assimp tree and call 'fnCallback'
110
- void deep_aiNodeVisit ( const aiNode* node, const std::function< void ( const aiNode*)>& fnCallback)
111
- {
112
- fnCallback (node);
113
- for ( unsigned ichild = 0 ; ichild < node->mNumChildren ; ++ichild)
114
- deep_aiNodeVisit (node-> mChildren [ichild], fnCallback) ;
115
- }
195
+ for ( unsigned imesh = 0 ; imesh < node-> mNumMeshes ; ++imesh) {
196
+ const aiMesh* mesh = scene-> mMeshes [node-> mMeshes [imesh]];
197
+ fnIndent (outs, nodeDepth) << " " ;
198
+ outs << " ->mesh " << imesh << " ' " << mesh-> mName . C_Str () << " ' "
199
+ << " meshid: " << node->mMeshes [imesh]
200
+ << " \n " ;
201
+ }
116
202
117
- // Returns the OpenCascade transformation converted from assimp matrix
118
- gp_Trsf toOccTrsf (const aiMatrix4x4& matrix)
119
- {
120
- // TODO Check scaling != 0
121
- const aiVector3D scaling = aiMatrixScaling (matrix);
122
- gp_Trsf trsf;
123
- trsf.SetValues (
124
- matrix.a1 / scaling.x , matrix.a2 / scaling.x , matrix.a3 / scaling.x , matrix.a4 ,
125
- matrix.b1 / scaling.y , matrix.b2 / scaling.y , matrix.b3 / scaling.y , matrix.b4 ,
126
- matrix.c1 / scaling.z , matrix.c2 / scaling.z , matrix.c3 / scaling.z , matrix.c4
203
+ ++nodeDepth;
204
+ },
205
+ [&](const aiNode*) { --nodeDepth; }
127
206
);
128
- return trsf;
207
+
208
+ outs << std::endl;
129
209
}
130
210
131
211
// Returns the Quantity_Color object equivalent to assimp 'color'
@@ -239,7 +319,6 @@ bool AssimpReader::readFile(const FilePath& filepath, TaskProgress* progress)
239
319
aiProcess_Triangulate
240
320
| aiProcess_JoinIdenticalVertices
241
321
// | aiProcess_SortByPType /* Crashes with assimp-5.3.1 on Windows */
242
-
243
322
// | aiProcess_OptimizeGraph
244
323
// | aiProcess_TransformUVCoords
245
324
// | aiProcess_FlipUVs
@@ -305,6 +384,9 @@ bool AssimpReader::readFile(const FilePath& filepath, TaskProgress* progress)
305
384
m_vecMaterial.at (i) = this ->createOccVisMaterial (material, filepath);
306
385
}
307
386
387
+ #ifdef MAYO_ASSIMP_READER_HANDLE_SCALING
388
+ deep_aiScenePrint (std::cout, m_scene);
389
+ #endif
308
390
return true ;
309
391
}
310
392
@@ -314,21 +396,20 @@ TDF_LabelSequence AssimpReader::transfer(DocumentPtr doc, TaskProgress* progress
314
396
return {};
315
397
316
398
m_mapNodeData.clear ();
399
+
317
400
// Compute data for each aiNode object in the scene
318
401
deep_aiNodeVisit (m_scene->mRootNode , [=](const aiNode* node) {
319
402
aiNodeData nodeData;
320
403
auto itParentData = m_mapNodeData.find (node->mParent );
321
404
if (itParentData != m_mapNodeData.cend ()) {
322
405
const aiNodeData& parentData = itParentData->second ;
323
406
nodeData.aiAbsoluteTrsf = parentData.aiAbsoluteTrsf * node->mTransformation ;
324
- nodeData.occAbsoluteTrsf = parentData.occAbsoluteTrsf * toOccTrsf (node->mTransformation );
325
407
}
326
408
else {
327
409
nodeData.aiAbsoluteTrsf = node->mTransformation ;
328
- nodeData.occAbsoluteTrsf = toOccTrsf (node->mTransformation );
329
410
}
330
411
331
- m_mapNodeData.insert ({ node, nodeData } );
412
+ m_mapNodeData.insert_or_assign ( node, std::move ( nodeData) );
332
413
});
333
414
334
415
// Compute count of meshes in the scene
@@ -371,7 +452,7 @@ void AssimpReader::applyProperties(const PropertyGroup* group)
371
452
}
372
453
373
454
OccHandle<Image_Texture> AssimpReader::findOccTexture (
374
- const std::string& strFilepath, const FilePath& modelFilepath
455
+ const std::string& strFilepath, const FilePath& modelFilepath
375
456
)
376
457
{
377
458
// Texture might be embedded
@@ -426,7 +507,7 @@ OccHandle<Image_Texture> AssimpReader::findOccTexture(
426
507
}
427
508
428
509
OccHandle<XCAFDoc_VisMaterial> AssimpReader::createOccVisMaterial (
429
- const aiMaterial* material, const FilePath& modelFilepath
510
+ const aiMaterial* material, const FilePath& modelFilepath
430
511
)
431
512
{
432
513
auto mat = makeOccHandle<XCAFDoc_VisMaterial>();
@@ -610,10 +691,10 @@ OccHandle<XCAFDoc_VisMaterial> AssimpReader::createOccVisMaterial(
610
691
}
611
692
612
693
void AssimpReader::transferSceneNode (
613
- const aiNode* node,
614
- DocumentPtr targetDoc,
615
- const TDF_Label& labelEntity,
616
- const std::function<void (const aiMesh*)>& fnCallbackMesh
694
+ const aiNode* node,
695
+ DocumentPtr targetDoc,
696
+ const TDF_Label& labelEntity,
697
+ const std::function<void (const aiMesh*)>& fnCallbackMesh
617
698
)
618
699
{
619
700
if (!node)
@@ -622,14 +703,14 @@ void AssimpReader::transferSceneNode(
622
703
const std::string nodeName = node->mName .C_Str ();
623
704
624
705
const aiNodeData nodeData = Cpp::findValue (node, m_mapNodeData);
625
- gp_Trsf nodeAbsoluteTrsf = nodeData.occAbsoluteTrsf ;
626
- if (hasScaleFactor (nodeAbsoluteTrsf))
627
- nodeAbsoluteTrsf.SetScaleFactor (1 .);
706
+ aiVector3D nodeScale;
707
+ aiQuaternion nodeRot;
708
+ aiVector3D nodePos;
709
+ nodeData.aiAbsoluteTrsf .Decompose (nodeScale, nodeRot, nodePos);
628
710
629
- #ifdef MAYO_ASSIMP_READER_HANDLE_SCALING
630
- const aiVector3D nodeScaling = aiMatrixScaling (nodeData.aiAbsoluteTrsf );
631
- const bool nodeHasScaling = hasScaleFactor (nodeScaling);
632
- #endif
711
+ gp_Trsf nodeAbsoluteTrsf;
712
+ nodeAbsoluteTrsf.SetRotationPart (gp_Quaternion{nodeRot.x , nodeRot.y , nodeRot.z , nodeRot.w });
713
+ nodeAbsoluteTrsf.SetTranslationPart (gp_Vec{nodePos.x , nodePos.y , nodePos.z });
633
714
634
715
// Produce shape corresponding to the node
635
716
for (unsigned imesh = 0 ; imesh < node->mNumMeshes ; ++imesh) {
@@ -641,14 +722,13 @@ void AssimpReader::transferSceneNode(
641
722
continue ; // Skip
642
723
643
724
#ifdef MAYO_ASSIMP_READER_HANDLE_SCALING
644
- if (nodeHasScaling ) {
725
+ if (hasScaleFactor (nodeScale) ) {
645
726
triangulation = triangulation->Copy ();
646
- for (int i = 1 ; i < triangulation->NbNodes (); ++i) {
647
- gp_Pnt pnt = triangulation->Node (i);
648
- pnt.SetX (pnt.X () * nodeScaling.x );
649
- pnt.SetY (pnt.Y () * nodeScaling.y );
650
- pnt.SetZ (pnt.Z () * nodeScaling.z );
651
- MeshUtils::setNode (triangulation, i , pnt);
727
+ for (int i = 1 ; i <= triangulation->NbNodes (); ++i) {
728
+ const gp_Pnt pnt = triangulation->Node (i);
729
+ MeshUtils::setNode (
730
+ triangulation, i, gp_Pnt{ pnt.X () * nodeScale.x , pnt.Y () * nodeScale.y , pnt.Z () * nodeScale.z }
731
+ );
652
732
}
653
733
}
654
734
#endif
0 commit comments