rev |
line source |
nuclear@0
|
1 /*
|
nuclear@0
|
2 ---------------------------------------------------------------------------
|
nuclear@0
|
3 Open Asset Import Library (assimp)
|
nuclear@0
|
4 ---------------------------------------------------------------------------
|
nuclear@0
|
5
|
nuclear@0
|
6 Copyright (c) 2006-2012, assimp team
|
nuclear@0
|
7
|
nuclear@0
|
8 All rights reserved.
|
nuclear@0
|
9
|
nuclear@0
|
10 Redistribution and use of this software in source and binary forms,
|
nuclear@0
|
11 with or without modification, are permitted provided that the following
|
nuclear@0
|
12 conditions are met:
|
nuclear@0
|
13
|
nuclear@0
|
14 * Redistributions of source code must retain the above
|
nuclear@0
|
15 copyright notice, this list of conditions and the
|
nuclear@0
|
16 following disclaimer.
|
nuclear@0
|
17
|
nuclear@0
|
18 * Redistributions in binary form must reproduce the above
|
nuclear@0
|
19 copyright notice, this list of conditions and the
|
nuclear@0
|
20 following disclaimer in the documentation and/or other
|
nuclear@0
|
21 materials provided with the distribution.
|
nuclear@0
|
22
|
nuclear@0
|
23 * Neither the name of the assimp team, nor the names of its
|
nuclear@0
|
24 contributors may be used to endorse or promote products
|
nuclear@0
|
25 derived from this software without specific prior
|
nuclear@0
|
26 written permission of the assimp team.
|
nuclear@0
|
27
|
nuclear@0
|
28 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
nuclear@0
|
29 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
nuclear@0
|
30 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
nuclear@0
|
31 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
nuclear@0
|
32 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
nuclear@0
|
33 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
nuclear@0
|
34 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
nuclear@0
|
35 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
nuclear@0
|
36 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
nuclear@0
|
37 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
nuclear@0
|
38 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
nuclear@0
|
39 ---------------------------------------------------------------------------
|
nuclear@0
|
40 */
|
nuclear@0
|
41
|
nuclear@0
|
42 /** @file MakeLeftHandedProcess.cpp
|
nuclear@0
|
43 * @brief Implementation of the post processing step to convert all
|
nuclear@0
|
44 * imported data to a left-handed coordinate system.
|
nuclear@0
|
45 *
|
nuclear@0
|
46 * Face order & UV flip are also implemented here, for the sake of a
|
nuclear@0
|
47 * better location.
|
nuclear@0
|
48 */
|
nuclear@0
|
49
|
nuclear@0
|
50 #include "AssimpPCH.h"
|
nuclear@0
|
51 #include "ConvertToLHProcess.h"
|
nuclear@0
|
52
|
nuclear@0
|
53 using namespace Assimp;
|
nuclear@0
|
54
|
nuclear@0
|
55 #ifndef ASSIMP_BUILD_NO_MAKELEFTHANDED_PROCESS
|
nuclear@0
|
56
|
nuclear@0
|
57 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
58 // Constructor to be privately used by Importer
|
nuclear@0
|
59 MakeLeftHandedProcess::MakeLeftHandedProcess()
|
nuclear@0
|
60 {}
|
nuclear@0
|
61
|
nuclear@0
|
62 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
63 // Destructor, private as well
|
nuclear@0
|
64 MakeLeftHandedProcess::~MakeLeftHandedProcess()
|
nuclear@0
|
65 {}
|
nuclear@0
|
66
|
nuclear@0
|
67 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
68 // Returns whether the processing step is present in the given flag field.
|
nuclear@0
|
69 bool MakeLeftHandedProcess::IsActive( unsigned int pFlags) const
|
nuclear@0
|
70 {
|
nuclear@0
|
71 return 0 != (pFlags & aiProcess_MakeLeftHanded);
|
nuclear@0
|
72 }
|
nuclear@0
|
73
|
nuclear@0
|
74 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
75 // Executes the post processing step on the given imported data.
|
nuclear@0
|
76 void MakeLeftHandedProcess::Execute( aiScene* pScene)
|
nuclear@0
|
77 {
|
nuclear@0
|
78 // Check for an existent root node to proceed
|
nuclear@0
|
79 ai_assert(pScene->mRootNode != NULL);
|
nuclear@0
|
80 DefaultLogger::get()->debug("MakeLeftHandedProcess begin");
|
nuclear@0
|
81
|
nuclear@0
|
82 // recursively convert all the nodes
|
nuclear@0
|
83 ProcessNode( pScene->mRootNode, aiMatrix4x4());
|
nuclear@0
|
84
|
nuclear@0
|
85 // process the meshes accordingly
|
nuclear@0
|
86 for( unsigned int a = 0; a < pScene->mNumMeshes; ++a)
|
nuclear@0
|
87 ProcessMesh( pScene->mMeshes[a]);
|
nuclear@0
|
88
|
nuclear@0
|
89 // process the materials accordingly
|
nuclear@0
|
90 for( unsigned int a = 0; a < pScene->mNumMaterials; ++a)
|
nuclear@0
|
91 ProcessMaterial( pScene->mMaterials[a]);
|
nuclear@0
|
92
|
nuclear@0
|
93 // transform all animation channels as well
|
nuclear@0
|
94 for( unsigned int a = 0; a < pScene->mNumAnimations; a++)
|
nuclear@0
|
95 {
|
nuclear@0
|
96 aiAnimation* anim = pScene->mAnimations[a];
|
nuclear@0
|
97 for( unsigned int b = 0; b < anim->mNumChannels; b++)
|
nuclear@0
|
98 {
|
nuclear@0
|
99 aiNodeAnim* nodeAnim = anim->mChannels[b];
|
nuclear@0
|
100 ProcessAnimation( nodeAnim);
|
nuclear@0
|
101 }
|
nuclear@0
|
102 }
|
nuclear@0
|
103 DefaultLogger::get()->debug("MakeLeftHandedProcess finished");
|
nuclear@0
|
104 }
|
nuclear@0
|
105
|
nuclear@0
|
106 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
107 // Recursively converts a node, all of its children and all of its meshes
|
nuclear@0
|
108 void MakeLeftHandedProcess::ProcessNode( aiNode* pNode, const aiMatrix4x4& pParentGlobalRotation)
|
nuclear@0
|
109 {
|
nuclear@0
|
110 // mirror all base vectors at the local Z axis
|
nuclear@0
|
111 pNode->mTransformation.c1 = -pNode->mTransformation.c1;
|
nuclear@0
|
112 pNode->mTransformation.c2 = -pNode->mTransformation.c2;
|
nuclear@0
|
113 pNode->mTransformation.c3 = -pNode->mTransformation.c3;
|
nuclear@0
|
114 pNode->mTransformation.c4 = -pNode->mTransformation.c4;
|
nuclear@0
|
115
|
nuclear@0
|
116 // now invert the Z axis again to keep the matrix determinant positive.
|
nuclear@0
|
117 // The local meshes will be inverted accordingly so that the result should look just fine again.
|
nuclear@0
|
118 pNode->mTransformation.a3 = -pNode->mTransformation.a3;
|
nuclear@0
|
119 pNode->mTransformation.b3 = -pNode->mTransformation.b3;
|
nuclear@0
|
120 pNode->mTransformation.c3 = -pNode->mTransformation.c3;
|
nuclear@0
|
121 pNode->mTransformation.d3 = -pNode->mTransformation.d3; // useless, but anyways...
|
nuclear@0
|
122
|
nuclear@0
|
123 // continue for all children
|
nuclear@0
|
124 for( size_t a = 0; a < pNode->mNumChildren; ++a)
|
nuclear@0
|
125 ProcessNode( pNode->mChildren[a], pParentGlobalRotation * pNode->mTransformation);
|
nuclear@0
|
126 }
|
nuclear@0
|
127
|
nuclear@0
|
128 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
129 // Converts a single mesh to left handed coordinates.
|
nuclear@0
|
130 void MakeLeftHandedProcess::ProcessMesh( aiMesh* pMesh)
|
nuclear@0
|
131 {
|
nuclear@0
|
132 // mirror positions, normals and stuff along the Z axis
|
nuclear@0
|
133 for( size_t a = 0; a < pMesh->mNumVertices; ++a)
|
nuclear@0
|
134 {
|
nuclear@0
|
135 pMesh->mVertices[a].z *= -1.0f;
|
nuclear@0
|
136 if( pMesh->HasNormals())
|
nuclear@0
|
137 pMesh->mNormals[a].z *= -1.0f;
|
nuclear@0
|
138 if( pMesh->HasTangentsAndBitangents())
|
nuclear@0
|
139 {
|
nuclear@0
|
140 pMesh->mTangents[a].z *= -1.0f;
|
nuclear@0
|
141 pMesh->mBitangents[a].z *= -1.0f;
|
nuclear@0
|
142 }
|
nuclear@0
|
143 }
|
nuclear@0
|
144
|
nuclear@0
|
145 // mirror offset matrices of all bones
|
nuclear@0
|
146 for( size_t a = 0; a < pMesh->mNumBones; ++a)
|
nuclear@0
|
147 {
|
nuclear@0
|
148 aiBone* bone = pMesh->mBones[a];
|
nuclear@0
|
149 bone->mOffsetMatrix.a3 = -bone->mOffsetMatrix.a3;
|
nuclear@0
|
150 bone->mOffsetMatrix.b3 = -bone->mOffsetMatrix.b3;
|
nuclear@0
|
151 bone->mOffsetMatrix.d3 = -bone->mOffsetMatrix.d3;
|
nuclear@0
|
152 bone->mOffsetMatrix.c1 = -bone->mOffsetMatrix.c1;
|
nuclear@0
|
153 bone->mOffsetMatrix.c2 = -bone->mOffsetMatrix.c2;
|
nuclear@0
|
154 bone->mOffsetMatrix.c4 = -bone->mOffsetMatrix.c4;
|
nuclear@0
|
155 }
|
nuclear@0
|
156
|
nuclear@0
|
157 // mirror bitangents as well as they're derived from the texture coords
|
nuclear@0
|
158 if( pMesh->HasTangentsAndBitangents())
|
nuclear@0
|
159 {
|
nuclear@0
|
160 for( unsigned int a = 0; a < pMesh->mNumVertices; a++)
|
nuclear@0
|
161 pMesh->mBitangents[a] *= -1.0f;
|
nuclear@0
|
162 }
|
nuclear@0
|
163 }
|
nuclear@0
|
164
|
nuclear@0
|
165 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
166 // Converts a single material to left handed coordinates.
|
nuclear@0
|
167 void MakeLeftHandedProcess::ProcessMaterial( aiMaterial* _mat)
|
nuclear@0
|
168 {
|
nuclear@0
|
169 aiMaterial* mat = (aiMaterial*)_mat;
|
nuclear@0
|
170 for (unsigned int a = 0; a < mat->mNumProperties;++a) {
|
nuclear@0
|
171 aiMaterialProperty* prop = mat->mProperties[a];
|
nuclear@0
|
172
|
nuclear@0
|
173 // Mapping axis for UV mappings?
|
nuclear@0
|
174 if (!::strcmp( prop->mKey.data, "$tex.mapaxis")) {
|
nuclear@0
|
175 ai_assert( prop->mDataLength >= sizeof(aiVector3D)); /* something is wrong with the validation if we end up here */
|
nuclear@0
|
176 aiVector3D* pff = (aiVector3D*)prop->mData;
|
nuclear@0
|
177
|
nuclear@0
|
178 pff->z *= -1.f;
|
nuclear@0
|
179 }
|
nuclear@0
|
180 }
|
nuclear@0
|
181 }
|
nuclear@0
|
182
|
nuclear@0
|
183 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
184 // Converts the given animation to LH coordinates.
|
nuclear@0
|
185 void MakeLeftHandedProcess::ProcessAnimation( aiNodeAnim* pAnim)
|
nuclear@0
|
186 {
|
nuclear@0
|
187 // position keys
|
nuclear@0
|
188 for( unsigned int a = 0; a < pAnim->mNumPositionKeys; a++)
|
nuclear@0
|
189 pAnim->mPositionKeys[a].mValue.z *= -1.0f;
|
nuclear@0
|
190
|
nuclear@0
|
191 // rotation keys
|
nuclear@0
|
192 for( unsigned int a = 0; a < pAnim->mNumRotationKeys; a++)
|
nuclear@0
|
193 {
|
nuclear@0
|
194 /* That's the safe version, but the float errors add up. So we try the short version instead
|
nuclear@0
|
195 aiMatrix3x3 rotmat = pAnim->mRotationKeys[a].mValue.GetMatrix();
|
nuclear@0
|
196 rotmat.a3 = -rotmat.a3; rotmat.b3 = -rotmat.b3;
|
nuclear@0
|
197 rotmat.c1 = -rotmat.c1; rotmat.c2 = -rotmat.c2;
|
nuclear@0
|
198 aiQuaternion rotquat( rotmat);
|
nuclear@0
|
199 pAnim->mRotationKeys[a].mValue = rotquat;
|
nuclear@0
|
200 */
|
nuclear@0
|
201 pAnim->mRotationKeys[a].mValue.x *= -1.0f;
|
nuclear@0
|
202 pAnim->mRotationKeys[a].mValue.y *= -1.0f;
|
nuclear@0
|
203 }
|
nuclear@0
|
204 }
|
nuclear@0
|
205
|
nuclear@0
|
206 #endif // !! ASSIMP_BUILD_NO_MAKELEFTHANDED_PROCESS
|
nuclear@0
|
207 #ifndef ASSIMP_BUILD_NO_FLIPUVS_PROCESS
|
nuclear@0
|
208 // # FlipUVsProcess
|
nuclear@0
|
209
|
nuclear@0
|
210 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
211 // Constructor to be privately used by Importer
|
nuclear@0
|
212 FlipUVsProcess::FlipUVsProcess()
|
nuclear@0
|
213 {}
|
nuclear@0
|
214
|
nuclear@0
|
215 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
216 // Destructor, private as well
|
nuclear@0
|
217 FlipUVsProcess::~FlipUVsProcess()
|
nuclear@0
|
218 {}
|
nuclear@0
|
219
|
nuclear@0
|
220 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
221 // Returns whether the processing step is present in the given flag field.
|
nuclear@0
|
222 bool FlipUVsProcess::IsActive( unsigned int pFlags) const
|
nuclear@0
|
223 {
|
nuclear@0
|
224 return 0 != (pFlags & aiProcess_FlipUVs);
|
nuclear@0
|
225 }
|
nuclear@0
|
226
|
nuclear@0
|
227 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
228 // Executes the post processing step on the given imported data.
|
nuclear@0
|
229 void FlipUVsProcess::Execute( aiScene* pScene)
|
nuclear@0
|
230 {
|
nuclear@0
|
231 DefaultLogger::get()->debug("FlipUVsProcess begin");
|
nuclear@0
|
232 for (unsigned int i = 0; i < pScene->mNumMeshes;++i)
|
nuclear@0
|
233 ProcessMesh(pScene->mMeshes[i]);
|
nuclear@0
|
234
|
nuclear@0
|
235 for (unsigned int i = 0; i < pScene->mNumMaterials;++i)
|
nuclear@0
|
236 ProcessMaterial(pScene->mMaterials[i]);
|
nuclear@0
|
237 DefaultLogger::get()->debug("FlipUVsProcess finished");
|
nuclear@0
|
238 }
|
nuclear@0
|
239
|
nuclear@0
|
240 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
241 // Converts a single material
|
nuclear@0
|
242 void FlipUVsProcess::ProcessMaterial (aiMaterial* _mat)
|
nuclear@0
|
243 {
|
nuclear@0
|
244 aiMaterial* mat = (aiMaterial*)_mat;
|
nuclear@0
|
245 for (unsigned int a = 0; a < mat->mNumProperties;++a) {
|
nuclear@0
|
246 aiMaterialProperty* prop = mat->mProperties[a];
|
nuclear@0
|
247
|
nuclear@0
|
248 // UV transformation key?
|
nuclear@0
|
249 if (!::strcmp( prop->mKey.data, "$tex.uvtrafo")) {
|
nuclear@0
|
250 ai_assert( prop->mDataLength >= sizeof(aiUVTransform)); /* something is wrong with the validation if we end up here */
|
nuclear@0
|
251 aiUVTransform* uv = (aiUVTransform*)prop->mData;
|
nuclear@0
|
252
|
nuclear@0
|
253 // just flip it, that's everything
|
nuclear@0
|
254 uv->mTranslation.y *= -1.f;
|
nuclear@0
|
255 uv->mRotation *= -1.f;
|
nuclear@0
|
256 }
|
nuclear@0
|
257 }
|
nuclear@0
|
258 }
|
nuclear@0
|
259
|
nuclear@0
|
260 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
261 // Converts a single mesh
|
nuclear@0
|
262 void FlipUVsProcess::ProcessMesh( aiMesh* pMesh)
|
nuclear@0
|
263 {
|
nuclear@0
|
264 // mirror texture y coordinate
|
nuclear@0
|
265 for( unsigned int a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; a++) {
|
nuclear@0
|
266 if( !pMesh->HasTextureCoords( a))
|
nuclear@0
|
267 break;
|
nuclear@0
|
268
|
nuclear@0
|
269 for( unsigned int b = 0; b < pMesh->mNumVertices; b++)
|
nuclear@0
|
270 pMesh->mTextureCoords[a][b].y = 1.0f - pMesh->mTextureCoords[a][b].y;
|
nuclear@0
|
271 }
|
nuclear@0
|
272 }
|
nuclear@0
|
273
|
nuclear@0
|
274 #endif // !ASSIMP_BUILD_NO_FLIPUVS_PROCESS
|
nuclear@0
|
275 #ifndef ASSIMP_BUILD_NO_FLIPWINDING_PROCESS
|
nuclear@0
|
276 // # FlipWindingOrderProcess
|
nuclear@0
|
277
|
nuclear@0
|
278 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
279 // Constructor to be privately used by Importer
|
nuclear@0
|
280 FlipWindingOrderProcess::FlipWindingOrderProcess()
|
nuclear@0
|
281 {}
|
nuclear@0
|
282
|
nuclear@0
|
283 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
284 // Destructor, private as well
|
nuclear@0
|
285 FlipWindingOrderProcess::~FlipWindingOrderProcess()
|
nuclear@0
|
286 {}
|
nuclear@0
|
287
|
nuclear@0
|
288 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
289 // Returns whether the processing step is present in the given flag field.
|
nuclear@0
|
290 bool FlipWindingOrderProcess::IsActive( unsigned int pFlags) const
|
nuclear@0
|
291 {
|
nuclear@0
|
292 return 0 != (pFlags & aiProcess_FlipWindingOrder);
|
nuclear@0
|
293 }
|
nuclear@0
|
294
|
nuclear@0
|
295 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
296 // Executes the post processing step on the given imported data.
|
nuclear@0
|
297 void FlipWindingOrderProcess::Execute( aiScene* pScene)
|
nuclear@0
|
298 {
|
nuclear@0
|
299 DefaultLogger::get()->debug("FlipWindingOrderProcess begin");
|
nuclear@0
|
300 for (unsigned int i = 0; i < pScene->mNumMeshes;++i)
|
nuclear@0
|
301 ProcessMesh(pScene->mMeshes[i]);
|
nuclear@0
|
302 DefaultLogger::get()->debug("FlipWindingOrderProcess finished");
|
nuclear@0
|
303 }
|
nuclear@0
|
304
|
nuclear@0
|
305 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
306 // Converts a single mesh
|
nuclear@0
|
307 void FlipWindingOrderProcess::ProcessMesh( aiMesh* pMesh)
|
nuclear@0
|
308 {
|
nuclear@0
|
309 // invert the order of all faces in this mesh
|
nuclear@0
|
310 for( unsigned int a = 0; a < pMesh->mNumFaces; a++)
|
nuclear@0
|
311 {
|
nuclear@0
|
312 aiFace& face = pMesh->mFaces[a];
|
nuclear@0
|
313 for( unsigned int b = 0; b < face.mNumIndices / 2; b++)
|
nuclear@0
|
314 std::swap( face.mIndices[b], face.mIndices[ face.mNumIndices - 1 - b]);
|
nuclear@0
|
315 }
|
nuclear@0
|
316 }
|
nuclear@0
|
317
|
nuclear@0
|
318 #endif // !! ASSIMP_BUILD_NO_FLIPWINDING_PROCESS
|