vrshoot

annotate libs/assimp/ScenePreprocessor.cpp @ 0:b2f14e535253

initial commit
author John Tsiombikas <nuclear@member.fsf.org>
date Sat, 01 Feb 2014 19:58:19 +0200
parents
children
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 }