rev |
line source |
nuclear@0
|
1 /*
|
nuclear@0
|
2 Open Asset Import Library (assimp)
|
nuclear@0
|
3 ----------------------------------------------------------------------
|
nuclear@0
|
4
|
nuclear@0
|
5 Copyright (c) 2006-2012, assimp team
|
nuclear@0
|
6 All rights reserved.
|
nuclear@0
|
7
|
nuclear@0
|
8 Redistribution and use of this software in source and binary forms,
|
nuclear@0
|
9 with or without modification, are permitted provided that the
|
nuclear@0
|
10 following conditions are met:
|
nuclear@0
|
11
|
nuclear@0
|
12 * Redistributions of source code must retain the above
|
nuclear@0
|
13 copyright notice, this list of conditions and the
|
nuclear@0
|
14 following disclaimer.
|
nuclear@0
|
15
|
nuclear@0
|
16 * Redistributions in binary form must reproduce the above
|
nuclear@0
|
17 copyright notice, this list of conditions and the
|
nuclear@0
|
18 following disclaimer in the documentation and/or other
|
nuclear@0
|
19 materials provided with the distribution.
|
nuclear@0
|
20
|
nuclear@0
|
21 * Neither the name of the assimp team, nor the names of its
|
nuclear@0
|
22 contributors may be used to endorse or promote products
|
nuclear@0
|
23 derived from this software without specific prior
|
nuclear@0
|
24 written permission of the assimp team.
|
nuclear@0
|
25
|
nuclear@0
|
26 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
nuclear@0
|
27 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
nuclear@0
|
28 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
nuclear@0
|
29 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
nuclear@0
|
30 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
nuclear@0
|
31 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
nuclear@0
|
32 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
nuclear@0
|
33 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
nuclear@0
|
34 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
nuclear@0
|
35 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
nuclear@0
|
36 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
nuclear@0
|
37
|
nuclear@0
|
38 ----------------------------------------------------------------------
|
nuclear@0
|
39 */
|
nuclear@0
|
40
|
nuclear@0
|
41 #include "AssimpPCH.h"
|
nuclear@0
|
42 #include "ScenePreprocessor.h"
|
nuclear@0
|
43
|
nuclear@0
|
44 using namespace Assimp;
|
nuclear@0
|
45
|
nuclear@0
|
46 // ---------------------------------------------------------------------------------------------
|
nuclear@0
|
47 void ScenePreprocessor::ProcessScene ()
|
nuclear@0
|
48 {
|
nuclear@0
|
49 ai_assert(scene != NULL);
|
nuclear@0
|
50
|
nuclear@0
|
51 // Process all meshes
|
nuclear@0
|
52 for (unsigned int i = 0; i < scene->mNumMeshes;++i)
|
nuclear@0
|
53 ProcessMesh(scene->mMeshes[i]);
|
nuclear@0
|
54
|
nuclear@0
|
55 // - nothing to do for nodes for the moment
|
nuclear@0
|
56 // - nothing to do for textures for the moment
|
nuclear@0
|
57 // - nothing to do for lights for the moment
|
nuclear@0
|
58 // - nothing to do for cameras for the moment
|
nuclear@0
|
59
|
nuclear@0
|
60 // Process all animations
|
nuclear@0
|
61 for (unsigned int i = 0; i < scene->mNumAnimations;++i)
|
nuclear@0
|
62 ProcessAnimation(scene->mAnimations[i]);
|
nuclear@0
|
63
|
nuclear@0
|
64 // Generate a default material if none was specified
|
nuclear@0
|
65 if (!scene->mNumMaterials && scene->mNumMeshes) {
|
nuclear@0
|
66 scene->mMaterials = new aiMaterial*[2];
|
nuclear@0
|
67 aiMaterial* helper;
|
nuclear@0
|
68
|
nuclear@0
|
69 aiString name;
|
nuclear@0
|
70
|
nuclear@0
|
71 scene->mMaterials[scene->mNumMaterials] = helper = new aiMaterial();
|
nuclear@0
|
72 aiColor3D clr(0.6f,0.6f,0.6f);
|
nuclear@0
|
73 helper->AddProperty(&clr,1,AI_MATKEY_COLOR_DIFFUSE);
|
nuclear@0
|
74
|
nuclear@0
|
75 // setup the default name to make this material identifyable
|
nuclear@0
|
76 name.Set(AI_DEFAULT_MATERIAL_NAME);
|
nuclear@0
|
77 helper->AddProperty(&name,AI_MATKEY_NAME);
|
nuclear@0
|
78
|
nuclear@0
|
79 DefaultLogger::get()->debug("ScenePreprocessor: Adding default material \'" AI_DEFAULT_MATERIAL_NAME "\'");
|
nuclear@0
|
80
|
nuclear@0
|
81 for (unsigned int i = 0; i < scene->mNumMeshes;++i) {
|
nuclear@0
|
82 scene->mMeshes[i]->mMaterialIndex = scene->mNumMaterials;
|
nuclear@0
|
83 }
|
nuclear@0
|
84
|
nuclear@0
|
85 scene->mNumMaterials++;
|
nuclear@0
|
86 }
|
nuclear@0
|
87 }
|
nuclear@0
|
88
|
nuclear@0
|
89 // ---------------------------------------------------------------------------------------------
|
nuclear@0
|
90 void ScenePreprocessor::ProcessMesh (aiMesh* mesh)
|
nuclear@0
|
91 {
|
nuclear@0
|
92 // If aiMesh::mNumUVComponents is *not* set assign the default value of 2
|
nuclear@0
|
93 for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i) {
|
nuclear@0
|
94 if (!mesh->mTextureCoords[i])
|
nuclear@0
|
95 mesh->mNumUVComponents[i] = 0;
|
nuclear@0
|
96
|
nuclear@0
|
97 else {
|
nuclear@0
|
98 if( !mesh->mNumUVComponents[i])
|
nuclear@0
|
99 mesh->mNumUVComponents[i] = 2;
|
nuclear@0
|
100
|
nuclear@0
|
101 aiVector3D* p = mesh->mTextureCoords[i], *end = p+mesh->mNumVertices;
|
nuclear@0
|
102
|
nuclear@0
|
103 // Ensure unsued components are zeroed. This will make 1D texture channels work
|
nuclear@0
|
104 // as if they were 2D channels .. just in case an application doesn't handle
|
nuclear@0
|
105 // this case
|
nuclear@0
|
106 if (2 == mesh->mNumUVComponents[i]) {
|
nuclear@0
|
107 for (; p != end; ++p)
|
nuclear@0
|
108 p->z = 0.f;
|
nuclear@0
|
109 }
|
nuclear@0
|
110 else if (1 == mesh->mNumUVComponents[i]) {
|
nuclear@0
|
111 for (; p != end; ++p)
|
nuclear@0
|
112 p->z = p->y = 0.f;
|
nuclear@0
|
113 }
|
nuclear@0
|
114 else if (3 == mesh->mNumUVComponents[i]) {
|
nuclear@0
|
115
|
nuclear@0
|
116 // Really 3D coordinates? Check whether the third coordinate is != 0 for at least one element
|
nuclear@0
|
117 for (; p != end; ++p) {
|
nuclear@0
|
118 if (p->z != 0)
|
nuclear@0
|
119 break;
|
nuclear@0
|
120 }
|
nuclear@0
|
121 if (p == end) {
|
nuclear@0
|
122 DefaultLogger::get()->warn("ScenePreprocessor: UVs are declared to be 3D but they're obviously not. Reverting to 2D.");
|
nuclear@0
|
123 mesh->mNumUVComponents[i] = 2;
|
nuclear@0
|
124 }
|
nuclear@0
|
125 }
|
nuclear@0
|
126 }
|
nuclear@0
|
127 }
|
nuclear@0
|
128
|
nuclear@0
|
129 // If the information which primitive types are there in the
|
nuclear@0
|
130 // mesh is currently not available, compute it.
|
nuclear@0
|
131 if (!mesh->mPrimitiveTypes) {
|
nuclear@0
|
132 for (unsigned int a = 0; a < mesh->mNumFaces; ++a) {
|
nuclear@0
|
133 aiFace& face = mesh->mFaces[a];
|
nuclear@0
|
134 switch (face.mNumIndices)
|
nuclear@0
|
135 {
|
nuclear@0
|
136 case 3u:
|
nuclear@0
|
137 mesh->mPrimitiveTypes |= aiPrimitiveType_TRIANGLE;
|
nuclear@0
|
138 break;
|
nuclear@0
|
139
|
nuclear@0
|
140 case 2u:
|
nuclear@0
|
141 mesh->mPrimitiveTypes |= aiPrimitiveType_LINE;
|
nuclear@0
|
142 break;
|
nuclear@0
|
143
|
nuclear@0
|
144 case 1u:
|
nuclear@0
|
145 mesh->mPrimitiveTypes |= aiPrimitiveType_POINT;
|
nuclear@0
|
146 break;
|
nuclear@0
|
147
|
nuclear@0
|
148 default:
|
nuclear@0
|
149 mesh->mPrimitiveTypes |= aiPrimitiveType_POLYGON;
|
nuclear@0
|
150 break;
|
nuclear@0
|
151 }
|
nuclear@0
|
152 }
|
nuclear@0
|
153 }
|
nuclear@0
|
154
|
nuclear@0
|
155 // If tangents and normals are given but no bitangents compute them
|
nuclear@0
|
156 if (mesh->mTangents && mesh->mNormals && !mesh->mBitangents) {
|
nuclear@0
|
157
|
nuclear@0
|
158 mesh->mBitangents = new aiVector3D[mesh->mNumVertices];
|
nuclear@0
|
159 for (unsigned int i = 0; i < mesh->mNumVertices;++i) {
|
nuclear@0
|
160 mesh->mBitangents[i] = mesh->mNormals[i] ^ mesh->mTangents[i];
|
nuclear@0
|
161 }
|
nuclear@0
|
162 }
|
nuclear@0
|
163 }
|
nuclear@0
|
164
|
nuclear@0
|
165 // ---------------------------------------------------------------------------------------------
|
nuclear@0
|
166 void ScenePreprocessor::ProcessAnimation (aiAnimation* anim)
|
nuclear@0
|
167 {
|
nuclear@0
|
168 double first = 10e10, last = -10e10;
|
nuclear@0
|
169 for (unsigned int i = 0; i < anim->mNumChannels;++i) {
|
nuclear@0
|
170 aiNodeAnim* channel = anim->mChannels[i];
|
nuclear@0
|
171
|
nuclear@0
|
172 /* If the exact duration of the animation is not given
|
nuclear@0
|
173 * compute it now.
|
nuclear@0
|
174 */
|
nuclear@0
|
175 if (anim->mDuration == -1.) {
|
nuclear@0
|
176
|
nuclear@0
|
177 // Position keys
|
nuclear@0
|
178 for (unsigned int i = 0; i < channel->mNumPositionKeys;++i) {
|
nuclear@0
|
179 aiVectorKey& key = channel->mPositionKeys[i];
|
nuclear@0
|
180 first = std::min (first, key.mTime);
|
nuclear@0
|
181 last = std::max (last, key.mTime);
|
nuclear@0
|
182 }
|
nuclear@0
|
183
|
nuclear@0
|
184 // Scaling keys
|
nuclear@0
|
185 for (unsigned int i = 0; i < channel->mNumScalingKeys;++i) {
|
nuclear@0
|
186 aiVectorKey& key = channel->mScalingKeys[i];
|
nuclear@0
|
187 first = std::min (first, key.mTime);
|
nuclear@0
|
188 last = std::max (last, key.mTime);
|
nuclear@0
|
189 }
|
nuclear@0
|
190
|
nuclear@0
|
191 // Rotation keys
|
nuclear@0
|
192 for (unsigned int i = 0; i < channel->mNumRotationKeys;++i) {
|
nuclear@0
|
193 aiQuatKey& key = channel->mRotationKeys[i];
|
nuclear@0
|
194 first = std::min (first, key.mTime);
|
nuclear@0
|
195 last = std::max (last, key.mTime);
|
nuclear@0
|
196 }
|
nuclear@0
|
197 }
|
nuclear@0
|
198
|
nuclear@0
|
199 /* Check whether the animation channel has no rotation
|
nuclear@0
|
200 * or position tracks. In this case we generate a dummy
|
nuclear@0
|
201 * track from the information we have in the transformation
|
nuclear@0
|
202 * matrix of the corresponding node.
|
nuclear@0
|
203 */
|
nuclear@0
|
204 if (!channel->mNumRotationKeys || !channel->mNumPositionKeys || !channel->mNumScalingKeys) {
|
nuclear@0
|
205 // Find the node that belongs to this animation
|
nuclear@0
|
206 aiNode* node = scene->mRootNode->FindNode(channel->mNodeName);
|
nuclear@0
|
207 if (node) // ValidateDS will complain later if 'node' is NULL
|
nuclear@0
|
208 {
|
nuclear@0
|
209 // Decompose the transformation matrix of the node
|
nuclear@0
|
210 aiVector3D scaling, position;
|
nuclear@0
|
211 aiQuaternion rotation;
|
nuclear@0
|
212
|
nuclear@0
|
213 node->mTransformation.Decompose(scaling, rotation,position);
|
nuclear@0
|
214
|
nuclear@0
|
215 // No rotation keys? Generate a dummy track
|
nuclear@0
|
216 if (!channel->mNumRotationKeys) {
|
nuclear@0
|
217 channel->mNumRotationKeys = 1;
|
nuclear@0
|
218 channel->mRotationKeys = new aiQuatKey[1];
|
nuclear@0
|
219 aiQuatKey& q = channel->mRotationKeys[0];
|
nuclear@0
|
220
|
nuclear@0
|
221 q.mTime = 0.;
|
nuclear@0
|
222 q.mValue = rotation;
|
nuclear@0
|
223
|
nuclear@0
|
224 DefaultLogger::get()->debug("ScenePreprocessor: Dummy rotation track has been generated");
|
nuclear@0
|
225 }
|
nuclear@0
|
226
|
nuclear@0
|
227 // No scaling keys? Generate a dummy track
|
nuclear@0
|
228 if (!channel->mNumScalingKeys) {
|
nuclear@0
|
229 channel->mNumScalingKeys = 1;
|
nuclear@0
|
230 channel->mScalingKeys = new aiVectorKey[1];
|
nuclear@0
|
231 aiVectorKey& q = channel->mScalingKeys[0];
|
nuclear@0
|
232
|
nuclear@0
|
233 q.mTime = 0.;
|
nuclear@0
|
234 q.mValue = scaling;
|
nuclear@0
|
235
|
nuclear@0
|
236 DefaultLogger::get()->debug("ScenePreprocessor: Dummy scaling track has been generated");
|
nuclear@0
|
237 }
|
nuclear@0
|
238
|
nuclear@0
|
239 // No position keys? Generate a dummy track
|
nuclear@0
|
240 if (!channel->mNumPositionKeys) {
|
nuclear@0
|
241 channel->mNumPositionKeys = 1;
|
nuclear@0
|
242 channel->mPositionKeys = new aiVectorKey[1];
|
nuclear@0
|
243 aiVectorKey& q = channel->mPositionKeys[0];
|
nuclear@0
|
244
|
nuclear@0
|
245 q.mTime = 0.;
|
nuclear@0
|
246 q.mValue = position;
|
nuclear@0
|
247
|
nuclear@0
|
248 DefaultLogger::get()->debug("ScenePreprocessor: Dummy position track has been generated");
|
nuclear@0
|
249 }
|
nuclear@0
|
250 }
|
nuclear@0
|
251 }
|
nuclear@0
|
252 }
|
nuclear@0
|
253
|
nuclear@0
|
254 if (anim->mDuration == -1.) {
|
nuclear@0
|
255 DefaultLogger::get()->debug("ScenePreprocessor: Setting animation duration");
|
nuclear@0
|
256 anim->mDuration = last - std::min( first, 0. );
|
nuclear@0
|
257 }
|
nuclear@0
|
258 }
|