diff --git a/code/FBXAnimation.cpp b/code/FBXAnimation.cpp index 0f98ad411..75319684c 100644 --- a/code/FBXAnimation.cpp +++ b/code/FBXAnimation.cpp @@ -150,7 +150,8 @@ AnimationCurveNode::AnimationCurveNode(uint64_t id, const Element& element, cons continue; } - ai_assert(dynamic_cast(ob) || dynamic_cast(ob)); + // XXX support constraints as DOM class + //ai_assert(dynamic_cast(ob) || dynamic_cast(ob)); target = ob; if(!target) { continue; @@ -161,7 +162,7 @@ AnimationCurveNode::AnimationCurveNode(uint64_t id, const Element& element, cons } } if(!target) { - DOMError("failed to resolve target Model/NodeAttribute for AnimationCurveNode",&element); + DOMWarning("failed to resolve target Model/NodeAttribute/Constraint for AnimationCurveNode",&element); } } diff --git a/code/FBXConverter.cpp b/code/FBXConverter.cpp index fae11b32f..7c3ddc6f1 100644 --- a/code/FBXConverter.cpp +++ b/code/FBXConverter.cpp @@ -415,7 +415,7 @@ private: } if(doc.Settings().readWeights && mesh.DeformerSkin() != NULL) { - ConvertWeights(out_mesh, model, mesh, std::numeric_limits::max()); + ConvertWeights(out_mesh, model, mesh, NO_MATERIAL_SEPARATION); } return static_cast(meshes.size() - 1); @@ -452,6 +452,8 @@ private: const std::vector& vertices = mesh.GetVertices(); const std::vector& faces = mesh.GetFaceIndexCounts(); + const bool process_weights = doc.Settings().readWeights && mesh.DeformerSkin() != NULL; + unsigned int count_faces = 0; unsigned int count_vertices = 0; @@ -467,7 +469,14 @@ private: } ai_assert(count_faces); + ai_assert(count_vertices); + // mapping from output indices to DOM indexing, needed to resolve weights + std::vector reverseMapping; + + if (process_weights) { + reverseMapping.resize(count_vertices); + } // allocate output data arrays, but don't fill them yet out_mesh->mNumVertices = count_vertices; @@ -570,6 +579,10 @@ private: for (unsigned int i = 0; i < pcount; ++i, ++cursor, ++in_cursor) { f.mIndices[i] = cursor; + if(reverseMapping.size()) { + reverseMapping[cursor] = in_cursor; + } + out_mesh->mVertices[cursor] = vertices[in_cursor]; if(out_mesh->mNormals) { @@ -595,16 +608,25 @@ private: ConvertMaterialForMesh(out_mesh,model,mesh,index); - if(doc.Settings().readWeights && mesh.DeformerSkin() != NULL) { - ConvertWeights(out_mesh, model, mesh, index); + if(process_weights) { + ConvertWeights(out_mesh, model, mesh, index, &reverseMapping); } return static_cast(meshes.size() - 1); } + static const unsigned int NO_MATERIAL_SEPARATION = /* std::numeric_limits::max() */ + static_cast(-1); + // ------------------------------------------------------------------------------------------------ - void ConvertWeights(aiMesh* out, const Model& model, const MeshGeometry& geo, unsigned int materialIndex) + /** - if materialIndex == NO_MATERIAL_SEPARATION, materials are not taken into + * account when determining which weights to include. + * - outputVertStartIndices is only used when a material index is specified, it gives for + * each output vertex the DOM index it maps to. */ + void ConvertWeights(aiMesh* out, const Model& model, const MeshGeometry& geo, + unsigned int materialIndex = NO_MATERIAL_SEPARATION, + std::vector* outputVertStartIndices = NULL) { ai_assert(geo.DeformerSkin()); @@ -617,7 +639,8 @@ private: std::vector bones; bones.reserve(sk.Clusters().size()); - const bool no_mat_check = materialIndex == std::numeric_limits::max(); + const bool no_mat_check = materialIndex == NO_MATERIAL_SEPARATION; + ai_assert(!no_mat_check || outputVertStartIndices); try { @@ -649,20 +672,29 @@ private: const unsigned int* const out_idx = geo.ToOutputVertexIndex(index, count); index_out_indices.push_back(no_index_sentinel); + count_out_indices.push_back(0); - for(unsigned int i = 0; i < count; ++i) { - const unsigned int out_face_idx = geo.FaceForVertexIndex(out_idx[i]); - ai_assert(out_face_idx <= mats.size()); - - if (no_mat_check || mats[out_face_idx] == materialIndex) { + for(unsigned int i = 0; i < count; ++i) { + if (no_mat_check || mats[geo.FaceForVertexIndex(out_idx[i])] == materialIndex) { - if (index_out_indices.back() == no_index_sentinel) { index_out_indices.back() = out_indices.size(); - count_out_indices.push_back(0); + } - out_indices.push_back(out_idx[i]); + if (no_mat_check) { + out_indices.push_back(out_idx[i]); + } + else { + // this extra lookup is in O(logn), so the entire algorithm becomes O(nlogn) + const std::vector::iterator it = std::lower_bound( + outputVertStartIndices->begin(), + outputVertStartIndices->end(), + out_idx[i] + ); + + out_indices.push_back(std::distance(outputVertStartIndices->begin(), it)); + } ++count_out_indices.back(); ok = true; diff --git a/code/FBXDocument.h b/code/FBXDocument.h index 805b6e162..37c1469fc 100644 --- a/code/FBXDocument.h +++ b/code/FBXDocument.h @@ -491,13 +491,13 @@ public: } ai_assert(facesVertexStartIndices.size() == faces.size()); - const std::vector::const_iterator it = std::upper_bound( + const std::vector::iterator it = std::upper_bound( facesVertexStartIndices.begin(), facesVertexStartIndices.end(), in_index ); - return *(it - 1); + return static_cast(std::distance(facesVertexStartIndices.begin(), it - 1)); } public: @@ -619,8 +619,9 @@ public: return curves; } - /** Model or NodeAttribute the curve is assigned to, this is always non-NULL - * and never an objects not deriving one of the two aforementioned classes.*/ + /** Object the curve is assigned to, this can be NULL if the + * target object has no DOM representation or could not + * be read for other reasons.*/ const Object* Target() const { return target; }