vrshoot

annotate libs/assimp/Q3DLoader.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 ---------------------------------------------------------------------------
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 Q3DLoader.cpp
nuclear@0 43 * @brief Implementation of the Q3D importer class
nuclear@0 44 */
nuclear@0 45
nuclear@0 46 #include "AssimpPCH.h"
nuclear@0 47 #ifndef ASSIMP_BUILD_NO_Q3D_IMPORTER
nuclear@0 48
nuclear@0 49 // internal headers
nuclear@0 50 #include "Q3DLoader.h"
nuclear@0 51 #include "StreamReader.h"
nuclear@0 52 #include "fast_atof.h"
nuclear@0 53
nuclear@0 54 using namespace Assimp;
nuclear@0 55
nuclear@0 56 static const aiImporterDesc desc = {
nuclear@0 57 "Quick3D Importer",
nuclear@0 58 "",
nuclear@0 59 "",
nuclear@0 60 "http://www.quick3d.com/",
nuclear@0 61 aiImporterFlags_SupportBinaryFlavour,
nuclear@0 62 0,
nuclear@0 63 0,
nuclear@0 64 0,
nuclear@0 65 0,
nuclear@0 66 "q3o q3s"
nuclear@0 67 };
nuclear@0 68
nuclear@0 69 // ------------------------------------------------------------------------------------------------
nuclear@0 70 // Constructor to be privately used by Importer
nuclear@0 71 Q3DImporter::Q3DImporter()
nuclear@0 72 {}
nuclear@0 73
nuclear@0 74 // ------------------------------------------------------------------------------------------------
nuclear@0 75 // Destructor, private as well
nuclear@0 76 Q3DImporter::~Q3DImporter()
nuclear@0 77 {}
nuclear@0 78
nuclear@0 79 // ------------------------------------------------------------------------------------------------
nuclear@0 80 // Returns whether the class can handle the format of the given file.
nuclear@0 81 bool Q3DImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const
nuclear@0 82 {
nuclear@0 83 const std::string extension = GetExtension(pFile);
nuclear@0 84
nuclear@0 85 if (extension == "q3s" || extension == "q3o")
nuclear@0 86 return true;
nuclear@0 87 else if (!extension.length() || checkSig) {
nuclear@0 88 if (!pIOHandler)
nuclear@0 89 return true;
nuclear@0 90 const char* tokens[] = {"quick3Do","quick3Ds"};
nuclear@0 91 return SearchFileHeaderForToken(pIOHandler,pFile,tokens,2);
nuclear@0 92 }
nuclear@0 93 return false;
nuclear@0 94 }
nuclear@0 95
nuclear@0 96 // ------------------------------------------------------------------------------------------------
nuclear@0 97 const aiImporterDesc* Q3DImporter::GetInfo () const
nuclear@0 98 {
nuclear@0 99 return &desc;
nuclear@0 100 }
nuclear@0 101
nuclear@0 102 // ------------------------------------------------------------------------------------------------
nuclear@0 103 // Imports the given file into the given scene structure.
nuclear@0 104 void Q3DImporter::InternReadFile( const std::string& pFile,
nuclear@0 105 aiScene* pScene, IOSystem* pIOHandler)
nuclear@0 106 {
nuclear@0 107 StreamReaderLE stream(pIOHandler->Open(pFile,"rb"));
nuclear@0 108
nuclear@0 109 // The header is 22 bytes large
nuclear@0 110 if (stream.GetRemainingSize() < 22)
nuclear@0 111 throw DeadlyImportError("File is either empty or corrupt: " + pFile);
nuclear@0 112
nuclear@0 113 // Check the file's signature
nuclear@0 114 if (ASSIMP_strincmp( (const char*)stream.GetPtr(), "quick3Do", 8 ) &&
nuclear@0 115 ASSIMP_strincmp( (const char*)stream.GetPtr(), "quick3Ds", 8 ))
nuclear@0 116 {
nuclear@0 117 throw DeadlyImportError("Not a Quick3D file. Signature string is: " +
nuclear@0 118 std::string((const char*)stream.GetPtr(),8));
nuclear@0 119 }
nuclear@0 120
nuclear@0 121 // Print the file format version
nuclear@0 122 DefaultLogger::get()->info("Quick3D File format version: " +
nuclear@0 123 std::string(&((const char*)stream.GetPtr())[8],2));
nuclear@0 124
nuclear@0 125 // ... an store it
nuclear@0 126 char major = ((const char*)stream.GetPtr())[8];
nuclear@0 127 char minor = ((const char*)stream.GetPtr())[9];
nuclear@0 128
nuclear@0 129 stream.IncPtr(10);
nuclear@0 130 unsigned int numMeshes = (unsigned int)stream.GetI4();
nuclear@0 131 unsigned int numMats = (unsigned int)stream.GetI4();
nuclear@0 132 unsigned int numTextures = (unsigned int)stream.GetI4();
nuclear@0 133
nuclear@0 134 std::vector<Material> materials;
nuclear@0 135 materials.reserve(numMats);
nuclear@0 136
nuclear@0 137 std::vector<Mesh> meshes;
nuclear@0 138 meshes.reserve(numMeshes);
nuclear@0 139
nuclear@0 140 // Allocate the scene root node
nuclear@0 141 pScene->mRootNode = new aiNode();
nuclear@0 142
nuclear@0 143 aiColor3D fgColor (0.6f,0.6f,0.6f);
nuclear@0 144
nuclear@0 145 // Now read all file chunks
nuclear@0 146 while (true)
nuclear@0 147 {
nuclear@0 148 if (stream.GetRemainingSize() < 1)break;
nuclear@0 149 char c = stream.GetI1();
nuclear@0 150 switch (c)
nuclear@0 151 {
nuclear@0 152 // Meshes chunk
nuclear@0 153 case 'm':
nuclear@0 154 {
nuclear@0 155 for (unsigned int quak = 0; quak < numMeshes; ++quak)
nuclear@0 156 {
nuclear@0 157 meshes.push_back(Mesh());
nuclear@0 158 Mesh& mesh = meshes.back();
nuclear@0 159
nuclear@0 160 // read all vertices
nuclear@0 161 unsigned int numVerts = (unsigned int)stream.GetI4();
nuclear@0 162 if (!numVerts)
nuclear@0 163 throw DeadlyImportError("Quick3D: Found mesh with zero vertices");
nuclear@0 164
nuclear@0 165 std::vector<aiVector3D>& verts = mesh.verts;
nuclear@0 166 verts.resize(numVerts);
nuclear@0 167
nuclear@0 168 for (unsigned int i = 0; i < numVerts;++i)
nuclear@0 169 {
nuclear@0 170 verts[i].x = stream.GetF4();
nuclear@0 171 verts[i].y = stream.GetF4();
nuclear@0 172 verts[i].z = stream.GetF4();
nuclear@0 173 }
nuclear@0 174
nuclear@0 175 // read all faces
nuclear@0 176 numVerts = (unsigned int)stream.GetI4();
nuclear@0 177 if (!numVerts)
nuclear@0 178 throw DeadlyImportError("Quick3D: Found mesh with zero faces");
nuclear@0 179
nuclear@0 180 std::vector<Face >& faces = mesh.faces;
nuclear@0 181 faces.reserve(numVerts);
nuclear@0 182
nuclear@0 183 // number of indices
nuclear@0 184 for (unsigned int i = 0; i < numVerts;++i)
nuclear@0 185 {
nuclear@0 186 faces.push_back(Face(stream.GetI2()) );
nuclear@0 187 if (faces.back().indices.empty())
nuclear@0 188 throw DeadlyImportError("Quick3D: Found face with zero indices");
nuclear@0 189 }
nuclear@0 190
nuclear@0 191 // indices
nuclear@0 192 for (unsigned int i = 0; i < numVerts;++i)
nuclear@0 193 {
nuclear@0 194 Face& vec = faces[i];
nuclear@0 195 for (unsigned int a = 0; a < (unsigned int)vec.indices.size();++a)
nuclear@0 196 vec.indices[a] = stream.GetI4();
nuclear@0 197 }
nuclear@0 198
nuclear@0 199 // material indices
nuclear@0 200 for (unsigned int i = 0; i < numVerts;++i)
nuclear@0 201 {
nuclear@0 202 faces[i].mat = (unsigned int)stream.GetI4();
nuclear@0 203 }
nuclear@0 204
nuclear@0 205 // read all normals
nuclear@0 206 numVerts = (unsigned int)stream.GetI4();
nuclear@0 207 std::vector<aiVector3D>& normals = mesh.normals;
nuclear@0 208 normals.resize(numVerts);
nuclear@0 209
nuclear@0 210 for (unsigned int i = 0; i < numVerts;++i)
nuclear@0 211 {
nuclear@0 212 normals[i].x = stream.GetF4();
nuclear@0 213 normals[i].y = stream.GetF4();
nuclear@0 214 normals[i].z = stream.GetF4();
nuclear@0 215 }
nuclear@0 216
nuclear@0 217 numVerts = (unsigned int)stream.GetI4();
nuclear@0 218 if (numTextures && numVerts)
nuclear@0 219 {
nuclear@0 220 // read all texture coordinates
nuclear@0 221 std::vector<aiVector3D>& uv = mesh.uv;
nuclear@0 222 uv.resize(numVerts);
nuclear@0 223
nuclear@0 224 for (unsigned int i = 0; i < numVerts;++i)
nuclear@0 225 {
nuclear@0 226 uv[i].x = stream.GetF4();
nuclear@0 227 uv[i].y = stream.GetF4();
nuclear@0 228 }
nuclear@0 229
nuclear@0 230 // UV indices
nuclear@0 231 for (unsigned int i = 0; i < (unsigned int)faces.size();++i)
nuclear@0 232 {
nuclear@0 233 Face& vec = faces[i];
nuclear@0 234 for (unsigned int a = 0; a < (unsigned int)vec.indices.size();++a)
nuclear@0 235 {
nuclear@0 236 vec.uvindices[a] = stream.GetI4();
nuclear@0 237 if (!i && !a)
nuclear@0 238 mesh.prevUVIdx = vec.uvindices[a];
nuclear@0 239 else if (vec.uvindices[a] != mesh.prevUVIdx)
nuclear@0 240 mesh.prevUVIdx = UINT_MAX;
nuclear@0 241 }
nuclear@0 242 }
nuclear@0 243 }
nuclear@0 244
nuclear@0 245 // we don't need the rest, but we need to get to the next chunk
nuclear@0 246 stream.IncPtr(36);
nuclear@0 247 if (minor > '0' && major == '3')
nuclear@0 248 stream.IncPtr(mesh.faces.size());
nuclear@0 249 }
nuclear@0 250 // stream.IncPtr(4); // unknown value here
nuclear@0 251 }
nuclear@0 252 break;
nuclear@0 253
nuclear@0 254 // materials chunk
nuclear@0 255 case 'c':
nuclear@0 256
nuclear@0 257 for (unsigned int i = 0; i < numMats; ++i)
nuclear@0 258 {
nuclear@0 259 materials.push_back(Material());
nuclear@0 260 Material& mat = materials.back();
nuclear@0 261
nuclear@0 262 // read the material name
nuclear@0 263 while (( c = stream.GetI1()))
nuclear@0 264 mat.name.data[mat.name.length++] = c;
nuclear@0 265
nuclear@0 266 // add the terminal character
nuclear@0 267 mat.name.data[mat.name.length] = '\0';
nuclear@0 268
nuclear@0 269 // read the ambient color
nuclear@0 270 mat.ambient.r = stream.GetF4();
nuclear@0 271 mat.ambient.g = stream.GetF4();
nuclear@0 272 mat.ambient.b = stream.GetF4();
nuclear@0 273
nuclear@0 274 // read the diffuse color
nuclear@0 275 mat.diffuse.r = stream.GetF4();
nuclear@0 276 mat.diffuse.g = stream.GetF4();
nuclear@0 277 mat.diffuse.b = stream.GetF4();
nuclear@0 278
nuclear@0 279 // read the ambient color
nuclear@0 280 mat.specular.r = stream.GetF4();
nuclear@0 281 mat.specular.g = stream.GetF4();
nuclear@0 282 mat.specular.b = stream.GetF4();
nuclear@0 283
nuclear@0 284 // read the transparency
nuclear@0 285 mat.transparency = stream.GetF4();
nuclear@0 286
nuclear@0 287 // unknown value here
nuclear@0 288 // stream.IncPtr(4);
nuclear@0 289 // FIX: it could be the texture index ...
nuclear@0 290 mat.texIdx = (unsigned int)stream.GetI4();
nuclear@0 291 }
nuclear@0 292
nuclear@0 293 break;
nuclear@0 294
nuclear@0 295 // texture chunk
nuclear@0 296 case 't':
nuclear@0 297
nuclear@0 298 pScene->mNumTextures = numTextures;
nuclear@0 299 if (!numTextures)break;
nuclear@0 300 pScene->mTextures = new aiTexture*[pScene->mNumTextures];
nuclear@0 301 // to make sure we won't crash if we leave through an exception
nuclear@0 302 ::memset(pScene->mTextures,0,sizeof(void*)*pScene->mNumTextures);
nuclear@0 303 for (unsigned int i = 0; i < pScene->mNumTextures; ++i)
nuclear@0 304 {
nuclear@0 305 aiTexture* tex = pScene->mTextures[i] = new aiTexture();
nuclear@0 306
nuclear@0 307 // skip the texture name
nuclear@0 308 while (stream.GetI1());
nuclear@0 309
nuclear@0 310 // read texture width and height
nuclear@0 311 tex->mWidth = (unsigned int)stream.GetI4();
nuclear@0 312 tex->mHeight = (unsigned int)stream.GetI4();
nuclear@0 313
nuclear@0 314 if (!tex->mWidth || !tex->mHeight)
nuclear@0 315 throw DeadlyImportError("Quick3D: Invalid texture. Width or height is zero");
nuclear@0 316
nuclear@0 317 register unsigned int mul = tex->mWidth * tex->mHeight;
nuclear@0 318 aiTexel* begin = tex->pcData = new aiTexel[mul];
nuclear@0 319 aiTexel* const end = & begin [mul];
nuclear@0 320
nuclear@0 321 for (;begin != end; ++begin)
nuclear@0 322 {
nuclear@0 323 begin->r = stream.GetI1();
nuclear@0 324 begin->g = stream.GetI1();
nuclear@0 325 begin->b = stream.GetI1();
nuclear@0 326 begin->a = 0xff;
nuclear@0 327 }
nuclear@0 328 }
nuclear@0 329
nuclear@0 330 break;
nuclear@0 331
nuclear@0 332 // scene chunk
nuclear@0 333 case 's':
nuclear@0 334 {
nuclear@0 335 // skip position and rotation
nuclear@0 336 stream.IncPtr(12);
nuclear@0 337
nuclear@0 338 for (unsigned int i = 0; i < 4;++i)
nuclear@0 339 for (unsigned int a = 0; a < 4;++a)
nuclear@0 340 pScene->mRootNode->mTransformation[i][a] = stream.GetF4();
nuclear@0 341
nuclear@0 342 stream.IncPtr(16);
nuclear@0 343
nuclear@0 344 // now setup a single camera
nuclear@0 345 pScene->mNumCameras = 1;
nuclear@0 346 pScene->mCameras = new aiCamera*[1];
nuclear@0 347 aiCamera* cam = pScene->mCameras[0] = new aiCamera();
nuclear@0 348 cam->mPosition.x = stream.GetF4();
nuclear@0 349 cam->mPosition.y = stream.GetF4();
nuclear@0 350 cam->mPosition.z = stream.GetF4();
nuclear@0 351 cam->mName.Set("Q3DCamera");
nuclear@0 352
nuclear@0 353 // skip eye rotation for the moment
nuclear@0 354 stream.IncPtr(12);
nuclear@0 355
nuclear@0 356 // read the default material color
nuclear@0 357 fgColor .r = stream.GetF4();
nuclear@0 358 fgColor .g = stream.GetF4();
nuclear@0 359 fgColor .b = stream.GetF4();
nuclear@0 360
nuclear@0 361 // skip some unimportant properties
nuclear@0 362 stream.IncPtr(29);
nuclear@0 363
nuclear@0 364 // setup a single point light with no attenuation
nuclear@0 365 pScene->mNumLights = 1;
nuclear@0 366 pScene->mLights = new aiLight*[1];
nuclear@0 367 aiLight* light = pScene->mLights[0] = new aiLight();
nuclear@0 368 light->mName.Set("Q3DLight");
nuclear@0 369 light->mType = aiLightSource_POINT;
nuclear@0 370
nuclear@0 371 light->mAttenuationConstant = 1;
nuclear@0 372 light->mAttenuationLinear = 0;
nuclear@0 373 light->mAttenuationQuadratic = 0;
nuclear@0 374
nuclear@0 375 light->mColorDiffuse.r = stream.GetF4();
nuclear@0 376 light->mColorDiffuse.g = stream.GetF4();
nuclear@0 377 light->mColorDiffuse.b = stream.GetF4();
nuclear@0 378
nuclear@0 379 light->mColorSpecular = light->mColorDiffuse;
nuclear@0 380
nuclear@0 381
nuclear@0 382 // We don't need the rest, but we need to know where this chunk ends.
nuclear@0 383 unsigned int temp = (unsigned int)(stream.GetI4() * stream.GetI4());
nuclear@0 384
nuclear@0 385 // skip the background file name
nuclear@0 386 while (stream.GetI1());
nuclear@0 387
nuclear@0 388 // skip background texture data + the remaining fields
nuclear@0 389 stream.IncPtr(temp*3 + 20); // 4 bytes of unknown data here
nuclear@0 390
nuclear@0 391 // TODO
nuclear@0 392 goto outer;
nuclear@0 393 }
nuclear@0 394 break;
nuclear@0 395
nuclear@0 396 default:
nuclear@0 397 throw DeadlyImportError("Quick3D: Unknown chunk");
nuclear@0 398 break;
nuclear@0 399 };
nuclear@0 400 }
nuclear@0 401 outer:
nuclear@0 402
nuclear@0 403 // If we have no mesh loaded - break here
nuclear@0 404 if (meshes.empty())
nuclear@0 405 throw DeadlyImportError("Quick3D: No meshes loaded");
nuclear@0 406
nuclear@0 407 // If we have no materials loaded - generate a default mat
nuclear@0 408 if (materials.empty())
nuclear@0 409 {
nuclear@0 410 DefaultLogger::get()->info("Quick3D: No material found, generating one");
nuclear@0 411 materials.push_back(Material());
nuclear@0 412 materials.back().diffuse = fgColor ;
nuclear@0 413 }
nuclear@0 414
nuclear@0 415 // find out which materials we'll need
nuclear@0 416 typedef std::pair<unsigned int, unsigned int> FaceIdx;
nuclear@0 417 typedef std::vector< FaceIdx > FaceIdxArray;
nuclear@0 418 FaceIdxArray* fidx = new FaceIdxArray[materials.size()];
nuclear@0 419
nuclear@0 420 unsigned int p = 0;
nuclear@0 421 for (std::vector<Mesh>::iterator it = meshes.begin(), end = meshes.end();
nuclear@0 422 it != end; ++it,++p)
nuclear@0 423 {
nuclear@0 424 unsigned int q = 0;
nuclear@0 425 for (std::vector<Face>::iterator fit = (*it).faces.begin(), fend = (*it).faces.end();
nuclear@0 426 fit != fend; ++fit,++q)
nuclear@0 427 {
nuclear@0 428 if ((*fit).mat >= materials.size())
nuclear@0 429 {
nuclear@0 430 DefaultLogger::get()->warn("Quick3D: Material index overflow");
nuclear@0 431 (*fit).mat = 0;
nuclear@0 432 }
nuclear@0 433 if (fidx[(*fit).mat].empty())++pScene->mNumMeshes;
nuclear@0 434 fidx[(*fit).mat].push_back( FaceIdx(p,q) );
nuclear@0 435 }
nuclear@0 436 }
nuclear@0 437 pScene->mNumMaterials = pScene->mNumMeshes;
nuclear@0 438 pScene->mMaterials = new aiMaterial*[pScene->mNumMaterials];
nuclear@0 439 pScene->mMeshes = new aiMesh*[pScene->mNumMaterials];
nuclear@0 440
nuclear@0 441 for (unsigned int i = 0, real = 0; i < (unsigned int)materials.size(); ++i)
nuclear@0 442 {
nuclear@0 443 if (fidx[i].empty())continue;
nuclear@0 444
nuclear@0 445 // Allocate a mesh and a material
nuclear@0 446 aiMesh* mesh = pScene->mMeshes[real] = new aiMesh();
nuclear@0 447 aiMaterial* mat = new aiMaterial();
nuclear@0 448 pScene->mMaterials[real] = mat;
nuclear@0 449
nuclear@0 450 mesh->mMaterialIndex = real;
nuclear@0 451
nuclear@0 452 // Build the output material
nuclear@0 453 Material& srcMat = materials[i];
nuclear@0 454 mat->AddProperty(&srcMat.diffuse, 1,AI_MATKEY_COLOR_DIFFUSE);
nuclear@0 455 mat->AddProperty(&srcMat.specular, 1,AI_MATKEY_COLOR_SPECULAR);
nuclear@0 456 mat->AddProperty(&srcMat.ambient, 1,AI_MATKEY_COLOR_AMBIENT);
nuclear@0 457
nuclear@0 458 // NOTE: Ignore transparency for the moment - it seems
nuclear@0 459 // unclear how to interpret the data
nuclear@0 460 #if 0
nuclear@0 461 if (!(minor > '0' && major == '3'))
nuclear@0 462 srcMat.transparency = 1.0f - srcMat.transparency;
nuclear@0 463 mat->AddProperty(&srcMat.transparency, 1, AI_MATKEY_OPACITY);
nuclear@0 464 #endif
nuclear@0 465
nuclear@0 466 // add shininess - Quick3D seems to use it ins its viewer
nuclear@0 467 srcMat.transparency = 16.f;
nuclear@0 468 mat->AddProperty(&srcMat.transparency, 1, AI_MATKEY_SHININESS);
nuclear@0 469
nuclear@0 470 int m = (int)aiShadingMode_Phong;
nuclear@0 471 mat->AddProperty(&m, 1, AI_MATKEY_SHADING_MODEL);
nuclear@0 472
nuclear@0 473 if (srcMat.name.length)
nuclear@0 474 mat->AddProperty(&srcMat.name,AI_MATKEY_NAME);
nuclear@0 475
nuclear@0 476 // Add a texture
nuclear@0 477 if (srcMat.texIdx < pScene->mNumTextures || real < pScene->mNumTextures)
nuclear@0 478 {
nuclear@0 479 srcMat.name.data[0] = '*';
nuclear@0 480 srcMat.name.length = ASSIMP_itoa10(&srcMat.name.data[1],1000,
nuclear@0 481 (srcMat.texIdx < pScene->mNumTextures ? srcMat.texIdx : real));
nuclear@0 482 mat->AddProperty(&srcMat.name,AI_MATKEY_TEXTURE_DIFFUSE(0));
nuclear@0 483 }
nuclear@0 484
nuclear@0 485 mesh->mNumFaces = (unsigned int)fidx[i].size();
nuclear@0 486 aiFace* faces = mesh->mFaces = new aiFace[mesh->mNumFaces];
nuclear@0 487
nuclear@0 488 // Now build the output mesh. First find out how many
nuclear@0 489 // vertices we'll need
nuclear@0 490 for (FaceIdxArray::const_iterator it = fidx[i].begin(),end = fidx[i].end();
nuclear@0 491 it != end; ++it)
nuclear@0 492 {
nuclear@0 493 mesh->mNumVertices += (unsigned int)meshes[(*it).first].faces[
nuclear@0 494 (*it).second].indices.size();
nuclear@0 495 }
nuclear@0 496
nuclear@0 497 aiVector3D* verts = mesh->mVertices = new aiVector3D[mesh->mNumVertices];
nuclear@0 498 aiVector3D* norms = mesh->mNormals = new aiVector3D[mesh->mNumVertices];
nuclear@0 499 aiVector3D* uv;
nuclear@0 500 if (real < pScene->mNumTextures)
nuclear@0 501 {
nuclear@0 502 uv = mesh->mTextureCoords[0] = new aiVector3D[mesh->mNumVertices];
nuclear@0 503 mesh->mNumUVComponents[0] = 2;
nuclear@0 504 }
nuclear@0 505 else uv = NULL;
nuclear@0 506
nuclear@0 507 // Build the final array
nuclear@0 508 unsigned int cnt = 0;
nuclear@0 509 for (FaceIdxArray::const_iterator it = fidx[i].begin(),end = fidx[i].end();
nuclear@0 510 it != end; ++it, ++faces)
nuclear@0 511 {
nuclear@0 512 Mesh& m = meshes[(*it).first];
nuclear@0 513 Face& face = m.faces[(*it).second];
nuclear@0 514 faces->mNumIndices = (unsigned int)face.indices.size();
nuclear@0 515 faces->mIndices = new unsigned int [faces->mNumIndices];
nuclear@0 516
nuclear@0 517
nuclear@0 518 aiVector3D faceNormal;
nuclear@0 519 bool fnOK = false;
nuclear@0 520
nuclear@0 521 for (unsigned int n = 0; n < faces->mNumIndices;++n, ++cnt, ++norms, ++verts)
nuclear@0 522 {
nuclear@0 523 if (face.indices[n] >= m.verts.size())
nuclear@0 524 {
nuclear@0 525 DefaultLogger::get()->warn("Quick3D: Vertex index overflow");
nuclear@0 526 face.indices[n] = 0;
nuclear@0 527 }
nuclear@0 528
nuclear@0 529 // copy vertices
nuclear@0 530 *verts = m.verts[ face.indices[n] ];
nuclear@0 531
nuclear@0 532 if (face.indices[n] >= m.normals.size() && faces->mNumIndices >= 3)
nuclear@0 533 {
nuclear@0 534 // we have no normal here - assign the face normal
nuclear@0 535 if (!fnOK)
nuclear@0 536 {
nuclear@0 537 const aiVector3D& pV1 = m.verts[ face.indices[0] ];
nuclear@0 538 const aiVector3D& pV2 = m.verts[ face.indices[1] ];
nuclear@0 539 const aiVector3D& pV3 = m.verts[ face.indices.size() - 1 ];
nuclear@0 540 faceNormal = (pV2 - pV1) ^ (pV3 - pV1).Normalize();
nuclear@0 541 fnOK = true;
nuclear@0 542 }
nuclear@0 543 *norms = faceNormal;
nuclear@0 544 }
nuclear@0 545 else *norms = m.normals[ face.indices[n] ];
nuclear@0 546
nuclear@0 547 // copy texture coordinates
nuclear@0 548 if (uv && m.uv.size())
nuclear@0 549 {
nuclear@0 550 if (m.prevUVIdx != 0xffffffff && m.uv.size() >= m.verts.size()) // workaround
nuclear@0 551 {
nuclear@0 552 *uv = m.uv[face.indices[n]];
nuclear@0 553 }
nuclear@0 554 else
nuclear@0 555 {
nuclear@0 556 if (face.uvindices[n] >= m.uv.size())
nuclear@0 557 {
nuclear@0 558 DefaultLogger::get()->warn("Quick3D: Texture coordinate index overflow");
nuclear@0 559 face.uvindices[n] = 0;
nuclear@0 560 }
nuclear@0 561 *uv = m.uv[face.uvindices[n]];
nuclear@0 562 }
nuclear@0 563 uv->y = 1.f - uv->y;
nuclear@0 564 ++uv;
nuclear@0 565 }
nuclear@0 566
nuclear@0 567 // setup the new vertex index
nuclear@0 568 faces->mIndices[n] = cnt;
nuclear@0 569 }
nuclear@0 570
nuclear@0 571 }
nuclear@0 572 ++real;
nuclear@0 573 }
nuclear@0 574
nuclear@0 575 // Delete our nice helper array
nuclear@0 576 delete[] fidx;
nuclear@0 577
nuclear@0 578 // Now we need to attach the meshes to the root node of the scene
nuclear@0 579 pScene->mRootNode->mNumMeshes = pScene->mNumMeshes;
nuclear@0 580 pScene->mRootNode->mMeshes = new unsigned int [pScene->mNumMeshes];
nuclear@0 581 for (unsigned int i = 0; i < pScene->mNumMeshes;++i)
nuclear@0 582 pScene->mRootNode->mMeshes[i] = i;
nuclear@0 583
nuclear@0 584 /*pScene->mRootNode->mTransformation *= aiMatrix4x4(
nuclear@0 585 1.f, 0.f, 0.f, 0.f,
nuclear@0 586 0.f, -1.f,0.f, 0.f,
nuclear@0 587 0.f, 0.f, 1.f, 0.f,
nuclear@0 588 0.f, 0.f, 0.f, 1.f);*/
nuclear@0 589
nuclear@0 590 // Add cameras and light sources to the scene root node
nuclear@0 591 pScene->mRootNode->mNumChildren = pScene->mNumLights+pScene->mNumCameras;
nuclear@0 592 if (pScene->mRootNode->mNumChildren)
nuclear@0 593 {
nuclear@0 594 pScene->mRootNode->mChildren = new aiNode* [ pScene->mRootNode->mNumChildren ];
nuclear@0 595
nuclear@0 596 // the light source
nuclear@0 597 aiNode* nd = pScene->mRootNode->mChildren[0] = new aiNode();
nuclear@0 598 nd->mParent = pScene->mRootNode;
nuclear@0 599 nd->mName.Set("Q3DLight");
nuclear@0 600 nd->mTransformation = pScene->mRootNode->mTransformation;
nuclear@0 601 nd->mTransformation.Inverse();
nuclear@0 602
nuclear@0 603 // camera
nuclear@0 604 nd = pScene->mRootNode->mChildren[1] = new aiNode();
nuclear@0 605 nd->mParent = pScene->mRootNode;
nuclear@0 606 nd->mName.Set("Q3DCamera");
nuclear@0 607 nd->mTransformation = pScene->mRootNode->mChildren[0]->mTransformation;
nuclear@0 608 }
nuclear@0 609 }
nuclear@0 610
nuclear@0 611 #endif // !! ASSIMP_BUILD_NO_Q3D_IMPORTER