diff --git a/code/Assjson/json_exporter.cpp b/code/Assjson/json_exporter.cpp index 848a08b4d..cd542b29e 100644 --- a/code/Assjson/json_exporter.cpp +++ b/code/Assjson/json_exporter.cpp @@ -13,7 +13,6 @@ Licensed under a 3-clause BSD license. See the LICENSE file for more information #include #include #include - #include #include @@ -28,832 +27,792 @@ Licensed under a 3-clause BSD license. See the LICENSE file for more information #include "mesh_splitter.h" - extern "C" { -#include "cencode.h" + #include "cencode.h" } +namespace Assimp { -namespace { -void Assimp2Json(const char*, Assimp::IOSystem*, const aiScene*, const Assimp::ExportProperties*); -} +void ExportAssimp2Json(const char*, Assimp::IOSystem*, const aiScene*, const Assimp::ExportProperties*); -Assimp::Exporter::ExportFormatEntry Assimp2Json_desc = Assimp::Exporter::ExportFormatEntry( - "assimp.json", - "Plain JSON representation of the Assimp scene data structure", - "assimp.json", - Assimp2Json, - 0u); - -namespace { +Exporter::ExportFormatEntry Assimp2Json_desc = Assimp::Exporter::ExportFormatEntry( + "json", + "Plain JSON representation of the Assimp scene data structure", + "json", + &ExportAssimp2Json, + 0u +); - // small utility class to simplify serializing the aiScene to Json -class JSONWriter -{ - +// small utility class to simplify serializing the aiScene to Json +class JSONWriter { public: + enum { + Flag_DoNotIndent = 0x1, + Flag_WriteSpecialFloats = 0x2, + }; - enum { - Flag_DoNotIndent = 0x1, - Flag_WriteSpecialFloats = 0x2, - }; + JSONWriter(Assimp::IOStream& out, unsigned int flags = 0u) + : out(out) + , first() + , flags(flags) { + // make sure that all formatting happens using the standard, C locale and not the user's current locale + buff.imbue(std::locale("C")); + } -public: + ~JSONWriter() { + Flush(); + } - JSONWriter(Assimp::IOStream& out, unsigned int flags = 0u) - : out(out) - , first() - , flags(flags) - { - // make sure that all formatting happens using the standard, C locale and not the user's current locale - buff.imbue( std::locale("C") ); - } + void Flush() { + const std::string s = buff.str(); + out.Write(s.c_str(), s.length(), 1); + buff.clear(); + } - ~JSONWriter() - { - Flush(); - } + void PushIndent() { + indent += '\t'; + } -public: + void PopIndent() { + indent.erase(indent.end() - 1); + } - void Flush() { - const std::string s = buff.str(); - out.Write(s.c_str(),s.length(),1); - buff.clear(); - } + void Key(const std::string& name) { + AddIndentation(); + Delimit(); + buff << '\"' + name + "\": "; + } - void PushIndent() { - indent += '\t'; - } + template + void Element(const Literal& name) { + AddIndentation(); + Delimit(); - void PopIndent() { - indent.erase(indent.end()-1); - } + LiteralToString(buff, name) << '\n'; + } - void Key(const std::string& name) { - AddIndentation(); - Delimit(); - buff << '\"'+name+"\": "; - } + template + void SimpleValue(const Literal& s) { + LiteralToString(buff, s) << '\n'; + } - template - void Element(const Literal& name) { - AddIndentation(); - Delimit(); + void SimpleValue(const void* buffer, size_t len) { + base64_encodestate s; + base64_init_encodestate(&s); - LiteralToString(buff, name) << '\n'; - } + char* const out = new char[std::max(len * 2, static_cast(16u))]; + const int n = base64_encode_block(reinterpret_cast(buffer), static_cast(len), out, &s); + out[n + base64_encode_blockend(out + n, &s)] = '\0'; - template - void SimpleValue(const Literal& s) { - LiteralToString(buff, s) << '\n'; - } + // base64 encoding may add newlines, but JSON strings may not contain 'real' newlines + // (only escaped ones). Remove any newlines in out. + for (char* cur = out; *cur; ++cur) { + if (*cur == '\n') { + *cur = ' '; + } + } + buff << '\"' << out << "\"\n"; + delete[] out; + } - void SimpleValue(const void* buffer, size_t len) { - base64_encodestate s; - base64_init_encodestate(&s); + void StartObj(bool is_element = false) { + // if this appears as a plain array element, we need to insert a delimiter and we should also indent it + if (is_element) { + AddIndentation(); + if (!first) { + buff << ','; + } + } + first = true; + buff << "{\n"; + PushIndent(); + } - char* const out = new char[std::max(len*2, static_cast(16u))]; - const int n = base64_encode_block(reinterpret_cast( buffer ), static_cast( len ),out,&s); - out[n+base64_encode_blockend(out + n,&s)] = '\0'; + void EndObj() { + PopIndent(); + AddIndentation(); + first = false; + buff << "}\n"; + } - // base64 encoding may add newlines, but JSON strings may not contain 'real' newlines - // (only escaped ones). Remove any newlines in out. - for(char* cur = out; *cur; ++cur) { - if(*cur == '\n') { - *cur = ' '; - } - } + void StartArray(bool is_element = false) { + // if this appears as a plain array element, we need to insert a delimiter and we should also indent it + if (is_element) { + AddIndentation(); + if (!first) { + buff << ','; + } + } + first = true; + buff << "[\n"; + PushIndent(); + } + void EndArray() { + PopIndent(); + AddIndentation(); + buff << "]\n"; + first = false; + } - buff << '\"' << out << "\"\n"; - delete[] out; - } + void AddIndentation() { + if (!(flags & Flag_DoNotIndent)) { + buff << indent; + } + } - void StartObj(bool is_element = false) { - // if this appears as a plain array element, we need to insert a delimiter and we should also indent it - if(is_element) { - AddIndentation(); - if(!first) { - buff << ','; - } - } - first = true; - buff << "{\n"; - PushIndent(); - } - - void EndObj() { - PopIndent(); - AddIndentation(); - first = false; - buff << "}\n"; - } - - void StartArray(bool is_element = false) { - // if this appears as a plain array element, we need to insert a delimiter and we should also indent it - if(is_element) { - AddIndentation(); - if(!first) { - buff << ','; - } - } - first = true; - buff << "[\n"; - PushIndent(); - } - - void EndArray() { - PopIndent(); - AddIndentation(); - buff << "]\n"; - first = false; - } - - void AddIndentation() { - if(!(flags & Flag_DoNotIndent)) { - buff << indent; - } - } - - void Delimit() { - if(!first) { - buff << ','; - } - else { - buff << ' '; - first = false; - } - } + void Delimit() { + if (!first) { + buff << ','; + } + else { + buff << ' '; + first = false; + } + } private: + template + std::stringstream& LiteralToString(std::stringstream& stream, const Literal& s) { + stream << s; + return stream; + } - template - std::stringstream& LiteralToString(std::stringstream& stream, const Literal& s) { - stream << s; - return stream; - } + std::stringstream& LiteralToString(std::stringstream& stream, const aiString& s) { + std::string t; - std::stringstream& LiteralToString(std::stringstream& stream, const aiString& s) { - std::string t; + // escape backslashes and single quotes, both would render the JSON invalid if left as is + t.reserve(s.length); + for (size_t i = 0; i < s.length; ++i) { - // escape backslashes and single quotes, both would render the JSON invalid if left as is - t.reserve(s.length); - for(size_t i = 0; i < s.length; ++i) { - - if (s.data[i] == '\\' || s.data[i] == '\'' || s.data[i] == '\"') { - t.push_back('\\'); - } + if (s.data[i] == '\\' || s.data[i] == '\'' || s.data[i] == '\"') { + t.push_back('\\'); + } - t.push_back(s.data[i]); - } - stream << "\""; - stream << t; - stream << "\""; - return stream; - } + t.push_back(s.data[i]); + } + stream << "\""; + stream << t; + stream << "\""; + return stream; + } - std::stringstream& LiteralToString(std::stringstream& stream, float f) { - if (!std::numeric_limits::is_iec559) { - // on a non IEEE-754 platform, we make no assumptions about the representation or existence - // of special floating-point numbers. - stream << f; - return stream; - } + std::stringstream& LiteralToString(std::stringstream& stream, float f) { + if (!std::numeric_limits::is_iec559) { + // on a non IEEE-754 platform, we make no assumptions about the representation or existence + // of special floating-point numbers. + stream << f; + return stream; + } - // JSON does not support writing Inf/Nan - // [RFC 4672: "Numeric values that cannot be represented as sequences of digits - // (such as Infinity and NaN) are not permitted."] - // Nevertheless, many parsers will accept the special keywords Infinity, -Infinity and NaN - if (std::numeric_limits::infinity() == fabs(f)) { - if (flags & Flag_WriteSpecialFloats) { - stream << (f < 0 ? "\"-" : "\"") + std::string( "Infinity\"" ); - return stream; - } - // we should print this warning, but we can't - this is called from within a generic assimp exporter, we cannot use cerr - // std::cerr << "warning: cannot represent infinite number literal, substituting 0 instead (use -i flag to enforce Infinity/NaN)" << std::endl; - stream << "0.0"; - return stream; - } - // f!=f is the most reliable test for NaNs that I know of - else if (f != f) { - if (flags & Flag_WriteSpecialFloats) { - stream << "\"NaN\""; - return stream; - } - // we should print this warning, but we can't - this is called from within a generic assimp exporter, we cannot use cerr - // std::cerr << "warning: cannot represent infinite number literal, substituting 0 instead (use -i flag to enforce Infinity/NaN)" << std::endl; - stream << "0.0"; - return stream; - } + // JSON does not support writing Inf/Nan + // [RFC 4672: "Numeric values that cannot be represented as sequences of digits + // (such as Infinity and NaN) are not permitted."] + // Nevertheless, many parsers will accept the special keywords Infinity, -Infinity and NaN + if (std::numeric_limits::infinity() == fabs(f)) { + if (flags & Flag_WriteSpecialFloats) { + stream << (f < 0 ? "\"-" : "\"") + std::string("Infinity\""); + return stream; + } + // we should print this warning, but we can't - this is called from within a generic assimp exporter, we cannot use cerr + // std::cerr << "warning: cannot represent infinite number literal, substituting 0 instead (use -i flag to enforce Infinity/NaN)" << std::endl; + stream << "0.0"; + return stream; + } + // f!=f is the most reliable test for NaNs that I know of + else if (f != f) { + if (flags & Flag_WriteSpecialFloats) { + stream << "\"NaN\""; + return stream; + } + // we should print this warning, but we can't - this is called from within a generic assimp exporter, we cannot use cerr + // std::cerr << "warning: cannot represent infinite number literal, substituting 0 instead (use -i flag to enforce Infinity/NaN)" << std::endl; + stream << "0.0"; + return stream; + } - stream << f; - return stream; - } + stream << f; + return stream; + } -private: - Assimp::IOStream& out; - std::string indent, newline; - std::stringstream buff; - bool first; +private: + Assimp::IOStream& out; + std::string indent, newline; + std::stringstream buff; + bool first; - unsigned int flags; + unsigned int flags; }; - -void Write(JSONWriter& out, const aiVector3D& ai, bool is_elem = true) -{ - out.StartArray(is_elem); - out.Element(ai.x); - out.Element(ai.y); - out.Element(ai.z); - out.EndArray(); +void Write(JSONWriter& out, const aiVector3D& ai, bool is_elem = true) { + out.StartArray(is_elem); + out.Element(ai.x); + out.Element(ai.y); + out.Element(ai.z); + out.EndArray(); } -void Write(JSONWriter& out, const aiQuaternion& ai, bool is_elem = true) -{ - out.StartArray(is_elem); - out.Element(ai.w); - out.Element(ai.x); - out.Element(ai.y); - out.Element(ai.z); - out.EndArray(); +void Write(JSONWriter& out, const aiQuaternion& ai, bool is_elem = true) { + out.StartArray(is_elem); + out.Element(ai.w); + out.Element(ai.x); + out.Element(ai.y); + out.Element(ai.z); + out.EndArray(); } -void Write(JSONWriter& out, const aiColor3D& ai, bool is_elem = true) -{ - out.StartArray(is_elem); - out.Element(ai.r); - out.Element(ai.g); - out.Element(ai.b); - out.EndArray(); +void Write(JSONWriter& out, const aiColor3D& ai, bool is_elem = true) { + out.StartArray(is_elem); + out.Element(ai.r); + out.Element(ai.g); + out.Element(ai.b); + out.EndArray(); } -void Write(JSONWriter& out, const aiMatrix4x4& ai, bool is_elem = true) -{ - out.StartArray(is_elem); - for(unsigned int x = 0; x < 4; ++x) { - for(unsigned int y = 0; y < 4; ++y) { - out.Element(ai[x][y]); - } - } - out.EndArray(); +void Write(JSONWriter& out, const aiMatrix4x4& ai, bool is_elem = true) { + out.StartArray(is_elem); + for (unsigned int x = 0; x < 4; ++x) { + for (unsigned int y = 0; y < 4; ++y) { + out.Element(ai[x][y]); + } + } + out.EndArray(); } -void Write(JSONWriter& out, const aiBone& ai, bool is_elem = true) -{ - out.StartObj(is_elem); +void Write(JSONWriter& out, const aiBone& ai, bool is_elem = true) { + out.StartObj(is_elem); - out.Key("name"); - out.SimpleValue(ai.mName); + out.Key("name"); + out.SimpleValue(ai.mName); - out.Key("offsetmatrix"); - Write(out,ai.mOffsetMatrix,false); + out.Key("offsetmatrix"); + Write(out, ai.mOffsetMatrix, false); - out.Key("weights"); - out.StartArray(); - for(unsigned int i = 0; i < ai.mNumWeights; ++i) { - out.StartArray(true); - out.Element(ai.mWeights[i].mVertexId); - out.Element(ai.mWeights[i].mWeight); - out.EndArray(); - } - out.EndArray(); - out.EndObj(); + out.Key("weights"); + out.StartArray(); + for (unsigned int i = 0; i < ai.mNumWeights; ++i) { + out.StartArray(true); + out.Element(ai.mWeights[i].mVertexId); + out.Element(ai.mWeights[i].mWeight); + out.EndArray(); + } + out.EndArray(); + out.EndObj(); +} + +void Write(JSONWriter& out, const aiFace& ai, bool is_elem = true) { + out.StartArray(is_elem); + for (unsigned int i = 0; i < ai.mNumIndices; ++i) { + out.Element(ai.mIndices[i]); + } + out.EndArray(); +} + +void Write(JSONWriter& out, const aiMesh& ai, bool is_elem = true) { + out.StartObj(is_elem); + + out.Key("name"); + out.SimpleValue(ai.mName); + + out.Key("materialindex"); + out.SimpleValue(ai.mMaterialIndex); + + out.Key("primitivetypes"); + out.SimpleValue(ai.mPrimitiveTypes); + + out.Key("vertices"); + out.StartArray(); + for (unsigned int i = 0; i < ai.mNumVertices; ++i) { + out.Element(ai.mVertices[i].x); + out.Element(ai.mVertices[i].y); + out.Element(ai.mVertices[i].z); + } + out.EndArray(); + + if (ai.HasNormals()) { + out.Key("normals"); + out.StartArray(); + for (unsigned int i = 0; i < ai.mNumVertices; ++i) { + out.Element(ai.mNormals[i].x); + out.Element(ai.mNormals[i].y); + out.Element(ai.mNormals[i].z); + } + out.EndArray(); + } + + if (ai.HasTangentsAndBitangents()) { + out.Key("tangents"); + out.StartArray(); + for (unsigned int i = 0; i < ai.mNumVertices; ++i) { + out.Element(ai.mTangents[i].x); + out.Element(ai.mTangents[i].y); + out.Element(ai.mTangents[i].z); + } + out.EndArray(); + + out.Key("bitangents"); + out.StartArray(); + for (unsigned int i = 0; i < ai.mNumVertices; ++i) { + out.Element(ai.mBitangents[i].x); + out.Element(ai.mBitangents[i].y); + out.Element(ai.mBitangents[i].z); + } + out.EndArray(); + } + + if (ai.GetNumUVChannels()) { + out.Key("numuvcomponents"); + out.StartArray(); + for (unsigned int n = 0; n < ai.GetNumUVChannels(); ++n) { + out.Element(ai.mNumUVComponents[n]); + } + out.EndArray(); + + out.Key("texturecoords"); + out.StartArray(); + for (unsigned int n = 0; n < ai.GetNumUVChannels(); ++n) { + const unsigned int numc = ai.mNumUVComponents[n] ? ai.mNumUVComponents[n] : 2; + + out.StartArray(true); + for (unsigned int i = 0; i < ai.mNumVertices; ++i) { + for (unsigned int c = 0; c < numc; ++c) { + out.Element(ai.mTextureCoords[n][i][c]); + } + } + out.EndArray(); + } + out.EndArray(); + } + + if (ai.GetNumColorChannels()) { + out.Key("colors"); + out.StartArray(); + for (unsigned int n = 0; n < ai.GetNumColorChannels(); ++n) { + out.StartArray(true); + for (unsigned int i = 0; i < ai.mNumVertices; ++i) { + out.Element(ai.mColors[n][i].r); + out.Element(ai.mColors[n][i].g); + out.Element(ai.mColors[n][i].b); + out.Element(ai.mColors[n][i].a); + } + out.EndArray(); + } + out.EndArray(); + } + + if (ai.mNumBones) { + out.Key("bones"); + out.StartArray(); + for (unsigned int n = 0; n < ai.mNumBones; ++n) { + Write(out, *ai.mBones[n]); + } + out.EndArray(); + } + + out.Key("faces"); + out.StartArray(); + for (unsigned int n = 0; n < ai.mNumFaces; ++n) { + Write(out, ai.mFaces[n]); + } + out.EndArray(); + + out.EndObj(); +} + +void Write(JSONWriter& out, const aiNode& ai, bool is_elem = true) { + out.StartObj(is_elem); + + out.Key("name"); + out.SimpleValue(ai.mName); + + out.Key("transformation"); + Write(out, ai.mTransformation, false); + + if (ai.mNumMeshes) { + out.Key("meshes"); + out.StartArray(); + for (unsigned int n = 0; n < ai.mNumMeshes; ++n) { + out.Element(ai.mMeshes[n]); + } + out.EndArray(); + } + + if (ai.mNumChildren) { + out.Key("children"); + out.StartArray(); + for (unsigned int n = 0; n < ai.mNumChildren; ++n) { + Write(out, *ai.mChildren[n]); + } + out.EndArray(); + } + + out.EndObj(); +} + +void Write(JSONWriter& out, const aiMaterial& ai, bool is_elem = true) { + out.StartObj(is_elem); + + out.Key("properties"); + out.StartArray(); + for (unsigned int i = 0; i < ai.mNumProperties; ++i) { + const aiMaterialProperty* const prop = ai.mProperties[i]; + out.StartObj(true); + out.Key("key"); + out.SimpleValue(prop->mKey); + out.Key("semantic"); + out.SimpleValue(prop->mSemantic); + out.Key("index"); + out.SimpleValue(prop->mIndex); + + out.Key("type"); + out.SimpleValue(prop->mType); + + out.Key("value"); + switch (prop->mType) { + case aiPTI_Float: + if (prop->mDataLength / sizeof(float) > 1) { + out.StartArray(); + for (unsigned int i = 0; i < prop->mDataLength / sizeof(float); ++i) { + out.Element(reinterpret_cast(prop->mData)[i]); + } + out.EndArray(); + } + else { + out.SimpleValue(*reinterpret_cast(prop->mData)); + } + break; + + case aiPTI_Integer: + if (prop->mDataLength / sizeof(int) > 1) { + out.StartArray(); + for (unsigned int i = 0; i < prop->mDataLength / sizeof(int); ++i) { + out.Element(reinterpret_cast(prop->mData)[i]); + } + out.EndArray(); + } else { + out.SimpleValue(*reinterpret_cast(prop->mData)); + } + break; + + case aiPTI_String: + { + aiString s; + aiGetMaterialString(&ai, prop->mKey.data, prop->mSemantic, prop->mIndex, &s); + out.SimpleValue(s); + } + break; + case aiPTI_Buffer: + { + // binary data is written as series of hex-encoded octets + out.SimpleValue(prop->mData, prop->mDataLength); + } + break; + default: + assert(false); + } + + out.EndObj(); + } + + out.EndArray(); + out.EndObj(); +} + +void Write(JSONWriter& out, const aiTexture& ai, bool is_elem = true) { + out.StartObj(is_elem); + + out.Key("width"); + out.SimpleValue(ai.mWidth); + + out.Key("height"); + out.SimpleValue(ai.mHeight); + + out.Key("formathint"); + out.SimpleValue(aiString(ai.achFormatHint)); + + out.Key("data"); + if (!ai.mHeight) { + out.SimpleValue(ai.pcData, ai.mWidth); + } + else { + out.StartArray(); + for (unsigned int y = 0; y < ai.mHeight; ++y) { + out.StartArray(true); + for (unsigned int x = 0; x < ai.mWidth; ++x) { + const aiTexel& tx = ai.pcData[y*ai.mWidth + x]; + out.StartArray(true); + out.Element(static_cast(tx.r)); + out.Element(static_cast(tx.g)); + out.Element(static_cast(tx.b)); + out.Element(static_cast(tx.a)); + out.EndArray(); + } + out.EndArray(); + } + out.EndArray(); + } + + out.EndObj(); +} + +void Write(JSONWriter& out, const aiLight& ai, bool is_elem = true) { + out.StartObj(is_elem); + + out.Key("name"); + out.SimpleValue(ai.mName); + + out.Key("type"); + out.SimpleValue(ai.mType); + + if (ai.mType == aiLightSource_SPOT || ai.mType == aiLightSource_UNDEFINED) { + out.Key("angleinnercone"); + out.SimpleValue(ai.mAngleInnerCone); + + out.Key("angleoutercone"); + out.SimpleValue(ai.mAngleOuterCone); + } + + out.Key("attenuationconstant"); + out.SimpleValue(ai.mAttenuationConstant); + + out.Key("attenuationlinear"); + out.SimpleValue(ai.mAttenuationLinear); + + out.Key("attenuationquadratic"); + out.SimpleValue(ai.mAttenuationQuadratic); + + out.Key("diffusecolor"); + Write(out, ai.mColorDiffuse, false); + + out.Key("specularcolor"); + Write(out, ai.mColorSpecular, false); + + out.Key("ambientcolor"); + Write(out, ai.mColorAmbient, false); + + if (ai.mType != aiLightSource_POINT) { + out.Key("direction"); + Write(out, ai.mDirection, false); + + } + + if (ai.mType != aiLightSource_DIRECTIONAL) { + out.Key("position"); + Write(out, ai.mPosition, false); + } + + out.EndObj(); +} + +void Write(JSONWriter& out, const aiNodeAnim& ai, bool is_elem = true) { + out.StartObj(is_elem); + + out.Key("name"); + out.SimpleValue(ai.mNodeName); + + out.Key("prestate"); + out.SimpleValue(ai.mPreState); + + out.Key("poststate"); + out.SimpleValue(ai.mPostState); + + if (ai.mNumPositionKeys) { + out.Key("positionkeys"); + out.StartArray(); + for (unsigned int n = 0; n < ai.mNumPositionKeys; ++n) { + const aiVectorKey& pos = ai.mPositionKeys[n]; + out.StartArray(true); + out.Element(pos.mTime); + Write(out, pos.mValue); + out.EndArray(); + } + out.EndArray(); + } + + if (ai.mNumRotationKeys) { + out.Key("rotationkeys"); + out.StartArray(); + for (unsigned int n = 0; n < ai.mNumRotationKeys; ++n) { + const aiQuatKey& rot = ai.mRotationKeys[n]; + out.StartArray(true); + out.Element(rot.mTime); + Write(out, rot.mValue); + out.EndArray(); + } + out.EndArray(); + } + + if (ai.mNumScalingKeys) { + out.Key("scalingkeys"); + out.StartArray(); + for (unsigned int n = 0; n < ai.mNumScalingKeys; ++n) { + const aiVectorKey& scl = ai.mScalingKeys[n]; + out.StartArray(true); + out.Element(scl.mTime); + Write(out, scl.mValue); + out.EndArray(); + } + out.EndArray(); + } + out.EndObj(); +} + +void Write(JSONWriter& out, const aiAnimation& ai, bool is_elem = true) { + out.StartObj(is_elem); + + out.Key("name"); + out.SimpleValue(ai.mName); + + out.Key("tickspersecond"); + out.SimpleValue(ai.mTicksPerSecond); + + out.Key("duration"); + out.SimpleValue(ai.mDuration); + + out.Key("channels"); + out.StartArray(); + for (unsigned int n = 0; n < ai.mNumChannels; ++n) { + Write(out, *ai.mChannels[n]); + } + out.EndArray(); + out.EndObj(); +} + +void Write(JSONWriter& out, const aiCamera& ai, bool is_elem = true) { + out.StartObj(is_elem); + + out.Key("name"); + out.SimpleValue(ai.mName); + + out.Key("aspect"); + out.SimpleValue(ai.mAspect); + + out.Key("clipplanefar"); + out.SimpleValue(ai.mClipPlaneFar); + + out.Key("clipplanenear"); + out.SimpleValue(ai.mClipPlaneNear); + + out.Key("horizontalfov"); + out.SimpleValue(ai.mHorizontalFOV); + + out.Key("up"); + Write(out, ai.mUp, false); + + out.Key("lookat"); + Write(out, ai.mLookAt, false); + + out.EndObj(); +} + +void WriteFormatInfo(JSONWriter& out) { + out.StartObj(); + out.Key("format"); + out.SimpleValue("\"assimp2json\""); + out.Key("version"); + out.SimpleValue(CURRENT_FORMAT_VERSION); + out.EndObj(); +} + +void Write(JSONWriter& out, const aiScene& ai) { + out.StartObj(); + + out.Key("__metadata__"); + WriteFormatInfo(out); + + out.Key("rootnode"); + Write(out, *ai.mRootNode, false); + + out.Key("flags"); + out.SimpleValue(ai.mFlags); + + if (ai.HasMeshes()) { + out.Key("meshes"); + out.StartArray(); + for (unsigned int n = 0; n < ai.mNumMeshes; ++n) { + Write(out, *ai.mMeshes[n]); + } + out.EndArray(); + } + + if (ai.HasMaterials()) { + out.Key("materials"); + out.StartArray(); + for (unsigned int n = 0; n < ai.mNumMaterials; ++n) { + Write(out, *ai.mMaterials[n]); + } + out.EndArray(); + } + + if (ai.HasAnimations()) { + out.Key("animations"); + out.StartArray(); + for (unsigned int n = 0; n < ai.mNumAnimations; ++n) { + Write(out, *ai.mAnimations[n]); + } + out.EndArray(); + } + + if (ai.HasLights()) { + out.Key("lights"); + out.StartArray(); + for (unsigned int n = 0; n < ai.mNumLights; ++n) { + Write(out, *ai.mLights[n]); + } + out.EndArray(); + } + + if (ai.HasCameras()) { + out.Key("cameras"); + out.StartArray(); + for (unsigned int n = 0; n < ai.mNumCameras; ++n) { + Write(out, *ai.mCameras[n]); + } + out.EndArray(); + } + + if (ai.HasTextures()) { + out.Key("textures"); + out.StartArray(); + for (unsigned int n = 0; n < ai.mNumTextures; ++n) { + Write(out, *ai.mTextures[n]); + } + out.EndArray(); + } + out.EndObj(); } -void Write(JSONWriter& out, const aiFace& ai, bool is_elem = true) -{ - out.StartArray(is_elem); - for(unsigned int i = 0; i < ai.mNumIndices; ++i) { - out.Element(ai.mIndices[i]); - } - out.EndArray(); +void ExportAssimp2Json(const char* file, Assimp::IOSystem* io, const aiScene* scene, const Assimp::ExportProperties*) { + std::unique_ptr str(io->Open(file, "wt")); + if (!str) { + //throw Assimp::DeadlyExportError("could not open output file"); + } + + // get a copy of the scene so we can modify it + aiScene* scenecopy_tmp; + aiCopyScene(scene, &scenecopy_tmp); + + try { + // split meshes so they fit into a 16 bit index buffer + MeshSplitter splitter; + splitter.SetLimit(1 << 16); + splitter.Execute(scenecopy_tmp); + + // XXX Flag_WriteSpecialFloats is turned on by default, right now we don't have a configuration interface for exporters + JSONWriter s(*str, JSONWriter::Flag_WriteSpecialFloats); + Write(s, *scenecopy_tmp); + + } + catch (...) { + aiFreeScene(scenecopy_tmp); + throw; + } + aiFreeScene(scenecopy_tmp); } - -void Write(JSONWriter& out, const aiMesh& ai, bool is_elem = true) -{ - out.StartObj(is_elem); - - out.Key("name"); - out.SimpleValue(ai.mName); - - out.Key("materialindex"); - out.SimpleValue(ai.mMaterialIndex); - - out.Key("primitivetypes"); - out.SimpleValue(ai.mPrimitiveTypes); - - out.Key("vertices"); - out.StartArray(); - for(unsigned int i = 0; i < ai.mNumVertices; ++i) { - out.Element(ai.mVertices[i].x); - out.Element(ai.mVertices[i].y); - out.Element(ai.mVertices[i].z); - } - out.EndArray(); - - if(ai.HasNormals()) { - out.Key("normals"); - out.StartArray(); - for(unsigned int i = 0; i < ai.mNumVertices; ++i) { - out.Element(ai.mNormals[i].x); - out.Element(ai.mNormals[i].y); - out.Element(ai.mNormals[i].z); - } - out.EndArray(); - } - - if(ai.HasTangentsAndBitangents()) { - out.Key("tangents"); - out.StartArray(); - for(unsigned int i = 0; i < ai.mNumVertices; ++i) { - out.Element(ai.mTangents[i].x); - out.Element(ai.mTangents[i].y); - out.Element(ai.mTangents[i].z); - } - out.EndArray(); - - out.Key("bitangents"); - out.StartArray(); - for(unsigned int i = 0; i < ai.mNumVertices; ++i) { - out.Element(ai.mBitangents[i].x); - out.Element(ai.mBitangents[i].y); - out.Element(ai.mBitangents[i].z); - } - out.EndArray(); - } - - if(ai.GetNumUVChannels()) { - out.Key("numuvcomponents"); - out.StartArray(); - for(unsigned int n = 0; n < ai.GetNumUVChannels(); ++n) { - out.Element(ai.mNumUVComponents[n]); - } - out.EndArray(); - - out.Key("texturecoords"); - out.StartArray(); - for(unsigned int n = 0; n < ai.GetNumUVChannels(); ++n) { - - const unsigned int numc = ai.mNumUVComponents[n] ? ai.mNumUVComponents[n] : 2; - - out.StartArray(true); - for(unsigned int i = 0; i < ai.mNumVertices; ++i) { - for(unsigned int c = 0; c < numc; ++c) { - out.Element(ai.mTextureCoords[n][i][c]); - } - } - out.EndArray(); - } - out.EndArray(); - } - - if(ai.GetNumColorChannels()) { - out.Key("colors"); - out.StartArray(); - for(unsigned int n = 0; n < ai.GetNumColorChannels(); ++n) { - - out.StartArray(true); - for(unsigned int i = 0; i < ai.mNumVertices; ++i) { - out.Element(ai.mColors[n][i].r); - out.Element(ai.mColors[n][i].g); - out.Element(ai.mColors[n][i].b); - out.Element(ai.mColors[n][i].a); - } - out.EndArray(); - } - out.EndArray(); - } - - if(ai.mNumBones) { - out.Key("bones"); - out.StartArray(); - for(unsigned int n = 0; n < ai.mNumBones; ++n) { - Write(out, *ai.mBones[n]); - } - out.EndArray(); - } - - - out.Key("faces"); - out.StartArray(); - for(unsigned int n = 0; n < ai.mNumFaces; ++n) { - Write(out, ai.mFaces[n]); - } - out.EndArray(); - - out.EndObj(); } - -void Write(JSONWriter& out, const aiNode& ai, bool is_elem = true) -{ - out.StartObj(is_elem); - - out.Key("name"); - out.SimpleValue(ai.mName); - - out.Key("transformation"); - Write(out,ai.mTransformation,false); - - if(ai.mNumMeshes) { - out.Key("meshes"); - out.StartArray(); - for(unsigned int n = 0; n < ai.mNumMeshes; ++n) { - out.Element(ai.mMeshes[n]); - } - out.EndArray(); - } - - if(ai.mNumChildren) { - out.Key("children"); - out.StartArray(); - for(unsigned int n = 0; n < ai.mNumChildren; ++n) { - Write(out,*ai.mChildren[n]); - } - out.EndArray(); - } - - out.EndObj(); -} - -void Write(JSONWriter& out, const aiMaterial& ai, bool is_elem = true) -{ - out.StartObj(is_elem); - - out.Key("properties"); - out.StartArray(); - for(unsigned int i = 0; i < ai.mNumProperties; ++i) { - const aiMaterialProperty* const prop = ai.mProperties[i]; - out.StartObj(true); - out.Key("key"); - out.SimpleValue(prop->mKey); - out.Key("semantic"); - out.SimpleValue(prop->mSemantic); - out.Key("index"); - out.SimpleValue(prop->mIndex); - - out.Key("type"); - out.SimpleValue(prop->mType); - - out.Key("value"); - switch(prop->mType) - { - case aiPTI_Float: - if(prop->mDataLength/sizeof(float) > 1) { - out.StartArray(); - for(unsigned int i = 0; i < prop->mDataLength/sizeof(float); ++i) { - out.Element(reinterpret_cast(prop->mData)[i]); - } - out.EndArray(); - } - else { - out.SimpleValue(*reinterpret_cast(prop->mData)); - } - break; - - case aiPTI_Integer: - if(prop->mDataLength/sizeof(int) > 1) { - out.StartArray(); - for(unsigned int i = 0; i < prop->mDataLength/sizeof(int); ++i) { - out.Element(reinterpret_cast(prop->mData)[i]); - } - out.EndArray(); - } - else { - out.SimpleValue(*reinterpret_cast(prop->mData)); - } - break; - case aiPTI_String: - { - aiString s; - aiGetMaterialString(&ai,prop->mKey.data,prop->mSemantic,prop->mIndex,&s); - out.SimpleValue(s); - } - break; - case aiPTI_Buffer: - { - // binary data is written as series of hex-encoded octets - out.SimpleValue(prop->mData,prop->mDataLength); - } - break; - default: - assert(false); - } - - out.EndObj(); - } - - out.EndArray(); - out.EndObj(); -} - -void Write(JSONWriter& out, const aiTexture& ai, bool is_elem = true) -{ - out.StartObj(is_elem); - - out.Key("width"); - out.SimpleValue(ai.mWidth); - - out.Key("height"); - out.SimpleValue(ai.mHeight); - - out.Key("formathint"); - out.SimpleValue(aiString(ai.achFormatHint)); - - out.Key("data"); - if(!ai.mHeight) { - out.SimpleValue(ai.pcData,ai.mWidth); - } - else { - out.StartArray(); - for(unsigned int y = 0; y < ai.mHeight; ++y) { - out.StartArray(true); - for(unsigned int x = 0; x < ai.mWidth; ++x) { - const aiTexel& tx = ai.pcData[y*ai.mWidth+x]; - out.StartArray(true); - out.Element(static_cast(tx.r)); - out.Element(static_cast(tx.g)); - out.Element(static_cast(tx.b)); - out.Element(static_cast(tx.a)); - out.EndArray(); - } - out.EndArray(); - } - out.EndArray(); - } - - out.EndObj(); -} - -void Write(JSONWriter& out, const aiLight& ai, bool is_elem = true) -{ - out.StartObj(is_elem); - - out.Key("name"); - out.SimpleValue(ai.mName); - - out.Key("type"); - out.SimpleValue(ai.mType); - - if(ai.mType == aiLightSource_SPOT || ai.mType == aiLightSource_UNDEFINED) { - out.Key("angleinnercone"); - out.SimpleValue(ai.mAngleInnerCone); - - out.Key("angleoutercone"); - out.SimpleValue(ai.mAngleOuterCone); - } - - out.Key("attenuationconstant"); - out.SimpleValue(ai.mAttenuationConstant); - - out.Key("attenuationlinear"); - out.SimpleValue(ai.mAttenuationLinear); - - out.Key("attenuationquadratic"); - out.SimpleValue(ai.mAttenuationQuadratic); - - out.Key("diffusecolor"); - Write(out,ai.mColorDiffuse,false); - - out.Key("specularcolor"); - Write(out,ai.mColorSpecular,false); - - out.Key("ambientcolor"); - Write(out,ai.mColorAmbient,false); - - if(ai.mType != aiLightSource_POINT) { - out.Key("direction"); - Write(out,ai.mDirection,false); - - } - - if(ai.mType != aiLightSource_DIRECTIONAL) { - out.Key("position"); - Write(out,ai.mPosition,false); - } - - out.EndObj(); -} - -void Write(JSONWriter& out, const aiNodeAnim& ai, bool is_elem = true) -{ - out.StartObj(is_elem); - - out.Key("name"); - out.SimpleValue(ai.mNodeName); - - out.Key("prestate"); - out.SimpleValue(ai.mPreState); - - out.Key("poststate"); - out.SimpleValue(ai.mPostState); - - if(ai.mNumPositionKeys) { - out.Key("positionkeys"); - out.StartArray(); - for(unsigned int n = 0; n < ai.mNumPositionKeys; ++n) { - const aiVectorKey& pos = ai.mPositionKeys[n]; - out.StartArray(true); - out.Element(pos.mTime); - Write(out,pos.mValue); - out.EndArray(); - } - out.EndArray(); - } - - if(ai.mNumRotationKeys) { - out.Key("rotationkeys"); - out.StartArray(); - for(unsigned int n = 0; n < ai.mNumRotationKeys; ++n) { - const aiQuatKey& rot = ai.mRotationKeys[n]; - out.StartArray(true); - out.Element(rot.mTime); - Write(out,rot.mValue); - out.EndArray(); - } - out.EndArray(); - } - - if(ai.mNumScalingKeys) { - out.Key("scalingkeys"); - out.StartArray(); - for(unsigned int n = 0; n < ai.mNumScalingKeys; ++n) { - const aiVectorKey& scl = ai.mScalingKeys[n]; - out.StartArray(true); - out.Element(scl.mTime); - Write(out,scl.mValue); - out.EndArray(); - } - out.EndArray(); - } - out.EndObj(); -} - -void Write(JSONWriter& out, const aiAnimation& ai, bool is_elem = true) -{ - out.StartObj(is_elem); - - out.Key("name"); - out.SimpleValue(ai.mName); - - out.Key("tickspersecond"); - out.SimpleValue(ai.mTicksPerSecond); - - out.Key("duration"); - out.SimpleValue(ai.mDuration); - - out.Key("channels"); - out.StartArray(); - for(unsigned int n = 0; n < ai.mNumChannels; ++n) { - Write(out,*ai.mChannels[n]); - } - out.EndArray(); - out.EndObj(); -} - -void Write(JSONWriter& out, const aiCamera& ai, bool is_elem = true) -{ - out.StartObj(is_elem); - - out.Key("name"); - out.SimpleValue(ai.mName); - - out.Key("aspect"); - out.SimpleValue(ai.mAspect); - - out.Key("clipplanefar"); - out.SimpleValue(ai.mClipPlaneFar); - - out.Key("clipplanenear"); - out.SimpleValue(ai.mClipPlaneNear); - - out.Key("horizontalfov"); - out.SimpleValue(ai.mHorizontalFOV); - - out.Key("up"); - Write(out,ai.mUp,false); - - out.Key("lookat"); - Write(out,ai.mLookAt,false); - - out.EndObj(); -} - -void WriteFormatInfo(JSONWriter& out) -{ - out.StartObj(); - out.Key("format"); - out.SimpleValue("\"assimp2json\""); - out.Key("version"); - out.SimpleValue(CURRENT_FORMAT_VERSION); - out.EndObj(); -} - -void Write(JSONWriter& out, const aiScene& ai) -{ - out.StartObj(); - - out.Key("__metadata__"); - WriteFormatInfo(out); - - out.Key("rootnode"); - Write(out,*ai.mRootNode, false); - - out.Key("flags"); - out.SimpleValue(ai.mFlags); - - if(ai.HasMeshes()) { - out.Key("meshes"); - out.StartArray(); - for(unsigned int n = 0; n < ai.mNumMeshes; ++n) { - Write(out,*ai.mMeshes[n]); - } - out.EndArray(); - } - - if(ai.HasMaterials()) { - out.Key("materials"); - out.StartArray(); - for(unsigned int n = 0; n < ai.mNumMaterials; ++n) { - Write(out,*ai.mMaterials[n]); - } - out.EndArray(); - } - - if(ai.HasAnimations()) { - out.Key("animations"); - out.StartArray(); - for(unsigned int n = 0; n < ai.mNumAnimations; ++n) { - Write(out,*ai.mAnimations[n]); - } - out.EndArray(); - } - - if(ai.HasLights()) { - out.Key("lights"); - out.StartArray(); - for(unsigned int n = 0; n < ai.mNumLights; ++n) { - Write(out,*ai.mLights[n]); - } - out.EndArray(); - } - - if(ai.HasCameras()) { - out.Key("cameras"); - out.StartArray(); - for(unsigned int n = 0; n < ai.mNumCameras; ++n) { - Write(out,*ai.mCameras[n]); - } - out.EndArray(); - } - - if(ai.HasTextures()) { - out.Key("textures"); - out.StartArray(); - for(unsigned int n = 0; n < ai.mNumTextures; ++n) { - Write(out,*ai.mTextures[n]); - } - out.EndArray(); - } - out.EndObj(); -} - - -void ExportAssimp2Json(const char* file, Assimp::IOSystem* io, const aiScene* scene, const Assimp::ExportProperties*) -{ - std::unique_ptr str(io->Open(file,"wt")); - if(!str) { - //throw Assimp::DeadlyExportError("could not open output file"); - } - - // get a copy of the scene so we can modify it - aiScene* scenecopy_tmp; - aiCopyScene(scene, &scenecopy_tmp); - - try { - // split meshes so they fit into a 16 bit index buffer - MeshSplitter splitter; - splitter.SetLimit(1 << 16); - splitter.Execute(scenecopy_tmp); - - // XXX Flag_WriteSpecialFloats is turned on by default, right now we don't have a configuration interface for exporters - JSONWriter s(*str,JSONWriter::Flag_WriteSpecialFloats); - Write(s,*scenecopy_tmp); - - } - catch(...) { - aiFreeScene(scenecopy_tmp); - throw; - } - aiFreeScene(scenecopy_tmp); -} - -} // - #endif // ASSIMP_BUILD_NO_ASSJSON_EXPORTER #endif // ASSIMP_BUILD_NO_EXPORT diff --git a/code/Assjson/mesh_splitter.cpp b/code/Assjson/mesh_splitter.cpp index 07ae0bd86..24385f9a0 100644 --- a/code/Assjson/mesh_splitter.cpp +++ b/code/Assjson/mesh_splitter.cpp @@ -6,7 +6,6 @@ Licensed under a 3-clause BSD license. See the LICENSE file for more information */ - #include "mesh_splitter.h" #include @@ -18,8 +17,7 @@ Licensed under a 3-clause BSD license. See the LICENSE file for more information // ------------------------------------------------------------------------------------------------ // Executes the post processing step on the given imported data. -void MeshSplitter :: Execute( aiScene* pScene) -{ +void MeshSplitter::Execute( aiScene* pScene) { std::vector > source_mesh_map; for( unsigned int a = 0; a < pScene->mNumMeshes; a++) { @@ -27,8 +25,7 @@ void MeshSplitter :: Execute( aiScene* pScene) } const unsigned int size = static_cast(source_mesh_map.size()); - if (size != pScene->mNumMeshes) - { + if (size != pScene->mNumMeshes) { // it seems something has been split. rebuild the mesh list delete[] pScene->mMeshes; pScene->mNumMeshes = size; @@ -45,8 +42,7 @@ void MeshSplitter :: Execute( aiScene* pScene) // ------------------------------------------------------------------------------------------------ -void MeshSplitter :: UpdateNode(aiNode* pcNode, const std::vector >& source_mesh_map) -{ +void MeshSplitter::UpdateNode(aiNode* pcNode, const std::vector >& source_mesh_map) { // TODO: should better use std::(multi)set for source_mesh_map. // for every index in out list build a new entry @@ -82,10 +78,9 @@ typedef std::pair PerVertexWeight; typedef std::vector VertexWeightTable; // ------------------------------------------------------------------------------------------------ -VertexWeightTable* ComputeVertexBoneWeightTable(const aiMesh* pMesh) -{ +VertexWeightTable* ComputeVertexBoneWeightTable(const aiMesh* pMesh) { if (!pMesh || !pMesh->mNumVertices || !pMesh->mNumBones) { - return NULL; + return nullptr; } VertexWeightTable* const avPerVertexWeights = new VertexWeightTable[pMesh->mNumVertices]; @@ -101,9 +96,7 @@ VertexWeightTable* ComputeVertexBoneWeightTable(const aiMesh* pMesh) } // ------------------------------------------------------------------------------------------------ -void MeshSplitter :: SplitMesh(unsigned int a, aiMesh* in_mesh, - std::vector >& source_mesh_map) -{ +void MeshSplitter :: SplitMesh(unsigned int a, aiMesh* in_mesh, std::vector >& source_mesh_map) { // TODO: should better use std::(multi)set for source_mesh_map. if (in_mesh->mNumVertices <= LIMIT) { diff --git a/code/COB/COBLoader.cpp b/code/COB/COBLoader.cpp index b9eb5b7ea..19e3cd59e 100644 --- a/code/COB/COBLoader.cpp +++ b/code/COB/COBLoader.cpp @@ -898,6 +898,7 @@ public: : nfo(nfo) , reader(reader) , cur(reader.GetCurrentPos()) { + // empty } ~chunk_guard() { @@ -905,7 +906,7 @@ public: if(nfo.size != static_cast(-1)) { try { reader.IncPtr( static_cast< int >( nfo.size ) - reader.GetCurrentPos() + cur ); - } catch (const DeadlyImportError& e ) { + } catch (const DeadlyImportError& ) { // out of limit so correct the value reader.IncPtr( reader.GetReadLimit() ); } @@ -913,15 +914,17 @@ public: } private: - const COB::ChunkInfo& nfo; StreamReaderLE& reader; long cur; }; // ------------------------------------------------------------------------------------------------ -void COBImporter::ReadBinaryFile(Scene& out, StreamReaderLE* reader) -{ +void COBImporter::ReadBinaryFile(Scene& out, StreamReaderLE* reader) { + if (nullptr == reader) { + return; + } + while(1) { std::string type; type += reader -> GetI1() diff --git a/code/Common/ImporterRegistry.cpp b/code/Common/ImporterRegistry.cpp index b99f145ab..32ac3b416 100644 --- a/code/Common/ImporterRegistry.cpp +++ b/code/Common/ImporterRegistry.cpp @@ -200,9 +200,6 @@ corresponding preprocessor flag to selectively disable formats. #ifndef ASSIMP_BUILD_NO_STEP_IMPORTER # include "Importer/StepFile/StepFileImporter.h" #endif -#ifndef ASSIMP_BUILD_NO_JT_IMPORTER -# include "JTImporter.h" -#endif namespace Assimp { @@ -361,10 +358,6 @@ void GetImporterInstanceList(std::vector< BaseImporter* >& out) #ifndef ASSIMP_BUILD_NO_STEP_IMPORTER out.push_back(new StepFile::StepFileImporter()); #endif -#ifndef ASSIMP_BUILD_NO_JT_IMPORTER - out.push_back(new JTImporter()); -#endif - } /** will delete all registered importers. */ diff --git a/code/FBX/FBXDocument.h b/code/FBX/FBXDocument.h index 53bd65878..18e5c38f1 100644 --- a/code/FBX/FBXDocument.h +++ b/code/FBX/FBXDocument.h @@ -627,7 +627,7 @@ public: return content; } - uint32_t ContentLength() const { + uint64_t ContentLength() const { return contentLength; } diff --git a/include/assimp/camera.h b/include/assimp/camera.h index dd45d90d1..e573eea5d 100644 --- a/include/assimp/camera.h +++ b/include/assimp/camera.h @@ -5,8 +5,6 @@ Open Asset Import Library (assimp) Copyright (c) 2006-2019, assimp team - - All rights reserved. Redistribution and use of this software in source and binary forms, @@ -60,7 +58,7 @@ extern "C" { * * Cameras have a representation in the node graph and can be animated. * An important aspect is that the camera itself is also part of the - * scenegraph. This means, any values such as the look-at vector are not + * scene-graph. This means, any values such as the look-at vector are not * *absolute*, they're relative to the coordinate system defined * by the node which corresponds to the camera. This allows for camera * animations. For static cameras parameters like the 'look-at' or 'up' vectors diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 28aeac65a..913813c3b 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -120,13 +120,13 @@ SET( IMPORTERS unit/utB3DImportExport.cpp unit/utMDCImportExport.cpp unit/utAssbinImportExport.cpp + unit/ImportExport/utAssjsonImportExport.cpp unit/ImportExport/utCOBImportExport.cpp unit/ImportExport/utOgreImportExport.cpp unit/ImportExport/utQ3BSPFileImportExport.cpp unit/ImportExport/utOFFImportExport.cpp unit/ImportExport/utNFFImportExport.cpp unit/ImportExport/utXGLImportExport.cpp -# unit/ImportExport/utJTImporter.cpp ) SET( MATERIAL @@ -166,11 +166,11 @@ SET( POST_PROCESSES ) SOURCE_GROUP( UnitTests\\Compiler FILES unit/CCompilerTest.c ) -SOURCE_GROUP( UnitTests\\Common FILES ${COMMON} ) -SOURCE_GROUP( UnitTests\\Importers FILES ${IMPORTERS} ) -SOURCE_GROUP( UnitTests\\Material FILES ${MATERIAL} ) -SOURCE_GROUP( UnitTests\\Math FILES ${MATH} ) -SOURCE_GROUP( UnitTests\\PostProcess FILES ${POST_PROCESSES}) +SOURCE_GROUP( UnitTests\\Common FILES ${COMMON} ) +SOURCE_GROUP( UnitTests\\ImportExport FILES ${IMPORTERS} ) +SOURCE_GROUP( UnitTests\\Material FILES ${MATERIAL} ) +SOURCE_GROUP( UnitTests\\Math FILES ${MATH} ) +SOURCE_GROUP( UnitTests\\PostProcess FILES ${POST_PROCESSES}) add_executable( unit ../contrib/gtest/src/gtest-all.cc diff --git a/test/models/PLY/cube_test.ply b/test/models/PLY/cube_test.ply index 45fae27fb..f2ac612e8 100644 --- a/test/models/PLY/cube_test.ply +++ b/test/models/PLY/cube_test.ply @@ -1,10 +1,6 @@ ply format ascii 1.0 -<<<<<<< HEAD -comment Created by Open Asset Import Library - http://assimp.sf.net (v4.1.732158294) -======= -comment Created by Open Asset Import Library - http://assimp.sf.net (v4.1.649942190) ->>>>>>> master +comment Created by Open Asset Import Library - http://assimp.sf.net (v4.1.993695325) element vertex 8 property float x property float y diff --git a/test/unit/AbstractImportExportBase.h b/test/unit/AbstractImportExportBase.h index 529b9cf7d..d6ae37d60 100644 --- a/test/unit/AbstractImportExportBase.h +++ b/test/unit/AbstractImportExportBase.h @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. @@ -39,17 +39,37 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. --------------------------------------------------------------------------- */ #pragma once +#ifndef AI_ABSTRACTIMPORTEXPORTBASE_H_INC +#define AI_ABSTRACTIMPORTEXPORTBASE_H_INC #include "UnitTestPCH.h" +// --------------------------------------------------------------------------- +/** Abstract base class to test import and export + */ + // --------------------------------------------------------------------------- class AbstractImportExportBase : public ::testing::Test { public: + /// @brief The class destructor. virtual ~AbstractImportExportBase(); - virtual bool importerTest() = 0; + + /// @brief The importer-test, will return true for successful import. + /// @return true for success, false for failure. + virtual bool importerTest(); + + /// @brief The exporter-test, will return true for successful import. + /// @return true for success, false for failure. virtual bool exporterTest(); }; +inline +bool AbstractImportExportBase::importerTest() { + return true; +} + inline bool AbstractImportExportBase::exporterTest() { return true; } + +#endif // AI_ABSTRACTIMPORTEXPORTBASE_H_INC diff --git a/test/unit/ImportExport/utAssjsonImportExport.cpp b/test/unit/ImportExport/utAssjsonImportExport.cpp new file mode 100644 index 000000000..20a2a9e24 --- /dev/null +++ b/test/unit/ImportExport/utAssjsonImportExport.cpp @@ -0,0 +1,69 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2019, assimp team + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above +copyright notice, this list of conditions and the +following disclaimer. + +* Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the +following disclaimer in the documentation and/or other +materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its +contributors may be used to endorse or promote products +derived from this software without specific prior +written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ +#include "UnitTestPCH.h" +#include "AbstractImportExportBase.h" + +#include +#include +#include +#include + +using namespace Assimp; + +#ifndef ASSIMP_BUILD_NO_EXPORT + +class utAssjsonImportExport : public AbstractImportExportBase { +public: + bool exporterTest() override { + Importer importer; + const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/OBJ/spider.obj", aiProcess_ValidateDataStructure); + + Exporter exporter; + aiReturn res = exporter.Export(scene, "json", "./spider_test.json"); + return aiReturn_SUCCESS == res; + } +}; + +TEST_F(utAssjsonImportExport, exportTest) { + EXPECT_TRUE(exporterTest()); +} + +#endif // ASSIMP_BUILD_NO_EXPORT diff --git a/test/unit/utAMFImportExport.cpp b/test/unit/utAMFImportExport.cpp index dc2c9b99b..6eb0b4418 100644 --- a/test/unit/utAMFImportExport.cpp +++ b/test/unit/utAMFImportExport.cpp @@ -5,8 +5,6 @@ Open Asset Import Library (assimp) Copyright (c) 2006-2019, assimp team - - All rights reserved. Redistribution and use of this software in source and binary forms, diff --git a/test/unit/utASEImportExport.cpp b/test/unit/utASEImportExport.cpp index 28168de7d..313f0f83a 100644 --- a/test/unit/utASEImportExport.cpp +++ b/test/unit/utASEImportExport.cpp @@ -5,8 +5,6 @@ Open Asset Import Library (assimp) Copyright (c) 2006-2019, assimp team - - All rights reserved. Redistribution and use of this software in source and binary forms, diff --git a/test/unit/utAssbinImportExport.cpp b/test/unit/utAssbinImportExport.cpp index 6def04796..011aaa649 100644 --- a/test/unit/utAssbinImportExport.cpp +++ b/test/unit/utAssbinImportExport.cpp @@ -5,8 +5,6 @@ Open Asset Import Library (assimp) Copyright (c) 2006-2019, assimp team - - All rights reserved. Redistribution and use of this software in source and binary forms, @@ -53,8 +51,8 @@ using namespace Assimp; class utAssbinImportExport : public AbstractImportExportBase { public: - virtual bool importerTest() { - Assimp::Importer importer; + bool importerTest() override { + Importer importer; const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/OBJ/spider.obj", aiProcess_ValidateDataStructure ); Exporter exporter; @@ -66,7 +64,7 @@ public: }; TEST_F( utAssbinImportExport, exportAssbin3DFromFileTest ) { - Assimp::Importer importer; + Importer importer; const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/OBJ/spider.obj", aiProcess_ValidateDataStructure ); EXPECT_NE( nullptr, scene ); } diff --git a/test/unit/utB3DImportExport.cpp b/test/unit/utB3DImportExport.cpp index d51ca51a6..ea75b1939 100644 --- a/test/unit/utB3DImportExport.cpp +++ b/test/unit/utB3DImportExport.cpp @@ -5,8 +5,6 @@ Open Asset Import Library (assimp) Copyright (c) 2006-2019, assimp team - - All rights reserved. Redistribution and use of this software in source and binary forms, diff --git a/test/unit/utFindDegenerates.cpp b/test/unit/utFindDegenerates.cpp index ea539df27..064031f34 100644 --- a/test/unit/utFindDegenerates.cpp +++ b/test/unit/utFindDegenerates.cpp @@ -5,8 +5,6 @@ Open Asset Import Library (assimp) Copyright (c) 2006-2019, assimp team - - All rights reserved. Redistribution and use of this software in source and binary forms, @@ -49,35 +47,42 @@ using namespace Assimp; class FindDegeneratesProcessTest : public ::testing::Test { public: + FindDegeneratesProcessTest() + : Test() + , mMesh( nullptr ) + , mProcess( nullptr ) { + // empty + } + +protected: virtual void SetUp(); virtual void TearDown(); protected: - aiMesh* mesh; - FindDegeneratesProcess* process; + aiMesh* mMesh; + FindDegeneratesProcess* mProcess; }; -// ------------------------------------------------------------------------------------------------ void FindDegeneratesProcessTest::SetUp() { - mesh = new aiMesh(); - process = new FindDegeneratesProcess(); + mMesh = new aiMesh(); + mProcess = new FindDegeneratesProcess(); - mesh->mNumFaces = 1000; - mesh->mFaces = new aiFace[1000]; + mMesh->mNumFaces = 1000; + mMesh->mFaces = new aiFace[1000]; - mesh->mNumVertices = 5000*2; - mesh->mVertices = new aiVector3D[5000*2]; + mMesh->mNumVertices = 5000*2; + mMesh->mVertices = new aiVector3D[5000*2]; for (unsigned int i = 0; i < 5000; ++i) { - mesh->mVertices[i] = mesh->mVertices[i+5000] = aiVector3D((float)i); + mMesh->mVertices[i] = mMesh->mVertices[i+5000] = aiVector3D((float)i); } - mesh->mPrimitiveTypes = aiPrimitiveType_LINE | aiPrimitiveType_POINT | + mMesh->mPrimitiveTypes = aiPrimitiveType_LINE | aiPrimitiveType_POINT | aiPrimitiveType_POLYGON | aiPrimitiveType_TRIANGLE; unsigned int numOut = 0, numFaces = 0; for (unsigned int i = 0; i < 1000; ++i) { - aiFace& f = mesh->mFaces[i]; + aiFace& f = mMesh->mFaces[i]; f.mNumIndices = (i % 5)+1; // between 1 and 5 f.mIndices = new unsigned int[f.mNumIndices]; bool had = false; @@ -102,46 +107,46 @@ void FindDegeneratesProcessTest::SetUp() { if (!had) ++numFaces; } - mesh->mNumUVComponents[0] = numOut; - mesh->mNumUVComponents[1] = numFaces; + mMesh->mNumUVComponents[0] = numOut; + mMesh->mNumUVComponents[1] = numFaces; } void FindDegeneratesProcessTest::TearDown() { - delete mesh; - delete process; + delete mMesh; + delete mProcess; } TEST_F(FindDegeneratesProcessTest, testDegeneratesDetection) { - process->EnableInstantRemoval(false); - process->ExecuteOnMesh(mesh); + mProcess->EnableInstantRemoval(false); + mProcess->ExecuteOnMesh(mMesh); unsigned int out = 0; for (unsigned int i = 0; i < 1000; ++i) { - aiFace& f = mesh->mFaces[i]; + aiFace& f = mMesh->mFaces[i]; out += f.mNumIndices; } - EXPECT_EQ(1000U, mesh->mNumFaces); - EXPECT_EQ(10000U, mesh->mNumVertices); - EXPECT_EQ(out, mesh->mNumUVComponents[0]); + EXPECT_EQ(1000U, mMesh->mNumFaces); + EXPECT_EQ(10000U, mMesh->mNumVertices); + EXPECT_EQ(out, mMesh->mNumUVComponents[0]); EXPECT_EQ(static_cast( aiPrimitiveType_LINE | aiPrimitiveType_POINT | aiPrimitiveType_POLYGON | aiPrimitiveType_TRIANGLE), - mesh->mPrimitiveTypes); + mMesh->mPrimitiveTypes); } TEST_F(FindDegeneratesProcessTest, testDegeneratesRemoval) { - process->EnableAreaCheck(false); - process->EnableInstantRemoval(true); - process->ExecuteOnMesh(mesh); + mProcess->EnableAreaCheck(false); + mProcess->EnableInstantRemoval(true); + mProcess->ExecuteOnMesh(mMesh); - EXPECT_EQ(mesh->mNumUVComponents[1], mesh->mNumFaces); + EXPECT_EQ(mMesh->mNumUVComponents[1], mMesh->mNumFaces); } TEST_F(FindDegeneratesProcessTest, testDegeneratesRemovalWithAreaCheck) { - process->EnableAreaCheck(true); - process->EnableInstantRemoval(true); - process->ExecuteOnMesh(mesh); + mProcess->EnableAreaCheck(true); + mProcess->EnableInstantRemoval(true); + mProcess->ExecuteOnMesh(mMesh); - EXPECT_EQ(mesh->mNumUVComponents[1]-100, mesh->mNumFaces); + EXPECT_EQ(mMesh->mNumUVComponents[1]-100, mMesh->mNumFaces); } diff --git a/test/unit/utFindInvalidData.cpp b/test/unit/utFindInvalidData.cpp index 5b874a2a4..7c70a71a9 100644 --- a/test/unit/utFindInvalidData.cpp +++ b/test/unit/utFindInvalidData.cpp @@ -5,8 +5,6 @@ Open Asset Import Library (assimp) Copyright (c) 2006-2019, assimp team - - All rights reserved. Redistribution and use of this software in source and binary forms, @@ -48,89 +46,100 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. using namespace std; using namespace Assimp; -class FindInvalidDataProcessTest : public ::testing::Test -{ +class utFindInvalidDataProcess : public ::testing::Test { public: + utFindInvalidDataProcess() + : Test() + , mMesh(nullptr) + , mProcess(nullptr) { + // empty + } + +protected: virtual void SetUp(); virtual void TearDown(); protected: - aiMesh* pcMesh; - FindInvalidDataProcess* piProcess; + aiMesh* mMesh; + FindInvalidDataProcess* mProcess; }; // ------------------------------------------------------------------------------------------------ -void FindInvalidDataProcessTest::SetUp() { +void utFindInvalidDataProcess::SetUp() { ASSERT_TRUE( AI_MAX_NUMBER_OF_TEXTURECOORDS >= 3); - piProcess = new FindInvalidDataProcess(); - pcMesh = new aiMesh(); + mProcess = new FindInvalidDataProcess(); + mMesh = new aiMesh(); - pcMesh->mNumVertices = 1000; - pcMesh->mVertices = new aiVector3D[1000]; - for (unsigned int i = 0; i < 1000;++i) - pcMesh->mVertices[i] = aiVector3D((float)i); + mMesh->mNumVertices = 1000; + mMesh->mVertices = new aiVector3D[1000]; + for (unsigned int i = 0; i < 1000; ++i) { + mMesh->mVertices[i] = aiVector3D((float)i); + } - pcMesh->mNormals = new aiVector3D[1000]; - for (unsigned int i = 0; i < 1000;++i) - pcMesh->mNormals[i] = aiVector3D((float)i+1); + mMesh->mNormals = new aiVector3D[1000]; + for (unsigned int i = 0; i < 1000; ++i) { + mMesh->mNormals[i] = aiVector3D((float)i + 1); + } - pcMesh->mTangents = new aiVector3D[1000]; - for (unsigned int i = 0; i < 1000;++i) - pcMesh->mTangents[i] = aiVector3D((float)i); + mMesh->mTangents = new aiVector3D[1000]; + for (unsigned int i = 0; i < 1000; ++i) { + mMesh->mTangents[i] = aiVector3D((float)i); + } - pcMesh->mBitangents = new aiVector3D[1000]; - for (unsigned int i = 0; i < 1000;++i) - pcMesh->mBitangents[i] = aiVector3D((float)i); + mMesh->mBitangents = new aiVector3D[1000]; + for (unsigned int i = 0; i < 1000; ++i) { + mMesh->mBitangents[i] = aiVector3D((float)i); + } - for (unsigned int a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS;++a) - { - pcMesh->mTextureCoords[a] = new aiVector3D[1000]; - for (unsigned int i = 0; i < 1000;++i) - pcMesh->mTextureCoords[a][i] = aiVector3D((float)i); + for (unsigned int a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS;++a) { + mMesh->mTextureCoords[a] = new aiVector3D[1000]; + for (unsigned int i = 0; i < 1000; ++i) { + mMesh->mTextureCoords[a][i] = aiVector3D((float)i); + } } } // ------------------------------------------------------------------------------------------------ -void FindInvalidDataProcessTest::TearDown() -{ - delete piProcess; - delete pcMesh; +void utFindInvalidDataProcess::TearDown() { + delete mProcess; + delete mMesh; } // ------------------------------------------------------------------------------------------------ -TEST_F(FindInvalidDataProcessTest, testStepNegativeResult) -{ - ::memset(pcMesh->mNormals,0,pcMesh->mNumVertices*sizeof(aiVector3D)); - ::memset(pcMesh->mBitangents,0,pcMesh->mNumVertices*sizeof(aiVector3D)); +TEST_F(utFindInvalidDataProcess, testStepNegativeResult) { + ::memset(mMesh->mNormals, 0, mMesh->mNumVertices*sizeof(aiVector3D) ); + ::memset(mMesh->mBitangents, 0, mMesh->mNumVertices*sizeof(aiVector3D) ); - pcMesh->mTextureCoords[2][455] = aiVector3D( std::numeric_limits::quiet_NaN() ); + mMesh->mTextureCoords[2][455] = aiVector3D( std::numeric_limits::quiet_NaN() ); - piProcess->ProcessMesh(pcMesh); + mProcess->ProcessMesh(mMesh); - EXPECT_TRUE(NULL != pcMesh->mVertices); - EXPECT_TRUE(NULL == pcMesh->mNormals); - EXPECT_TRUE(NULL == pcMesh->mTangents); - EXPECT_TRUE(NULL == pcMesh->mBitangents); + EXPECT_TRUE(NULL != mMesh->mVertices); + EXPECT_EQ(NULL, mMesh->mNormals); + EXPECT_EQ(NULL, mMesh->mTangents); + EXPECT_EQ(NULL, mMesh->mBitangents); - for (unsigned int i = 0; i < 2;++i) - EXPECT_TRUE(NULL != pcMesh->mTextureCoords[i]); + for (unsigned int i = 0; i < 2; ++i) { + EXPECT_TRUE(NULL != mMesh->mTextureCoords[i]); + } - for (unsigned int i = 2; i < AI_MAX_NUMBER_OF_TEXTURECOORDS;++i) - EXPECT_TRUE(NULL == pcMesh->mTextureCoords[i]); + for (unsigned int i = 2; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i) { + EXPECT_EQ(NULL, mMesh->mTextureCoords[i]); + } } // ------------------------------------------------------------------------------------------------ -TEST_F(FindInvalidDataProcessTest, testStepPositiveResult) -{ - piProcess->ProcessMesh(pcMesh); +TEST_F(utFindInvalidDataProcess, testStepPositiveResult) { + mProcess->ProcessMesh(mMesh); - EXPECT_TRUE(NULL != pcMesh->mVertices); + EXPECT_NE(nullptr, mMesh->mVertices); - EXPECT_TRUE(NULL != pcMesh->mNormals); - EXPECT_TRUE(NULL != pcMesh->mTangents); - EXPECT_TRUE(NULL != pcMesh->mBitangents); + EXPECT_NE(nullptr, mMesh->mNormals); + EXPECT_NE(nullptr, mMesh->mTangents); + EXPECT_NE(nullptr, mMesh->mBitangents); - for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS;++i) - EXPECT_TRUE(NULL != pcMesh->mTextureCoords[i]); + for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i) { + EXPECT_NE(nullptr, mMesh->mTextureCoords[i]); + } } diff --git a/test/unit/utGenBoundingBoxesProcess.cpp b/test/unit/utGenBoundingBoxesProcess.cpp index a26edb7e3..2c2f831bc 100644 --- a/test/unit/utGenBoundingBoxesProcess.cpp +++ b/test/unit/utGenBoundingBoxesProcess.cpp @@ -48,13 +48,21 @@ using namespace Assimp; class utGenBoundingBoxesProcess : public ::testing::Test { public: + utGenBoundingBoxesProcess() + : Test() + , mProcess(nullptr) + , mMesh(nullptr) + , mScene(nullptr) { + // empty + } + void SetUp() override { mProcess = new GenBoundingBoxesProcess; mMesh = new aiMesh(); mMesh->mNumVertices = 100; mMesh->mVertices = new aiVector3D[100]; for (unsigned int i = 0; i < 100; ++i) { - mMesh->mVertices[i] = aiVector3D(i, i, i); + mMesh->mVertices[i] = aiVector3D((ai_real)i, (ai_real)i, (ai_real)i); } mScene = new aiScene(); mScene->mNumMeshes = 1; diff --git a/test/unit/utJoinVertices.cpp b/test/unit/utJoinVertices.cpp index 6b832b73d..215b0dd90 100644 --- a/test/unit/utJoinVertices.cpp +++ b/test/unit/utJoinVertices.cpp @@ -5,8 +5,6 @@ Open Asset Import Library (assimp) Copyright (c) 2006-2019, assimp team - - All rights reserved. Redistribution and use of this software in source and binary forms, @@ -49,8 +47,16 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. using namespace std; using namespace Assimp; -class JoinVerticesTest : public ::testing::Test { +class utJoinVertices : public ::testing::Test { public: + utJoinVertices() + : Test() + , piProcess(nullptr) + , pcMesh(nullptr) { + // empty + } + +protected: virtual void SetUp(); virtual void TearDown(); @@ -60,8 +66,7 @@ protected: }; // ------------------------------------------------------------------------------------------------ -void JoinVerticesTest::SetUp() -{ +void utJoinVertices::SetUp() { // construct the process piProcess = new JoinVerticesProcess(); @@ -71,11 +76,9 @@ void JoinVerticesTest::SetUp() pcMesh->mNumVertices = 900; aiVector3D*& pv = pcMesh->mVertices = new aiVector3D[900]; - for (unsigned int i = 0; i < 3;++i) - { + for (unsigned int i = 0; i < 3;++i) { const unsigned int base = i*300; - for (unsigned int a = 0; a < 300;++a) - { + for (unsigned int a = 0; a < 300;++a) { pv[base+a].x = pv[base+a].y = pv[base+a].z = (float)a; } } @@ -83,38 +86,37 @@ void JoinVerticesTest::SetUp() // generate faces - each vertex is referenced once pcMesh->mNumFaces = 300; pcMesh->mFaces = new aiFace[300]; - for (unsigned int i = 0,p = 0; i < 300;++i) - { + for (unsigned int i = 0,p = 0; i < 300;++i) { aiFace& face = pcMesh->mFaces[i]; face.mIndices = new unsigned int[ face.mNumIndices = 3 ]; - for (unsigned int a = 0; a < 3;++a) + for (unsigned int a = 0; a < 3; ++a) { face.mIndices[a] = p++; + } } // generate extra members - set them to zero to make sure they're identical pcMesh->mTextureCoords[0] = new aiVector3D[900]; - for (unsigned int i = 0; i < 900;++i)pcMesh->mTextureCoords[0][i] = aiVector3D( 0.f ); - - pcMesh->mNormals = new aiVector3D[900]; - for (unsigned int i = 0; i < 900;++i)pcMesh->mNormals[i] = aiVector3D( 0.f ); - - pcMesh->mTangents = new aiVector3D[900]; - for (unsigned int i = 0; i < 900;++i)pcMesh->mTangents[i] = aiVector3D( 0.f ); - pcMesh->mBitangents = new aiVector3D[900]; - for (unsigned int i = 0; i < 900;++i)pcMesh->mBitangents[i] = aiVector3D( 0.f ); + pcMesh->mNormals = new aiVector3D[900]; + pcMesh->mTangents = new aiVector3D[900]; + for (unsigned int i = 0; i < 900; ++i) { + pcMesh->mTextureCoords[0][i] = aiVector3D(0.f); + pcMesh->mNormals[i] = aiVector3D(0.f); + pcMesh->mTangents[i] = aiVector3D(0.f); + pcMesh->mBitangents[i] = aiVector3D(0.f); + } } // ------------------------------------------------------------------------------------------------ -void JoinVerticesTest::TearDown() -{ +void utJoinVertices::TearDown() { delete this->pcMesh; + pcMesh = nullptr; delete this->piProcess; + piProcess = nullptr; } // ------------------------------------------------------------------------------------------------ -TEST_F(JoinVerticesTest, testProcess) -{ +TEST_F(utJoinVertices, testProcess) { // execute the step on the given data piProcess->ProcessMesh(pcMesh,0); @@ -122,15 +124,14 @@ TEST_F(JoinVerticesTest, testProcess) ASSERT_EQ(300U, pcMesh->mNumFaces); ASSERT_EQ(300U, pcMesh->mNumVertices); - ASSERT_TRUE(NULL != pcMesh->mNormals); - ASSERT_TRUE(NULL != pcMesh->mTangents); - ASSERT_TRUE(NULL != pcMesh->mBitangents); - ASSERT_TRUE(NULL != pcMesh->mTextureCoords[0]); + ASSERT_TRUE( nullptr != pcMesh->mNormals); + ASSERT_TRUE( nullptr != pcMesh->mTangents); + ASSERT_TRUE( nullptr != pcMesh->mBitangents); + ASSERT_TRUE( nullptr != pcMesh->mTextureCoords[0]); // the order doesn't care float fSum = 0.f; - for (unsigned int i = 0; i < 300;++i) - { + for (unsigned int i = 0; i < 300; ++i) { aiVector3D& v = pcMesh->mVertices[i]; fSum += v.x + v.y + v.z; @@ -141,4 +142,3 @@ TEST_F(JoinVerticesTest, testProcess) } EXPECT_EQ(150.f*299.f*3.f, fSum); // gaussian sum equation } - diff --git a/test/unit/utLimitBoneWeights.cpp b/test/unit/utLimitBoneWeights.cpp index 5172976b4..927a9e37c 100644 --- a/test/unit/utLimitBoneWeights.cpp +++ b/test/unit/utLimitBoneWeights.cpp @@ -5,8 +5,6 @@ Open Asset Import Library (assimp) Copyright (c) 2006-2019, assimp team - - All rights reserved. Redistribution and use of this software in source and binary forms, @@ -50,83 +48,83 @@ using namespace Assimp; class LimitBoneWeightsTest : public ::testing::Test { public: + LimitBoneWeightsTest() + : Test() + , mProcess(nullptr) + , mMesh(nullptr) { + // empty + } + +protected: virtual void SetUp(); virtual void TearDown(); protected: - LimitBoneWeightsProcess* piProcess; - aiMesh* pcMesh; + LimitBoneWeightsProcess *mProcess; + aiMesh *mMesh; }; // ------------------------------------------------------------------------------------------------ -void LimitBoneWeightsTest::SetUp() -{ +void LimitBoneWeightsTest::SetUp() { // construct the process - this->piProcess = new LimitBoneWeightsProcess(); + this->mProcess = new LimitBoneWeightsProcess(); // now need to create a nice mesh for testing purposes - this->pcMesh = new aiMesh(); + this->mMesh = new aiMesh(); - pcMesh->mNumVertices = 500; - pcMesh->mVertices = new aiVector3D[500]; // uninit. - pcMesh->mNumBones = 30; - pcMesh->mBones = new aiBone*[30]; + mMesh->mNumVertices = 500; + mMesh->mVertices = new aiVector3D[500]; // uninit. + mMesh->mNumBones = 30; + mMesh->mBones = new aiBone*[30]; unsigned int iCur = 0; - for (unsigned int i = 0; i < 30;++i) - { - aiBone* pc = pcMesh->mBones[i] = new aiBone(); + for (unsigned int i = 0; i < 30;++i) { + aiBone* pc = mMesh->mBones[i] = new aiBone(); pc->mNumWeights = 250; pc->mWeights = new aiVertexWeight[pc->mNumWeights]; - for (unsigned int qq = 0; qq < pc->mNumWeights;++qq) - { + for (unsigned int qq = 0; qq < pc->mNumWeights;++qq) { aiVertexWeight& v = pc->mWeights[qq]; v.mVertexId = iCur++; - if (500 == iCur)iCur = 0; + if (500 == iCur) { + iCur = 0; + } v.mWeight = 1.0f / 15; // each vertex should occur once in two bones } } } // ------------------------------------------------------------------------------------------------ -void LimitBoneWeightsTest::TearDown() -{ - delete pcMesh; - delete piProcess; +void LimitBoneWeightsTest::TearDown() { + delete mMesh; + delete mProcess; } // ------------------------------------------------------------------------------------------------ -TEST_F(LimitBoneWeightsTest, testProcess) -{ +TEST_F(LimitBoneWeightsTest, testProcess) { // execute the step on the given data - piProcess->ProcessMesh(pcMesh); + mProcess->ProcessMesh(mMesh); // check whether everything is ok ... typedef std::vector VertexWeightList; - VertexWeightList* asWeights = new VertexWeightList[pcMesh->mNumVertices]; + VertexWeightList* asWeights = new VertexWeightList[mMesh->mNumVertices]; - for (unsigned int i = 0; i < pcMesh->mNumVertices;++i) + for (unsigned int i = 0; i < mMesh->mNumVertices; ++i) { asWeights[i].reserve(4); + } // sort back as per-vertex lists - for (unsigned int i = 0; i < pcMesh->mNumBones;++i) - { - aiBone& pcBone = **(pcMesh->mBones+i); - for (unsigned int q = 0; q < pcBone.mNumWeights;++q) - { + for (unsigned int i = 0; i < mMesh->mNumBones;++i) { + aiBone& pcBone = **(mMesh->mBones+i); + for (unsigned int q = 0; q < pcBone.mNumWeights;++q) { aiVertexWeight weight = pcBone.mWeights[q]; asWeights[weight.mVertexId].push_back(LimitBoneWeightsProcess::Weight (i,weight.mWeight)); } } // now validate the size of the lists and check whether all weights sum to 1.0f - for (unsigned int i = 0; i < pcMesh->mNumVertices;++i) - { + for (unsigned int i = 0; i < mMesh->mNumVertices;++i) { EXPECT_LE(asWeights[i].size(), 4U); float fSum = 0.0f; - for (VertexWeightList::const_iterator - iter = asWeights[i].begin(); - iter != asWeights[i].end();++iter) - { + for (VertexWeightList::const_iterator iter = asWeights[i].begin(); iter != asWeights[i].end();++iter) { fSum += (*iter).mWeight; } EXPECT_GE(fSum, 0.95F); diff --git a/test/unit/utPretransformVertices.cpp b/test/unit/utPretransformVertices.cpp index 22d1b28b4..0839740ac 100644 --- a/test/unit/utPretransformVertices.cpp +++ b/test/unit/utPretransformVertices.cpp @@ -51,18 +51,24 @@ using namespace Assimp; class PretransformVerticesTest : public ::testing::Test { public: + PretransformVerticesTest() + : Test() + , mScene(nullptr) + , mProcess(nullptr) { + // empty + } + +protected: virtual void SetUp(); virtual void TearDown(); protected: - - aiScene* scene; - PretransformVertices* process; + aiScene *mScene; + PretransformVertices *mProcess; }; // ------------------------------------------------------------------------------------------------ -void AddNodes(unsigned int num, aiNode* father, unsigned int depth) -{ +void AddNodes(unsigned int num, aiNode* father, unsigned int depth) { father->mChildren = new aiNode*[father->mNumChildren = 5]; for (unsigned int i = 0; i < 5; ++i) { aiNode* nd = father->mChildren[i] = new aiNode(); @@ -79,26 +85,26 @@ void AddNodes(unsigned int num, aiNode* father, unsigned int depth) } if (depth > 1) { - for (unsigned int i = 0; i < 5; ++i) - AddNodes(i, father->mChildren[i],depth-1); + for (unsigned int i = 0; i < 5; ++i) { + AddNodes(i, father->mChildren[i], depth - 1); + } } } // ------------------------------------------------------------------------------------------------ -void PretransformVerticesTest::SetUp() -{ - scene = new aiScene(); +void PretransformVerticesTest::SetUp() { + mScene = new aiScene(); // add 5 empty materials - scene->mMaterials = new aiMaterial*[scene->mNumMaterials = 5]; + mScene->mMaterials = new aiMaterial*[mScene->mNumMaterials = 5]; for (unsigned int i = 0; i < 5;++i) { - scene->mMaterials[i] = new aiMaterial(); + mScene->mMaterials[i] = new aiMaterial(); } // add 25 test meshes - scene->mMeshes = new aiMesh*[scene->mNumMeshes = 25]; - for ( unsigned int i = 0; i < 25; ++i) { - aiMesh* mesh = scene->mMeshes[ i ] = new aiMesh(); + mScene->mMeshes = new aiMesh*[mScene->mNumMeshes = 25]; + for ( unsigned int i = 0; i < 25; ++i) { + aiMesh* mesh = mScene->mMeshes[ i ] = new aiMesh(); mesh->mPrimitiveTypes = aiPrimitiveType_POINT; mesh->mFaces = new aiFace[ mesh->mNumFaces = 10+i ]; @@ -124,36 +130,33 @@ void PretransformVerticesTest::SetUp() } // construct some nodes (1+25) - scene->mRootNode = new aiNode(); - scene->mRootNode->mName.Set("Root"); - AddNodes(0,scene->mRootNode,2); + mScene->mRootNode = new aiNode(); + mScene->mRootNode->mName.Set("Root"); + AddNodes(0, mScene->mRootNode, 2); - process = new PretransformVertices(); + mProcess = new PretransformVertices(); } // ------------------------------------------------------------------------------------------------ -void PretransformVerticesTest::TearDown() -{ - delete scene; - delete process; +void PretransformVerticesTest::TearDown() { + delete mScene; + delete mProcess; } // ------------------------------------------------------------------------------------------------ -TEST_F(PretransformVerticesTest, testProcessCollapseHierarchy) -{ - process->KeepHierarchy(false); - process->Execute(scene); +TEST_F(PretransformVerticesTest, testProcessCollapseHierarchy) { + mProcess->KeepHierarchy(false); + mProcess->Execute(mScene); - EXPECT_EQ(5U, scene->mNumMaterials); - EXPECT_EQ(10U, scene->mNumMeshes); // every second mesh has normals + EXPECT_EQ(5U, mScene->mNumMaterials); + EXPECT_EQ(10U, mScene->mNumMeshes); // every second mesh has normals } // ------------------------------------------------------------------------------------------------ -TEST_F(PretransformVerticesTest, testProcessKeepHierarchy) -{ - process->KeepHierarchy(true); - process->Execute(scene); +TEST_F(PretransformVerticesTest, testProcessKeepHierarchy) { + mProcess->KeepHierarchy(true); + mProcess->Execute(mScene); - EXPECT_EQ(5U, scene->mNumMaterials); - EXPECT_EQ(49U, scene->mNumMeshes); // see note on mesh 12 above + EXPECT_EQ(5U, mScene->mNumMaterials); + EXPECT_EQ(49U, mScene->mNumMeshes); // see note on mesh 12 above } diff --git a/test/unit/utScenePreprocessor.cpp b/test/unit/utScenePreprocessor.cpp index 2c181a90f..7233e1379 100644 --- a/test/unit/utScenePreprocessor.cpp +++ b/test/unit/utScenePreprocessor.cpp @@ -50,67 +50,67 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. using namespace std; using namespace Assimp; - -class ScenePreprocessorTest : public ::testing::Test -{ +class ScenePreprocessorTest : public ::testing::Test { public: + ScenePreprocessorTest() + : Test() + , mScenePreprocessor(nullptr) + , mScene(nullptr) { + // empty + } +protected: virtual void SetUp(); virtual void TearDown(); protected: - void CheckIfOnly(aiMesh* p, unsigned int num, unsigned flag); + void ProcessAnimation(aiAnimation* anim) { mScenePreprocessor->ProcessAnimation(anim); } + void ProcessMesh(aiMesh* mesh) { mScenePreprocessor->ProcessMesh(mesh); } - void ProcessAnimation(aiAnimation* anim) { pp->ProcessAnimation(anim); } - void ProcessMesh(aiMesh* mesh) { pp->ProcessMesh(mesh); } - - ScenePreprocessor* pp; - aiScene* scene; +private: + ScenePreprocessor *mScenePreprocessor; + aiScene *mScene; }; // ------------------------------------------------------------------------------------------------ -void ScenePreprocessorTest::SetUp() -{ +void ScenePreprocessorTest::SetUp() { // setup a dummy scene with a single node - scene = new aiScene(); - scene->mRootNode = new aiNode(); - scene->mRootNode->mName.Set(""); + mScene = new aiScene(); + mScene->mRootNode = new aiNode(); + mScene->mRootNode->mName.Set(""); // add some translation - scene->mRootNode->mTransformation.a4 = 1.f; - scene->mRootNode->mTransformation.b4 = 2.f; - scene->mRootNode->mTransformation.c4 = 3.f; + mScene->mRootNode->mTransformation.a4 = 1.f; + mScene->mRootNode->mTransformation.b4 = 2.f; + mScene->mRootNode->mTransformation.c4 = 3.f; // and allocate a ScenePreprocessor to operate on the scene - pp = new ScenePreprocessor(scene); + mScenePreprocessor = new ScenePreprocessor(mScene); } // ------------------------------------------------------------------------------------------------ -void ScenePreprocessorTest::TearDown() -{ - delete pp; - delete scene; +void ScenePreprocessorTest::TearDown() { + delete mScenePreprocessor; + delete mScene; } // ------------------------------------------------------------------------------------------------ // Check whether ProcessMesh() returns flag for a mesh that consist of primitives with num indices -void ScenePreprocessorTest::CheckIfOnly(aiMesh* p, unsigned int num, unsigned int flag) -{ +void ScenePreprocessorTest::CheckIfOnly(aiMesh* p, unsigned int num, unsigned int flag) { // Triangles only for (unsigned i = 0; i < p->mNumFaces;++i) { p->mFaces[i].mNumIndices = num; } - pp->ProcessMesh(p); + mScenePreprocessor->ProcessMesh(p); EXPECT_EQ(flag, p->mPrimitiveTypes); p->mPrimitiveTypes = 0; } // ------------------------------------------------------------------------------------------------ // Check whether a mesh is preprocessed correctly. Case 1: The mesh needs preprocessing -TEST_F(ScenePreprocessorTest, testMeshPreprocessingPos) -{ - aiMesh* p = new aiMesh(); +TEST_F(ScenePreprocessorTest, testMeshPreprocessingPos) { + aiMesh* p = new aiMesh; p->mNumFaces = 100; p->mFaces = new aiFace[p->mNumFaces]; @@ -145,9 +145,8 @@ TEST_F(ScenePreprocessorTest, testMeshPreprocessingPos) // ------------------------------------------------------------------------------------------------ // Check whether a mesh is preprocessed correctly. Case 1: The mesh doesn't need preprocessing -TEST_F(ScenePreprocessorTest, testMeshPreprocessingNeg) -{ - aiMesh* p = new aiMesh(); +TEST_F(ScenePreprocessorTest, testMeshPreprocessingNeg) { + aiMesh* p = new aiMesh; p->mPrimitiveTypes = aiPrimitiveType_TRIANGLE|aiPrimitiveType_POLYGON; ProcessMesh(p); @@ -160,8 +159,7 @@ TEST_F(ScenePreprocessorTest, testMeshPreprocessingNeg) // ------------------------------------------------------------------------------------------------ // Make a dummy animation with a single channel, '' -aiAnimation* MakeDummyAnimation() -{ +aiAnimation* MakeDummyAnimation() { aiAnimation* p = new aiAnimation(); p->mNumChannels = 1; p->mChannels = new aiNodeAnim*[1]; @@ -172,8 +170,7 @@ aiAnimation* MakeDummyAnimation() // ------------------------------------------------------------------------------------------------ // Check whether an anim is preprocessed correctly. Case 1: The anim needs preprocessing -TEST_F(ScenePreprocessorTest, testAnimationPreprocessingPos) -{ +TEST_F(ScenePreprocessorTest, testAnimationPreprocessingPos) { aiAnimation* p = MakeDummyAnimation(); aiNodeAnim* anim = p->mChannels[0]; diff --git a/test/unit/utSortByPType.cpp b/test/unit/utSortByPType.cpp index 1aa9dad0a..749e618da 100644 --- a/test/unit/utSortByPType.cpp +++ b/test/unit/utSortByPType.cpp @@ -52,12 +52,20 @@ using namespace Assimp; class SortByPTypeProcessTest : public ::testing::Test { public: + SortByPTypeProcessTest() + : Test() + , mProcess1(nullptr) + , mScene(nullptr) { + // empty + } + +protected: virtual void SetUp(); virtual void TearDown(); protected: - SortByPTypeProcess* process1; - aiScene* scene; + SortByPTypeProcess* mProcess1; + aiScene* mScene; }; // ------------------------------------------------------------------------------------------------ @@ -75,8 +83,7 @@ static unsigned int num[10][4] = { }; // ------------------------------------------------------------------------------------------------ -static unsigned int result[10] = -{ +static unsigned int result[10] = { aiPrimitiveType_POLYGON, aiPrimitiveType_TRIANGLE, aiPrimitiveType_LINE, @@ -90,19 +97,16 @@ static unsigned int result[10] = }; // ------------------------------------------------------------------------------------------------ -void SortByPTypeProcessTest::SetUp() -{ -// process0 = new DeterminePTypeHelperProcess(); - process1 = new SortByPTypeProcess(); - scene = new aiScene(); +void SortByPTypeProcessTest::SetUp() { + mProcess1 = new SortByPTypeProcess(); + mScene = new aiScene(); - scene->mNumMeshes = 10; - scene->mMeshes = new aiMesh*[10]; + mScene->mNumMeshes = 10; + mScene->mMeshes = new aiMesh*[10]; bool five = false; - for (unsigned int i = 0; i < 10; ++i) - { - aiMesh* mesh = scene->mMeshes[i] = new aiMesh(); + for (unsigned int i = 0; i < 10; ++i) { + aiMesh* mesh = mScene->mMeshes[i] = new aiMesh(); mesh->mNumFaces = 1000; aiFace* faces = mesh->mFaces = new aiFace[1000]; aiVector3D* pv = mesh->mVertices = new aiVector3D[mesh->mNumFaces*5]; @@ -115,27 +119,24 @@ void SortByPTypeProcessTest::SetUp() unsigned int remaining[4] = {num[i][0],num[i][1],num[i][2],num[i][3]}; unsigned int n = 0; - for (unsigned int m = 0; m < 1000; ++m) - { + for (unsigned int m = 0; m < 1000; ++m) { unsigned int idx = m % 4; - while (true) - { - if (!remaining[idx]) - { - if (4 == ++idx)idx = 0; + while (true) { + if (!remaining[idx]) { + if (4 == ++idx) { + idx = 0; + } continue; } break; } faces->mNumIndices = idx+1; - if (4 == faces->mNumIndices) - { + if (4 == faces->mNumIndices) { if(five)++faces->mNumIndices; five = !five; } faces->mIndices = new unsigned int[faces->mNumIndices]; - for (unsigned int q = 0; q mNumIndices;++q,++n) - { + for (unsigned int q = 0; q mNumIndices;++q,++n) { faces->mIndices[q] = n; float f = (float)remaining[idx]; @@ -152,12 +153,11 @@ void SortByPTypeProcessTest::SetUp() mesh->mNumVertices = n; } - scene->mRootNode = new aiNode(); - scene->mRootNode->mNumChildren = 5; - scene->mRootNode->mChildren = new aiNode*[5]; - for (unsigned int i = 0; i< 5;++i ) - { - aiNode* node = scene->mRootNode->mChildren[i] = new aiNode(); + mScene->mRootNode = new aiNode(); + mScene->mRootNode->mNumChildren = 5; + mScene->mRootNode->mChildren = new aiNode*[5]; + for (unsigned int i = 0; i< 5;++i ) { + aiNode* node = mScene->mRootNode->mChildren[i] = new aiNode(); node->mNumMeshes = 2; node->mMeshes = new unsigned int[2]; node->mMeshes[0] = (i<<1u); @@ -166,48 +166,28 @@ void SortByPTypeProcessTest::SetUp() } // ------------------------------------------------------------------------------------------------ -void SortByPTypeProcessTest::TearDown() -{ - //delete process0; - delete process1; - delete scene; +void SortByPTypeProcessTest::TearDown() { + delete mProcess1; + delete mScene; } // ------------------------------------------------------------------------------------------------ -//TEST_F(SortByPTypeProcessTest, DeterminePTypeStep() -//{ -// process0->Execute(scene); -// -// for (unsigned int i = 0; i < 10; ++i) -// { -// aiMesh* mesh = scene->mMeshes[i]; -// EXPECT_TRUE(mesh->mPrimitiveTypes == result[i]); -// } -//} - -// ------------------------------------------------------------------------------------------------ -TEST_F(SortByPTypeProcessTest, SortByPTypeStep) -{ - // process0->Execute(scene); - - // and another small test for ScenePreprocessor - ScenePreprocessor s(scene); +TEST_F(SortByPTypeProcessTest, SortByPTypeStep) { + ScenePreprocessor s(mScene); s.ProcessScene(); for (unsigned int m = 0; m< 10;++m) - EXPECT_EQ(result[m], scene->mMeshes[m]->mPrimitiveTypes); + EXPECT_EQ(result[m], mScene->mMeshes[m]->mPrimitiveTypes); - process1->Execute(scene); + mProcess1->Execute(mScene); unsigned int idx = 0; - for (unsigned int m = 0,real = 0; m< 10;++m) - { - for (unsigned int n = 0; n < 4;++n) - { + for (unsigned int m = 0,real = 0; m< 10;++m) { + for (unsigned int n = 0; n < 4;++n) { if ((idx = num[m][n])) { - EXPECT_TRUE(real < scene->mNumMeshes); + EXPECT_TRUE(real < mScene->mNumMeshes); - aiMesh* mesh = scene->mMeshes[real]; + aiMesh* mesh = mScene->mMeshes[real]; EXPECT_TRUE(NULL != mesh); EXPECT_EQ(AI_PRIMITIVE_TYPE_FOR_N_INDICES(n+1), mesh->mPrimitiveTypes); @@ -218,8 +198,7 @@ TEST_F(SortByPTypeProcessTest, SortByPTypeStep) EXPECT_TRUE(NULL != mesh->mTextureCoords[0]); EXPECT_TRUE(mesh->mNumFaces == idx); - for (unsigned int f = 0; f < mesh->mNumFaces;++f) - { + for (unsigned int f = 0; f < mesh->mNumFaces;++f) { aiFace& face = mesh->mFaces[f]; EXPECT_TRUE(face.mNumIndices == (n+1) || (3 == n && face.mNumIndices > 3)); } @@ -228,4 +207,3 @@ TEST_F(SortByPTypeProcessTest, SortByPTypeStep) } } } -