vrshoot

annotate libs/assimp/FBXMeshGeometry.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 /** @file FBXMeshGeometry.cpp
nuclear@0 42 * @brief Assimp::FBX::MeshGeometry implementation
nuclear@0 43 */
nuclear@0 44 #include "AssimpPCH.h"
nuclear@0 45
nuclear@0 46 #ifndef ASSIMP_BUILD_NO_FBX_IMPORTER
nuclear@0 47
nuclear@0 48 #include <functional>
nuclear@0 49
nuclear@0 50 #include "FBXParser.h"
nuclear@0 51 #include "FBXDocument.h"
nuclear@0 52 #include "FBXImporter.h"
nuclear@0 53 #include "FBXImportSettings.h"
nuclear@0 54 #include "FBXDocumentUtil.h"
nuclear@0 55
nuclear@0 56
nuclear@0 57 namespace Assimp {
nuclear@0 58 namespace FBX {
nuclear@0 59
nuclear@0 60 using namespace Util;
nuclear@0 61
nuclear@0 62
nuclear@0 63 // ------------------------------------------------------------------------------------------------
nuclear@0 64 Geometry::Geometry(uint64_t id, const Element& element, const std::string& name, const Document& doc)
nuclear@0 65 : Object(id, element,name)
nuclear@0 66 , skin()
nuclear@0 67 {
nuclear@0 68 const std::vector<const Connection*>& conns = doc.GetConnectionsByDestinationSequenced(ID(),"Deformer");
nuclear@0 69 BOOST_FOREACH(const Connection* con, conns) {
nuclear@0 70 const Skin* const sk = ProcessSimpleConnection<Skin>(*con, false, "Skin -> Geometry", element);
nuclear@0 71 if(sk) {
nuclear@0 72 skin = sk;
nuclear@0 73 break;
nuclear@0 74 }
nuclear@0 75 }
nuclear@0 76 }
nuclear@0 77
nuclear@0 78
nuclear@0 79 // ------------------------------------------------------------------------------------------------
nuclear@0 80 Geometry::~Geometry()
nuclear@0 81 {
nuclear@0 82
nuclear@0 83 }
nuclear@0 84
nuclear@0 85
nuclear@0 86
nuclear@0 87 // ------------------------------------------------------------------------------------------------
nuclear@0 88 MeshGeometry::MeshGeometry(uint64_t id, const Element& element, const std::string& name, const Document& doc)
nuclear@0 89 : Geometry(id, element,name, doc)
nuclear@0 90 {
nuclear@0 91 const Scope* sc = element.Compound();
nuclear@0 92 if (!sc) {
nuclear@0 93 DOMError("failed to read Geometry object (class: Mesh), no data scope found");
nuclear@0 94 }
nuclear@0 95
nuclear@0 96 // must have Mesh elements:
nuclear@0 97 const Element& Vertices = GetRequiredElement(*sc,"Vertices",&element);
nuclear@0 98 const Element& PolygonVertexIndex = GetRequiredElement(*sc,"PolygonVertexIndex",&element);
nuclear@0 99
nuclear@0 100 // optional Mesh elements:
nuclear@0 101 const ElementCollection& Layer = sc->GetCollection("Layer");
nuclear@0 102
nuclear@0 103 std::vector<aiVector3D> tempVerts;
nuclear@0 104 ParseVectorDataArray(tempVerts,Vertices);
nuclear@0 105
nuclear@0 106 if(tempVerts.empty()) {
nuclear@0 107 FBXImporter::LogWarn("encountered mesh with no vertices");
nuclear@0 108 return;
nuclear@0 109 }
nuclear@0 110
nuclear@0 111 std::vector<int> tempFaces;
nuclear@0 112 ParseVectorDataArray(tempFaces,PolygonVertexIndex);
nuclear@0 113
nuclear@0 114 if(tempFaces.empty()) {
nuclear@0 115 FBXImporter::LogWarn("encountered mesh with no faces");
nuclear@0 116 return;
nuclear@0 117 }
nuclear@0 118
nuclear@0 119 vertices.reserve(tempFaces.size());
nuclear@0 120 faces.reserve(tempFaces.size() / 3);
nuclear@0 121
nuclear@0 122 mapping_offsets.resize(tempVerts.size());
nuclear@0 123 mapping_counts.resize(tempVerts.size(),0);
nuclear@0 124 mappings.resize(tempFaces.size());
nuclear@0 125
nuclear@0 126 const size_t vertex_count = tempVerts.size();
nuclear@0 127
nuclear@0 128 // generate output vertices, computing an adjacency table to
nuclear@0 129 // preserve the mapping from fbx indices to *this* indexing.
nuclear@0 130 unsigned int count = 0;
nuclear@0 131 BOOST_FOREACH(int index, tempFaces) {
nuclear@0 132 const int absi = index < 0 ? (-index - 1) : index;
nuclear@0 133 if(static_cast<size_t>(absi) >= vertex_count) {
nuclear@0 134 DOMError("polygon vertex index out of range",&PolygonVertexIndex);
nuclear@0 135 }
nuclear@0 136
nuclear@0 137 vertices.push_back(tempVerts[absi]);
nuclear@0 138 ++count;
nuclear@0 139
nuclear@0 140 ++mapping_counts[absi];
nuclear@0 141
nuclear@0 142 if (index < 0) {
nuclear@0 143 faces.push_back(count);
nuclear@0 144 count = 0;
nuclear@0 145 }
nuclear@0 146 }
nuclear@0 147
nuclear@0 148 unsigned int cursor = 0;
nuclear@0 149 for (size_t i = 0, e = tempVerts.size(); i < e; ++i) {
nuclear@0 150 mapping_offsets[i] = cursor;
nuclear@0 151 cursor += mapping_counts[i];
nuclear@0 152
nuclear@0 153 mapping_counts[i] = 0;
nuclear@0 154 }
nuclear@0 155
nuclear@0 156 cursor = 0;
nuclear@0 157 BOOST_FOREACH(int index, tempFaces) {
nuclear@0 158 const int absi = index < 0 ? (-index - 1) : index;
nuclear@0 159 mappings[mapping_offsets[absi] + mapping_counts[absi]++] = cursor++;
nuclear@0 160 }
nuclear@0 161
nuclear@0 162 // if settings.readAllLayers is true:
nuclear@0 163 // * read all layers, try to load as many vertex channels as possible
nuclear@0 164 // if settings.readAllLayers is false:
nuclear@0 165 // * read only the layer with index 0, but warn about any further layers
nuclear@0 166 for (ElementMap::const_iterator it = Layer.first; it != Layer.second; ++it) {
nuclear@0 167 const TokenList& tokens = (*it).second->Tokens();
nuclear@0 168
nuclear@0 169 const char* err;
nuclear@0 170 const int index = ParseTokenAsInt(*tokens[0], err);
nuclear@0 171 if(err) {
nuclear@0 172 DOMError(err,&element);
nuclear@0 173 }
nuclear@0 174
nuclear@0 175 if(doc.Settings().readAllLayers || index == 0) {
nuclear@0 176 const Scope& layer = GetRequiredScope(*(*it).second);
nuclear@0 177 ReadLayer(layer);
nuclear@0 178 }
nuclear@0 179 else {
nuclear@0 180 FBXImporter::LogWarn("ignoring additional geometry layers");
nuclear@0 181 }
nuclear@0 182 }
nuclear@0 183 }
nuclear@0 184
nuclear@0 185
nuclear@0 186 // ------------------------------------------------------------------------------------------------
nuclear@0 187 MeshGeometry::~MeshGeometry()
nuclear@0 188 {
nuclear@0 189
nuclear@0 190 }
nuclear@0 191
nuclear@0 192
nuclear@0 193
nuclear@0 194 // ------------------------------------------------------------------------------------------------
nuclear@0 195 void MeshGeometry::ReadLayer(const Scope& layer)
nuclear@0 196 {
nuclear@0 197 const ElementCollection& LayerElement = layer.GetCollection("LayerElement");
nuclear@0 198 for (ElementMap::const_iterator eit = LayerElement.first; eit != LayerElement.second; ++eit) {
nuclear@0 199 const Scope& elayer = GetRequiredScope(*(*eit).second);
nuclear@0 200
nuclear@0 201 ReadLayerElement(elayer);
nuclear@0 202 }
nuclear@0 203 }
nuclear@0 204
nuclear@0 205
nuclear@0 206 // ------------------------------------------------------------------------------------------------
nuclear@0 207 void MeshGeometry::ReadLayerElement(const Scope& layerElement)
nuclear@0 208 {
nuclear@0 209 const Element& Type = GetRequiredElement(layerElement,"Type");
nuclear@0 210 const Element& TypedIndex = GetRequiredElement(layerElement,"TypedIndex");
nuclear@0 211
nuclear@0 212 const std::string& type = ParseTokenAsString(GetRequiredToken(Type,0));
nuclear@0 213 const int typedIndex = ParseTokenAsInt(GetRequiredToken(TypedIndex,0));
nuclear@0 214
nuclear@0 215 const Scope& top = GetRequiredScope(element);
nuclear@0 216 const ElementCollection candidates = top.GetCollection(type);
nuclear@0 217
nuclear@0 218 for (ElementMap::const_iterator it = candidates.first; it != candidates.second; ++it) {
nuclear@0 219 const int index = ParseTokenAsInt(GetRequiredToken(*(*it).second,0));
nuclear@0 220 if(index == typedIndex) {
nuclear@0 221 ReadVertexData(type,typedIndex,GetRequiredScope(*(*it).second));
nuclear@0 222 return;
nuclear@0 223 }
nuclear@0 224 }
nuclear@0 225
nuclear@0 226 FBXImporter::LogError(Formatter::format("failed to resolve vertex layer element: ")
nuclear@0 227 << type << ", index: " << typedIndex);
nuclear@0 228 }
nuclear@0 229
nuclear@0 230
nuclear@0 231 // ------------------------------------------------------------------------------------------------
nuclear@0 232 void MeshGeometry::ReadVertexData(const std::string& type, int index, const Scope& source)
nuclear@0 233 {
nuclear@0 234 const std::string& MappingInformationType = ParseTokenAsString(GetRequiredToken(
nuclear@0 235 GetRequiredElement(source,"MappingInformationType"),0)
nuclear@0 236 );
nuclear@0 237
nuclear@0 238 const std::string& ReferenceInformationType = ParseTokenAsString(GetRequiredToken(
nuclear@0 239 GetRequiredElement(source,"ReferenceInformationType"),0)
nuclear@0 240 );
nuclear@0 241
nuclear@0 242 if (type == "LayerElementUV") {
nuclear@0 243 if(index >= AI_MAX_NUMBER_OF_TEXTURECOORDS) {
nuclear@0 244 FBXImporter::LogError(Formatter::format("ignoring UV layer, maximum number of UV channels exceeded: ")
nuclear@0 245 << index << " (limit is " << AI_MAX_NUMBER_OF_TEXTURECOORDS << ")" );
nuclear@0 246 return;
nuclear@0 247 }
nuclear@0 248
nuclear@0 249 const Element* Name = source["Name"];
nuclear@0 250 uvNames[index] = "";
nuclear@0 251 if(Name) {
nuclear@0 252 uvNames[index] = ParseTokenAsString(GetRequiredToken(*Name,0));
nuclear@0 253 }
nuclear@0 254
nuclear@0 255 ReadVertexDataUV(uvs[index],source,
nuclear@0 256 MappingInformationType,
nuclear@0 257 ReferenceInformationType
nuclear@0 258 );
nuclear@0 259 }
nuclear@0 260 else if (type == "LayerElementMaterial") {
nuclear@0 261 if (materials.size() > 0) {
nuclear@0 262 FBXImporter::LogError("ignoring additional material layer");
nuclear@0 263 return;
nuclear@0 264 }
nuclear@0 265
nuclear@0 266 std::vector<int> temp_materials;
nuclear@0 267
nuclear@0 268 ReadVertexDataMaterials(temp_materials,source,
nuclear@0 269 MappingInformationType,
nuclear@0 270 ReferenceInformationType
nuclear@0 271 );
nuclear@0 272
nuclear@0 273 // sometimes, there will be only negative entries. Drop the material
nuclear@0 274 // layer in such a case (I guess it means a default material should
nuclear@0 275 // be used). This is what the converter would do anyway, and it
nuclear@0 276 // avoids loosing the material if there are more material layers
nuclear@0 277 // coming of which at least one contains actual data (did observe
nuclear@0 278 // that with one test file).
nuclear@0 279 const size_t count_neg = std::count_if(temp_materials.begin(),temp_materials.end(),std::bind2nd(std::less<int>(),0));
nuclear@0 280 if(count_neg == temp_materials.size()) {
nuclear@0 281 FBXImporter::LogWarn("ignoring dummy material layer (all entries -1)");
nuclear@0 282 return;
nuclear@0 283 }
nuclear@0 284
nuclear@0 285 std::swap(temp_materials, materials);
nuclear@0 286 }
nuclear@0 287 else if (type == "LayerElementNormal") {
nuclear@0 288 if (normals.size() > 0) {
nuclear@0 289 FBXImporter::LogError("ignoring additional normal layer");
nuclear@0 290 return;
nuclear@0 291 }
nuclear@0 292
nuclear@0 293 ReadVertexDataNormals(normals,source,
nuclear@0 294 MappingInformationType,
nuclear@0 295 ReferenceInformationType
nuclear@0 296 );
nuclear@0 297 }
nuclear@0 298 else if (type == "LayerElementTangent") {
nuclear@0 299 if (tangents.size() > 0) {
nuclear@0 300 FBXImporter::LogError("ignoring additional tangent layer");
nuclear@0 301 return;
nuclear@0 302 }
nuclear@0 303
nuclear@0 304 ReadVertexDataTangents(tangents,source,
nuclear@0 305 MappingInformationType,
nuclear@0 306 ReferenceInformationType
nuclear@0 307 );
nuclear@0 308 }
nuclear@0 309 else if (type == "LayerElementBinormal") {
nuclear@0 310 if (binormals.size() > 0) {
nuclear@0 311 FBXImporter::LogError("ignoring additional binormal layer");
nuclear@0 312 return;
nuclear@0 313 }
nuclear@0 314
nuclear@0 315 ReadVertexDataBinormals(binormals,source,
nuclear@0 316 MappingInformationType,
nuclear@0 317 ReferenceInformationType
nuclear@0 318 );
nuclear@0 319 }
nuclear@0 320 else if (type == "LayerElementColor") {
nuclear@0 321 if(index >= AI_MAX_NUMBER_OF_COLOR_SETS) {
nuclear@0 322 FBXImporter::LogError(Formatter::format("ignoring vertex color layer, maximum number of color sets exceeded: ")
nuclear@0 323 << index << " (limit is " << AI_MAX_NUMBER_OF_COLOR_SETS << ")" );
nuclear@0 324 return;
nuclear@0 325 }
nuclear@0 326
nuclear@0 327 ReadVertexDataColors(colors[index],source,
nuclear@0 328 MappingInformationType,
nuclear@0 329 ReferenceInformationType
nuclear@0 330 );
nuclear@0 331 }
nuclear@0 332 }
nuclear@0 333
nuclear@0 334
nuclear@0 335 // ------------------------------------------------------------------------------------------------
nuclear@0 336 // Lengthy utility function to read and resolve a FBX vertex data array - that is, the
nuclear@0 337 // output is in polygon vertex order. This logic is used for reading normals, UVs, colors,
nuclear@0 338 // tangents ..
nuclear@0 339 template <typename T>
nuclear@0 340 void ResolveVertexDataArray(std::vector<T>& data_out, const Scope& source,
nuclear@0 341 const std::string& MappingInformationType,
nuclear@0 342 const std::string& ReferenceInformationType,
nuclear@0 343 const char* dataElementName,
nuclear@0 344 const char* indexDataElementName,
nuclear@0 345 size_t vertex_count,
nuclear@0 346 const std::vector<unsigned int>& mapping_counts,
nuclear@0 347 const std::vector<unsigned int>& mapping_offsets,
nuclear@0 348 const std::vector<unsigned int>& mappings)
nuclear@0 349 {
nuclear@0 350 std::vector<T> tempUV;
nuclear@0 351 ParseVectorDataArray(tempUV,GetRequiredElement(source,dataElementName));
nuclear@0 352
nuclear@0 353 // handle permutations of Mapping and Reference type - it would be nice to
nuclear@0 354 // deal with this more elegantly and with less redundancy, but right
nuclear@0 355 // now it seems unavoidable.
nuclear@0 356 if (MappingInformationType == "ByVertice" && ReferenceInformationType == "Direct") {
nuclear@0 357 data_out.resize(vertex_count);
nuclear@0 358 for (size_t i = 0, e = tempUV.size(); i < e; ++i) {
nuclear@0 359
nuclear@0 360 const unsigned int istart = mapping_offsets[i], iend = istart + mapping_counts[i];
nuclear@0 361 for (unsigned int j = istart; j < iend; ++j) {
nuclear@0 362 data_out[mappings[j]] = tempUV[i];
nuclear@0 363 }
nuclear@0 364 }
nuclear@0 365 }
nuclear@0 366 else if (MappingInformationType == "ByVertice" && ReferenceInformationType == "IndexToDirect") {
nuclear@0 367 data_out.resize(vertex_count);
nuclear@0 368
nuclear@0 369 std::vector<int> uvIndices;
nuclear@0 370 ParseVectorDataArray(uvIndices,GetRequiredElement(source,indexDataElementName));
nuclear@0 371
nuclear@0 372 for (size_t i = 0, e = uvIndices.size(); i < e; ++i) {
nuclear@0 373
nuclear@0 374 const unsigned int istart = mapping_offsets[i], iend = istart + mapping_counts[i];
nuclear@0 375 for (unsigned int j = istart; j < iend; ++j) {
nuclear@0 376 if(static_cast<size_t>(uvIndices[i]) >= tempUV.size()) {
nuclear@0 377 DOMError("index out of range",&GetRequiredElement(source,indexDataElementName));
nuclear@0 378 }
nuclear@0 379 data_out[mappings[j]] = tempUV[uvIndices[i]];
nuclear@0 380 }
nuclear@0 381 }
nuclear@0 382 }
nuclear@0 383 else if (MappingInformationType == "ByPolygonVertex" && ReferenceInformationType == "Direct") {
nuclear@0 384 if (tempUV.size() != vertex_count) {
nuclear@0 385 FBXImporter::LogError(Formatter::format("length of input data unexpected for ByPolygon mapping: ")
nuclear@0 386 << tempUV.size() << ", expected " << vertex_count
nuclear@0 387 );
nuclear@0 388 return;
nuclear@0 389 }
nuclear@0 390
nuclear@0 391 data_out.swap(tempUV);
nuclear@0 392 }
nuclear@0 393 else if (MappingInformationType == "ByPolygonVertex" && ReferenceInformationType == "IndexToDirect") {
nuclear@0 394 data_out.resize(vertex_count);
nuclear@0 395
nuclear@0 396 std::vector<int> uvIndices;
nuclear@0 397 ParseVectorDataArray(uvIndices,GetRequiredElement(source,indexDataElementName));
nuclear@0 398
nuclear@0 399 if (uvIndices.size() != vertex_count) {
nuclear@0 400 FBXImporter::LogError("length of input data unexpected for ByPolygonVertex mapping");
nuclear@0 401 return;
nuclear@0 402 }
nuclear@0 403
nuclear@0 404 unsigned int next = 0;
nuclear@0 405 BOOST_FOREACH(int i, uvIndices) {
nuclear@0 406 if(static_cast<size_t>(i) >= tempUV.size()) {
nuclear@0 407 DOMError("index out of range",&GetRequiredElement(source,indexDataElementName));
nuclear@0 408 }
nuclear@0 409
nuclear@0 410 data_out[next++] = tempUV[i];
nuclear@0 411 }
nuclear@0 412 }
nuclear@0 413 else {
nuclear@0 414 FBXImporter::LogError(Formatter::format("ignoring vertex data channel, access type not implemented: ")
nuclear@0 415 << MappingInformationType << "," << ReferenceInformationType);
nuclear@0 416 }
nuclear@0 417 }
nuclear@0 418
nuclear@0 419 // ------------------------------------------------------------------------------------------------
nuclear@0 420 void MeshGeometry::ReadVertexDataNormals(std::vector<aiVector3D>& normals_out, const Scope& source,
nuclear@0 421 const std::string& MappingInformationType,
nuclear@0 422 const std::string& ReferenceInformationType)
nuclear@0 423 {
nuclear@0 424 ResolveVertexDataArray(normals_out,source,MappingInformationType,ReferenceInformationType,
nuclear@0 425 "Normals",
nuclear@0 426 "NormalsIndex",
nuclear@0 427 vertices.size(),
nuclear@0 428 mapping_counts,
nuclear@0 429 mapping_offsets,
nuclear@0 430 mappings);
nuclear@0 431 }
nuclear@0 432
nuclear@0 433
nuclear@0 434 // ------------------------------------------------------------------------------------------------
nuclear@0 435 void MeshGeometry::ReadVertexDataUV(std::vector<aiVector2D>& uv_out, const Scope& source,
nuclear@0 436 const std::string& MappingInformationType,
nuclear@0 437 const std::string& ReferenceInformationType)
nuclear@0 438 {
nuclear@0 439 ResolveVertexDataArray(uv_out,source,MappingInformationType,ReferenceInformationType,
nuclear@0 440 "UV",
nuclear@0 441 "UVIndex",
nuclear@0 442 vertices.size(),
nuclear@0 443 mapping_counts,
nuclear@0 444 mapping_offsets,
nuclear@0 445 mappings);
nuclear@0 446 }
nuclear@0 447
nuclear@0 448
nuclear@0 449 // ------------------------------------------------------------------------------------------------
nuclear@0 450 void MeshGeometry::ReadVertexDataColors(std::vector<aiColor4D>& colors_out, const Scope& source,
nuclear@0 451 const std::string& MappingInformationType,
nuclear@0 452 const std::string& ReferenceInformationType)
nuclear@0 453 {
nuclear@0 454 ResolveVertexDataArray(colors_out,source,MappingInformationType,ReferenceInformationType,
nuclear@0 455 "Colors",
nuclear@0 456 "ColorIndex",
nuclear@0 457 vertices.size(),
nuclear@0 458 mapping_counts,
nuclear@0 459 mapping_offsets,
nuclear@0 460 mappings);
nuclear@0 461 }
nuclear@0 462
nuclear@0 463
nuclear@0 464 // ------------------------------------------------------------------------------------------------
nuclear@0 465 void MeshGeometry::ReadVertexDataTangents(std::vector<aiVector3D>& tangents_out, const Scope& source,
nuclear@0 466 const std::string& MappingInformationType,
nuclear@0 467 const std::string& ReferenceInformationType)
nuclear@0 468 {
nuclear@0 469 ResolveVertexDataArray(tangents_out,source,MappingInformationType,ReferenceInformationType,
nuclear@0 470 "Tangent",
nuclear@0 471 "TangentIndex",
nuclear@0 472 vertices.size(),
nuclear@0 473 mapping_counts,
nuclear@0 474 mapping_offsets,
nuclear@0 475 mappings);
nuclear@0 476 }
nuclear@0 477
nuclear@0 478
nuclear@0 479 // ------------------------------------------------------------------------------------------------
nuclear@0 480 void MeshGeometry::ReadVertexDataBinormals(std::vector<aiVector3D>& binormals_out, const Scope& source,
nuclear@0 481 const std::string& MappingInformationType,
nuclear@0 482 const std::string& ReferenceInformationType)
nuclear@0 483 {
nuclear@0 484 ResolveVertexDataArray(binormals_out,source,MappingInformationType,ReferenceInformationType,
nuclear@0 485 "Binormal",
nuclear@0 486 "BinormalIndex",
nuclear@0 487 vertices.size(),
nuclear@0 488 mapping_counts,
nuclear@0 489 mapping_offsets,
nuclear@0 490 mappings);
nuclear@0 491 }
nuclear@0 492
nuclear@0 493
nuclear@0 494 // ------------------------------------------------------------------------------------------------
nuclear@0 495 void MeshGeometry::ReadVertexDataMaterials(std::vector<int>& materials_out, const Scope& source,
nuclear@0 496 const std::string& MappingInformationType,
nuclear@0 497 const std::string& ReferenceInformationType)
nuclear@0 498 {
nuclear@0 499 const size_t face_count = faces.size();
nuclear@0 500 ai_assert(face_count);
nuclear@0 501
nuclear@0 502 // materials are handled separately. First of all, they are assigned per-face
nuclear@0 503 // and not per polyvert. Secondly, ReferenceInformationType=IndexToDirect
nuclear@0 504 // has a slightly different meaning for materials.
nuclear@0 505 ParseVectorDataArray(materials_out,GetRequiredElement(source,"Materials"));
nuclear@0 506
nuclear@0 507 if (MappingInformationType == "AllSame") {
nuclear@0 508 // easy - same material for all faces
nuclear@0 509 if (materials_out.empty()) {
nuclear@0 510 FBXImporter::LogError(Formatter::format("expected material index, ignoring"));
nuclear@0 511 return;
nuclear@0 512 }
nuclear@0 513 else if (materials_out.size() > 1) {
nuclear@0 514 FBXImporter::LogWarn(Formatter::format("expected only a single material index, ignoring all except the first one"));
nuclear@0 515 materials_out.clear();
nuclear@0 516 }
nuclear@0 517
nuclear@0 518 materials.assign(vertices.size(),materials_out[0]);
nuclear@0 519 }
nuclear@0 520 else if (MappingInformationType == "ByPolygon" && ReferenceInformationType == "IndexToDirect") {
nuclear@0 521 materials.resize(face_count);
nuclear@0 522
nuclear@0 523 if(materials_out.size() != face_count) {
nuclear@0 524 FBXImporter::LogError(Formatter::format("length of input data unexpected for ByPolygon mapping: ")
nuclear@0 525 << materials_out.size() << ", expected " << face_count
nuclear@0 526 );
nuclear@0 527 return;
nuclear@0 528 }
nuclear@0 529 }
nuclear@0 530 else {
nuclear@0 531 FBXImporter::LogError(Formatter::format("ignoring material assignments, access type not implemented: ")
nuclear@0 532 << MappingInformationType << "," << ReferenceInformationType);
nuclear@0 533 }
nuclear@0 534 }
nuclear@0 535
nuclear@0 536 } // !FBX
nuclear@0 537 } // !Assimp
nuclear@0 538
nuclear@0 539 #endif
nuclear@0 540