Merge branch 'master' into fbxExceptionSafety
commit
88be8ec698
|
@ -1718,14 +1718,14 @@ aiString FBXConverter::GetTexturePath(const Texture *tex) {
|
|||
bool textureReady = false; //tells if our texture is ready (if it was loaded or if it was found)
|
||||
unsigned int index=0;
|
||||
|
||||
VideoMap::const_iterator it = textures_converted.find(*media);
|
||||
VideoMap::const_iterator it = textures_converted.find(media);
|
||||
if (it != textures_converted.end()) {
|
||||
index = (*it).second;
|
||||
textureReady = true;
|
||||
} else {
|
||||
if (media->ContentLength() > 0) {
|
||||
index = ConvertVideo(*media);
|
||||
textures_converted[*media] = index;
|
||||
textures_converted[media] = index;
|
||||
textureReady = true;
|
||||
}
|
||||
}
|
||||
|
@ -2224,12 +2224,12 @@ void FBXConverter::SetShadingPropertiesRaw(aiMaterial *out_mat, const PropertyTa
|
|||
if (media != nullptr && media->ContentLength() > 0) {
|
||||
unsigned int index;
|
||||
|
||||
VideoMap::const_iterator videoIt = textures_converted.find(*media);
|
||||
VideoMap::const_iterator videoIt = textures_converted.find(media);
|
||||
if (videoIt != textures_converted.end()) {
|
||||
index = videoIt->second;
|
||||
} else {
|
||||
index = ConvertVideo(*media);
|
||||
textures_converted[*media] = index;
|
||||
textures_converted[media] = index;
|
||||
}
|
||||
|
||||
// setup texture reference string (copied from ColladaLoader::FindFilenameForEffectTexture)
|
||||
|
@ -3496,7 +3496,7 @@ void FBXConverter::ConvertOrphanedEmbeddedTextures() {
|
|||
if (realTexture) {
|
||||
const Video *media = realTexture->Media();
|
||||
unsigned int index = ConvertVideo(*media);
|
||||
textures_converted[*media] = index;
|
||||
textures_converted[media] = index;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -429,7 +429,7 @@ private:
|
|||
using MaterialMap = std::fbx_unordered_map<const Material*, unsigned int>;
|
||||
MaterialMap materials_converted;
|
||||
|
||||
using VideoMap = std::fbx_unordered_map<const Video, unsigned int>;
|
||||
using VideoMap = std::fbx_unordered_map<const Video*, unsigned int>;
|
||||
VideoMap textures_converted;
|
||||
|
||||
using MeshMap = std::fbx_unordered_map<const Geometry*, std::vector<unsigned int> >;
|
||||
|
|
|
@ -638,20 +638,6 @@ public:
|
|||
return ptr;
|
||||
}
|
||||
|
||||
bool operator==(const Video& other) const
|
||||
{
|
||||
return (
|
||||
type == other.type
|
||||
&& relativeFileName == other.relativeFileName
|
||||
&& fileName == other.fileName
|
||||
);
|
||||
}
|
||||
|
||||
bool operator<(const Video& other) const
|
||||
{
|
||||
return std::tie(type, relativeFileName, fileName) < std::tie(other.type, other.relativeFileName, other.fileName);
|
||||
}
|
||||
|
||||
private:
|
||||
std::string type;
|
||||
std::string relativeFileName;
|
||||
|
@ -1192,25 +1178,4 @@ private:
|
|||
} // Namespace FBX
|
||||
} // Namespace Assimp
|
||||
|
||||
namespace std
|
||||
{
|
||||
template <>
|
||||
struct hash<const Assimp::FBX::Video>
|
||||
{
|
||||
std::size_t operator()(const Assimp::FBX::Video& video) const
|
||||
{
|
||||
using std::size_t;
|
||||
using std::hash;
|
||||
using std::string;
|
||||
|
||||
size_t res = 17;
|
||||
res = res * 31 + hash<string>()(video.Name());
|
||||
res = res * 31 + hash<string>()(video.RelativeFilename());
|
||||
res = res * 31 + hash<string>()(video.Type());
|
||||
|
||||
return res;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif // INCLUDED_AI_FBX_DOCUMENT_H
|
||||
|
|
|
@ -641,7 +641,11 @@ void ParseVectorDataArray(std::vector<aiVector3D>& out, const Element& el)
|
|||
ReadBinaryDataArray(type, count, data, end, buff, el);
|
||||
|
||||
ai_assert(data == end);
|
||||
ai_assert(buff.size() == count * (type == 'd' ? 8 : 4));
|
||||
uint64_t dataToRead = static_cast<uint64_t>(count) * (type == 'd' ? 8 : 4);
|
||||
ai_assert(buff.size() == dataToRead);
|
||||
if (dataToRead > buff.size()) {
|
||||
ParseError("Invalid read size (binary)",&el);
|
||||
}
|
||||
|
||||
const uint32_t count3 = count / 3;
|
||||
out.reserve(count3);
|
||||
|
@ -728,7 +732,11 @@ void ParseVectorDataArray(std::vector<aiColor4D>& out, const Element& el)
|
|||
ReadBinaryDataArray(type, count, data, end, buff, el);
|
||||
|
||||
ai_assert(data == end);
|
||||
ai_assert(buff.size() == count * (type == 'd' ? 8 : 4));
|
||||
uint64_t dataToRead = static_cast<uint64_t>(count) * (type == 'd' ? 8 : 4);
|
||||
ai_assert(buff.size() == dataToRead);
|
||||
if (dataToRead > buff.size()) {
|
||||
ParseError("Invalid read size (binary)",&el);
|
||||
}
|
||||
|
||||
const uint32_t count4 = count / 4;
|
||||
out.reserve(count4);
|
||||
|
@ -807,7 +815,11 @@ void ParseVectorDataArray(std::vector<aiVector2D>& out, const Element& el)
|
|||
ReadBinaryDataArray(type, count, data, end, buff, el);
|
||||
|
||||
ai_assert(data == end);
|
||||
ai_assert(buff.size() == count * (type == 'd' ? 8 : 4));
|
||||
uint64_t dataToRead = static_cast<uint64_t>(count) * (type == 'd' ? 8 : 4);
|
||||
ai_assert(buff.size() == dataToRead);
|
||||
if (dataToRead > buff.size()) {
|
||||
ParseError("Invalid read size (binary)",&el);
|
||||
}
|
||||
|
||||
const uint32_t count2 = count / 2;
|
||||
out.reserve(count2);
|
||||
|
@ -879,7 +891,11 @@ void ParseVectorDataArray(std::vector<int>& out, const Element& el)
|
|||
ReadBinaryDataArray(type, count, data, end, buff, el);
|
||||
|
||||
ai_assert(data == end);
|
||||
ai_assert(buff.size() == count * 4);
|
||||
uint64_t dataToRead = static_cast<uint64_t>(count) * 4;
|
||||
ai_assert(buff.size() == dataToRead);
|
||||
if (dataToRead > buff.size()) {
|
||||
ParseError("Invalid read size (binary)",&el);
|
||||
}
|
||||
|
||||
out.reserve(count);
|
||||
|
||||
|
@ -937,7 +953,11 @@ void ParseVectorDataArray(std::vector<float>& out, const Element& el)
|
|||
ReadBinaryDataArray(type, count, data, end, buff, el);
|
||||
|
||||
ai_assert(data == end);
|
||||
ai_assert(buff.size() == count * (type == 'd' ? 8 : 4));
|
||||
uint64_t dataToRead = static_cast<uint64_t>(count) * (type == 'd' ? 8 : 4);
|
||||
ai_assert(buff.size() == dataToRead);
|
||||
if (dataToRead > buff.size()) {
|
||||
ParseError("Invalid read size (binary)",&el);
|
||||
}
|
||||
|
||||
if (type == 'd') {
|
||||
const double* d = reinterpret_cast<const double*>(&buff[0]);
|
||||
|
@ -998,7 +1018,11 @@ void ParseVectorDataArray(std::vector<unsigned int>& out, const Element& el)
|
|||
ReadBinaryDataArray(type, count, data, end, buff, el);
|
||||
|
||||
ai_assert(data == end);
|
||||
ai_assert(buff.size() == count * 4);
|
||||
uint64_t dataToRead = static_cast<uint64_t>(count) * 4;
|
||||
ai_assert(buff.size() == dataToRead);
|
||||
if (dataToRead > buff.size()) {
|
||||
ParseError("Invalid read size (binary)",&el);
|
||||
}
|
||||
|
||||
out.reserve(count);
|
||||
|
||||
|
@ -1063,7 +1087,11 @@ void ParseVectorDataArray(std::vector<uint64_t>& out, const Element& el)
|
|||
ReadBinaryDataArray(type, count, data, end, buff, el);
|
||||
|
||||
ai_assert(data == end);
|
||||
ai_assert(buff.size() == count * 8);
|
||||
uint64_t dataToRead = static_cast<uint64_t>(count) * 8;
|
||||
ai_assert(buff.size() == dataToRead);
|
||||
if (dataToRead > buff.size()) {
|
||||
ParseError("Invalid read size (binary)",&el);
|
||||
}
|
||||
|
||||
out.reserve(count);
|
||||
|
||||
|
@ -1121,7 +1149,11 @@ void ParseVectorDataArray(std::vector<int64_t>& out, const Element& el)
|
|||
ReadBinaryDataArray(type, count, data, end, buff, el);
|
||||
|
||||
ai_assert(data == end);
|
||||
ai_assert(buff.size() == count * 8);
|
||||
uint64_t dataToRead = static_cast<uint64_t>(count) * 8;
|
||||
ai_assert(buff.size() == dataToRead);
|
||||
if (dataToRead > buff.size()) {
|
||||
ParseError("Invalid read size (binary)",&el);
|
||||
}
|
||||
|
||||
out.reserve(count);
|
||||
|
||||
|
|
|
@ -453,11 +453,16 @@ void glTF2Importer::ImportMeshes(glTF2::Asset &r) {
|
|||
aim->mNumAnimMeshes = (unsigned int)targets.size();
|
||||
aim->mAnimMeshes = new aiAnimMesh *[aim->mNumAnimMeshes];
|
||||
for (size_t i = 0; i < targets.size(); i++) {
|
||||
aim->mAnimMeshes[i] = aiCreateAnimMesh(aim);
|
||||
bool needPositions = targets[i].position.size() > 0;
|
||||
bool needNormals = targets[i].normal.size() > 0;
|
||||
bool needTangents = targets[i].tangent.size() > 0;
|
||||
// GLTF morph does not support colors and texCoords
|
||||
aim->mAnimMeshes[i] = aiCreateAnimMesh(aim,
|
||||
needPositions, needNormals, needTangents, false, false);
|
||||
aiAnimMesh &aiAnimMesh = *(aim->mAnimMeshes[i]);
|
||||
Mesh::Primitive::Target &target = targets[i];
|
||||
|
||||
if (target.position.size() > 0) {
|
||||
if (needPositions) {
|
||||
aiVector3D *positionDiff = nullptr;
|
||||
target.position[0]->ExtractData(positionDiff);
|
||||
for (unsigned int vertexId = 0; vertexId < aim->mNumVertices; vertexId++) {
|
||||
|
@ -465,7 +470,7 @@ void glTF2Importer::ImportMeshes(glTF2::Asset &r) {
|
|||
}
|
||||
delete[] positionDiff;
|
||||
}
|
||||
if (target.normal.size() > 0) {
|
||||
if (needNormals) {
|
||||
aiVector3D *normalDiff = nullptr;
|
||||
target.normal[0]->ExtractData(normalDiff);
|
||||
for (unsigned int vertexId = 0; vertexId < aim->mNumVertices; vertexId++) {
|
||||
|
@ -473,7 +478,7 @@ void glTF2Importer::ImportMeshes(glTF2::Asset &r) {
|
|||
}
|
||||
delete[] normalDiff;
|
||||
}
|
||||
if (target.tangent.size() > 0) {
|
||||
if (needTangents) {
|
||||
Tangent *tangent = nullptr;
|
||||
attr.tangent[0]->ExtractData(tangent);
|
||||
|
||||
|
@ -1069,9 +1074,11 @@ aiNodeAnim *CreateNodeAnim(glTF2::Asset&, Node &node, AnimationSamplers &sampler
|
|||
samplers.translation->output->ExtractData(values);
|
||||
anim->mNumPositionKeys = static_cast<uint32_t>(samplers.translation->input->count);
|
||||
anim->mPositionKeys = new aiVectorKey[anim->mNumPositionKeys];
|
||||
unsigned int ii = (samplers.translation->interpolation == Interpolation_CUBICSPLINE) ? 1 : 0;
|
||||
for (unsigned int i = 0; i < anim->mNumPositionKeys; ++i) {
|
||||
anim->mPositionKeys[i].mTime = times[i] * kMillisecondsFromSeconds;
|
||||
anim->mPositionKeys[i].mValue = values[i];
|
||||
anim->mPositionKeys[i].mValue = values[ii];
|
||||
ii += (samplers.translation->interpolation == Interpolation_CUBICSPLINE) ? 3 : 1;
|
||||
}
|
||||
delete[] times;
|
||||
delete[] values;
|
||||
|
@ -1091,12 +1098,14 @@ aiNodeAnim *CreateNodeAnim(glTF2::Asset&, Node &node, AnimationSamplers &sampler
|
|||
samplers.rotation->output->ExtractData(values);
|
||||
anim->mNumRotationKeys = static_cast<uint32_t>(samplers.rotation->input->count);
|
||||
anim->mRotationKeys = new aiQuatKey[anim->mNumRotationKeys];
|
||||
unsigned int ii = (samplers.rotation->interpolation == Interpolation_CUBICSPLINE) ? 1 : 0;
|
||||
for (unsigned int i = 0; i < anim->mNumRotationKeys; ++i) {
|
||||
anim->mRotationKeys[i].mTime = times[i] * kMillisecondsFromSeconds;
|
||||
anim->mRotationKeys[i].mValue.x = values[i].w;
|
||||
anim->mRotationKeys[i].mValue.y = values[i].x;
|
||||
anim->mRotationKeys[i].mValue.z = values[i].y;
|
||||
anim->mRotationKeys[i].mValue.w = values[i].z;
|
||||
anim->mRotationKeys[i].mValue.x = values[ii].w;
|
||||
anim->mRotationKeys[i].mValue.y = values[ii].x;
|
||||
anim->mRotationKeys[i].mValue.z = values[ii].y;
|
||||
anim->mRotationKeys[i].mValue.w = values[ii].z;
|
||||
ii += (samplers.rotation->interpolation == Interpolation_CUBICSPLINE) ? 3 : 1;
|
||||
}
|
||||
delete[] times;
|
||||
delete[] values;
|
||||
|
@ -1117,9 +1126,11 @@ aiNodeAnim *CreateNodeAnim(glTF2::Asset&, Node &node, AnimationSamplers &sampler
|
|||
samplers.scale->output->ExtractData(values);
|
||||
anim->mNumScalingKeys = static_cast<uint32_t>(samplers.scale->input->count);
|
||||
anim->mScalingKeys = new aiVectorKey[anim->mNumScalingKeys];
|
||||
unsigned int ii = (samplers.scale->interpolation == Interpolation_CUBICSPLINE) ? 1 : 0;
|
||||
for (unsigned int i = 0; i < anim->mNumScalingKeys; ++i) {
|
||||
anim->mScalingKeys[i].mTime = times[i] * kMillisecondsFromSeconds;
|
||||
anim->mScalingKeys[i].mValue = values[i];
|
||||
anim->mScalingKeys[i].mValue = values[ii];
|
||||
ii += (samplers.scale->interpolation == Interpolation_CUBICSPLINE) ? 3 : 1;
|
||||
}
|
||||
delete[] times;
|
||||
delete[] values;
|
||||
|
@ -1148,11 +1159,14 @@ aiMeshMorphAnim *CreateMeshMorphAnim(glTF2::Asset&, Node &node, AnimationSampler
|
|||
samplers.weight->output->ExtractData(values);
|
||||
anim->mNumKeys = static_cast<uint32_t>(samplers.weight->input->count);
|
||||
|
||||
const unsigned int numMorphs = (unsigned int)samplers.weight->output->count / anim->mNumKeys;
|
||||
// for Interpolation_CUBICSPLINE can have more outputs
|
||||
const unsigned int weightStride = (unsigned int)samplers.weight->output->count / anim->mNumKeys;
|
||||
const unsigned int numMorphs = (samplers.weight->interpolation == Interpolation_CUBICSPLINE) ? weightStride - 2 : weightStride;
|
||||
|
||||
anim->mKeys = new aiMeshMorphKey[anim->mNumKeys];
|
||||
unsigned int k = 0u;
|
||||
unsigned int ii = (samplers.weight->interpolation == Interpolation_CUBICSPLINE) ? 1 : 0;
|
||||
for (unsigned int i = 0u; i < anim->mNumKeys; ++i) {
|
||||
unsigned int k = weightStride * i + ii;
|
||||
anim->mKeys[i].mTime = times[i] * kMillisecondsFromSeconds;
|
||||
anim->mKeys[i].mNumValuesAndWeights = numMorphs;
|
||||
anim->mKeys[i].mValues = new unsigned int[numMorphs];
|
||||
|
|
|
@ -44,42 +44,46 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
|
||||
namespace Assimp {
|
||||
|
||||
aiAnimMesh *aiCreateAnimMesh(const aiMesh *mesh)
|
||||
aiAnimMesh *aiCreateAnimMesh(const aiMesh *mesh, bool needPositions, bool needNormals, bool needTangents, bool needColors, bool needTexCoords)
|
||||
{
|
||||
aiAnimMesh *animesh = new aiAnimMesh;
|
||||
animesh->mNumVertices = mesh->mNumVertices;
|
||||
if (mesh->mVertices) {
|
||||
if (needPositions && mesh->mVertices) {
|
||||
animesh->mVertices = new aiVector3D[animesh->mNumVertices];
|
||||
std::memcpy(animesh->mVertices, mesh->mVertices, mesh->mNumVertices * sizeof(aiVector3D));
|
||||
}
|
||||
if (mesh->mNormals) {
|
||||
if (needNormals && mesh->mNormals) {
|
||||
animesh->mNormals = new aiVector3D[animesh->mNumVertices];
|
||||
std::memcpy(animesh->mNormals, mesh->mNormals, mesh->mNumVertices * sizeof(aiVector3D));
|
||||
}
|
||||
if (mesh->mTangents) {
|
||||
if (needTangents && mesh->mTangents) {
|
||||
animesh->mTangents = new aiVector3D[animesh->mNumVertices];
|
||||
std::memcpy(animesh->mTangents, mesh->mTangents, mesh->mNumVertices * sizeof(aiVector3D));
|
||||
}
|
||||
if (mesh->mBitangents) {
|
||||
if (needTangents && mesh->mBitangents) {
|
||||
animesh->mBitangents = new aiVector3D[animesh->mNumVertices];
|
||||
std::memcpy(animesh->mBitangents, mesh->mBitangents, mesh->mNumVertices * sizeof(aiVector3D));
|
||||
}
|
||||
|
||||
for (int i = 0; i < AI_MAX_NUMBER_OF_COLOR_SETS; ++i) {
|
||||
if (mesh->mColors[i]) {
|
||||
animesh->mColors[i] = new aiColor4D[animesh->mNumVertices];
|
||||
std::memcpy(animesh->mColors[i], mesh->mColors[i], mesh->mNumVertices * sizeof(aiColor4D));
|
||||
} else {
|
||||
animesh->mColors[i] = nullptr;
|
||||
if (needColors) {
|
||||
for (int i = 0; i < AI_MAX_NUMBER_OF_COLOR_SETS; ++i) {
|
||||
if (mesh->mColors[i]) {
|
||||
animesh->mColors[i] = new aiColor4D[animesh->mNumVertices];
|
||||
std::memcpy(animesh->mColors[i], mesh->mColors[i], mesh->mNumVertices * sizeof(aiColor4D));
|
||||
} else {
|
||||
animesh->mColors[i] = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i) {
|
||||
if (mesh->mTextureCoords[i]) {
|
||||
animesh->mTextureCoords[i] = new aiVector3D[animesh->mNumVertices];
|
||||
std::memcpy(animesh->mTextureCoords[i], mesh->mTextureCoords[i], mesh->mNumVertices * sizeof(aiVector3D));
|
||||
} else {
|
||||
animesh->mTextureCoords[i] = nullptr;
|
||||
if (needTexCoords) {
|
||||
for (int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i) {
|
||||
if (mesh->mTextureCoords[i]) {
|
||||
animesh->mTextureCoords[i] = new aiVector3D[animesh->mNumVertices];
|
||||
std::memcpy(animesh->mTextureCoords[i], mesh->mTextureCoords[i], mesh->mNumVertices * sizeof(aiVector3D));
|
||||
} else {
|
||||
animesh->mTextureCoords[i] = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
return animesh;
|
||||
|
|
|
@ -57,10 +57,20 @@ namespace Assimp {
|
|||
|
||||
/**
|
||||
* Create aiAnimMesh from aiMesh.
|
||||
* @param mesh The input mesh to create an animated mesh from.
|
||||
* @param mesh The input mesh to create an animated mesh from.
|
||||
* @param needPositions If true, positions will be copied from.
|
||||
* @param needNormals If true, normals will be copied from.
|
||||
* @param needTangents If true, tangents and bitangents will be copied from.
|
||||
* @param needColors If true, colors will be copied from.
|
||||
* @param needTexCoords If true, texCoords will be copied from.
|
||||
* @return The new created animated mesh.
|
||||
*/
|
||||
ASSIMP_API aiAnimMesh *aiCreateAnimMesh(const aiMesh *mesh);
|
||||
ASSIMP_API aiAnimMesh *aiCreateAnimMesh(const aiMesh *mesh,
|
||||
bool needPositions = true,
|
||||
bool needNormals = true,
|
||||
bool needTangents = true,
|
||||
bool needColors = true,
|
||||
bool needTexCoords = true);
|
||||
|
||||
} // end of namespace Assimp
|
||||
|
||||
|
|
Loading…
Reference in New Issue