OSDN Git Service

162b99549a087c56c7f4997dc657b98111bc8611
[qtgeoviewer/QtGeoViewer.git] / Src / LibQtGeoViewerCore / Format / AssimpReader.cpp
1 #include "stdafx.h"
2 #include "AssimpReader.h"
3
4 #include <LibQtGeoViewerCore/SceneMain.h>
5
6 #include "../FileUtil.h"
7
8 #include <C2/util/string_util.h>
9 #include <LibGeo/Path.h>
10
11 #include <assimp/Importer.hpp>
12 #include <assimp/scene.h>
13 #include <assimp/postprocess.h>
14 #include "AssimpUtil.h"
15
16 #include <QFileInfo>
17
18
19
20 bool AssimpReader::Load(SceneMain& scene, const std::string& filename)
21 {
22         unsigned int ai_option =
23                 aiProcess_JoinIdenticalVertices;
24
25         Assimp::Importer importer;
26         const aiScene* ai_scene = importer.ReadFile(filename, ai_option);
27         if (!ai_scene)
28                 return false;
29
30         std::string dirpath = lib_geo::Path::GetParentDirPath(filename);
31
32         BoneMap bone_map;
33         std::map<int, MeshBuf*> AiToLGMesh;
34
35         bool HasAnimation = (ai_scene->mNumAnimations > 0);
36
37         GeomObject* geom = scene.CreateNewGeometry();
38         for (unsigned int i = 0; i < ai_scene->mNumMeshes; ++i)
39         {
40                 aiMesh* mesh = ai_scene->mMeshes[i];
41                 MeshBuf* mbuf = geom->CreateNewMeshBuf();
42
43                 AiToLGMesh[i] = mbuf;
44
45                 lib_geo::BaseMesh& mesh_dst = mbuf->m_Mesh;
46
47                 geom->m_Name = mesh->mName.C_Str();
48                 if (geom->m_Name.empty())
49                 {
50                         std::ostringstream oss;
51                         oss << FileUtil::GetFileTitle(filename) << "-" << i;
52                         geom->m_Name = oss.str();
53                 }
54
55                 AssimpUtil::CopyAIVerts(mesh_dst, mesh);
56                 AssimpUtil::CopyAIFaces(mesh_dst, mesh);
57                 AssimpUtil::CopyMaterials(geom, mbuf, ai_scene, scene, dirpath);
58
59                 ResetBone(geom, bone_map, mesh);
60
61                 if (!mesh_dst.HasNormal())
62                 {
63                         mesh_dst.CreateNormalsEachVerts();
64                         mesh_dst.UpdateNormal();
65                 }
66
67                 if (HasAnimation)
68                         geom->m_BoneAnimation.m_SrcVertPos = mesh_dst.m_Verts;
69         }
70
71         SetBoneToGeom(ai_scene, bone_map, geom);
72
73         ApplyASTransform(ai_scene->mRootNode, ai_scene->mRootNode->mTransformation, AiToLGMesh);
74
75         if (HasAnimation)
76         {
77                 const aiAnimation* anim = ai_scene->mAnimations[0];
78                 for (unsigned int j = 0; j < anim->mNumChannels; ++j)
79                 {
80                         aiNodeAnim* ch = anim->mChannels[j];
81                         Bone* bone = bone_map.Bones[ch->mNodeName.C_Str()];
82                         if (bone == NULL)
83                                 continue;
84
85                         SetKeyToBone(ch, bone);
86                 }
87         }
88
89         geom->InitializeBufferCommon();
90         geom->m_FileFormat = GeomFileFormat::XFile;
91         geom->m_FilePath   = filename;
92
93         for (auto& mb : AiToLGMesh)
94         {
95                 mb.second->UpdateBBox();
96                 mb.second->ResetIniBBox();
97         }
98
99         scene.UpdateTransform();
100
101         scene.ReportDoneEditGeometry();
102
103         return true;
104 }
105
106 void AssimpReader::ApplyASTransform(aiNode* n, aiMatrix4x4& t, std::map<int, MeshBuf*>& AiToLGMesh)
107 {
108         for (int i = 0; i < n->mNumMeshes; ++i)
109         {
110                 std::map<int, MeshBuf*>::iterator& mp = AiToLGMesh.find(n->mMeshes[i]);
111                 if (mp == AiToLGMesh.end())
112                         continue;
113
114                 lm::matrix4f m;
115                 ae::ConvertMat(m, t);
116                 mp->second->m_Mesh.ApplyTransform(m);
117         }
118
119         for (int i = 0; i < n->mNumChildren; ++i)
120         {
121                 aiNode* cn = n->mChildren[i];
122                 ApplyASTransform(cn, t * cn->mTransformation, AiToLGMesh);
123         }
124 }
125
126 void AssimpReader::SetKeyToBone(aiNodeAnim* ch, Bone* bone)
127 {
128         // \83t\83@\83C\83\8b\83t\83H\81[\83}\83b\83g\82Ì\8ed\97l\82Æ\82µ\82Ä\82Í, \91®\90«\82²\82Æ\82É\83L\81[\97v\91f\90\94\82ª\88Ù\82È\82é\89Â\94\\90«\82ª\82 \82é\82ª,
129         // \90§\8cä\82ª\96Ê\93|\82È\82Ì\82Å\88ê\92v\82µ\82Ä\82¢\82é\82Æ\82¢\82¤\91O\92ñ\82Å\8f\88\97\9d\82ð\8dì\82Á\82Ä\82¢\82é.
130         int num_key = AssimpUtil::GetNumKeyOfFrame(ch);
131         bone->m_Translate.resize(num_key);
132         bone->m_Scale.resize(num_key);
133         bone->m_Rotate.resize(num_key);
134
135         for (unsigned int k = 0; k < ch->mNumPositionKeys; ++k)
136         {
137                 ae::ConvertVec(bone->m_Translate[k], ch->mPositionKeys[k].mValue);
138         }
139
140         for (unsigned int k = 0; k < ch->mNumScalingKeys; ++k)
141         {
142                 ae::ConvertVec(bone->m_Scale[k], ch->mScalingKeys[k].mValue);
143         }
144
145         for (unsigned int k = 0; k < ch->mNumRotationKeys; ++k)
146         {
147                 ae::AiQuatToLmQuat(bone->m_Rotate[k], ch->mRotationKeys[k].mValue);
148         }
149 }
150
151 void AssimpReader::ResetBone(GeomObject* geom, BoneMap& bone_map, aiMesh* mesh)
152 {
153         geom->m_BoneAnimation.m_Bones.resize(mesh->mNumBones);
154         for (unsigned int j = 0; j < mesh->mNumBones; ++j)
155         {
156                 const aiBone* s_bone = mesh->mBones[j];
157                 Bone& d_bone = geom->m_BoneAnimation.m_Bones[j];
158                 d_bone.m_Name = s_bone->mName.C_Str();
159
160                 ConvertBoneWeight(s_bone, d_bone);
161
162                 lm::matrix4f offset;
163                 ae::ConvertMat(offset, s_bone->mOffsetMatrix);
164                 d_bone.SetOffset(offset);
165
166                 bone_map.Bones[d_bone.m_Name] = &d_bone;
167         }
168 }
169
170 void AssimpReader::ConvertBoneWeight(const aiBone* s_bone, geom::Bone& d_bone)
171 {
172         d_bone.m_Weights.resize(s_bone->mNumWeights);
173         for (unsigned int k = 0; k < s_bone->mNumWeights; ++k)
174         {
175                 BoneWeight& bw = d_bone.m_Weights[k];
176                 aiVertexWeight& vw = s_bone->mWeights[k];
177                 bw.m_Vid    = vw.mVertexId;
178                 bw.m_Weight = vw.mWeight;
179         }
180 }
181
182 void AssimpReader::SetBoneToGeom(const aiScene* ai_scene, geom::BoneMap& bone_map, geom::GeomObject* geom)
183 {
184         const aiNode* root = ai_scene->mRootNode;
185         for (unsigned int j = 0; j < root->mNumChildren; ++j)
186         {
187                 aiNode* n = root->mChildren[j];
188                 for (unsigned int k = 0; k < n->mNumChildren; ++k)
189                 {
190                         aiNode* nc = n->mChildren[k];
191                         Bone* b_root = bone_map.Bones[nc->mName.C_Str()];
192                         if (b_root == NULL)
193                         {
194                                 b_root = new Bone();
195                                 bone_map.Bones[nc->mName.C_Str()] = b_root;
196                                 b_root->m_Name = nc->mName.C_Str();
197                                 geom->m_BoneAnimation.m_Bones.push_back(b_root);
198                         }
199
200                         BoneNode* br = new BoneNode();
201                         geom->m_BoneAnimation.m_RootNodes.push_back(br);
202
203                         br->m_Bone = b_root;
204                         ae::ConvertMat(br->m_Transform, n->mTransformation);
205
206                         std::set<aiNode*> passed;
207                         AssimpUtil::CreateBoneTree(bone_map, br, nc, passed);
208                 }
209         }
210 }
211
212 void AssimpReader::LoadAnimation(const aiScene* ai_scene, BoneMap& bone_map)
213 {
214         const aiAnimation* anim = ai_scene->mAnimations[0];
215         for (unsigned int j = 0; j < anim->mNumChannels; ++j)
216         {
217                 aiNodeAnim* ch = anim->mChannels[j];
218                 Bone* bone = bone_map.Bones[ch->mNodeName.C_Str()];
219                 if (bone == NULL)
220                         continue;
221
222                 int num_key = AssimpUtil::GetNumKeyOfFrame(ch);
223
224                 // \83t\83@\83C\83\8b\83t\83H\81[\83}\83b\83g\82Ì\8ed\97l\82Æ\82µ\82Ä\82Í, \91®\90«\82²\82Æ\82É\83L\81[\97v\91f\90\94\82ª\88Ù\82È\82é\89Â\94\\90«\82ª\82 \82é\82ª,
225                 // \90§\8cä\82ª\96Ê\93|\82È\82Ì\82Å\88ê\92v\82µ\82Ä\82¢\82é\82Æ\82¢\82¤\91O\92ñ\82Å\8f\88\97\9d\82ð\8dì\82Á\82Ä\82¢\82é.
226                 bone->m_Translate.resize(num_key);
227                 bone->m_Scale.resize(num_key);
228                 bone->m_Rotate.resize(num_key);
229
230                 for (unsigned int k = 0; k < ch->mNumPositionKeys; ++k)
231                 {
232                         ae::ConvertVec(bone->m_Translate[k], ch->mPositionKeys[k].mValue);
233                 }
234
235                 for (unsigned int k = 0; k < ch->mNumScalingKeys; ++k)
236                 {
237                         ae::ConvertVec(bone->m_Scale[k], ch->mScalingKeys[k].mValue);
238                 }
239
240                 for (unsigned int k = 0; k < ch->mNumRotationKeys; ++k)
241                 {
242                         ae::AiQuatToLmQuat(bone->m_Rotate[k], ch->mRotationKeys[k].mValue);
243                 }
244
245                 bone->m_KeyIdxOffset = GetNumMinusKeyFrames(ch);
246         }
247 }
248
249 // 0\95b\96¢\96\9e\82Ì\83L\81[\83t\83\8c\81[\83\80\90\94\82ð\90\94\82¦\82é
250 int AssimpReader::GetNumMinusKeyFrames(const aiNodeAnim* ch) const
251 {
252         for (unsigned int i = 0; i < ch->mNumPositionKeys; ++i)
253         {
254                 if(ch->mPositionKeys[i].mTime >= 0)
255                         return i;
256         }
257
258         // \91S\83t\83\8c\81[\83\80\82ª0\95b\96¢\96\9e
259         assert(false);
260
261         return ch->mNumPositionKeys;
262 }