Merge branch 'master' into fbxBlendshapes

pull/3819/head
vfxgordon 2021-04-29 15:21:16 -07:00 committed by GitHub
commit 5298ed8f9e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 44 additions and 12 deletions

View File

@ -88,7 +88,7 @@ using namespace Assimp::Blender;
using namespace Assimp::Formatter; using namespace Assimp::Formatter;
static const aiImporterDesc blenderDesc = { static const aiImporterDesc blenderDesc = {
"Blender 3D Importer \nhttp://www.blender3d.org", "Blender 3D Importer (http://www.blender3d.org)",
"", "",
"", "",
"No animation support yet", "No animation support yet",

View File

@ -162,6 +162,9 @@ inline static bool ReadValue(Value &val, T &out) {
template <class T> template <class T>
inline static bool ReadMember(Value &obj, const char *id, T &out) { inline static bool ReadMember(Value &obj, const char *id, T &out) {
if (!obj.IsObject()) {
return false;
}
Value::MemberIterator it = obj.FindMember(id); Value::MemberIterator it = obj.FindMember(id);
if (it != obj.MemberEnd()) { if (it != obj.MemberEnd()) {
return ReadHelper<T>::Read(it->value, out); return ReadHelper<T>::Read(it->value, out);
@ -176,6 +179,9 @@ inline static T MemberOrDefault(Value &obj, const char *id, T defaultValue) {
} }
inline Value *FindMember(Value &val, const char *id) { inline Value *FindMember(Value &val, const char *id) {
if (!val.IsObject()) {
return nullptr;
}
Value::MemberIterator it = val.FindMember(id); Value::MemberIterator it = val.FindMember(id);
return (it != val.MemberEnd()) ? &it->value : nullptr; return (it != val.MemberEnd()) ? &it->value : nullptr;
} }
@ -193,6 +199,9 @@ inline void throwUnexpectedTypeError(const char (&expectedTypeName)[N], const ch
// Look-up functions with type checks. Context and extra context help the user identify the problem if there's an error. // Look-up functions with type checks. Context and extra context help the user identify the problem if there's an error.
inline Value *FindStringInContext(Value &val, const char *memberId, const char* context, const char* extraContext = nullptr) { inline Value *FindStringInContext(Value &val, const char *memberId, const char* context, const char* extraContext = nullptr) {
if (!val.IsObject()) {
return nullptr;
}
Value::MemberIterator it = val.FindMember(memberId); Value::MemberIterator it = val.FindMember(memberId);
if (it == val.MemberEnd()) { if (it == val.MemberEnd()) {
return nullptr; return nullptr;
@ -204,6 +213,9 @@ inline Value *FindStringInContext(Value &val, const char *memberId, const char*
} }
inline Value *FindNumberInContext(Value &val, const char *memberId, const char* context, const char* extraContext = nullptr) { inline Value *FindNumberInContext(Value &val, const char *memberId, const char* context, const char* extraContext = nullptr) {
if (!val.IsObject()) {
return nullptr;
}
Value::MemberIterator it = val.FindMember(memberId); Value::MemberIterator it = val.FindMember(memberId);
if (it == val.MemberEnd()) { if (it == val.MemberEnd()) {
return nullptr; return nullptr;
@ -215,6 +227,9 @@ inline Value *FindNumberInContext(Value &val, const char *memberId, const char*
} }
inline Value *FindUIntInContext(Value &val, const char *memberId, const char* context, const char* extraContext = nullptr) { inline Value *FindUIntInContext(Value &val, const char *memberId, const char* context, const char* extraContext = nullptr) {
if (!val.IsObject()) {
return nullptr;
}
Value::MemberIterator it = val.FindMember(memberId); Value::MemberIterator it = val.FindMember(memberId);
if (it == val.MemberEnd()) { if (it == val.MemberEnd()) {
return nullptr; return nullptr;
@ -226,6 +241,9 @@ inline Value *FindUIntInContext(Value &val, const char *memberId, const char* co
} }
inline Value *FindArrayInContext(Value &val, const char *memberId, const char* context, const char* extraContext = nullptr) { inline Value *FindArrayInContext(Value &val, const char *memberId, const char* context, const char* extraContext = nullptr) {
if (!val.IsObject()) {
return nullptr;
}
Value::MemberIterator it = val.FindMember(memberId); Value::MemberIterator it = val.FindMember(memberId);
if (it == val.MemberEnd()) { if (it == val.MemberEnd()) {
return nullptr; return nullptr;
@ -237,6 +255,9 @@ inline Value *FindArrayInContext(Value &val, const char *memberId, const char* c
} }
inline Value *FindObjectInContext(Value &val, const char *memberId, const char* context, const char* extraContext = nullptr) { inline Value *FindObjectInContext(Value &val, const char *memberId, const char* context, const char* extraContext = nullptr) {
if (!val.IsObject()) {
return nullptr;
}
Value::MemberIterator it = val.FindMember(memberId); Value::MemberIterator it = val.FindMember(memberId);
if (it == val.MemberEnd()) { if (it == val.MemberEnd()) {
return nullptr; return nullptr;
@ -886,7 +907,7 @@ inline void Accessor::Read(Value &obj, Asset &r) {
componentType = MemberOrDefault(obj, "componentType", ComponentType_BYTE); componentType = MemberOrDefault(obj, "componentType", ComponentType_BYTE);
{ {
const Value* countValue = FindUInt(obj, "count"); const Value* countValue = FindUInt(obj, "count");
if (!countValue || countValue->GetInt() < 1) if (!countValue || countValue->GetUint() < 1)
{ {
throw DeadlyImportError("A strictly positive count value is required, when reading ", id.c_str(), name.empty() ? "" : " (" + name + ")"); throw DeadlyImportError("A strictly positive count value is required, when reading ", id.c_str(), name.empty() ? "" : " (" + name + ")");
} }
@ -1105,7 +1126,9 @@ inline Accessor::Indexer::Indexer(Accessor &acc) :
template <class T> template <class T>
T Accessor::Indexer::GetValue(int i) { T Accessor::Indexer::GetValue(int i) {
ai_assert(data); ai_assert(data);
ai_assert(i * stride < accessor.GetMaxByteSize()); if (i * stride >= accessor.GetMaxByteSize()) {
throw DeadlyImportError("GLTF: Invalid index ", i, ", count out of range for buffer with stride ", stride, " and size ", accessor.GetMaxByteSize(), ".");
}
// Ensure that the memcpy doesn't overwrite the local. // Ensure that the memcpy doesn't overwrite the local.
const size_t sizeToCopy = std::min(elemSize, sizeof(T)); const size_t sizeToCopy = std::min(elemSize, sizeof(T));
T value = T(); T value = T();

View File

@ -1172,7 +1172,7 @@ aiNodeAnim *CreateNodeAnim(glTF2::Asset&, Node &node, AnimationSamplers &sampler
static const float kMillisecondsFromSeconds = 1000.f; static const float kMillisecondsFromSeconds = 1000.f;
if (samplers.translation) { if (samplers.translation && samplers.translation->input && samplers.translation->output) {
float *times = nullptr; float *times = nullptr;
samplers.translation->input->ExtractData(times); samplers.translation->input->ExtractData(times);
aiVector3D *values = nullptr; aiVector3D *values = nullptr;
@ -1196,7 +1196,7 @@ aiNodeAnim *CreateNodeAnim(glTF2::Asset&, Node &node, AnimationSamplers &sampler
anim->mPositionKeys->mValue.z = node.translation.value[2]; anim->mPositionKeys->mValue.z = node.translation.value[2];
} }
if (samplers.rotation) { if (samplers.rotation && samplers.rotation->input && samplers.rotation->output) {
float *times = nullptr; float *times = nullptr;
samplers.rotation->input->ExtractData(times); samplers.rotation->input->ExtractData(times);
aiQuaternion *values = nullptr; aiQuaternion *values = nullptr;
@ -1224,7 +1224,7 @@ aiNodeAnim *CreateNodeAnim(glTF2::Asset&, Node &node, AnimationSamplers &sampler
anim->mRotationKeys->mValue.w = node.rotation.value[3]; anim->mRotationKeys->mValue.w = node.rotation.value[3];
} }
if (samplers.scale) { if (samplers.scale && samplers.scale->input && samplers.scale->output) {
float *times = nullptr; float *times = nullptr;
samplers.scale->input->ExtractData(times); samplers.scale->input->ExtractData(times);
aiVector3D *values = nullptr; aiVector3D *values = nullptr;

View File

@ -90,10 +90,12 @@ DefaultIOStream::~DefaultIOStream() {
size_t DefaultIOStream::Read(void *pvBuffer, size_t DefaultIOStream::Read(void *pvBuffer,
size_t pSize, size_t pSize,
size_t pCount) { size_t pCount) {
if (0 == pCount) {
return 0;
}
ai_assert(nullptr != pvBuffer); ai_assert(nullptr != pvBuffer);
ai_assert(0 != pSize); ai_assert(0 != pSize);
ai_assert(0 != pCount);
return (mFile ? ::fread(pvBuffer, pSize, pCount, mFile) : 0); return (mFile ? ::fread(pvBuffer, pSize, pCount, mFile) : 0);
} }

View File

@ -135,7 +135,9 @@ void SortByPTypeProcess::Execute(aiScene *pScene) {
std::vector<unsigned int>::iterator meshIdx = replaceMeshIndex.begin(); std::vector<unsigned int>::iterator meshIdx = replaceMeshIndex.begin();
for (unsigned int i = 0; i < pScene->mNumMeshes; ++i) { for (unsigned int i = 0; i < pScene->mNumMeshes; ++i) {
aiMesh *const mesh = pScene->mMeshes[i]; aiMesh *const mesh = pScene->mMeshes[i];
ai_assert(0 != mesh->mPrimitiveTypes); if (mesh->mPrimitiveTypes == 0) {
throw DeadlyImportError("Mesh with invalid primitive type: ", mesh->mName.C_Str());
}
// if there's just one primitive type in the mesh there's nothing to do for us // if there's just one primitive type in the mesh there's nothing to do for us
unsigned int num = 0; unsigned int num = 0;

View File

@ -209,9 +209,14 @@ enum aiPostProcessSteps
/** <hr>Removes the node graph and pre-transforms all vertices with /** <hr>Removes the node graph and pre-transforms all vertices with
* the local transformation matrices of their nodes. * the local transformation matrices of their nodes.
* *
* The output scene still contains nodes, however there is only a * If the resulting scene can be reduced to a single mesh, with a single
* root node with children, each one referencing only one mesh, * material, no lights, and no cameras, then the output scene will contain
* and each mesh referencing one material. For rendering, you can * only a root node (with no children) that references the single mesh.
* Otherwise, the output scene will be reduced to a root node with a single
* level of child nodes, each one referencing one mesh, and each mesh
* referencing one material.
*
* In either case, for rendering, you can
* simply render all meshes in order - you don't need to pay * simply render all meshes in order - you don't need to pay
* attention to local transformations and the node hierarchy. * attention to local transformations and the node hierarchy.
* Animations are removed during this step. * Animations are removed during this step.