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