// ------------------------------------------------------------------------------------------------ // read an array of floats void ParseVectorDataArray(std::vector<float>& out, const Element& el) { out.resize( 0 ); const TokenList& tok = el.Tokens(); if(tok.empty()) { ParseError("unexpected empty element",&el); } if(tok[0]->IsBinary()) { const char* data = tok[0]->begin(), *end = tok[0]->end(); char type; uint32_t count; ReadBinaryDataArrayHead(data, end, type, count, el); if(!count) { return; } if (type != 'd' && type != 'f') { ParseError("expected float or double array (binary)",&el); } std::vector<char> buff; ReadBinaryDataArray(type, count, data, end, buff, el); ai_assert(data == end); ai_assert(buff.size() == count * (type == 'd' ? 8 : 4)); if (type == 'd') { const double* d = reinterpret_cast<const double*>(&buff[0]); for (unsigned int i = 0; i < count; ++i, ++d) { out.push_back(static_cast<float>(*d)); } } else if (type == 'f') { const float* f = reinterpret_cast<const float*>(&buff[0]); for (unsigned int i = 0; i < count; ++i, ++f) { out.push_back(*f); } } return; } const size_t dim = ParseTokenAsDim(*tok[0]); // see notes in ParseVectorDataArray() out.reserve(dim); const Scope& scope = GetRequiredScope(el); const Element& a = GetRequiredElement(scope,"a",&el); for (TokenList::const_iterator it = a.Tokens().begin(), end = a.Tokens().end(); it != end; ) { const float ival = ParseTokenAsFloat(**it++); out.push_back(ival); } }
// ------------------------------------------------------------------------------------------------ // read an array of int64_ts void ParseVectorDataArray(std::vector<int64_t>& out, const Element& el) { out.resize( 0 ); const TokenList& tok = el.Tokens(); if (tok.empty()) { ParseError("unexpected empty element", &el); } if (tok[0]->IsBinary()) { const char* data = tok[0]->begin(), *end = tok[0]->end(); char type; uint32_t count; ReadBinaryDataArrayHead(data, end, type, count, el); if (!count) { return; } if (type != 'l') { ParseError("expected long array (binary)", &el); } std::vector<char> buff; ReadBinaryDataArray(type, count, data, end, buff, el); ai_assert(data == end); ai_assert(buff.size() == count * 8); out.reserve(count); const int64_t* ip = reinterpret_cast<const int64_t*>(&buff[0]); for (unsigned int i = 0; i < count; ++i, ++ip) { BE_NCONST int64_t val = *ip; AI_SWAP8(val); out.push_back(val); } return; } const size_t dim = ParseTokenAsDim(*tok[0]); // see notes in ParseVectorDataArray() out.reserve(dim); const Scope& scope = GetRequiredScope(el); const Element& a = GetRequiredElement(scope, "a", &el); for (TokenList::const_iterator it = a.Tokens().begin(), end = a.Tokens().end(); it != end;) { const int64_t ival = ParseTokenAsInt64(**it++); out.push_back(ival); } }
// ------------------------------------------------------------------------------------------------ // read an array of float2 tuples void ParseVectorDataArray(std::vector<aiVector2D>& out, const Element& el) { out.resize( 0 ); const TokenList& tok = el.Tokens(); if(tok.empty()) { ParseError("unexpected empty element",&el); } if(tok[0]->IsBinary()) { const char* data = tok[0]->begin(), *end = tok[0]->end(); char type; uint32_t count; ReadBinaryDataArrayHead(data, end, type, count, el); if(count % 2 != 0) { ParseError("number of floats is not a multiple of two (2) (binary)",&el); } if(!count) { return; } if (type != 'd' && type != 'f') { ParseError("expected float or double array (binary)",&el); } std::vector<char> buff; ReadBinaryDataArray(type, count, data, end, buff, el); ai_assert(data == end); ai_assert(buff.size() == count * (type == 'd' ? 8 : 4)); const uint32_t count2 = count / 2; out.reserve(count2); if (type == 'd') { const double* d = reinterpret_cast<const double*>(&buff[0]); for (unsigned int i = 0; i < count2; ++i, d += 2) { out.push_back(aiVector2D(static_cast<float>(d[0]), static_cast<float>(d[1]))); } } else if (type == 'f') { const float* f = reinterpret_cast<const float*>(&buff[0]); for (unsigned int i = 0; i < count2; ++i, f += 2) { out.push_back(aiVector2D(f[0],f[1])); } } return; } const size_t dim = ParseTokenAsDim(*tok[0]); // see notes in ParseVectorDataArray() above out.reserve(dim); const Scope& scope = GetRequiredScope(el); const Element& a = GetRequiredElement(scope,"a",&el); if (a.Tokens().size() % 2 != 0) { ParseError("number of floats is not a multiple of two (2)",&el); } for (TokenList::const_iterator it = a.Tokens().begin(), end = a.Tokens().end(); it != end; ) { aiVector2D v; v.x = ParseTokenAsFloat(**it++); v.y = ParseTokenAsFloat(**it++); out.push_back(v); } }
// ------------------------------------------------------------------------------------------------ // read an array of float3 tuples void ParseVectorDataArray(std::vector<aiVector3D>& out, const Element& el) { out.resize( 0 ); const TokenList& tok = el.Tokens(); if(tok.empty()) { ParseError("unexpected empty element",&el); } if(tok[0]->IsBinary()) { const char* data = tok[0]->begin(), *end = tok[0]->end(); char type; uint32_t count; ReadBinaryDataArrayHead(data, end, type, count, el); if(count % 3 != 0) { ParseError("number of floats is not a multiple of three (3) (binary)",&el); } if(!count) { return; } if (type != 'd' && type != 'f') { ParseError("expected float or double array (binary)",&el); } std::vector<char> buff; ReadBinaryDataArray(type, count, data, end, buff, el); ai_assert(data == end); ai_assert(buff.size() == count * (type == 'd' ? 8 : 4)); const uint32_t count3 = count / 3; out.reserve(count3); if (type == 'd') { const double* d = reinterpret_cast<const double*>(&buff[0]); for (unsigned int i = 0; i < count3; ++i, d += 3) { out.push_back(aiVector3D(static_cast<float>(d[0]), static_cast<float>(d[1]), static_cast<float>(d[2]))); } // for debugging /*for ( size_t i = 0; i < out.size(); i++ ) { aiVector3D vec3( out[ i ] ); std::stringstream stream; stream << " vec3.x = " << vec3.x << " vec3.y = " << vec3.y << " vec3.z = " << vec3.z << std::endl; DefaultLogger::get()->info( stream.str() ); }*/ } else if (type == 'f') { const float* f = reinterpret_cast<const float*>(&buff[0]); for (unsigned int i = 0; i < count3; ++i, f += 3) { out.push_back(aiVector3D(f[0],f[1],f[2])); } } return; } const size_t dim = ParseTokenAsDim(*tok[0]); // may throw bad_alloc if the input is rubbish, but this need // not to be prevented - importing would fail but we wouldn't // crash since assimp handles this case properly. out.reserve(dim); const Scope& scope = GetRequiredScope(el); const Element& a = GetRequiredElement(scope,"a",&el); if (a.Tokens().size() % 3 != 0) { ParseError("number of floats is not a multiple of three (3)",&el); } for (TokenList::const_iterator it = a.Tokens().begin(), end = a.Tokens().end(); it != end; ) { aiVector3D v; v.x = ParseTokenAsFloat(**it++); v.y = ParseTokenAsFloat(**it++); v.z = ParseTokenAsFloat(**it++); out.push_back(v); } }
void ResolveVertexDataArray(std::vector<T>& data_out, const Scope& source, const std::string& MappingInformationType, const std::string& ReferenceInformationType, const char* dataElementName, const char* indexDataElementName, size_t vertex_count, const std::vector<unsigned int>& mapping_counts, const std::vector<unsigned int>& mapping_offsets, const std::vector<unsigned int>& mappings) { std::vector<T> tempUV; ParseVectorDataArray(tempUV,GetRequiredElement(source,dataElementName)); // handle permutations of Mapping and Reference type - it would be nice to // deal with this more elegantly and with less redundancy, but right // now it seems unavoidable. if (MappingInformationType == "ByVertice" && ReferenceInformationType == "Direct") { data_out.resize(vertex_count); for (size_t i = 0, e = tempUV.size(); i < e; ++i) { const unsigned int istart = mapping_offsets[i], iend = istart + mapping_counts[i]; for (unsigned int j = istart; j < iend; ++j) { data_out[mappings[j]] = tempUV[i]; } } } else if (MappingInformationType == "ByVertice" && ReferenceInformationType == "IndexToDirect") { data_out.resize(vertex_count); std::vector<int> uvIndices; ParseVectorDataArray(uvIndices,GetRequiredElement(source,indexDataElementName)); for (size_t i = 0, e = uvIndices.size(); i < e; ++i) { const unsigned int istart = mapping_offsets[i], iend = istart + mapping_counts[i]; for (unsigned int j = istart; j < iend; ++j) { if(static_cast<size_t>(uvIndices[i]) >= tempUV.size()) { DOMError("index out of range",&GetRequiredElement(source,indexDataElementName)); } data_out[mappings[j]] = tempUV[uvIndices[i]]; } } } else if (MappingInformationType == "ByPolygonVertex" && ReferenceInformationType == "Direct") { if (tempUV.size() != vertex_count) { FBXImporter::LogError(Formatter::format("length of input data unexpected for ByPolygon mapping: ") << tempUV.size() << ", expected " << vertex_count ); return; } data_out.swap(tempUV); } else if (MappingInformationType == "ByPolygonVertex" && ReferenceInformationType == "IndexToDirect") { data_out.resize(vertex_count); std::vector<int> uvIndices; ParseVectorDataArray(uvIndices,GetRequiredElement(source,indexDataElementName)); if (uvIndices.size() != vertex_count) { FBXImporter::LogError("length of input data unexpected for ByPolygonVertex mapping"); return; } unsigned int next = 0; BOOST_FOREACH(int i, uvIndices) { if(static_cast<size_t>(i) >= tempUV.size()) { DOMError("index out of range",&GetRequiredElement(source,indexDataElementName)); } data_out[next++] = tempUV[i]; } }