Merge branch 'master' into test_gitignore_cleanup

pull/2564/head
RichardTea 2019-07-25 12:41:30 +01:00
commit 59a5343a1a
41 changed files with 2059 additions and 587 deletions

View File

@ -0,0 +1,109 @@
/*
cencoder.c - c source to a base64 encoding algorithm implementation
This is part of the libb64 project, and has been placed in the public domain.
For details, see http://sourceforge.net/projects/libb64
*/
#include "cencode.h" // changed from <B64/cencode.h>
const int CHARS_PER_LINE = 72;
void base64_init_encodestate(base64_encodestate* state_in)
{
state_in->step = step_A;
state_in->result = 0;
state_in->stepcount = 0;
}
char base64_encode_value(char value_in)
{
static const char* encoding = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
if (value_in > 63) return '=';
return encoding[(int)value_in];
}
int base64_encode_block(const char* plaintext_in, int length_in, char* code_out, base64_encodestate* state_in)
{
const char* plainchar = plaintext_in;
const char* const plaintextend = plaintext_in + length_in;
char* codechar = code_out;
char result;
char fragment;
result = state_in->result;
switch (state_in->step)
{
while (1)
{
case step_A:
if (plainchar == plaintextend)
{
state_in->result = result;
state_in->step = step_A;
return codechar - code_out;
}
fragment = *plainchar++;
result = (fragment & 0x0fc) >> 2;
*codechar++ = base64_encode_value(result);
result = (fragment & 0x003) << 4;
case step_B:
if (plainchar == plaintextend)
{
state_in->result = result;
state_in->step = step_B;
return codechar - code_out;
}
fragment = *plainchar++;
result |= (fragment & 0x0f0) >> 4;
*codechar++ = base64_encode_value(result);
result = (fragment & 0x00f) << 2;
case step_C:
if (plainchar == plaintextend)
{
state_in->result = result;
state_in->step = step_C;
return codechar - code_out;
}
fragment = *plainchar++;
result |= (fragment & 0x0c0) >> 6;
*codechar++ = base64_encode_value(result);
result = (fragment & 0x03f) >> 0;
*codechar++ = base64_encode_value(result);
++(state_in->stepcount);
if (state_in->stepcount == CHARS_PER_LINE/4)
{
*codechar++ = '\n';
state_in->stepcount = 0;
}
}
}
/* control should not reach here */
return codechar - code_out;
}
int base64_encode_blockend(char* code_out, base64_encodestate* state_in)
{
char* codechar = code_out;
switch (state_in->step)
{
case step_B:
*codechar++ = base64_encode_value(state_in->result);
*codechar++ = '=';
*codechar++ = '=';
break;
case step_C:
*codechar++ = base64_encode_value(state_in->result);
*codechar++ = '=';
break;
case step_A:
break;
}
*codechar++ = '\n';
return codechar - code_out;
}

View File

@ -0,0 +1,31 @@
/*
cencode.h - c header for a base64 encoding algorithm
This is part of the libb64 project, and has been placed in the public domain.
For details, see http://sourceforge.net/projects/libb64
*/
#ifndef BASE64_CENCODE_H
#define BASE64_CENCODE_H
typedef enum
{
step_A, step_B, step_C
} base64_encodestep;
typedef struct
{
base64_encodestep step;
char result;
int stepcount;
} base64_encodestate;
void base64_init_encodestate(base64_encodestate* state_in);
char base64_encode_value(char value_in);
int base64_encode_block(const char* plaintext_in, int length_in, char* code_out, base64_encodestate* state_in);
int base64_encode_blockend(char* code_out, base64_encodestate* state_in);
#endif /* BASE64_CENCODE_H */

View File

@ -0,0 +1,818 @@
/*
Assimp2Json
Copyright (c) 2011, Alexander C. Gessler
Licensed under a 3-clause BSD license. See the LICENSE file for more information.
*/
#ifndef ASSIMP_BUILD_NO_EXPORT
#ifndef ASSIMP_BUILD_NO_ASSJSON_EXPORTER
#include <assimp/Importer.hpp>
#include <assimp/Exporter.hpp>
#include <assimp/IOStream.hpp>
#include <assimp/IOSystem.hpp>
#include <assimp/scene.h>
#include <sstream>
#include <limits>
#include <cassert>
#include <memory>
#define CURRENT_FORMAT_VERSION 100
// grab scoped_ptr from assimp to avoid a dependency on boost.
//#include <assimp/../../code/BoostWorkaround/boost/scoped_ptr.hpp>
#include "mesh_splitter.h"
extern "C" {
#include "cencode.h"
}
namespace Assimp {
void ExportAssimp2Json(const char*, Assimp::IOSystem*, const aiScene*, const Assimp::ExportProperties*);
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 {
public:
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"));
}
~JSONWriter() {
Flush();
}
void Flush() {
const std::string s = buff.str();
out.Write(s.c_str(), s.length(), 1);
buff.clear();
}
void PushIndent() {
indent += '\t';
}
void PopIndent() {
indent.erase(indent.end() - 1);
}
void Key(const std::string& name) {
AddIndentation();
Delimit();
buff << '\"' + name + "\": ";
}
template<typename Literal>
void Element(const Literal& name) {
AddIndentation();
Delimit();
LiteralToString(buff, name) << '\n';
}
template<typename Literal>
void SimpleValue(const Literal& s) {
LiteralToString(buff, s) << '\n';
}
void SimpleValue(const void* buffer, size_t len) {
base64_encodestate s;
base64_init_encodestate(&s);
char* const out = new char[std::max(len * 2, static_cast<size_t>(16u))];
const int n = base64_encode_block(reinterpret_cast<const char*>(buffer), static_cast<int>(len), out, &s);
out[n + base64_encode_blockend(out + n, &s)] = '\0';
// 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 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;
}
}
private:
template<typename Literal>
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;
// 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('\\');
}
t.push_back(s.data[i]);
}
stream << "\"";
stream << t;
stream << "\"";
return stream;
}
std::stringstream& LiteralToString(std::stringstream& stream, float f) {
if (!std::numeric_limits<float>::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<float>::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;
}
private:
Assimp::IOStream& out;
std::string indent, newline;
std::stringstream buff;
bool first;
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 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 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);
out.Key("name");
out.SimpleValue(ai.mName);
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();
}
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<float*>(prop->mData)[i]);
}
out.EndArray();
}
else {
out.SimpleValue(*reinterpret_cast<float*>(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<int*>(prop->mData)[i]);
}
out.EndArray();
} else {
out.SimpleValue(*reinterpret_cast<int*>(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<unsigned int>(tx.r));
out.Element(static_cast<unsigned int>(tx.g));
out.Element(static_cast<unsigned int>(tx.b));
out.Element(static_cast<unsigned int>(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<Assimp::IOStream> 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

View File

@ -0,0 +1,320 @@
/*
Assimp2Json
Copyright (c) 2011, Alexander C. Gessler
Licensed under a 3-clause BSD license. See the LICENSE file for more information.
*/
#include "mesh_splitter.h"
#include <assimp/scene.h>
// ----------------------------------------------------------------------------
// Note: this is largely based on assimp's SplitLargeMeshes_Vertex process.
// it is refactored and the coding style is slightly improved, though.
// ----------------------------------------------------------------------------
// ------------------------------------------------------------------------------------------------
// Executes the post processing step on the given imported data.
void MeshSplitter::Execute( aiScene* pScene) {
std::vector<std::pair<aiMesh*, unsigned int> > source_mesh_map;
for( unsigned int a = 0; a < pScene->mNumMeshes; a++) {
SplitMesh(a, pScene->mMeshes[a],source_mesh_map);
}
const unsigned int size = static_cast<unsigned int>(source_mesh_map.size());
if (size != pScene->mNumMeshes) {
// it seems something has been split. rebuild the mesh list
delete[] pScene->mMeshes;
pScene->mNumMeshes = size;
pScene->mMeshes = new aiMesh*[size]();
for (unsigned int i = 0; i < size;++i) {
pScene->mMeshes[i] = source_mesh_map[i].first;
}
// now we need to update all nodes
UpdateNode(pScene->mRootNode,source_mesh_map);
}
}
// ------------------------------------------------------------------------------------------------
void MeshSplitter::UpdateNode(aiNode* pcNode, const std::vector<std::pair<aiMesh*, unsigned int> >& source_mesh_map) {
// TODO: should better use std::(multi)set for source_mesh_map.
// for every index in out list build a new entry
std::vector<unsigned int> aiEntries;
aiEntries.reserve(pcNode->mNumMeshes + 1);
for (unsigned int i = 0; i < pcNode->mNumMeshes;++i) {
for (unsigned int a = 0, end = static_cast<unsigned int>(source_mesh_map.size()); a < end;++a) {
if (source_mesh_map[a].second == pcNode->mMeshes[i]) {
aiEntries.push_back(a);
}
}
}
// now build the new list
delete pcNode->mMeshes;
pcNode->mNumMeshes = static_cast<unsigned int>(aiEntries.size());
pcNode->mMeshes = new unsigned int[pcNode->mNumMeshes];
for (unsigned int b = 0; b < pcNode->mNumMeshes;++b) {
pcNode->mMeshes[b] = aiEntries[b];
}
// recursively update children
for (unsigned int i = 0, end = pcNode->mNumChildren; i < end;++i) {
UpdateNode ( pcNode->mChildren[i], source_mesh_map );
}
return;
}
#define WAS_NOT_COPIED 0xffffffff
typedef std::pair <unsigned int,float> PerVertexWeight;
typedef std::vector <PerVertexWeight> VertexWeightTable;
// ------------------------------------------------------------------------------------------------
VertexWeightTable* ComputeVertexBoneWeightTable(const aiMesh* pMesh) {
if (!pMesh || !pMesh->mNumVertices || !pMesh->mNumBones) {
return nullptr;
}
VertexWeightTable* const avPerVertexWeights = new VertexWeightTable[pMesh->mNumVertices];
for (unsigned int i = 0; i < pMesh->mNumBones;++i) {
aiBone* bone = pMesh->mBones[i];
for (unsigned int a = 0; a < bone->mNumWeights;++a) {
const aiVertexWeight& weight = bone->mWeights[a];
avPerVertexWeights[weight.mVertexId].push_back( std::make_pair(i,weight.mWeight) );
}
}
return avPerVertexWeights;
}
// ------------------------------------------------------------------------------------------------
void MeshSplitter :: SplitMesh(unsigned int a, aiMesh* in_mesh, std::vector<std::pair<aiMesh*, unsigned int> >& source_mesh_map) {
// TODO: should better use std::(multi)set for source_mesh_map.
if (in_mesh->mNumVertices <= LIMIT) {
source_mesh_map.push_back(std::make_pair(in_mesh,a));
return;
}
// build a per-vertex weight list if necessary
VertexWeightTable* avPerVertexWeights = ComputeVertexBoneWeightTable(in_mesh);
// we need to split this mesh into sub meshes. Estimate submesh size
const unsigned int sub_meshes = (in_mesh->mNumVertices / LIMIT) + 1;
// create a std::vector<unsigned int> to remember which vertices have already
// been copied and to which position (i.e. output index)
std::vector<unsigned int> was_copied_to;
was_copied_to.resize(in_mesh->mNumVertices,WAS_NOT_COPIED);
// Try to find a good estimate for the number of output faces
// per mesh. Add 12.5% as buffer
unsigned int size_estimated = in_mesh->mNumFaces / sub_meshes;
size_estimated += size_estimated / 8;
// now generate all submeshes
unsigned int base = 0;
while (true) {
const unsigned int out_vertex_index = LIMIT;
aiMesh* out_mesh = new aiMesh();
out_mesh->mNumVertices = 0;
out_mesh->mMaterialIndex = in_mesh->mMaterialIndex;
// the name carries the adjacency information between the meshes
out_mesh->mName = in_mesh->mName;
typedef std::vector<aiVertexWeight> BoneWeightList;
if (in_mesh->HasBones()) {
out_mesh->mBones = new aiBone*[in_mesh->mNumBones]();
}
// clear the temporary helper array
if (base) {
std::fill(was_copied_to.begin(), was_copied_to.end(), WAS_NOT_COPIED);
}
std::vector<aiFace> vFaces;
// reserve enough storage for most cases
if (in_mesh->HasPositions()) {
out_mesh->mVertices = new aiVector3D[out_vertex_index];
}
if (in_mesh->HasNormals()) {
out_mesh->mNormals = new aiVector3D[out_vertex_index];
}
if (in_mesh->HasTangentsAndBitangents()) {
out_mesh->mTangents = new aiVector3D[out_vertex_index];
out_mesh->mBitangents = new aiVector3D[out_vertex_index];
}
for (unsigned int c = 0; in_mesh->HasVertexColors(c);++c) {
out_mesh->mColors[c] = new aiColor4D[out_vertex_index];
}
for (unsigned int c = 0; in_mesh->HasTextureCoords(c);++c) {
out_mesh->mNumUVComponents[c] = in_mesh->mNumUVComponents[c];
out_mesh->mTextureCoords[c] = new aiVector3D[out_vertex_index];
}
vFaces.reserve(size_estimated);
// (we will also need to copy the array of indices)
while (base < in_mesh->mNumFaces) {
const unsigned int iNumIndices = in_mesh->mFaces[base].mNumIndices;
// doesn't catch degenerates but is quite fast
unsigned int iNeed = 0;
for (unsigned int v = 0; v < iNumIndices;++v) {
unsigned int index = in_mesh->mFaces[base].mIndices[v];
// check whether we do already have this vertex
if (WAS_NOT_COPIED == was_copied_to[index]) {
iNeed++;
}
}
if (out_mesh->mNumVertices + iNeed > out_vertex_index) {
// don't use this face
break;
}
vFaces.push_back(aiFace());
aiFace& rFace = vFaces.back();
// setup face type and number of indices
rFace.mNumIndices = iNumIndices;
rFace.mIndices = new unsigned int[iNumIndices];
// need to update the output primitive types
switch (rFace.mNumIndices)
{
case 1:
out_mesh->mPrimitiveTypes |= aiPrimitiveType_POINT;
break;
case 2:
out_mesh->mPrimitiveTypes |= aiPrimitiveType_LINE;
break;
case 3:
out_mesh->mPrimitiveTypes |= aiPrimitiveType_TRIANGLE;
break;
default:
out_mesh->mPrimitiveTypes |= aiPrimitiveType_POLYGON;
}
// and copy the contents of the old array, offset them by current base
for (unsigned int v = 0; v < iNumIndices;++v) {
const unsigned int index = in_mesh->mFaces[base].mIndices[v];
// check whether we do already have this vertex
if (WAS_NOT_COPIED != was_copied_to[index]) {
rFace.mIndices[v] = was_copied_to[index];
continue;
}
// copy positions
out_mesh->mVertices[out_mesh->mNumVertices] = (in_mesh->mVertices[index]);
// copy normals
if (in_mesh->HasNormals()) {
out_mesh->mNormals[out_mesh->mNumVertices] = (in_mesh->mNormals[index]);
}
// copy tangents/bi-tangents
if (in_mesh->HasTangentsAndBitangents()) {
out_mesh->mTangents[out_mesh->mNumVertices] = (in_mesh->mTangents[index]);
out_mesh->mBitangents[out_mesh->mNumVertices] = (in_mesh->mBitangents[index]);
}
// texture coordinates
for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_TEXTURECOORDS;++c) {
if (in_mesh->HasTextureCoords( c)) {
out_mesh->mTextureCoords[c][out_mesh->mNumVertices] = in_mesh->mTextureCoords[c][index];
}
}
// vertex colors
for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_COLOR_SETS;++c) {
if (in_mesh->HasVertexColors( c)) {
out_mesh->mColors[c][out_mesh->mNumVertices] = in_mesh->mColors[c][index];
}
}
// check whether we have bone weights assigned to this vertex
rFace.mIndices[v] = out_mesh->mNumVertices;
if (avPerVertexWeights) {
VertexWeightTable& table = avPerVertexWeights[ out_mesh->mNumVertices ];
for (VertexWeightTable::const_iterator iter = table.begin(), end = table.end(); iter != end;++iter) {
// allocate the bone weight array if necessary and store it in the mBones field (HACK!)
BoneWeightList* weight_list = reinterpret_cast<BoneWeightList*>(out_mesh->mBones[(*iter).first]);
if (!weight_list) {
weight_list = new BoneWeightList();
out_mesh->mBones[(*iter).first] = reinterpret_cast<aiBone*>(weight_list);
}
weight_list->push_back(aiVertexWeight(out_mesh->mNumVertices,(*iter).second));
}
}
was_copied_to[index] = out_mesh->mNumVertices;
out_mesh->mNumVertices++;
}
base++;
if(out_mesh->mNumVertices == out_vertex_index) {
// break here. The face is only added if it was complete
break;
}
}
// check which bones we'll need to create for this submesh
if (in_mesh->HasBones()) {
aiBone** ppCurrent = out_mesh->mBones;
for (unsigned int k = 0; k < in_mesh->mNumBones;++k) {
// check whether the bone exists
BoneWeightList* const weight_list = reinterpret_cast<BoneWeightList*>(out_mesh->mBones[k]);
if (weight_list) {
const aiBone* const bone_in = in_mesh->mBones[k];
aiBone* const bone_out = new aiBone();
*ppCurrent++ = bone_out;
bone_out->mName = aiString(bone_in->mName);
bone_out->mOffsetMatrix =bone_in->mOffsetMatrix;
bone_out->mNumWeights = (unsigned int)weight_list->size();
bone_out->mWeights = new aiVertexWeight[bone_out->mNumWeights];
// copy the vertex weights
::memcpy(bone_out->mWeights, &(*weight_list)[0],bone_out->mNumWeights * sizeof(aiVertexWeight));
delete weight_list;
out_mesh->mNumBones++;
}
}
}
// copy the face list to the mesh
out_mesh->mFaces = new aiFace[vFaces.size()];
out_mesh->mNumFaces = (unsigned int)vFaces.size();
for (unsigned int p = 0; p < out_mesh->mNumFaces;++p) {
out_mesh->mFaces[p] = vFaces[p];
}
// add the newly created mesh to the list
source_mesh_map.push_back(std::make_pair(out_mesh,a));
if (base == in_mesh->mNumFaces) {
break;
}
}
// delete the per-vertex weight list again
delete[] avPerVertexWeights;
// now delete the old mesh data
delete in_mesh;
}

View File

@ -0,0 +1,61 @@
/*
Assimp2Json
Copyright (c) 2011, Alexander C. Gessler
Licensed under a 3-clause BSD license. See the LICENSE file for more information.
*/
#ifndef INCLUDED_MESH_SPLITTER
#define INCLUDED_MESH_SPLITTER
// ----------------------------------------------------------------------------
// Note: this is largely based on assimp's SplitLargeMeshes_Vertex process.
// it is refactored and the coding style is slightly improved, though.
// ----------------------------------------------------------------------------
#include <vector>
struct aiScene;
struct aiMesh;
struct aiNode;
// ---------------------------------------------------------------------------
/** Splits meshes of unique vertices into meshes with no more vertices than
* a given, configurable threshold value.
*/
class MeshSplitter
{
public:
void SetLimit(unsigned int l) {
LIMIT = l;
}
unsigned int GetLimit() const {
return LIMIT;
}
public:
// -------------------------------------------------------------------
/** Executes the post processing step on the given imported data.
* At the moment a process is not supposed to fail.
* @param pScene The imported data to work at.
*/
void Execute( aiScene* pScene);
private:
void UpdateNode(aiNode* pcNode, const std::vector<std::pair<aiMesh*, unsigned int> >& source_mesh_map);
void SplitMesh (unsigned int index, aiMesh* mesh, std::vector<std::pair<aiMesh*, unsigned int> >& source_mesh_map);
public:
unsigned int LIMIT;
};
#endif // INCLUDED_MESH_SPLITTER

View File

@ -810,6 +810,14 @@ ADD_ASSIMP_IMPORTER( MMD
MMD/MMDVmdParser.h MMD/MMDVmdParser.h
) )
ADD_ASSIMP_EXPORTER( Assjson
Assjson/cencode.c
Assjson/cencode.h
Assjson/json_exporter.cpp
Assjson/mesh_splitter.cpp
Assjson/mesh_splitter.h
)
# Workaround for issue #2406 - force problematic large file to be optimized to prevent string table overflow error # Workaround for issue #2406 - force problematic large file to be optimized to prevent string table overflow error
# Used -Os instead of -O2 as previous issues had mentioned, since -Os is roughly speaking -O2, excluding any # Used -Os instead of -O2 as previous issues had mentioned, since -Os is roughly speaking -O2, excluding any
# optimizations that take up extra space. Given that the issue is a string table overflowing, -Os seemed appropriate # optimizations that take up extra space. Given that the issue is a string table overflowing, -Os seemed appropriate

View File

@ -898,6 +898,7 @@ public:
: nfo(nfo) : nfo(nfo)
, reader(reader) , reader(reader)
, cur(reader.GetCurrentPos()) { , cur(reader.GetCurrentPos()) {
// empty
} }
~chunk_guard() { ~chunk_guard() {
@ -905,7 +906,7 @@ public:
if(nfo.size != static_cast<unsigned int>(-1)) { if(nfo.size != static_cast<unsigned int>(-1)) {
try { try {
reader.IncPtr( static_cast< int >( nfo.size ) - reader.GetCurrentPos() + cur ); reader.IncPtr( static_cast< int >( nfo.size ) - reader.GetCurrentPos() + cur );
} catch (const DeadlyImportError& e ) { } catch (const DeadlyImportError& ) {
// out of limit so correct the value // out of limit so correct the value
reader.IncPtr( reader.GetReadLimit() ); reader.IncPtr( reader.GetReadLimit() );
} }
@ -913,15 +914,17 @@ public:
} }
private: private:
const COB::ChunkInfo& nfo; const COB::ChunkInfo& nfo;
StreamReaderLE& reader; StreamReaderLE& reader;
long cur; long cur;
}; };
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void COBImporter::ReadBinaryFile(Scene& out, StreamReaderLE* reader) void COBImporter::ReadBinaryFile(Scene& out, StreamReaderLE* reader) {
{ if (nullptr == reader) {
return;
}
while(1) { while(1) {
std::string type; std::string type;
type += reader -> GetI1() type += reader -> GetI1()

View File

@ -5,8 +5,6 @@ Open Asset Import Library (assimp)
Copyright (c) 2006-2019, assimp team Copyright (c) 2006-2019, assimp team
All rights reserved. All rights reserved.
Redistribution and use of this software in source and binary forms, Redistribution and use of this software in source and binary forms,
@ -43,7 +41,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/** @file Implementation of the Collada loader */ /** @file Implementation of the Collada loader */
#ifndef ASSIMP_BUILD_NO_COLLADA_IMPORTER #ifndef ASSIMP_BUILD_NO_COLLADA_IMPORTER
#include "ColladaLoader.h" #include "ColladaLoader.h"
@ -67,7 +64,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <numeric> #include <numeric>
#include <memory> #include <memory>
using namespace Assimp; namespace Assimp {
using namespace Assimp::Formatter; using namespace Assimp::Formatter;
static const aiImporterDesc desc = { static const aiImporterDesc desc = {
@ -112,7 +110,7 @@ ColladaLoader::~ColladaLoader() {
// Returns whether the class can handle the format of the given file. // Returns whether the class can handle the format of the given file.
bool ColladaLoader::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const { bool ColladaLoader::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const {
// check file extension // check file extension
std::string extension = GetExtension(pFile); const std::string extension = GetExtension(pFile);
if (extension == "dae") { if (extension == "dae") {
return true; return true;
@ -166,12 +164,13 @@ void ColladaLoader::InternReadFile( const std::string& pFile, aiScene* pScene, I
// parse the input file // parse the input file
ColladaParser parser( pIOHandler, pFile); ColladaParser parser( pIOHandler, pFile);
if( !parser.mRootNode) if( !parser.mRootNode) {
throw DeadlyImportError( "Collada: File came out empty. Something is wrong here."); throw DeadlyImportError( "Collada: File came out empty. Something is wrong here.");
}
// reserve some storage to avoid unnecessary reallocs // reserve some storage to avoid unnecessary reallocs
newMats.reserve(parser.mMaterialLibrary.size()*2); newMats.reserve(parser.mMaterialLibrary.size()*2u);
mMeshes.reserve(parser.mMeshLibrary.size()*2); mMeshes.reserve(parser.mMeshLibrary.size()*2u);
mCameras.reserve(parser.mCameraLibrary.size()); mCameras.reserve(parser.mCameraLibrary.size());
mLights.reserve(parser.mLightLibrary.size()); mLights.reserve(parser.mLightLibrary.size());
@ -192,27 +191,27 @@ void ColladaLoader::InternReadFile( const std::string& pFile, aiScene* pScene, I
0, 0, 0, 1); 0, 0, 0, 1);
if( !ignoreUpDirection ) { if( !ignoreUpDirection ) {
// Convert to Y_UP, if different orientation // Convert to Y_UP, if different orientation
if( parser.mUpDirection == ColladaParser::UP_X) if( parser.mUpDirection == ColladaParser::UP_X) {
pScene->mRootNode->mTransformation *= aiMatrix4x4( pScene->mRootNode->mTransformation *= aiMatrix4x4(
0, -1, 0, 0, 0, -1, 0, 0,
1, 0, 0, 0, 1, 0, 0, 0,
0, 0, 1, 0, 0, 0, 1, 0,
0, 0, 0, 1); 0, 0, 0, 1);
else if( parser.mUpDirection == ColladaParser::UP_Z) } else if( parser.mUpDirection == ColladaParser::UP_Z) {
pScene->mRootNode->mTransformation *= aiMatrix4x4( pScene->mRootNode->mTransformation *= aiMatrix4x4(
1, 0, 0, 0, 1, 0, 0, 0,
0, 0, 1, 0, 0, 0, 1, 0,
0, -1, 0, 0, 0, -1, 0, 0,
0, 0, 0, 1); 0, 0, 0, 1);
} }
}
// Store scene metadata // Store scene metadata
if (!parser.mAssetMetaData.empty()) { if (!parser.mAssetMetaData.empty()) {
const size_t numMeta(parser.mAssetMetaData.size()); const size_t numMeta(parser.mAssetMetaData.size());
pScene->mMetaData = aiMetadata::Alloc(static_cast<unsigned int>(numMeta)); pScene->mMetaData = aiMetadata::Alloc(static_cast<unsigned int>(numMeta));
size_t i = 0; size_t i = 0;
for (auto it = parser.mAssetMetaData.cbegin(); it != parser.mAssetMetaData.cend(); ++it, ++i) for (auto it = parser.mAssetMetaData.cbegin(); it != parser.mAssetMetaData.cend(); ++it, ++i) {
{
pScene->mMetaData->Set(static_cast<unsigned int>(i), (*it).first, (*it).second); pScene->mMetaData->Set(static_cast<unsigned int>(i), (*it).first, (*it).second);
} }
} }
@ -232,9 +231,8 @@ void ColladaLoader::InternReadFile( const std::string& pFile, aiScene* pScene, I
// store all animations // store all animations
StoreAnimations( pScene, parser); StoreAnimations( pScene, parser);
// If no meshes have been loaded, it's probably just an animated skeleton. // If no meshes have been loaded, it's probably just an animated skeleton.
if (!pScene->mNumMeshes) { if ( 0u == pScene->mNumMeshes) {
if (!noSkeletonMesh) { if (!noSkeletonMesh) {
SkeletonMeshBuilder hero(pScene); SkeletonMeshBuilder hero(pScene);
@ -302,13 +300,12 @@ void ColladaLoader::ResolveNodeInstances( const ColladaParser& pParser, const Co
// FIX for http://sourceforge.net/tracker/?func=detail&aid=3054873&group_id=226462&atid=1067632 // FIX for http://sourceforge.net/tracker/?func=detail&aid=3054873&group_id=226462&atid=1067632
// need to check for both name and ID to catch all. To avoid breaking valid files, // need to check for both name and ID to catch all. To avoid breaking valid files,
// the workaround is only enabled when the first attempt to resolve the node has failed. // the workaround is only enabled when the first attempt to resolve the node has failed.
if (!nd) { if (nullptr == nd) {
nd = FindNode(pParser.mRootNode, nodeInst.mNode); nd = FindNode(pParser.mRootNode, nodeInst.mNode);
} }
if (!nd) if (nullptr == nd) {
ASSIMP_LOG_ERROR_F("Collada: Unable to resolve reference to instanced node ", nodeInst.mNode); ASSIMP_LOG_ERROR_F("Collada: Unable to resolve reference to instanced node ", nodeInst.mNode);
} else {
else {
// attach this node to the list of children // attach this node to the list of children
resolved.push_back(nd); resolved.push_back(nd);
} }
@ -431,8 +428,7 @@ void ColladaLoader::BuildCamerasForNode( const ColladaParser& pParser, const Col
out->mAspect = std::tan(AI_DEG_TO_RAD(srcCamera->mHorFov)) / out->mAspect = std::tan(AI_DEG_TO_RAD(srcCamera->mHorFov)) /
std::tan(AI_DEG_TO_RAD(srcCamera->mVerFov)); std::tan(AI_DEG_TO_RAD(srcCamera->mVerFov));
} }
} } else if (srcCamera->mAspect != 10e10f && srcCamera->mVerFov != 10e10f) {
else if (srcCamera->mAspect != 10e10f && srcCamera->mVerFov != 10e10f) {
out->mHorizontalFOV = 2.0f * AI_RAD_TO_DEG(std::atan(srcCamera->mAspect * out->mHorizontalFOV = 2.0f * AI_RAD_TO_DEG(std::atan(srcCamera->mAspect *
std::tan(AI_DEG_TO_RAD(srcCamera->mVerFov) * 0.5f))); std::tan(AI_DEG_TO_RAD(srcCamera->mVerFov) * 0.5f)));
} }
@ -470,7 +466,7 @@ void ColladaLoader::BuildMeshesForNode( const ColladaParser& pParser, const Coll
} }
} }
if( !srcMesh) { if( nullptr == srcMesh) {
ASSIMP_LOG_WARN_F( "Collada: Unable to find geometry for ID \"", mid.mMeshOrController, "\". Skipping." ); ASSIMP_LOG_WARN_F( "Collada: Unable to find geometry for ID \"", mid.mMeshOrController, "\". Skipping." );
continue; continue;
} }
@ -770,12 +766,13 @@ aiMesh* ColladaLoader::CreateMesh( const ColladaParser& pParser, const Collada::
IndexPairVector::const_iterator iit = weightStartPerVertex[orgIndex]; IndexPairVector::const_iterator iit = weightStartPerVertex[orgIndex];
size_t pairCount = pSrcController->mWeightCounts[orgIndex]; size_t pairCount = pSrcController->mWeightCounts[orgIndex];
for( size_t b = 0; b < pairCount; ++b, ++iit) for( size_t b = 0; b < pairCount; ++b, ++iit) {
{ const size_t jointIndex = iit->first;
size_t jointIndex = iit->first; const size_t vertexIndex = iit->second;
size_t vertexIndex = iit->second; ai_real weight = 1.0f;
if (!weights.mValues.empty()) {
ai_real weight = ReadFloat( weightsAcc, weights, vertexIndex, 0); weight = ReadFloat(weightsAcc, weights, vertexIndex, 0);
}
// one day I gonna kill that XSI Collada exporter // one day I gonna kill that XSI Collada exporter
if( weight > 0.0f) if( weight > 0.0f)
@ -790,19 +787,21 @@ aiMesh* ColladaLoader::CreateMesh( const ColladaParser& pParser, const Collada::
// count the number of bones which influence vertices of the current submesh // count the number of bones which influence vertices of the current submesh
size_t numRemainingBones = 0; size_t numRemainingBones = 0;
for( std::vector<std::vector<aiVertexWeight> >::const_iterator it = dstBones.begin(); it != dstBones.end(); ++it) for( std::vector<std::vector<aiVertexWeight> >::const_iterator it = dstBones.begin(); it != dstBones.end(); ++it) {
if( it->size() > 0) if( it->size() > 0) {
numRemainingBones++; ++numRemainingBones;
}
}
// create bone array and copy bone weights one by one // create bone array and copy bone weights one by one
dstMesh->mNumBones = static_cast<unsigned int>(numRemainingBones); dstMesh->mNumBones = static_cast<unsigned int>(numRemainingBones);
dstMesh->mBones = new aiBone*[numRemainingBones]; dstMesh->mBones = new aiBone*[numRemainingBones];
size_t boneCount = 0; size_t boneCount = 0;
for( size_t a = 0; a < numBones; ++a) for( size_t a = 0; a < numBones; ++a) {
{
// omit bones without weights // omit bones without weights
if( dstBones[a].size() == 0) if( dstBones[a].empty() ) {
continue; continue;
}
// create bone with its weights // create bone with its weights
aiBone* bone = new aiBone; aiBone* bone = new aiBone;
@ -848,14 +847,16 @@ aiMesh* ColladaLoader::CreateMesh( const ColladaParser& pParser, const Collada::
// and replace the bone's name by the node's name so that the user can use the standard // and replace the bone's name by the node's name so that the user can use the standard
// find-by-name method to associate nodes with bones. // find-by-name method to associate nodes with bones.
const Collada::Node* bnode = FindNode( pParser.mRootNode, bone->mName.data); const Collada::Node* bnode = FindNode( pParser.mRootNode, bone->mName.data);
if( !bnode) if( !bnode) {
bnode = FindNodeBySID( pParser.mRootNode, bone->mName.data); bnode = FindNodeBySID( pParser.mRootNode, bone->mName.data);
}
// assign the name that we would have assigned for the source node // assign the name that we would have assigned for the source node
if( bnode) if( bnode) {
bone->mName.Set( FindNameForNode( bnode)); bone->mName.Set( FindNameForNode( bnode));
else } else {
ASSIMP_LOG_WARN_F( "ColladaLoader::CreateMesh(): could not find corresponding node for joint \"", bone->mName.data, "\"." ); ASSIMP_LOG_WARN_F( "ColladaLoader::CreateMesh(): could not find corresponding node for joint \"", bone->mName.data, "\"." );
}
// and insert bone // and insert bone
dstMesh->mBones[boneCount++] = bone; dstMesh->mBones[boneCount++] = bone;
@ -867,89 +868,80 @@ aiMesh* ColladaLoader::CreateMesh( const ColladaParser& pParser, const Collada::
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Stores all meshes in the given scene // Stores all meshes in the given scene
void ColladaLoader::StoreSceneMeshes( aiScene* pScene) void ColladaLoader::StoreSceneMeshes( aiScene* pScene) {
{
pScene->mNumMeshes = static_cast<unsigned int>(mMeshes.size()); pScene->mNumMeshes = static_cast<unsigned int>(mMeshes.size());
if( mMeshes.size() > 0) if( mMeshes.empty() ) {
{ return;
}
pScene->mMeshes = new aiMesh*[mMeshes.size()]; pScene->mMeshes = new aiMesh*[mMeshes.size()];
std::copy( mMeshes.begin(), mMeshes.end(), pScene->mMeshes); std::copy( mMeshes.begin(), mMeshes.end(), pScene->mMeshes);
mMeshes.clear(); mMeshes.clear();
} }
}
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Stores all cameras in the given scene // Stores all cameras in the given scene
void ColladaLoader::StoreSceneCameras( aiScene* pScene) void ColladaLoader::StoreSceneCameras( aiScene* pScene) {
{
pScene->mNumCameras = static_cast<unsigned int>(mCameras.size()); pScene->mNumCameras = static_cast<unsigned int>(mCameras.size());
if( mCameras.size() > 0) if( mCameras.empty() ) {
{ return;
}
pScene->mCameras = new aiCamera*[mCameras.size()]; pScene->mCameras = new aiCamera*[mCameras.size()];
std::copy( mCameras.begin(), mCameras.end(), pScene->mCameras); std::copy( mCameras.begin(), mCameras.end(), pScene->mCameras);
mCameras.clear(); mCameras.clear();
} }
}
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Stores all lights in the given scene // Stores all lights in the given scene
void ColladaLoader::StoreSceneLights( aiScene* pScene) void ColladaLoader::StoreSceneLights( aiScene* pScene) {
{
pScene->mNumLights = static_cast<unsigned int>(mLights.size()); pScene->mNumLights = static_cast<unsigned int>(mLights.size());
if( mLights.size() > 0) if( mLights.empty() ) {
{ return;
}
pScene->mLights = new aiLight*[mLights.size()]; pScene->mLights = new aiLight*[mLights.size()];
std::copy( mLights.begin(), mLights.end(), pScene->mLights); std::copy( mLights.begin(), mLights.end(), pScene->mLights);
mLights.clear(); mLights.clear();
} }
}
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Stores all textures in the given scene // Stores all textures in the given scene
void ColladaLoader::StoreSceneTextures( aiScene* pScene) void ColladaLoader::StoreSceneTextures( aiScene* pScene) {
{
pScene->mNumTextures = static_cast<unsigned int>(mTextures.size()); pScene->mNumTextures = static_cast<unsigned int>(mTextures.size());
if( mTextures.size() > 0) if( mTextures.empty() ) {
{ return;
}
pScene->mTextures = new aiTexture*[mTextures.size()]; pScene->mTextures = new aiTexture*[mTextures.size()];
std::copy( mTextures.begin(), mTextures.end(), pScene->mTextures); std::copy( mTextures.begin(), mTextures.end(), pScene->mTextures);
mTextures.clear(); mTextures.clear();
} }
}
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Stores all materials in the given scene // Stores all materials in the given scene
void ColladaLoader::StoreSceneMaterials( aiScene* pScene) void ColladaLoader::StoreSceneMaterials( aiScene* pScene) {
{
pScene->mNumMaterials = static_cast<unsigned int>(newMats.size()); pScene->mNumMaterials = static_cast<unsigned int>(newMats.size());
if (newMats.empty() ) {
if (newMats.size() > 0) { return;
pScene->mMaterials = new aiMaterial*[newMats.size()];
for (unsigned int i = 0; i < newMats.size();++i)
pScene->mMaterials[i] = newMats[i].second;
newMats.clear();
} }
pScene->mMaterials = new aiMaterial*[newMats.size()];
for (unsigned int i = 0; i < newMats.size();++i) {
pScene->mMaterials[i] = newMats[i].second;
}
newMats.clear();
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Stores all animations // Stores all animations
void ColladaLoader::StoreAnimations( aiScene* pScene, const ColladaParser& pParser) void ColladaLoader::StoreAnimations( aiScene* pScene, const ColladaParser& pParser) {
{
// recursively collect all animations from the collada scene // recursively collect all animations from the collada scene
StoreAnimations( pScene, pParser, &pParser.mAnims, ""); StoreAnimations( pScene, pParser, &pParser.mAnims, "");
// catch special case: many animations with the same length, each affecting only a single node. // catch special case: many animations with the same length, each affecting only a single node.
// we need to unite all those single-node-anims to a proper combined animation // we need to unite all those single-node-anims to a proper combined animation
for( size_t a = 0; a < mAnims.size(); ++a) for( size_t a = 0; a < mAnims.size(); ++a) {
{
aiAnimation* templateAnim = mAnims[a]; aiAnimation* templateAnim = mAnims[a];
if( templateAnim->mNumChannels == 1) if( templateAnim->mNumChannels == 1) {
{
// search for other single-channel-anims with the same duration // search for other single-channel-anims with the same duration
std::vector<size_t> collectedAnimIndices; std::vector<size_t> collectedAnimIndices;
for( size_t b = a+1; b < mAnims.size(); ++b) for( size_t b = a+1; b < mAnims.size(); ++b) {
{
aiAnimation* other = mAnims[b]; aiAnimation* other = mAnims[b];
if( other->mNumChannels == 1 && other->mDuration == templateAnim->mDuration && if( other->mNumChannels == 1 && other->mDuration == templateAnim->mDuration &&
other->mTicksPerSecond == templateAnim->mTicksPerSecond ) other->mTicksPerSecond == templateAnim->mTicksPerSecond )
@ -1880,19 +1872,23 @@ const Collada::Node* ColladaLoader::FindNode( const Collada::Node* pNode, const
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Finds a node in the collada scene by the given SID // Finds a node in the collada scene by the given SID
const Collada::Node* ColladaLoader::FindNodeBySID( const Collada::Node* pNode, const std::string& pSID) const const Collada::Node* ColladaLoader::FindNodeBySID( const Collada::Node* pNode, const std::string& pSID) const {
{ if (nullptr == pNode) {
if( pNode->mSID == pSID) return nullptr;
return pNode;
for( size_t a = 0; a < pNode->mChildren.size(); ++a)
{
const Collada::Node* node = FindNodeBySID( pNode->mChildren[a], pSID);
if( node)
return node;
} }
return NULL; if (pNode->mSID == pSID) {
return pNode;
}
for( size_t a = 0; a < pNode->mChildren.size(); ++a) {
const Collada::Node* node = FindNodeBySID( pNode->mChildren[a], pSID);
if (node) {
return node;
}
}
return nullptr;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
@ -1926,4 +1922,6 @@ std::string ColladaLoader::FindNameForNode( const Collada::Node* pNode)
} }
} }
} // Namespace Assimp
#endif // !! ASSIMP_BUILD_NO_DAE_IMPORTER #endif // !! ASSIMP_BUILD_NO_DAE_IMPORTER

View File

@ -47,10 +47,6 @@ namespace Assimp {
aiAnimMesh *aiCreateAnimMesh(const aiMesh *mesh) aiAnimMesh *aiCreateAnimMesh(const aiMesh *mesh)
{ {
aiAnimMesh *animesh = new aiAnimMesh; aiAnimMesh *animesh = new aiAnimMesh;
animesh->mVertices = NULL;
animesh->mNormals = NULL;
animesh->mTangents = NULL;
animesh->mBitangents = NULL;
animesh->mNumVertices = mesh->mNumVertices; animesh->mNumVertices = mesh->mNumVertices;
if (mesh->mVertices) { if (mesh->mVertices) {
animesh->mVertices = new aiVector3D[animesh->mNumVertices]; animesh->mVertices = new aiVector3D[animesh->mNumVertices];

View File

@ -102,6 +102,7 @@ void ExportSceneX3D(const char*, IOSystem*, const aiScene*, const ExportProperti
void ExportSceneFBX(const char*, IOSystem*, const aiScene*, const ExportProperties*); void ExportSceneFBX(const char*, IOSystem*, const aiScene*, const ExportProperties*);
void ExportSceneFBXA(const char*, IOSystem*, const aiScene*, const ExportProperties*); void ExportSceneFBXA(const char*, IOSystem*, const aiScene*, const ExportProperties*);
void ExportScene3MF( const char*, IOSystem*, const aiScene*, const ExportProperties* ); void ExportScene3MF( const char*, IOSystem*, const aiScene*, const ExportProperties* );
void ExportAssimp2Json(const char* , IOSystem*, const aiScene* , const Assimp::ExportProperties*);
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// global array of all export formats which Assimp supports in its current build // global array of all export formats which Assimp supports in its current build
@ -179,7 +180,11 @@ Exporter::ExportFormatEntry gExporters[] =
#endif #endif
#ifndef ASSIMP_BUILD_NO_3MF_EXPORTER #ifndef ASSIMP_BUILD_NO_3MF_EXPORTER
Exporter::ExportFormatEntry( "3mf", "The 3MF-File-Format", "3mf", &ExportScene3MF, 0 ) Exporter::ExportFormatEntry( "3mf", "The 3MF-File-Format", "3mf", &ExportScene3MF, 0 ),
#endif
#ifndef ASSIMP_BUILD_NO_Assjson_EXPORTER
Exporter::ExportFormatEntry("json", "Plain JSON representation of the Assimp scene data structure", "json", &ExportAssimp2Json, 0)
#endif #endif
}; };

View File

@ -364,7 +364,7 @@ void GetImporterInstanceList(std::vector< BaseImporter* >& out)
void DeleteImporterInstanceList(std::vector< BaseImporter* >& deleteList){ void DeleteImporterInstanceList(std::vector< BaseImporter* >& deleteList){
for(size_t i= 0; i<deleteList.size();++i){ for(size_t i= 0; i<deleteList.size();++i){
delete deleteList[i]; delete deleteList[i];
deleteList[i]=NULL; deleteList[i]=nullptr;
}//for }//for
} }

View File

@ -420,11 +420,6 @@ namespace Assimp {
out_camera->mAspect = cam.AspectWidth() / cam.AspectHeight(); out_camera->mAspect = cam.AspectWidth() / cam.AspectHeight();
//cameras are defined along positive x direction
/*out_camera->mPosition = cam.Position();
out_camera->mLookAt = (cam.InterestPosition() - out_camera->mPosition).Normalize();
out_camera->mUp = cam.UpVector();*/
out_camera->mPosition = aiVector3D(0.0f); out_camera->mPosition = aiVector3D(0.0f);
out_camera->mLookAt = aiVector3D(1.0f, 0.0f, 0.0f); out_camera->mLookAt = aiVector3D(1.0f, 0.0f, 0.0f);
out_camera->mUp = aiVector3D(0.0f, 1.0f, 0.0f); out_camera->mUp = aiVector3D(0.0f, 1.0f, 0.0f);
@ -667,8 +662,7 @@ namespace Assimp {
if ((v - all_ones).SquareLength() > zero_epsilon) { if ((v - all_ones).SquareLength() > zero_epsilon) {
return true; return true;
} }
} } else if (ok) {
else if (ok) {
if (v.SquareLength() > zero_epsilon) { if (v.SquareLength() > zero_epsilon) {
return true; return true;
} }
@ -1253,10 +1247,10 @@ namespace Assimp {
ai_assert(count_faces); ai_assert(count_faces);
ai_assert(count_vertices); ai_assert(count_vertices);
// mapping from output indices to DOM indexing, needed to resolve weights // mapping from output indices to DOM indexing, needed to resolve weights or blendshapes
std::vector<unsigned int> reverseMapping; std::vector<unsigned int> reverseMapping;
std::map<unsigned int, unsigned int> translateIndexMap; std::map<unsigned int, unsigned int> translateIndexMap;
if (process_weights) { if (process_weights || mesh.GetBlendShapes().size() > 0) {
reverseMapping.resize(count_vertices); reverseMapping.resize(count_vertices);
} }
@ -1413,8 +1407,10 @@ namespace Assimp {
unsigned int count = 0; unsigned int count = 0;
const unsigned int* outIndices = mesh.ToOutputVertexIndex(index, count); const unsigned int* outIndices = mesh.ToOutputVertexIndex(index, count);
for (unsigned int k = 0; k < count; k++) { for (unsigned int k = 0; k < count; k++) {
unsigned int index = translateIndexMap[outIndices[k]]; unsigned int outIndex = outIndices[k];
if (translateIndexMap.find(outIndex) == translateIndexMap.end())
continue;
unsigned int index = translateIndexMap[outIndex];
animMesh->mVertices[index] += vertex; animMesh->mVertices[index] += vertex;
if (animMesh->mNormals != nullptr) { if (animMesh->mNormals != nullptr) {
animMesh->mNormals[index] += normal; animMesh->mNormals[index] += normal;
@ -1428,6 +1424,15 @@ namespace Assimp {
} }
} }
const size_t numAnimMeshes = animMeshes.size();
if (numAnimMeshes > 0) {
out_mesh->mNumAnimMeshes = static_cast<unsigned int>(numAnimMeshes);
out_mesh->mAnimMeshes = new aiAnimMesh*[numAnimMeshes];
for (size_t i = 0; i < numAnimMeshes; i++) {
out_mesh->mAnimMeshes[i] = animMeshes.at(i);
}
}
return static_cast<unsigned int>(meshes.size() - 1); return static_cast<unsigned int>(meshes.size() - 1);
} }
@ -1734,8 +1739,7 @@ namespace Assimp {
void FBXConverter::TrySetTextureProperties(aiMaterial* out_mat, const TextureMap& textures, void FBXConverter::TrySetTextureProperties(aiMaterial* out_mat, const TextureMap& textures,
const std::string& propName, const std::string& propName,
aiTextureType target, const MeshGeometry* const mesh) aiTextureType target, const MeshGeometry* const mesh) {
{
TextureMap::const_iterator it = textures.find(propName); TextureMap::const_iterator it = textures.find(propName);
if (it == textures.end()) { if (it == textures.end()) {
return; return;

View File

@ -52,6 +52,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "FBXUtil.h" #include "FBXUtil.h"
#include "FBXProperties.h" #include "FBXProperties.h"
#include "FBXImporter.h" #include "FBXImporter.h"
#include <assimp/anim.h> #include <assimp/anim.h>
#include <assimp/material.h> #include <assimp/material.h>
#include <assimp/light.h> #include <assimp/light.h>

View File

@ -627,7 +627,7 @@ public:
return content; return content;
} }
uint32_t ContentLength() const { uint64_t ContentLength() const {
return contentLength; return contentLength;
} }

View File

@ -1617,6 +1617,17 @@ void FBXExporter::WriteObjects ()
// at the same time we can build a list of all the skeleton nodes, // at the same time we can build a list of all the skeleton nodes,
// which will be used later to mark them as type "limbNode". // which will be used later to mark them as type "limbNode".
std::unordered_set<const aiNode*> limbnodes; std::unordered_set<const aiNode*> limbnodes;
//actual bone nodes in fbx, without parenting-up
std::unordered_set<std::string> setAllBoneNamesInScene;
for(unsigned int m = 0; m < mScene->mNumMeshes; ++ m)
{
aiMesh* pMesh = mScene->mMeshes[m];
for(unsigned int b = 0; b < pMesh->mNumBones; ++ b)
setAllBoneNamesInScene.insert(pMesh->mBones[b]->mName.data);
}
aiMatrix4x4 mxTransIdentity;
// and a map of nodes by bone name, as finding them is annoying. // and a map of nodes by bone name, as finding them is annoying.
std::map<std::string,aiNode*> node_by_bone; std::map<std::string,aiNode*> node_by_bone;
for (size_t mi = 0; mi < mScene->mNumMeshes; ++mi) { for (size_t mi = 0; mi < mScene->mNumMeshes; ++mi) {
@ -1660,6 +1671,11 @@ void FBXExporter::WriteObjects ()
if (node_name.find(MAGIC_NODE_TAG) != std::string::npos) { if (node_name.find(MAGIC_NODE_TAG) != std::string::npos) {
continue; continue;
} }
//not a bone in scene && no effect in transform
if(setAllBoneNamesInScene.find(node_name)==setAllBoneNamesInScene.end()
&& parent->mTransformation == mxTransIdentity) {
continue;
}
// otherwise check if this is the root of the skeleton // otherwise check if this is the root of the skeleton
bool end = false; bool end = false;
// is the mesh part of this node? // is the mesh part of this node?
@ -1824,7 +1840,10 @@ void FBXExporter::WriteObjects ()
// this should be the same as the bone's mOffsetMatrix. // this should be the same as the bone's mOffsetMatrix.
// if it's not the same, the skeleton isn't in the bind pose. // if it's not the same, the skeleton isn't in the bind pose.
const float epsilon = 1e-4f; // some error is to be expected float epsilon = 1e-4f; // some error is to be expected
float epsilon_custom = mProperties->GetPropertyFloat("BINDPOSE_EPSILON", -1);
if(epsilon_custom > 0)
epsilon = epsilon_custom;
bool bone_xform_okay = true; bool bone_xform_okay = true;
if (b && ! tr.Equal(b->mOffsetMatrix, epsilon)) { if (b && ! tr.Equal(b->mOffsetMatrix, epsilon)) {
not_in_bind_pose.insert(b); not_in_bind_pose.insert(b);

View File

@ -963,7 +963,6 @@ void ParseVectorDataArray(std::vector<float>& out, const Element& el)
} }
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// read an array of uints // read an array of uints
void ParseVectorDataArray(std::vector<unsigned int>& out, const Element& el) void ParseVectorDataArray(std::vector<unsigned int>& out, const Element& el)
@ -1280,7 +1279,6 @@ float ParseTokenAsFloat(const Token& t)
return i; return i;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// wrapper around ParseTokenAsInt() with ParseError handling // wrapper around ParseTokenAsInt() with ParseError handling
int ParseTokenAsInt(const Token& t) int ParseTokenAsInt(const Token& t)
@ -1293,8 +1291,6 @@ int ParseTokenAsInt(const Token& t)
return i; return i;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// wrapper around ParseTokenAsInt64() with ParseError handling // wrapper around ParseTokenAsInt64() with ParseError handling
int64_t ParseTokenAsInt64(const Token& t) int64_t ParseTokenAsInt64(const Token& t)

View File

@ -118,7 +118,7 @@ void ObjFileParser::parseFile( IOStreamBuffer<char> &streamBuffer ) {
size_t lastFilePos( 0 ); size_t lastFilePos( 0 );
std::vector<char> buffer; std::vector<char> buffer;
while ( streamBuffer.getNextDataLine( buffer, '\0' ) ) { while ( streamBuffer.getNextDataLine( buffer, '\\' ) ) {
m_DataIt = buffer.begin(); m_DataIt = buffer.begin();
m_DataItEnd = buffer.end(); m_DataItEnd = buffer.end();

View File

@ -127,7 +127,8 @@ inline void CompressVertex(const aiVector3D& v, uint32_t& out)
n.X = (int32_t)v.x; n.X = (int32_t)v.x;
n.Y = (int32_t)v.y; n.Y = (int32_t)v.y;
n.Z = (int32_t)v.z; n.Z = (int32_t)v.z;
out = t; ::memcpy( &out, &t, sizeof(int32_t));
//out = t;
} }
// UNREAL vertex decompression // UNREAL vertex decompression

View File

@ -5,8 +5,6 @@ Open Asset Import Library (assimp)
Copyright (c) 2006-2019, assimp team Copyright (c) 2006-2019, assimp team
All rights reserved. All rights reserved.
Redistribution and use of this software in source and binary forms, 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. * 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 * 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 <b>relative</b> to the coordinate system defined * *absolute*, they're <b>relative</b> to the coordinate system defined
* by the node which corresponds to the camera. This allows for camera * by the node which corresponds to the camera. This allows for camera
* animations. For static cameras parameters like the 'look-at' or 'up' vectors * animations. For static cameras parameters like the 'look-at' or 'up' vectors

View File

@ -981,8 +981,12 @@ enum aiComponent
#define AI_CONFIG_EXPORT_XFILE_64BIT "EXPORT_XFILE_64BIT" #define AI_CONFIG_EXPORT_XFILE_64BIT "EXPORT_XFILE_64BIT"
/** /** @brief Specifies whether the assimp export shall be able to export point clouds
* *
* When this flag is not defined the render data has to contain valid faces.
* Point clouds are only a collection of vertices which have nor spatial organization
* by a face and the validation process will remove them. Enabling this feature will
* switch off the flag and enable the functionality to export pure point clouds.
*/ */
#define AI_CONFIG_EXPORT_POINT_CLOUDS "EXPORT_POINT_CLOUDS" #define AI_CONFIG_EXPORT_POINT_CLOUDS "EXPORT_POINT_CLOUDS"

View File

@ -120,6 +120,7 @@ SET( IMPORTERS
unit/utB3DImportExport.cpp unit/utB3DImportExport.cpp
unit/utMDCImportExport.cpp unit/utMDCImportExport.cpp
unit/utAssbinImportExport.cpp unit/utAssbinImportExport.cpp
unit/ImportExport/utAssjsonImportExport.cpp
unit/ImportExport/utCOBImportExport.cpp unit/ImportExport/utCOBImportExport.cpp
unit/ImportExport/utOgreImportExport.cpp unit/ImportExport/utOgreImportExport.cpp
unit/ImportExport/utQ3BSPFileImportExport.cpp unit/ImportExport/utQ3BSPFileImportExport.cpp
@ -166,7 +167,7 @@ SET( POST_PROCESSES
SOURCE_GROUP( UnitTests\\Compiler FILES unit/CCompilerTest.c ) SOURCE_GROUP( UnitTests\\Compiler FILES unit/CCompilerTest.c )
SOURCE_GROUP( UnitTests\\Common FILES ${COMMON} ) SOURCE_GROUP( UnitTests\\Common FILES ${COMMON} )
SOURCE_GROUP( UnitTests\\Importers FILES ${IMPORTERS} ) SOURCE_GROUP( UnitTests\\ImportExport FILES ${IMPORTERS} )
SOURCE_GROUP( UnitTests\\Material FILES ${MATERIAL} ) SOURCE_GROUP( UnitTests\\Material FILES ${MATERIAL} )
SOURCE_GROUP( UnitTests\\Math FILES ${MATH} ) SOURCE_GROUP( UnitTests\\Math FILES ${MATH} )
SOURCE_GROUP( UnitTests\\PostProcess FILES ${POST_PROCESSES}) SOURCE_GROUP( UnitTests\\PostProcess FILES ${POST_PROCESSES})

Binary file not shown.

View File

@ -3,7 +3,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
Copyright (c) 2006-2016, assimp team Copyright (c) 2006-2019, assimp team
All rights reserved. All rights reserved.
@ -39,17 +39,37 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
*/ */
#pragma once #pragma once
#ifndef AI_ABSTRACTIMPORTEXPORTBASE_H_INC
#define AI_ABSTRACTIMPORTEXPORTBASE_H_INC
#include "UnitTestPCH.h" #include "UnitTestPCH.h"
// ---------------------------------------------------------------------------
/** Abstract base class to test import and export
*/
// ---------------------------------------------------------------------------
class AbstractImportExportBase : public ::testing::Test { class AbstractImportExportBase : public ::testing::Test {
public: public:
/// @brief The class destructor.
virtual ~AbstractImportExportBase(); 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(); virtual bool exporterTest();
}; };
inline
bool AbstractImportExportBase::importerTest() {
return true;
}
inline inline
bool AbstractImportExportBase::exporterTest() { bool AbstractImportExportBase::exporterTest() {
return true; return true;
} }
#endif // AI_ABSTRACTIMPORTEXPORTBASE_H_INC

View File

@ -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 <assimp/Importer.hpp>
#include <assimp/Exporter.hpp>
#include <assimp/postprocess.h>
#include <assimp/scene.h>
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

View File

@ -5,8 +5,6 @@ Open Asset Import Library (assimp)
Copyright (c) 2006-2019, assimp team Copyright (c) 2006-2019, assimp team
All rights reserved. All rights reserved.
Redistribution and use of this software in source and binary forms, Redistribution and use of this software in source and binary forms,

View File

@ -5,8 +5,6 @@ Open Asset Import Library (assimp)
Copyright (c) 2006-2019, assimp team Copyright (c) 2006-2019, assimp team
All rights reserved. All rights reserved.
Redistribution and use of this software in source and binary forms, Redistribution and use of this software in source and binary forms,

View File

@ -5,8 +5,6 @@ Open Asset Import Library (assimp)
Copyright (c) 2006-2019, assimp team Copyright (c) 2006-2019, assimp team
All rights reserved. All rights reserved.
Redistribution and use of this software in source and binary forms, Redistribution and use of this software in source and binary forms,
@ -53,8 +51,8 @@ using namespace Assimp;
class utAssbinImportExport : public AbstractImportExportBase { class utAssbinImportExport : public AbstractImportExportBase {
public: public:
virtual bool importerTest() { bool importerTest() override {
Assimp::Importer importer; Importer importer;
const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/OBJ/spider.obj", aiProcess_ValidateDataStructure ); const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/OBJ/spider.obj", aiProcess_ValidateDataStructure );
Exporter exporter; Exporter exporter;
@ -66,7 +64,7 @@ public:
}; };
TEST_F( utAssbinImportExport, exportAssbin3DFromFileTest ) { TEST_F( utAssbinImportExport, exportAssbin3DFromFileTest ) {
Assimp::Importer importer; Importer importer;
const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/OBJ/spider.obj", aiProcess_ValidateDataStructure ); const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/OBJ/spider.obj", aiProcess_ValidateDataStructure );
EXPECT_NE( nullptr, scene ); EXPECT_NE( nullptr, scene );
} }

View File

@ -5,8 +5,6 @@ Open Asset Import Library (assimp)
Copyright (c) 2006-2019, assimp team Copyright (c) 2006-2019, assimp team
All rights reserved. All rights reserved.
Redistribution and use of this software in source and binary forms, Redistribution and use of this software in source and binary forms,

View File

@ -5,8 +5,6 @@ Open Asset Import Library (assimp)
Copyright (c) 2006-2019, assimp team Copyright (c) 2006-2019, assimp team
All rights reserved. All rights reserved.
Redistribution and use of this software in source and binary forms, Redistribution and use of this software in source and binary forms,
@ -73,11 +71,6 @@ TEST_F(BlenderWorkTest,work_279) {
ASSERT_TRUE(pTest->HasMaterials()); ASSERT_TRUE(pTest->HasMaterials());
ASSERT_TRUE(pTest->HasMeshes()); ASSERT_TRUE(pTest->HasMeshes());
ASSERT_TRUE(pTest->mMeshes[0]->mNumVertices > 0); ASSERT_TRUE(pTest->mMeshes[0]->mNumVertices > 0);
ASSERT_EQ(44, pTest->mMeshes[0]->mNumFaces); ASSERT_EQ(44u, pTest->mMeshes[0]->mNumFaces);
EXPECT_EQ(1, pTest->mNumMaterials); EXPECT_EQ(1u, pTest->mNumMaterials);
} }

View File

@ -70,10 +70,10 @@ TEST_F( utFBXImporterExporter, importBareBoxWithoutColorsAndTextureCoords ) {
Assimp::Importer importer; Assimp::Importer importer;
const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/FBX/box.fbx", aiProcess_ValidateDataStructure ); const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/FBX/box.fbx", aiProcess_ValidateDataStructure );
EXPECT_NE( nullptr, scene ); EXPECT_NE( nullptr, scene );
EXPECT_EQ(scene->mNumMeshes, 1); EXPECT_EQ(scene->mNumMeshes, 1u);
aiMesh* mesh = scene->mMeshes[0]; aiMesh* mesh = scene->mMeshes[0];
EXPECT_EQ(mesh->mNumFaces, 12); EXPECT_EQ(mesh->mNumFaces, 12u);
EXPECT_EQ(mesh->mNumVertices, 36); EXPECT_EQ(mesh->mNumVertices, 36u);
} }
TEST_F(utFBXImporterExporter, importCubesWithNoNames) { TEST_F(utFBXImporterExporter, importCubesWithNoNames) {
@ -85,13 +85,13 @@ TEST_F(utFBXImporterExporter, importCubesWithNoNames) {
const auto root = scene->mRootNode; const auto root = scene->mRootNode;
ASSERT_STREQ(root->mName.C_Str(), "RootNode"); ASSERT_STREQ(root->mName.C_Str(), "RootNode");
ASSERT_TRUE(root->mChildren); ASSERT_TRUE(root->mChildren);
ASSERT_EQ(root->mNumChildren, 2); ASSERT_EQ(root->mNumChildren, 2u);
const auto child0 = root->mChildren[0]; const auto child0 = root->mChildren[0];
ASSERT_TRUE(child0); ASSERT_TRUE(child0);
ASSERT_STREQ(child0->mName.C_Str(), "RootNode001"); ASSERT_STREQ(child0->mName.C_Str(), "RootNode001");
ASSERT_TRUE(child0->mChildren); ASSERT_TRUE(child0->mChildren);
ASSERT_EQ(child0->mNumChildren, 1); ASSERT_EQ(child0->mNumChildren, 1u);
const auto child00 = child0->mChildren[0]; const auto child00 = child0->mChildren[0];
ASSERT_TRUE(child00); ASSERT_TRUE(child00);
@ -101,7 +101,7 @@ TEST_F(utFBXImporterExporter, importCubesWithNoNames) {
ASSERT_TRUE(child1); ASSERT_TRUE(child1);
ASSERT_STREQ(child1->mName.C_Str(), "RootNode002"); ASSERT_STREQ(child1->mName.C_Str(), "RootNode002");
ASSERT_TRUE(child1->mChildren); ASSERT_TRUE(child1->mChildren);
ASSERT_EQ(child1->mNumChildren, 1); ASSERT_EQ(child1->mNumChildren, 1u);
const auto child10 = child1->mChildren[0]; const auto child10 = child1->mChildren[0];
ASSERT_TRUE(child10); ASSERT_TRUE(child10);
@ -117,13 +117,13 @@ TEST_F(utFBXImporterExporter, importCubesWithUnicodeDuplicatedNames) {
const auto root = scene->mRootNode; const auto root = scene->mRootNode;
ASSERT_STREQ(root->mName.C_Str(), "RootNode"); ASSERT_STREQ(root->mName.C_Str(), "RootNode");
ASSERT_TRUE(root->mChildren); ASSERT_TRUE(root->mChildren);
ASSERT_EQ(root->mNumChildren, 2); ASSERT_EQ(root->mNumChildren, 2u);
const auto child0 = root->mChildren[0]; const auto child0 = root->mChildren[0];
ASSERT_TRUE(child0); ASSERT_TRUE(child0);
ASSERT_STREQ(child0->mName.C_Str(), "Cube2"); ASSERT_STREQ(child0->mName.C_Str(), "Cube2");
ASSERT_TRUE(child0->mChildren); ASSERT_TRUE(child0->mChildren);
ASSERT_EQ(child0->mNumChildren, 1); ASSERT_EQ(child0->mNumChildren, 1u);
const auto child00 = child0->mChildren[0]; const auto child00 = child0->mChildren[0];
ASSERT_TRUE(child00); ASSERT_TRUE(child00);
@ -133,7 +133,7 @@ TEST_F(utFBXImporterExporter, importCubesWithUnicodeDuplicatedNames) {
ASSERT_TRUE(child1); ASSERT_TRUE(child1);
ASSERT_STREQ(child1->mName.C_Str(), "Cube3"); ASSERT_STREQ(child1->mName.C_Str(), "Cube3");
ASSERT_TRUE(child1->mChildren); ASSERT_TRUE(child1->mChildren);
ASSERT_EQ(child1->mNumChildren, 1); ASSERT_EQ(child1->mNumChildren, 1u);
const auto child10 = child1->mChildren[0]; const auto child10 = child1->mChildren[0];
ASSERT_TRUE(child10); ASSERT_TRUE(child10);
@ -149,13 +149,13 @@ TEST_F(utFBXImporterExporter, importCubesComplexTransform) {
const auto root = scene->mRootNode; const auto root = scene->mRootNode;
ASSERT_STREQ(root->mName.C_Str(), "RootNode"); ASSERT_STREQ(root->mName.C_Str(), "RootNode");
ASSERT_TRUE(root->mChildren); ASSERT_TRUE(root->mChildren);
ASSERT_EQ(root->mNumChildren, 2); ASSERT_EQ(root->mNumChildren, 2u);
const auto child0 = root->mChildren[0]; const auto child0 = root->mChildren[0];
ASSERT_TRUE(child0); ASSERT_TRUE(child0);
ASSERT_STREQ(child0->mName.C_Str(), "Cube2"); ASSERT_STREQ(child0->mName.C_Str(), "Cube2");
ASSERT_TRUE(child0->mChildren); ASSERT_TRUE(child0->mChildren);
ASSERT_EQ(child0->mNumChildren, 1); ASSERT_EQ(child0->mNumChildren, 1u);
const auto child00 = child0->mChildren[0]; const auto child00 = child0->mChildren[0];
ASSERT_TRUE(child00); ASSERT_TRUE(child00);
@ -177,35 +177,36 @@ TEST_F(utFBXImporterExporter, importCubesComplexTransform) {
"Cube1001_$AssimpFbx$_ScalingPivotInverse", "Cube1001_$AssimpFbx$_ScalingPivotInverse",
"Cube1001" "Cube1001"
}; };
for (size_t i = 0; i < chain_length; ++i) for (size_t i = 0; i < chain_length; ++i) {
{
ASSERT_TRUE(parent->mChildren); ASSERT_TRUE(parent->mChildren);
ASSERT_EQ(parent->mNumChildren, 1); ASSERT_EQ(parent->mNumChildren, 1u);
auto node = parent->mChildren[0]; auto node = parent->mChildren[0];
ASSERT_TRUE(node); ASSERT_TRUE(node);
ASSERT_STREQ(node->mName.C_Str(), chainStr[i]); ASSERT_STREQ(node->mName.C_Str(), chainStr[i]);
parent = node; parent = node;
} }
ASSERT_EQ(0, parent->mNumChildren) << "Leaf node"; ASSERT_EQ(0u, parent->mNumChildren) << "Leaf node";
} }
TEST_F( utFBXImporterExporter, importPhongMaterial ) { TEST_F( utFBXImporterExporter, importPhongMaterial ) {
Assimp::Importer importer; Assimp::Importer importer;
const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/FBX/phong_cube.fbx", aiProcess_ValidateDataStructure ); const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/FBX/phong_cube.fbx", aiProcess_ValidateDataStructure );
EXPECT_NE( nullptr, scene ); EXPECT_NE( nullptr, scene );
EXPECT_EQ( (unsigned int)1, scene->mNumMaterials ); EXPECT_EQ( 1u, scene->mNumMaterials );
const aiMaterial *mat = scene->mMaterials[0]; const aiMaterial *mat = scene->mMaterials[0];
EXPECT_NE( nullptr, mat ); EXPECT_NE( nullptr, mat );
float f; aiColor3D c; float f;
aiColor3D c;
// phong_cube.fbx has all properties defined // phong_cube.fbx has all properties defined
EXPECT_EQ( mat->Get(AI_MATKEY_COLOR_DIFFUSE, c), aiReturn_SUCCESS ); EXPECT_EQ( mat->Get(AI_MATKEY_COLOR_DIFFUSE, c), aiReturn_SUCCESS );
EXPECT_EQ( c, aiColor3D(0.5, 0.25, 0.25) ); EXPECT_EQ( c, aiColor3D(0.5, 0.25, 0.25) );
EXPECT_EQ( mat->Get(AI_MATKEY_COLOR_SPECULAR, c), aiReturn_SUCCESS ); EXPECT_EQ( mat->Get(AI_MATKEY_COLOR_SPECULAR, c), aiReturn_SUCCESS );
EXPECT_EQ( c, aiColor3D(0.25, 0.25, 0.5) ); EXPECT_EQ( c, aiColor3D(0.25, 0.25, 0.5) );
EXPECT_EQ( mat->Get(AI_MATKEY_SHININESS_STRENGTH, f), aiReturn_SUCCESS ); EXPECT_EQ( mat->Get(AI_MATKEY_SHININESS_STRENGTH, f), aiReturn_SUCCESS );
EXPECT_EQ( f, 0.5 ); EXPECT_EQ( f, 0.5f );
EXPECT_EQ( mat->Get(AI_MATKEY_SHININESS, f), aiReturn_SUCCESS ); EXPECT_EQ( mat->Get(AI_MATKEY_SHININESS, f), aiReturn_SUCCESS );
EXPECT_EQ( f, 10.0 ); EXPECT_EQ( f, 10.0f );
EXPECT_EQ( mat->Get(AI_MATKEY_COLOR_AMBIENT, c), aiReturn_SUCCESS ); EXPECT_EQ( mat->Get(AI_MATKEY_COLOR_AMBIENT, c), aiReturn_SUCCESS );
EXPECT_EQ( c, aiColor3D(0.125, 0.25, 0.25) ); EXPECT_EQ( c, aiColor3D(0.125, 0.25, 0.25) );
EXPECT_EQ( mat->Get(AI_MATKEY_COLOR_EMISSIVE, c), aiReturn_SUCCESS ); EXPECT_EQ( mat->Get(AI_MATKEY_COLOR_EMISSIVE, c), aiReturn_SUCCESS );
@ -213,7 +214,7 @@ TEST_F( utFBXImporterExporter, importPhongMaterial ) {
EXPECT_EQ( mat->Get(AI_MATKEY_COLOR_TRANSPARENT, c), aiReturn_SUCCESS ); EXPECT_EQ( mat->Get(AI_MATKEY_COLOR_TRANSPARENT, c), aiReturn_SUCCESS );
EXPECT_EQ( c, aiColor3D(0.75, 0.5, 0.25) ); EXPECT_EQ( c, aiColor3D(0.75, 0.5, 0.25) );
EXPECT_EQ( mat->Get(AI_MATKEY_OPACITY, f), aiReturn_SUCCESS ); EXPECT_EQ( mat->Get(AI_MATKEY_OPACITY, f), aiReturn_SUCCESS );
EXPECT_EQ( f, 0.5 ); EXPECT_EQ( f, 0.5f );
} }
TEST_F(utFBXImporterExporter, importUnitScaleFactor) { TEST_F(utFBXImporterExporter, importUnitScaleFactor) {
@ -234,7 +235,7 @@ TEST_F(utFBXImporterExporter, importEmbeddedAsciiTest) {
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/FBX/embedded_ascii/box.FBX", aiProcess_ValidateDataStructure); const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/FBX/embedded_ascii/box.FBX", aiProcess_ValidateDataStructure);
EXPECT_NE(nullptr, scene); EXPECT_NE(nullptr, scene);
EXPECT_EQ(1, scene->mNumMaterials); EXPECT_EQ(1u, scene->mNumMaterials);
aiMaterial *mat = scene->mMaterials[0]; aiMaterial *mat = scene->mMaterials[0];
ASSERT_NE(nullptr, mat); ASSERT_NE(nullptr, mat);
@ -243,7 +244,7 @@ TEST_F(utFBXImporterExporter, importEmbeddedAsciiTest) {
EXPECT_EQ(aiReturn_SUCCESS, mat->GetTexture(aiTextureType_DIFFUSE, 0, &path, nullptr, nullptr, nullptr, nullptr, modes)); EXPECT_EQ(aiReturn_SUCCESS, mat->GetTexture(aiTextureType_DIFFUSE, 0, &path, nullptr, nullptr, nullptr, nullptr, modes));
ASSERT_STREQ(path.C_Str(), "..\\..\\..\\Desktop\\uv_test.png"); ASSERT_STREQ(path.C_Str(), "..\\..\\..\\Desktop\\uv_test.png");
ASSERT_EQ(1, scene->mNumTextures); ASSERT_EQ(1u, scene->mNumTextures);
ASSERT_TRUE(scene->mTextures[0]->pcData); ASSERT_TRUE(scene->mTextures[0]->pcData);
ASSERT_EQ(439176u, scene->mTextures[0]->mWidth) << "FBX ASCII base64 compression splits data by 512Kb, it should be two parts for this texture"; ASSERT_EQ(439176u, scene->mTextures[0]->mWidth) << "FBX ASCII base64 compression splits data by 512Kb, it should be two parts for this texture";
} }
@ -254,7 +255,7 @@ TEST_F(utFBXImporterExporter, importEmbeddedFragmentedAsciiTest) {
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/FBX/embedded_ascii/box_embedded_texture_fragmented.fbx", aiProcess_ValidateDataStructure); const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/FBX/embedded_ascii/box_embedded_texture_fragmented.fbx", aiProcess_ValidateDataStructure);
EXPECT_NE(nullptr, scene); EXPECT_NE(nullptr, scene);
EXPECT_EQ(1, scene->mNumMaterials); EXPECT_EQ(1u, scene->mNumMaterials);
aiMaterial *mat = scene->mMaterials[0]; aiMaterial *mat = scene->mMaterials[0];
ASSERT_NE(nullptr, mat); ASSERT_NE(nullptr, mat);
@ -263,7 +264,7 @@ TEST_F(utFBXImporterExporter, importEmbeddedFragmentedAsciiTest) {
ASSERT_EQ(aiReturn_SUCCESS, mat->GetTexture(aiTextureType_DIFFUSE, 0, &path, nullptr, nullptr, nullptr, nullptr, modes)); ASSERT_EQ(aiReturn_SUCCESS, mat->GetTexture(aiTextureType_DIFFUSE, 0, &path, nullptr, nullptr, nullptr, nullptr, modes));
ASSERT_STREQ(path.C_Str(), "paper.png"); ASSERT_STREQ(path.C_Str(), "paper.png");
ASSERT_EQ(1, scene->mNumTextures); ASSERT_EQ(1u, scene->mNumTextures);
ASSERT_TRUE(scene->mTextures[0]->pcData); ASSERT_TRUE(scene->mTextures[0]->pcData);
ASSERT_EQ(968029u, scene->mTextures[0]->mWidth) << "FBX ASCII base64 compression splits data by 512Kb, it should be two parts for this texture"; ASSERT_EQ(968029u, scene->mTextures[0]->mWidth) << "FBX ASCII base64 compression splits data by 512Kb, it should be two parts for this texture";
} }

View File

@ -5,8 +5,6 @@ Open Asset Import Library (assimp)
Copyright (c) 2006-2019, assimp team Copyright (c) 2006-2019, assimp team
All rights reserved. All rights reserved.
Redistribution and use of this software in source and binary forms, Redistribution and use of this software in source and binary forms,
@ -49,35 +47,42 @@ using namespace Assimp;
class FindDegeneratesProcessTest : public ::testing::Test { class FindDegeneratesProcessTest : public ::testing::Test {
public: public:
FindDegeneratesProcessTest()
: Test()
, mMesh( nullptr )
, mProcess( nullptr ) {
// empty
}
protected:
virtual void SetUp(); virtual void SetUp();
virtual void TearDown(); virtual void TearDown();
protected: protected:
aiMesh* mesh; aiMesh* mMesh;
FindDegeneratesProcess* process; FindDegeneratesProcess* mProcess;
}; };
// ------------------------------------------------------------------------------------------------
void FindDegeneratesProcessTest::SetUp() { void FindDegeneratesProcessTest::SetUp() {
mesh = new aiMesh(); mMesh = new aiMesh();
process = new FindDegeneratesProcess(); mProcess = new FindDegeneratesProcess();
mesh->mNumFaces = 1000; mMesh->mNumFaces = 1000;
mesh->mFaces = new aiFace[1000]; mMesh->mFaces = new aiFace[1000];
mesh->mNumVertices = 5000*2; mMesh->mNumVertices = 5000*2;
mesh->mVertices = new aiVector3D[5000*2]; mMesh->mVertices = new aiVector3D[5000*2];
for (unsigned int i = 0; i < 5000; ++i) { 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; aiPrimitiveType_POLYGON | aiPrimitiveType_TRIANGLE;
unsigned int numOut = 0, numFaces = 0; unsigned int numOut = 0, numFaces = 0;
for (unsigned int i = 0; i < 1000; ++i) { 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.mNumIndices = (i % 5)+1; // between 1 and 5
f.mIndices = new unsigned int[f.mNumIndices]; f.mIndices = new unsigned int[f.mNumIndices];
bool had = false; bool had = false;
@ -102,46 +107,46 @@ void FindDegeneratesProcessTest::SetUp() {
if (!had) if (!had)
++numFaces; ++numFaces;
} }
mesh->mNumUVComponents[0] = numOut; mMesh->mNumUVComponents[0] = numOut;
mesh->mNumUVComponents[1] = numFaces; mMesh->mNumUVComponents[1] = numFaces;
} }
void FindDegeneratesProcessTest::TearDown() { void FindDegeneratesProcessTest::TearDown() {
delete mesh; delete mMesh;
delete process; delete mProcess;
} }
TEST_F(FindDegeneratesProcessTest, testDegeneratesDetection) { TEST_F(FindDegeneratesProcessTest, testDegeneratesDetection) {
process->EnableInstantRemoval(false); mProcess->EnableInstantRemoval(false);
process->ExecuteOnMesh(mesh); mProcess->ExecuteOnMesh(mMesh);
unsigned int out = 0; unsigned int out = 0;
for (unsigned int i = 0; i < 1000; ++i) { for (unsigned int i = 0; i < 1000; ++i) {
aiFace& f = mesh->mFaces[i]; aiFace& f = mMesh->mFaces[i];
out += f.mNumIndices; out += f.mNumIndices;
} }
EXPECT_EQ(1000U, mesh->mNumFaces); EXPECT_EQ(1000U, mMesh->mNumFaces);
EXPECT_EQ(10000U, mesh->mNumVertices); EXPECT_EQ(10000U, mMesh->mNumVertices);
EXPECT_EQ(out, mesh->mNumUVComponents[0]); EXPECT_EQ(out, mMesh->mNumUVComponents[0]);
EXPECT_EQ(static_cast<unsigned int>( EXPECT_EQ(static_cast<unsigned int>(
aiPrimitiveType_LINE | aiPrimitiveType_POINT | aiPrimitiveType_LINE | aiPrimitiveType_POINT |
aiPrimitiveType_POLYGON | aiPrimitiveType_TRIANGLE), aiPrimitiveType_POLYGON | aiPrimitiveType_TRIANGLE),
mesh->mPrimitiveTypes); mMesh->mPrimitiveTypes);
} }
TEST_F(FindDegeneratesProcessTest, testDegeneratesRemoval) { TEST_F(FindDegeneratesProcessTest, testDegeneratesRemoval) {
process->EnableAreaCheck(false); mProcess->EnableAreaCheck(false);
process->EnableInstantRemoval(true); mProcess->EnableInstantRemoval(true);
process->ExecuteOnMesh(mesh); mProcess->ExecuteOnMesh(mMesh);
EXPECT_EQ(mesh->mNumUVComponents[1], mesh->mNumFaces); EXPECT_EQ(mMesh->mNumUVComponents[1], mMesh->mNumFaces);
} }
TEST_F(FindDegeneratesProcessTest, testDegeneratesRemovalWithAreaCheck) { TEST_F(FindDegeneratesProcessTest, testDegeneratesRemovalWithAreaCheck) {
process->EnableAreaCheck(true); mProcess->EnableAreaCheck(true);
process->EnableInstantRemoval(true); mProcess->EnableInstantRemoval(true);
process->ExecuteOnMesh(mesh); mProcess->ExecuteOnMesh(mMesh);
EXPECT_EQ(mesh->mNumUVComponents[1]-100, mesh->mNumFaces); EXPECT_EQ(mMesh->mNumUVComponents[1]-100, mMesh->mNumFaces);
} }

View File

@ -5,8 +5,6 @@ Open Asset Import Library (assimp)
Copyright (c) 2006-2019, assimp team Copyright (c) 2006-2019, assimp team
All rights reserved. All rights reserved.
Redistribution and use of this software in source and binary forms, 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 std;
using namespace Assimp; using namespace Assimp;
class FindInvalidDataProcessTest : public ::testing::Test class utFindInvalidDataProcess : public ::testing::Test {
{
public: public:
utFindInvalidDataProcess()
: Test()
, mMesh(nullptr)
, mProcess(nullptr) {
// empty
}
protected:
virtual void SetUp(); virtual void SetUp();
virtual void TearDown(); virtual void TearDown();
protected: protected:
aiMesh* pcMesh; aiMesh* mMesh;
FindInvalidDataProcess* piProcess; FindInvalidDataProcess* mProcess;
}; };
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void FindInvalidDataProcessTest::SetUp() { void utFindInvalidDataProcess::SetUp() {
ASSERT_TRUE( AI_MAX_NUMBER_OF_TEXTURECOORDS >= 3); ASSERT_TRUE( AI_MAX_NUMBER_OF_TEXTURECOORDS >= 3);
piProcess = new FindInvalidDataProcess(); mProcess = new FindInvalidDataProcess();
pcMesh = new aiMesh(); mMesh = new aiMesh();
pcMesh->mNumVertices = 1000; mMesh->mNumVertices = 1000;
pcMesh->mVertices = new aiVector3D[1000]; mMesh->mVertices = new aiVector3D[1000];
for (unsigned int i = 0; i < 1000;++i) for (unsigned int i = 0; i < 1000; ++i) {
pcMesh->mVertices[i] = aiVector3D((float)i); mMesh->mVertices[i] = aiVector3D((float)i);
}
pcMesh->mNormals = new aiVector3D[1000]; mMesh->mNormals = new aiVector3D[1000];
for (unsigned int i = 0; i < 1000;++i) for (unsigned int i = 0; i < 1000; ++i) {
pcMesh->mNormals[i] = aiVector3D((float)i+1); mMesh->mNormals[i] = aiVector3D((float)i + 1);
}
pcMesh->mTangents = new aiVector3D[1000]; mMesh->mTangents = new aiVector3D[1000];
for (unsigned int i = 0; i < 1000;++i) for (unsigned int i = 0; i < 1000; ++i) {
pcMesh->mTangents[i] = aiVector3D((float)i); mMesh->mTangents[i] = aiVector3D((float)i);
}
pcMesh->mBitangents = new aiVector3D[1000]; mMesh->mBitangents = new aiVector3D[1000];
for (unsigned int i = 0; i < 1000;++i) for (unsigned int i = 0; i < 1000; ++i) {
pcMesh->mBitangents[i] = aiVector3D((float)i); mMesh->mBitangents[i] = aiVector3D((float)i);
}
for (unsigned int a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS;++a) for (unsigned int a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS;++a) {
{ mMesh->mTextureCoords[a] = new aiVector3D[1000];
pcMesh->mTextureCoords[a] = new aiVector3D[1000]; for (unsigned int i = 0; i < 1000; ++i) {
for (unsigned int i = 0; i < 1000;++i) mMesh->mTextureCoords[a][i] = aiVector3D((float)i);
pcMesh->mTextureCoords[a][i] = aiVector3D((float)i); }
} }
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void FindInvalidDataProcessTest::TearDown() void utFindInvalidDataProcess::TearDown() {
{ delete mProcess;
delete piProcess; delete mMesh;
delete pcMesh;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
TEST_F(FindInvalidDataProcessTest, testStepNegativeResult) TEST_F(utFindInvalidDataProcess, testStepNegativeResult) {
{ ::memset(mMesh->mNormals, 0, mMesh->mNumVertices*sizeof(aiVector3D) );
::memset(pcMesh->mNormals,0,pcMesh->mNumVertices*sizeof(aiVector3D)); ::memset(mMesh->mBitangents, 0, mMesh->mNumVertices*sizeof(aiVector3D) );
::memset(pcMesh->mBitangents,0,pcMesh->mNumVertices*sizeof(aiVector3D));
pcMesh->mTextureCoords[2][455] = aiVector3D( std::numeric_limits<float>::quiet_NaN() ); mMesh->mTextureCoords[2][455] = aiVector3D( std::numeric_limits<float>::quiet_NaN() );
piProcess->ProcessMesh(pcMesh); mProcess->ProcessMesh(mMesh);
EXPECT_TRUE(NULL != pcMesh->mVertices); EXPECT_TRUE(NULL != mMesh->mVertices);
EXPECT_TRUE(NULL == pcMesh->mNormals); EXPECT_EQ(NULL, mMesh->mNormals);
EXPECT_TRUE(NULL == pcMesh->mTangents); EXPECT_EQ(NULL, mMesh->mTangents);
EXPECT_TRUE(NULL == pcMesh->mBitangents); EXPECT_EQ(NULL, mMesh->mBitangents);
for (unsigned int i = 0; i < 2;++i) for (unsigned int i = 0; i < 2; ++i) {
EXPECT_TRUE(NULL != pcMesh->mTextureCoords[i]); EXPECT_TRUE(NULL != mMesh->mTextureCoords[i]);
}
for (unsigned int i = 2; i < AI_MAX_NUMBER_OF_TEXTURECOORDS;++i) for (unsigned int i = 2; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i) {
EXPECT_TRUE(NULL == pcMesh->mTextureCoords[i]); EXPECT_EQ(NULL, mMesh->mTextureCoords[i]);
}
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
TEST_F(FindInvalidDataProcessTest, testStepPositiveResult) TEST_F(utFindInvalidDataProcess, testStepPositiveResult) {
{ mProcess->ProcessMesh(mMesh);
piProcess->ProcessMesh(pcMesh);
EXPECT_TRUE(NULL != pcMesh->mVertices); EXPECT_NE(nullptr, mMesh->mVertices);
EXPECT_TRUE(NULL != pcMesh->mNormals); EXPECT_NE(nullptr, mMesh->mNormals);
EXPECT_TRUE(NULL != pcMesh->mTangents); EXPECT_NE(nullptr, mMesh->mTangents);
EXPECT_TRUE(NULL != pcMesh->mBitangents); EXPECT_NE(nullptr, mMesh->mBitangents);
for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS;++i) for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i) {
EXPECT_TRUE(NULL != pcMesh->mTextureCoords[i]); EXPECT_NE(nullptr, mMesh->mTextureCoords[i]);
}
} }

View File

@ -48,13 +48,21 @@ using namespace Assimp;
class utGenBoundingBoxesProcess : public ::testing::Test { class utGenBoundingBoxesProcess : public ::testing::Test {
public: public:
utGenBoundingBoxesProcess()
: Test()
, mProcess(nullptr)
, mMesh(nullptr)
, mScene(nullptr) {
// empty
}
void SetUp() override { void SetUp() override {
mProcess = new GenBoundingBoxesProcess; mProcess = new GenBoundingBoxesProcess;
mMesh = new aiMesh(); mMesh = new aiMesh();
mMesh->mNumVertices = 100; mMesh->mNumVertices = 100;
mMesh->mVertices = new aiVector3D[100]; mMesh->mVertices = new aiVector3D[100];
for (unsigned int i = 0; i < 100; ++i) { 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 = new aiScene();
mScene->mNumMeshes = 1; mScene->mNumMeshes = 1;

View File

@ -74,7 +74,7 @@ TEST_F( utIssues, OpacityBugWhenExporting_727 ) {
if ( newScene->mNumMaterials > 0 ) { if ( newScene->mNumMaterials > 0 ) {
std::cout << "Desc = " << desc->description << "\n"; std::cout << "Desc = " << desc->description << "\n";
EXPECT_EQ( AI_SUCCESS, newScene->mMaterials[ 0 ]->Get( AI_MATKEY_OPACITY, newOpacity ) ); EXPECT_EQ( AI_SUCCESS, newScene->mMaterials[ 0 ]->Get( AI_MATKEY_OPACITY, newOpacity ) );
EXPECT_EQ( opacity, newOpacity ); EXPECT_FLOAT_EQ( opacity, newOpacity );
} }
delete scene; delete scene;
} }

View File

@ -5,8 +5,6 @@ Open Asset Import Library (assimp)
Copyright (c) 2006-2019, assimp team Copyright (c) 2006-2019, assimp team
All rights reserved. All rights reserved.
Redistribution and use of this software in source and binary forms, 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 std;
using namespace Assimp; using namespace Assimp;
class JoinVerticesTest : public ::testing::Test { class utJoinVertices : public ::testing::Test {
public: public:
utJoinVertices()
: Test()
, piProcess(nullptr)
, pcMesh(nullptr) {
// empty
}
protected:
virtual void SetUp(); virtual void SetUp();
virtual void TearDown(); virtual void TearDown();
@ -60,8 +66,7 @@ protected:
}; };
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void JoinVerticesTest::SetUp() void utJoinVertices::SetUp() {
{
// construct the process // construct the process
piProcess = new JoinVerticesProcess(); piProcess = new JoinVerticesProcess();
@ -71,11 +76,9 @@ void JoinVerticesTest::SetUp()
pcMesh->mNumVertices = 900; pcMesh->mNumVertices = 900;
aiVector3D*& pv = pcMesh->mVertices = new aiVector3D[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; 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; 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 // generate faces - each vertex is referenced once
pcMesh->mNumFaces = 300; pcMesh->mNumFaces = 300;
pcMesh->mFaces = new aiFace[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]; aiFace& face = pcMesh->mFaces[i];
face.mIndices = new unsigned int[ face.mNumIndices = 3 ]; 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++; face.mIndices[a] = p++;
} }
}
// generate extra members - set them to zero to make sure they're identical // generate extra members - set them to zero to make sure they're identical
pcMesh->mTextureCoords[0] = new aiVector3D[900]; 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]; 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; delete this->pcMesh;
pcMesh = nullptr;
delete this->piProcess; delete this->piProcess;
piProcess = nullptr;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
TEST_F(JoinVerticesTest, testProcess) TEST_F(utJoinVertices, testProcess) {
{
// execute the step on the given data // execute the step on the given data
piProcess->ProcessMesh(pcMesh,0); piProcess->ProcessMesh(pcMesh,0);
@ -122,15 +124,14 @@ TEST_F(JoinVerticesTest, testProcess)
ASSERT_EQ(300U, pcMesh->mNumFaces); ASSERT_EQ(300U, pcMesh->mNumFaces);
ASSERT_EQ(300U, pcMesh->mNumVertices); ASSERT_EQ(300U, pcMesh->mNumVertices);
ASSERT_TRUE(NULL != pcMesh->mNormals); ASSERT_TRUE( nullptr != pcMesh->mNormals);
ASSERT_TRUE(NULL != pcMesh->mTangents); ASSERT_TRUE( nullptr != pcMesh->mTangents);
ASSERT_TRUE(NULL != pcMesh->mBitangents); ASSERT_TRUE( nullptr != pcMesh->mBitangents);
ASSERT_TRUE(NULL != pcMesh->mTextureCoords[0]); ASSERT_TRUE( nullptr != pcMesh->mTextureCoords[0]);
// the order doesn't care // the order doesn't care
float fSum = 0.f; 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]; aiVector3D& v = pcMesh->mVertices[i];
fSum += v.x + v.y + v.z; 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 EXPECT_EQ(150.f*299.f*3.f, fSum); // gaussian sum equation
} }

View File

@ -5,8 +5,6 @@ Open Asset Import Library (assimp)
Copyright (c) 2006-2019, assimp team Copyright (c) 2006-2019, assimp team
All rights reserved. All rights reserved.
Redistribution and use of this software in source and binary forms, Redistribution and use of this software in source and binary forms,
@ -50,83 +48,83 @@ using namespace Assimp;
class LimitBoneWeightsTest : public ::testing::Test { class LimitBoneWeightsTest : public ::testing::Test {
public: public:
LimitBoneWeightsTest()
: Test()
, mProcess(nullptr)
, mMesh(nullptr) {
// empty
}
protected:
virtual void SetUp(); virtual void SetUp();
virtual void TearDown(); virtual void TearDown();
protected: protected:
LimitBoneWeightsProcess* piProcess; LimitBoneWeightsProcess *mProcess;
aiMesh* pcMesh; aiMesh *mMesh;
}; };
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void LimitBoneWeightsTest::SetUp() void LimitBoneWeightsTest::SetUp() {
{
// construct the process // construct the process
this->piProcess = new LimitBoneWeightsProcess(); this->mProcess = new LimitBoneWeightsProcess();
// now need to create a nice mesh for testing purposes // now need to create a nice mesh for testing purposes
this->pcMesh = new aiMesh(); this->mMesh = new aiMesh();
pcMesh->mNumVertices = 500; mMesh->mNumVertices = 500;
pcMesh->mVertices = new aiVector3D[500]; // uninit. mMesh->mVertices = new aiVector3D[500]; // uninit.
pcMesh->mNumBones = 30; mMesh->mNumBones = 30;
pcMesh->mBones = new aiBone*[30]; mMesh->mBones = new aiBone*[30];
unsigned int iCur = 0; unsigned int iCur = 0;
for (unsigned int i = 0; i < 30;++i) for (unsigned int i = 0; i < 30;++i) {
{ aiBone* pc = mMesh->mBones[i] = new aiBone();
aiBone* pc = pcMesh->mBones[i] = new aiBone();
pc->mNumWeights = 250; pc->mNumWeights = 250;
pc->mWeights = new aiVertexWeight[pc->mNumWeights]; 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]; aiVertexWeight& v = pc->mWeights[qq];
v.mVertexId = iCur++; 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 v.mWeight = 1.0f / 15; // each vertex should occur once in two bones
} }
} }
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void LimitBoneWeightsTest::TearDown() void LimitBoneWeightsTest::TearDown() {
{ delete mMesh;
delete pcMesh; delete mProcess;
delete piProcess;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
TEST_F(LimitBoneWeightsTest, testProcess) TEST_F(LimitBoneWeightsTest, testProcess) {
{
// execute the step on the given data // execute the step on the given data
piProcess->ProcessMesh(pcMesh); mProcess->ProcessMesh(mMesh);
// check whether everything is ok ... // check whether everything is ok ...
typedef std::vector<LimitBoneWeightsProcess::Weight> VertexWeightList; typedef std::vector<LimitBoneWeightsProcess::Weight> 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); asWeights[i].reserve(4);
}
// sort back as per-vertex lists // sort back as per-vertex lists
for (unsigned int i = 0; i < pcMesh->mNumBones;++i) for (unsigned int i = 0; i < mMesh->mNumBones;++i) {
{ aiBone& pcBone = **(mMesh->mBones+i);
aiBone& pcBone = **(pcMesh->mBones+i); for (unsigned int q = 0; q < pcBone.mNumWeights;++q) {
for (unsigned int q = 0; q < pcBone.mNumWeights;++q)
{
aiVertexWeight weight = pcBone.mWeights[q]; aiVertexWeight weight = pcBone.mWeights[q];
asWeights[weight.mVertexId].push_back(LimitBoneWeightsProcess::Weight (i,weight.mWeight)); 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 // 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); EXPECT_LE(asWeights[i].size(), 4U);
float fSum = 0.0f; float fSum = 0.0f;
for (VertexWeightList::const_iterator for (VertexWeightList::const_iterator iter = asWeights[i].begin(); iter != asWeights[i].end();++iter) {
iter = asWeights[i].begin();
iter != asWeights[i].end();++iter)
{
fSum += (*iter).mWeight; fSum += (*iter).mWeight;
} }
EXPECT_GE(fSum, 0.95F); EXPECT_GE(fSum, 0.95F);

View File

@ -448,3 +448,37 @@ TEST_F(utObjImportExport, import_without_linend) {
const aiScene *scene = myImporter.ReadFile(ASSIMP_TEST_MODELS_DIR "/OBJ/box_without_lineending.obj", 0); const aiScene *scene = myImporter.ReadFile(ASSIMP_TEST_MODELS_DIR "/OBJ/box_without_lineending.obj", 0);
ASSERT_NE(nullptr, scene); ASSERT_NE(nullptr, scene);
} }
TEST_F(utObjImportExport, import_with_line_continuations) {
static const char *ObjModel =
"v -0.5 -0.5 0.5\n"
"v -0.5 \\\n"
" -0.5 -0.5\n"
"v -0.5 \\\n"
" 0.5 \\\n"
" -0.5\n"
"f 1 2 3\n";
Assimp::Importer myImporter;
const aiScene *scene = myImporter.ReadFileFromMemory(ObjModel, strlen(ObjModel), 0);
EXPECT_NE(nullptr, scene);
EXPECT_EQ(scene->mNumMeshes, 1U);
EXPECT_EQ(scene->mMeshes[0]->mNumVertices, 3U);
EXPECT_EQ(scene->mMeshes[0]->mNumFaces, 1U);
auto vertices = scene->mMeshes[0]->mVertices;
const float threshold = 0.0001f;
EXPECT_NEAR(vertices[0].x, -0.5f, threshold);
EXPECT_NEAR(vertices[0].y, -0.5f, threshold);
EXPECT_NEAR(vertices[0].z, 0.5f, threshold);
EXPECT_NEAR(vertices[1].x, -0.5f, threshold);
EXPECT_NEAR(vertices[1].y, -0.5f, threshold);
EXPECT_NEAR(vertices[1].z, -0.5f, threshold);
EXPECT_NEAR(vertices[2].x, -0.5f, threshold);
EXPECT_NEAR(vertices[2].y, 0.5f, threshold);
EXPECT_NEAR(vertices[2].z, -0.5f, threshold);
}

View File

@ -51,18 +51,24 @@ using namespace Assimp;
class PretransformVerticesTest : public ::testing::Test { class PretransformVerticesTest : public ::testing::Test {
public: public:
PretransformVerticesTest()
: Test()
, mScene(nullptr)
, mProcess(nullptr) {
// empty
}
protected:
virtual void SetUp(); virtual void SetUp();
virtual void TearDown(); virtual void TearDown();
protected: protected:
aiScene *mScene;
aiScene* scene; PretransformVertices *mProcess;
PretransformVertices* process;
}; };
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
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]; father->mChildren = new aiNode*[father->mNumChildren = 5];
for (unsigned int i = 0; i < 5; ++i) { for (unsigned int i = 0; i < 5; ++i) {
aiNode* nd = father->mChildren[i] = new aiNode(); aiNode* nd = father->mChildren[i] = new aiNode();
@ -79,26 +85,26 @@ void AddNodes(unsigned int num, aiNode* father, unsigned int depth)
} }
if (depth > 1) { if (depth > 1) {
for (unsigned int i = 0; i < 5; ++i) for (unsigned int i = 0; i < 5; ++i) {
AddNodes(i, father->mChildren[i], depth - 1); AddNodes(i, father->mChildren[i], depth - 1);
} }
} }
}
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void PretransformVerticesTest::SetUp() void PretransformVerticesTest::SetUp() {
{ mScene = new aiScene();
scene = new aiScene();
// add 5 empty materials // 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) { for (unsigned int i = 0; i < 5;++i) {
scene->mMaterials[i] = new aiMaterial(); mScene->mMaterials[i] = new aiMaterial();
} }
// add 25 test meshes // add 25 test meshes
scene->mMeshes = new aiMesh*[scene->mNumMeshes = 25]; mScene->mMeshes = new aiMesh*[mScene->mNumMeshes = 25];
for ( unsigned int i = 0; i < 25; ++i) { for ( unsigned int i = 0; i < 25; ++i) {
aiMesh* mesh = scene->mMeshes[ i ] = new aiMesh(); aiMesh* mesh = mScene->mMeshes[ i ] = new aiMesh();
mesh->mPrimitiveTypes = aiPrimitiveType_POINT; mesh->mPrimitiveTypes = aiPrimitiveType_POINT;
mesh->mFaces = new aiFace[ mesh->mNumFaces = 10+i ]; mesh->mFaces = new aiFace[ mesh->mNumFaces = 10+i ];
@ -124,36 +130,33 @@ void PretransformVerticesTest::SetUp()
} }
// construct some nodes (1+25) // construct some nodes (1+25)
scene->mRootNode = new aiNode(); mScene->mRootNode = new aiNode();
scene->mRootNode->mName.Set("Root"); mScene->mRootNode->mName.Set("Root");
AddNodes(0,scene->mRootNode,2); AddNodes(0, mScene->mRootNode, 2);
process = new PretransformVertices(); mProcess = new PretransformVertices();
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void PretransformVerticesTest::TearDown() void PretransformVerticesTest::TearDown() {
{ delete mScene;
delete scene; delete mProcess;
delete process;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
TEST_F(PretransformVerticesTest, testProcessCollapseHierarchy) TEST_F(PretransformVerticesTest, testProcessCollapseHierarchy) {
{ mProcess->KeepHierarchy(false);
process->KeepHierarchy(false); mProcess->Execute(mScene);
process->Execute(scene);
EXPECT_EQ(5U, scene->mNumMaterials); EXPECT_EQ(5U, mScene->mNumMaterials);
EXPECT_EQ(10U, scene->mNumMeshes); // every second mesh has normals EXPECT_EQ(10U, mScene->mNumMeshes); // every second mesh has normals
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
TEST_F(PretransformVerticesTest, testProcessKeepHierarchy) TEST_F(PretransformVerticesTest, testProcessKeepHierarchy) {
{ mProcess->KeepHierarchy(true);
process->KeepHierarchy(true); mProcess->Execute(mScene);
process->Execute(scene);
EXPECT_EQ(5U, scene->mNumMaterials); EXPECT_EQ(5U, mScene->mNumMaterials);
EXPECT_EQ(49U, scene->mNumMeshes); // see note on mesh 12 above EXPECT_EQ(49U, mScene->mNumMeshes); // see note on mesh 12 above
} }

View File

@ -50,67 +50,67 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
using namespace std; using namespace std;
using namespace Assimp; using namespace Assimp;
class ScenePreprocessorTest : public ::testing::Test {
class ScenePreprocessorTest : public ::testing::Test
{
public: public:
ScenePreprocessorTest()
: Test()
, mScenePreprocessor(nullptr)
, mScene(nullptr) {
// empty
}
protected:
virtual void SetUp(); virtual void SetUp();
virtual void TearDown(); virtual void TearDown();
protected: protected:
void CheckIfOnly(aiMesh* p, unsigned int num, unsigned flag); 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); } private:
void ProcessMesh(aiMesh* mesh) { pp->ProcessMesh(mesh); } ScenePreprocessor *mScenePreprocessor;
aiScene *mScene;
ScenePreprocessor* pp;
aiScene* scene;
}; };
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void ScenePreprocessorTest::SetUp() void ScenePreprocessorTest::SetUp() {
{
// setup a dummy scene with a single node // setup a dummy scene with a single node
scene = new aiScene(); mScene = new aiScene();
scene->mRootNode = new aiNode(); mScene->mRootNode = new aiNode();
scene->mRootNode->mName.Set("<test>"); mScene->mRootNode->mName.Set("<test>");
// add some translation // add some translation
scene->mRootNode->mTransformation.a4 = 1.f; mScene->mRootNode->mTransformation.a4 = 1.f;
scene->mRootNode->mTransformation.b4 = 2.f; mScene->mRootNode->mTransformation.b4 = 2.f;
scene->mRootNode->mTransformation.c4 = 3.f; mScene->mRootNode->mTransformation.c4 = 3.f;
// and allocate a ScenePreprocessor to operate on the scene // and allocate a ScenePreprocessor to operate on the scene
pp = new ScenePreprocessor(scene); mScenePreprocessor = new ScenePreprocessor(mScene);
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void ScenePreprocessorTest::TearDown() void ScenePreprocessorTest::TearDown() {
{ delete mScenePreprocessor;
delete pp; delete mScene;
delete scene;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Check whether ProcessMesh() returns flag for a mesh that consist of primitives with num indices // 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 // Triangles only
for (unsigned i = 0; i < p->mNumFaces;++i) { for (unsigned i = 0; i < p->mNumFaces;++i) {
p->mFaces[i].mNumIndices = num; p->mFaces[i].mNumIndices = num;
} }
pp->ProcessMesh(p); mScenePreprocessor->ProcessMesh(p);
EXPECT_EQ(flag, p->mPrimitiveTypes); EXPECT_EQ(flag, p->mPrimitiveTypes);
p->mPrimitiveTypes = 0; p->mPrimitiveTypes = 0;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Check whether a mesh is preprocessed correctly. Case 1: The mesh needs preprocessing // Check whether a mesh is preprocessed correctly. Case 1: The mesh needs preprocessing
TEST_F(ScenePreprocessorTest, testMeshPreprocessingPos) TEST_F(ScenePreprocessorTest, testMeshPreprocessingPos) {
{ aiMesh* p = new aiMesh;
aiMesh* p = new aiMesh();
p->mNumFaces = 100; p->mNumFaces = 100;
p->mFaces = new aiFace[p->mNumFaces]; 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 // Check whether a mesh is preprocessed correctly. Case 1: The mesh doesn't need preprocessing
TEST_F(ScenePreprocessorTest, testMeshPreprocessingNeg) TEST_F(ScenePreprocessorTest, testMeshPreprocessingNeg) {
{ aiMesh* p = new aiMesh;
aiMesh* p = new aiMesh();
p->mPrimitiveTypes = aiPrimitiveType_TRIANGLE|aiPrimitiveType_POLYGON; p->mPrimitiveTypes = aiPrimitiveType_TRIANGLE|aiPrimitiveType_POLYGON;
ProcessMesh(p); ProcessMesh(p);
@ -160,8 +159,7 @@ TEST_F(ScenePreprocessorTest, testMeshPreprocessingNeg)
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Make a dummy animation with a single channel, '<test>' // Make a dummy animation with a single channel, '<test>'
aiAnimation* MakeDummyAnimation() aiAnimation* MakeDummyAnimation() {
{
aiAnimation* p = new aiAnimation(); aiAnimation* p = new aiAnimation();
p->mNumChannels = 1; p->mNumChannels = 1;
p->mChannels = new aiNodeAnim*[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 // Check whether an anim is preprocessed correctly. Case 1: The anim needs preprocessing
TEST_F(ScenePreprocessorTest, testAnimationPreprocessingPos) TEST_F(ScenePreprocessorTest, testAnimationPreprocessingPos) {
{
aiAnimation* p = MakeDummyAnimation(); aiAnimation* p = MakeDummyAnimation();
aiNodeAnim* anim = p->mChannels[0]; aiNodeAnim* anim = p->mChannels[0];

View File

@ -52,12 +52,20 @@ using namespace Assimp;
class SortByPTypeProcessTest : public ::testing::Test { class SortByPTypeProcessTest : public ::testing::Test {
public: public:
SortByPTypeProcessTest()
: Test()
, mProcess1(nullptr)
, mScene(nullptr) {
// empty
}
protected:
virtual void SetUp(); virtual void SetUp();
virtual void TearDown(); virtual void TearDown();
protected: protected:
SortByPTypeProcess* process1; SortByPTypeProcess* mProcess1;
aiScene* scene; 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_POLYGON,
aiPrimitiveType_TRIANGLE, aiPrimitiveType_TRIANGLE,
aiPrimitiveType_LINE, aiPrimitiveType_LINE,
@ -90,19 +97,16 @@ static unsigned int result[10] =
}; };
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void SortByPTypeProcessTest::SetUp() void SortByPTypeProcessTest::SetUp() {
{ mProcess1 = new SortByPTypeProcess();
// process0 = new DeterminePTypeHelperProcess(); mScene = new aiScene();
process1 = new SortByPTypeProcess();
scene = new aiScene();
scene->mNumMeshes = 10; mScene->mNumMeshes = 10;
scene->mMeshes = new aiMesh*[10]; mScene->mMeshes = new aiMesh*[10];
bool five = false; bool five = false;
for (unsigned int i = 0; i < 10; ++i) for (unsigned int i = 0; i < 10; ++i) {
{ aiMesh* mesh = mScene->mMeshes[i] = new aiMesh();
aiMesh* mesh = scene->mMeshes[i] = new aiMesh();
mesh->mNumFaces = 1000; mesh->mNumFaces = 1000;
aiFace* faces = mesh->mFaces = new aiFace[1000]; aiFace* faces = mesh->mFaces = new aiFace[1000];
aiVector3D* pv = mesh->mVertices = new aiVector3D[mesh->mNumFaces*5]; 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 remaining[4] = {num[i][0],num[i][1],num[i][2],num[i][3]};
unsigned int n = 0; 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; unsigned int idx = m % 4;
while (true) while (true) {
{ if (!remaining[idx]) {
if (!remaining[idx]) if (4 == ++idx) {
{ idx = 0;
if (4 == ++idx)idx = 0; }
continue; continue;
} }
break; break;
} }
faces->mNumIndices = idx+1; faces->mNumIndices = idx+1;
if (4 == faces->mNumIndices) if (4 == faces->mNumIndices) {
{
if(five)++faces->mNumIndices; if(five)++faces->mNumIndices;
five = !five; five = !five;
} }
faces->mIndices = new unsigned int[faces->mNumIndices]; faces->mIndices = new unsigned int[faces->mNumIndices];
for (unsigned int q = 0; q <faces->mNumIndices;++q,++n) for (unsigned int q = 0; q <faces->mNumIndices;++q,++n) {
{
faces->mIndices[q] = n; faces->mIndices[q] = n;
float f = (float)remaining[idx]; float f = (float)remaining[idx];
@ -152,12 +153,11 @@ void SortByPTypeProcessTest::SetUp()
mesh->mNumVertices = n; mesh->mNumVertices = n;
} }
scene->mRootNode = new aiNode(); mScene->mRootNode = new aiNode();
scene->mRootNode->mNumChildren = 5; mScene->mRootNode->mNumChildren = 5;
scene->mRootNode->mChildren = new aiNode*[5]; mScene->mRootNode->mChildren = new aiNode*[5];
for (unsigned int i = 0; i< 5;++i ) for (unsigned int i = 0; i< 5;++i ) {
{ aiNode* node = mScene->mRootNode->mChildren[i] = new aiNode();
aiNode* node = scene->mRootNode->mChildren[i] = new aiNode();
node->mNumMeshes = 2; node->mNumMeshes = 2;
node->mMeshes = new unsigned int[2]; node->mMeshes = new unsigned int[2];
node->mMeshes[0] = (i<<1u); node->mMeshes[0] = (i<<1u);
@ -166,48 +166,27 @@ void SortByPTypeProcessTest::SetUp()
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void SortByPTypeProcessTest::TearDown() void SortByPTypeProcessTest::TearDown() {
{ delete mProcess1;
//delete process0; delete mScene;
delete process1;
delete scene;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
//TEST_F(SortByPTypeProcessTest, DeterminePTypeStep() TEST_F(SortByPTypeProcessTest, SortByPTypeStep) {
//{ ScenePreprocessor s(mScene);
// 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);
s.ProcessScene(); s.ProcessScene();
for (unsigned int m = 0; m< 10;++m) 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; unsigned int idx = 0;
for (unsigned int m = 0,real = 0; m< 10;++m) for (unsigned int m = 0,real = 0; m< 10;++m) {
{ for (unsigned int n = 0; n < 4;++n) {
for (unsigned int n = 0; n < 4;++n) if ((idx = num[m][n])) {
{ EXPECT_TRUE(real < mScene->mNumMeshes);
if ((idx = num[m][n]))
{
EXPECT_TRUE(real < scene->mNumMeshes);
aiMesh* mesh = scene->mMeshes[real]; aiMesh* mesh = mScene->mMeshes[real];
EXPECT_TRUE(NULL != mesh); EXPECT_TRUE(NULL != mesh);
EXPECT_EQ(AI_PRIMITIVE_TYPE_FOR_N_INDICES(n+1), mesh->mPrimitiveTypes); EXPECT_EQ(AI_PRIMITIVE_TYPE_FOR_N_INDICES(n+1), mesh->mPrimitiveTypes);
@ -218,8 +197,7 @@ TEST_F(SortByPTypeProcessTest, SortByPTypeStep)
EXPECT_TRUE(NULL != mesh->mTextureCoords[0]); EXPECT_TRUE(NULL != mesh->mTextureCoords[0]);
EXPECT_TRUE(mesh->mNumFaces == idx); 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]; aiFace& face = mesh->mFaces[f];
EXPECT_TRUE(face.mNumIndices == (n+1) || (3 == n && face.mNumIndices > 3)); EXPECT_TRUE(face.mNumIndices == (n+1) || (3 == n && face.mNumIndices > 3));
} }
@ -228,4 +206,3 @@ TEST_F(SortByPTypeProcessTest, SortByPTypeStep)
} }
} }
} }

View File

@ -5,8 +5,6 @@ Open Asset Import Library (assimp)
Copyright (c) 2006-2019, assimp team Copyright (c) 2006-2019, assimp team
All rights reserved. All rights reserved.
Redistribution and use of this software in source and binary forms, Redistribution and use of this software in source and binary forms,
@ -55,17 +53,23 @@ class utglTF2ImportExport : public AbstractImportExportBase {
public: public:
virtual bool importerTest() { virtual bool importerTest() {
Assimp::Importer importer; Assimp::Importer importer;
const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/glTF2/BoxTextured-glTF/BoxTextured.gltf", aiProcess_ValidateDataStructure); const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/glTF2/BoxTextured-glTF/BoxTextured.gltf",
aiProcess_ValidateDataStructure);
EXPECT_NE( scene, nullptr ); EXPECT_NE( scene, nullptr );
if ( !scene ) return false; if (!scene) {
return false;
}
EXPECT_TRUE( scene->HasMaterials() ); EXPECT_TRUE( scene->HasMaterials() );
if ( !scene->HasMaterials() ) return false; if (!scene->HasMaterials()) {
return false;
}
const aiMaterial *material = scene->mMaterials[0]; const aiMaterial *material = scene->mMaterials[0];
aiString path; aiString path;
aiTextureMapMode modes[2]; aiTextureMapMode modes[2];
EXPECT_EQ( aiReturn_SUCCESS, material->GetTexture(aiTextureType_DIFFUSE, 0, &path, nullptr, nullptr, nullptr, nullptr, modes) ); EXPECT_EQ( aiReturn_SUCCESS, material->GetTexture(aiTextureType_DIFFUSE, 0, &path, nullptr, nullptr,
nullptr, nullptr, modes) );
EXPECT_STREQ( path.C_Str(), "CesiumLogoFlat.png" ); EXPECT_STREQ( path.C_Str(), "CesiumLogoFlat.png" );
EXPECT_EQ( modes[0], aiTextureMapMode_Mirror ); EXPECT_EQ( modes[0], aiTextureMapMode_Mirror );
EXPECT_EQ( modes[1], aiTextureMapMode_Clamp ); EXPECT_EQ( modes[1], aiTextureMapMode_Clamp );
@ -75,7 +79,8 @@ public:
virtual bool binaryImporterTest() { virtual bool binaryImporterTest() {
Assimp::Importer importer; Assimp::Importer importer;
const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/glTF2/2CylinderEngine-glTF-Binary/2CylinderEngine.glb", aiProcess_ValidateDataStructure); const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/glTF2/2CylinderEngine-glTF-Binary/2CylinderEngine.glb",
aiProcess_ValidateDataStructure);
return nullptr != scene; return nullptr != scene;
} }
@ -83,7 +88,8 @@ public:
virtual bool exporterTest() { virtual bool exporterTest() {
Assimp::Importer importer; Assimp::Importer importer;
Assimp::Exporter exporter; Assimp::Exporter exporter;
const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/glTF2/BoxTextured-glTF/BoxTextured.gltf", aiProcess_ValidateDataStructure ); const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/glTF2/BoxTextured-glTF/BoxTextured.gltf",
aiProcess_ValidateDataStructure );
EXPECT_NE( nullptr, scene ); EXPECT_NE( nullptr, scene );
EXPECT_EQ( aiReturn_SUCCESS, exporter.Export( scene, "gltf2", ASSIMP_TEST_MODELS_DIR "/glTF2/BoxTextured-glTF/BoxTextured_out.gltf" ) ); EXPECT_EQ( aiReturn_SUCCESS, exporter.Export( scene, "gltf2", ASSIMP_TEST_MODELS_DIR "/glTF2/BoxTextured-glTF/BoxTextured_out.gltf" ) );
@ -105,7 +111,8 @@ TEST_F( utglTF2ImportExport, importBinaryglTF2FromFileTest ) {
TEST_F(utglTF2ImportExport, importglTF2AndExportToOBJ) { TEST_F(utglTF2ImportExport, importglTF2AndExportToOBJ) {
Assimp::Importer importer; Assimp::Importer importer;
Assimp::Exporter exporter; Assimp::Exporter exporter;
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/glTF2/BoxTextured-glTF/BoxTextured.gltf", aiProcess_ValidateDataStructure); const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/glTF2/BoxTextured-glTF/BoxTextured.gltf",
aiProcess_ValidateDataStructure);
EXPECT_NE(nullptr, scene); EXPECT_NE(nullptr, scene);
EXPECT_EQ(aiReturn_SUCCESS, exporter.Export(scene, "obj", ASSIMP_TEST_MODELS_DIR "/glTF2/BoxTextured-glTF/BoxTextured_out.obj")); EXPECT_EQ(aiReturn_SUCCESS, exporter.Export(scene, "obj", ASSIMP_TEST_MODELS_DIR "/glTF2/BoxTextured-glTF/BoxTextured_out.obj"));
} }
@ -113,7 +120,8 @@ TEST_F(utglTF2ImportExport, importglTF2AndExportToOBJ) {
TEST_F(utglTF2ImportExport, importglTF2EmbeddedAndExportToOBJ) { TEST_F(utglTF2ImportExport, importglTF2EmbeddedAndExportToOBJ) {
Assimp::Importer importer; Assimp::Importer importer;
Assimp::Exporter exporter; Assimp::Exporter exporter;
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/glTF2/BoxTextured-glTF-Embedded/BoxTextured.gltf", aiProcess_ValidateDataStructure); const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/glTF2/BoxTextured-glTF-Embedded/BoxTextured.gltf",
aiProcess_ValidateDataStructure);
EXPECT_NE(nullptr, scene); EXPECT_NE(nullptr, scene);
EXPECT_EQ(aiReturn_SUCCESS, exporter.Export(scene, "obj", ASSIMP_TEST_MODELS_DIR "/glTF2/BoxTextured-glTF-Embedded/BoxTextured_out.obj")); EXPECT_EQ(aiReturn_SUCCESS, exporter.Export(scene, "obj", ASSIMP_TEST_MODELS_DIR "/glTF2/BoxTextured-glTF-Embedded/BoxTextured_out.obj"));
} }
@ -124,10 +132,9 @@ TEST_F(utglTF2ImportExport, importglTF2PrimitiveModePointsWithoutIndices) {
//Points without indices //Points without indices
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/glTF2/glTF-Asset-Generator/Mesh_PrimitiveMode/Mesh_PrimitiveMode_00.gltf", aiProcess_ValidateDataStructure); const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/glTF2/glTF-Asset-Generator/Mesh_PrimitiveMode/Mesh_PrimitiveMode_00.gltf", aiProcess_ValidateDataStructure);
EXPECT_NE(nullptr, scene); EXPECT_NE(nullptr, scene);
EXPECT_EQ(scene->mMeshes[0]->mNumVertices, 1024); EXPECT_EQ(scene->mMeshes[0]->mNumVertices, 1024u);
for (unsigned int i = 0; i < scene->mMeshes[0]->mNumFaces; ++i) for (unsigned int i = 0; i < scene->mMeshes[0]->mNumFaces; ++i) {
{ EXPECT_EQ(scene->mMeshes[0]->mFaces[i].mNumIndices, 1u);
EXPECT_EQ(scene->mMeshes[0]->mFaces[i].mNumIndices, 1);
EXPECT_EQ(scene->mMeshes[0]->mFaces[i].mIndices[0], i); EXPECT_EQ(scene->mMeshes[0]->mFaces[i].mIndices[0], i);
} }
} }
@ -137,12 +144,11 @@ TEST_F(utglTF2ImportExport, importglTF2PrimitiveModeLinesWithoutIndices) {
//Lines without indices //Lines without indices
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/glTF2/glTF-Asset-Generator/Mesh_PrimitiveMode/Mesh_PrimitiveMode_01.gltf", aiProcess_ValidateDataStructure); const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/glTF2/glTF-Asset-Generator/Mesh_PrimitiveMode/Mesh_PrimitiveMode_01.gltf", aiProcess_ValidateDataStructure);
EXPECT_NE(nullptr, scene); EXPECT_NE(nullptr, scene);
EXPECT_EQ(scene->mMeshes[0]->mNumVertices, 8); EXPECT_EQ(scene->mMeshes[0]->mNumVertices, 8u);
for (unsigned int i = 0; i < scene->mMeshes[0]->mNumFaces; ++i) for (unsigned int i = 0; i < scene->mMeshes[0]->mNumFaces; ++i) {
{ EXPECT_EQ(scene->mMeshes[0]->mFaces[i].mNumIndices, 2u);
EXPECT_EQ(scene->mMeshes[0]->mFaces[i].mNumIndices, 2); EXPECT_EQ(scene->mMeshes[0]->mFaces[i].mIndices[0], i*2u);
EXPECT_EQ(scene->mMeshes[0]->mFaces[i].mIndices[0], i*2); EXPECT_EQ(scene->mMeshes[0]->mFaces[i].mIndices[1], i*2u + 1u);
EXPECT_EQ(scene->mMeshes[0]->mFaces[i].mIndices[1], i*2 + 1);
} }
} }
@ -151,15 +157,14 @@ TEST_F(utglTF2ImportExport, importglTF2PrimitiveModeLinesLoopWithoutIndices) {
//Lines loop without indices //Lines loop without indices
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/glTF2/glTF-Asset-Generator/Mesh_PrimitiveMode/Mesh_PrimitiveMode_02.gltf", aiProcess_ValidateDataStructure); const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/glTF2/glTF-Asset-Generator/Mesh_PrimitiveMode/Mesh_PrimitiveMode_02.gltf", aiProcess_ValidateDataStructure);
EXPECT_NE(nullptr, scene); EXPECT_NE(nullptr, scene);
EXPECT_EQ(scene->mMeshes[0]->mNumVertices, 4); EXPECT_EQ(scene->mMeshes[0]->mNumVertices, 4u);
std::array<int, 5> l1 = {{ 0, 1, 2, 3, 0 }}; std::array<unsigned int, 5> l1 = {{ 0u, 1u, 2u, 3u, 0u }};
EXPECT_EQ(scene->mMeshes[0]->mFaces[0].mNumIndices, 2); EXPECT_EQ(scene->mMeshes[0]->mFaces[0].mNumIndices, 2u);
for (unsigned int i = 0; i < scene->mMeshes[0]->mNumFaces; ++i) for (unsigned int i = 0; i < scene->mMeshes[0]->mNumFaces; ++i) {
{ EXPECT_EQ(scene->mMeshes[0]->mFaces[i].mNumIndices, 2u);
EXPECT_EQ(scene->mMeshes[0]->mFaces[i].mNumIndices, 2);
EXPECT_EQ(scene->mMeshes[0]->mFaces[i].mIndices[0], l1[i]); EXPECT_EQ(scene->mMeshes[0]->mFaces[i].mIndices[0], l1[i]);
EXPECT_EQ(scene->mMeshes[0]->mFaces[i].mIndices[1], l1[i + 1]); EXPECT_EQ(scene->mMeshes[0]->mFaces[i].mIndices[1], l1[i + 1u]);
} }
} }
@ -168,14 +173,13 @@ TEST_F(utglTF2ImportExport, importglTF2PrimitiveModeLinesStripWithoutIndices) {
//Lines strip without indices //Lines strip without indices
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/glTF2/glTF-Asset-Generator/Mesh_PrimitiveMode/Mesh_PrimitiveMode_03.gltf", aiProcess_ValidateDataStructure); const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/glTF2/glTF-Asset-Generator/Mesh_PrimitiveMode/Mesh_PrimitiveMode_03.gltf", aiProcess_ValidateDataStructure);
EXPECT_NE(nullptr, scene); EXPECT_NE(nullptr, scene);
EXPECT_EQ(scene->mMeshes[0]->mNumVertices, 5); EXPECT_EQ(scene->mMeshes[0]->mNumVertices, 5u);
EXPECT_EQ(scene->mMeshes[0]->mFaces[0].mNumIndices, 2); EXPECT_EQ(scene->mMeshes[0]->mFaces[0].mNumIndices, 2u);
for (unsigned int i = 0; i < scene->mMeshes[0]->mNumFaces; ++i) for (unsigned int i = 0; i < scene->mMeshes[0]->mNumFaces; ++i) {
{ EXPECT_EQ(scene->mMeshes[0]->mFaces[i].mNumIndices, 2u);
EXPECT_EQ(scene->mMeshes[0]->mFaces[i].mNumIndices, 2);
EXPECT_EQ(scene->mMeshes[0]->mFaces[i].mIndices[0], i); EXPECT_EQ(scene->mMeshes[0]->mFaces[i].mIndices[0], i);
EXPECT_EQ(scene->mMeshes[0]->mFaces[i].mIndices[1], i + 1); EXPECT_EQ(scene->mMeshes[0]->mFaces[i].mIndices[1], i + 1u);
} }
} }
@ -184,19 +188,17 @@ TEST_F(utglTF2ImportExport, importglTF2PrimitiveModeTrianglesStripWithoutIndices
//Triangles strip without indices //Triangles strip without indices
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/glTF2/glTF-Asset-Generator/Mesh_PrimitiveMode/Mesh_PrimitiveMode_04.gltf", aiProcess_ValidateDataStructure); const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/glTF2/glTF-Asset-Generator/Mesh_PrimitiveMode/Mesh_PrimitiveMode_04.gltf", aiProcess_ValidateDataStructure);
EXPECT_NE(nullptr, scene); EXPECT_NE(nullptr, scene);
EXPECT_EQ(scene->mMeshes[0]->mNumFaces, 2); EXPECT_EQ(scene->mMeshes[0]->mNumFaces, 2u);
EXPECT_EQ(scene->mMeshes[0]->mNumVertices, 4); EXPECT_EQ(scene->mMeshes[0]->mNumVertices, 4u);
std::array<int, 3> f1 = {{ 0, 1, 2 }}; std::array<unsigned int, 3> f1 = {{ 0u, 1u, 2u }};
EXPECT_EQ(scene->mMeshes[0]->mFaces[0].mNumIndices, 3); EXPECT_EQ(scene->mMeshes[0]->mFaces[0].mNumIndices, 3u);
for (int i = 0; i < 3; ++i) for (unsigned int i = 0; i < 3; ++i) {
{
EXPECT_EQ(scene->mMeshes[0]->mFaces[0].mIndices[i], f1[i]); EXPECT_EQ(scene->mMeshes[0]->mFaces[0].mIndices[i], f1[i]);
} }
std::array<int, 3> f2 = {{ 2, 1, 3 }}; std::array<unsigned int, 3> f2 = {{ 2u, 1u, 3u }};
EXPECT_EQ(scene->mMeshes[0]->mFaces[1].mNumIndices, 3); EXPECT_EQ(scene->mMeshes[0]->mFaces[1].mNumIndices, 3u);
for (int i = 0; i < 3; ++i) for (size_t i = 0; i < 3; ++i) {
{
EXPECT_EQ(scene->mMeshes[0]->mFaces[1].mIndices[i], f2[i]); EXPECT_EQ(scene->mMeshes[0]->mFaces[1].mIndices[i], f2[i]);
} }
} }
@ -206,19 +208,17 @@ TEST_F(utglTF2ImportExport, importglTF2PrimitiveModeTrianglesFanWithoutIndices)
//Triangles fan without indices //Triangles fan without indices
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/glTF2/glTF-Asset-Generator/Mesh_PrimitiveMode/Mesh_PrimitiveMode_05.gltf", aiProcess_ValidateDataStructure); const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/glTF2/glTF-Asset-Generator/Mesh_PrimitiveMode/Mesh_PrimitiveMode_05.gltf", aiProcess_ValidateDataStructure);
EXPECT_NE(nullptr, scene); EXPECT_NE(nullptr, scene);
EXPECT_EQ(scene->mMeshes[0]->mNumFaces, 2); EXPECT_EQ(scene->mMeshes[0]->mNumFaces, 2u);
EXPECT_EQ(scene->mMeshes[0]->mNumVertices, 4); EXPECT_EQ(scene->mMeshes[0]->mNumVertices, 4u);
std::array<int, 3> f1 = {{ 0, 1, 2 }}; std::array<unsigned int, 3> f1 = {{ 0u, 1u, 2u }};
EXPECT_EQ(scene->mMeshes[0]->mFaces[0].mNumIndices, 3); EXPECT_EQ(scene->mMeshes[0]->mFaces[0].mNumIndices, 3u);
for (int i = 0; i < 3; ++i) for (size_t i = 0; i < 3; ++i) {
{
EXPECT_EQ(scene->mMeshes[0]->mFaces[0].mIndices[i], f1[i]); EXPECT_EQ(scene->mMeshes[0]->mFaces[0].mIndices[i], f1[i]);
} }
std::array<int, 3> f2 = {{ 0, 2, 3 }}; std::array<unsigned int, 3> f2 = {{ 0u, 2u, 3u }};
EXPECT_EQ(scene->mMeshes[0]->mFaces[1].mNumIndices, 3); EXPECT_EQ(scene->mMeshes[0]->mFaces[1].mNumIndices, 3u);
for (int i = 0; i < 3; ++i) for (size_t i = 0; i < 3; ++i) {
{
EXPECT_EQ(scene->mMeshes[0]->mFaces[1].mIndices[i], f2[i]); EXPECT_EQ(scene->mMeshes[0]->mFaces[1].mIndices[i], f2[i]);
} }
} }
@ -228,19 +228,17 @@ TEST_F(utglTF2ImportExport, importglTF2PrimitiveModeTrianglesWithoutIndices) {
//Triangles without indices //Triangles without indices
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/glTF2/glTF-Asset-Generator/Mesh_PrimitiveMode/Mesh_PrimitiveMode_06.gltf", aiProcess_ValidateDataStructure); const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/glTF2/glTF-Asset-Generator/Mesh_PrimitiveMode/Mesh_PrimitiveMode_06.gltf", aiProcess_ValidateDataStructure);
EXPECT_NE(nullptr, scene); EXPECT_NE(nullptr, scene);
EXPECT_EQ(scene->mMeshes[0]->mNumFaces, 2); EXPECT_EQ(scene->mMeshes[0]->mNumFaces, 2u);
EXPECT_EQ(scene->mMeshes[0]->mNumVertices, 6); EXPECT_EQ(scene->mMeshes[0]->mNumVertices, 6u);
std::array<int, 3> f1 = {{ 0, 1, 2 }}; std::array<unsigned int, 3> f1 = {{ 0u, 1u, 2u }};
EXPECT_EQ(scene->mMeshes[0]->mFaces[0].mNumIndices, 3); EXPECT_EQ(scene->mMeshes[0]->mFaces[0].mNumIndices, 3u);
for (int i = 0; i < 3; ++i) for (size_t i = 0; i < 3; ++i) {
{
EXPECT_EQ(scene->mMeshes[0]->mFaces[0].mIndices[i], f1[i]); EXPECT_EQ(scene->mMeshes[0]->mFaces[0].mIndices[i], f1[i]);
} }
std::array<int, 3> f2 = {{ 3, 4, 5 }}; std::array<unsigned int, 3> f2 = {{ 3u, 4u, 5u }};
EXPECT_EQ(scene->mMeshes[0]->mFaces[1].mNumIndices, 3); EXPECT_EQ(scene->mMeshes[0]->mFaces[1].mNumIndices, 3u);
for (int i = 0; i < 3; ++i) for (size_t i = 0; i < 3; ++i) {
{
EXPECT_EQ(scene->mMeshes[0]->mFaces[1].mIndices[i], f2[i]); EXPECT_EQ(scene->mMeshes[0]->mFaces[1].mIndices[i], f2[i]);
} }
} }
@ -250,10 +248,9 @@ TEST_F(utglTF2ImportExport, importglTF2PrimitiveModePoints) {
//Line loop //Line loop
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/glTF2/glTF-Asset-Generator/Mesh_PrimitiveMode/Mesh_PrimitiveMode_07.gltf", aiProcess_ValidateDataStructure); const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/glTF2/glTF-Asset-Generator/Mesh_PrimitiveMode/Mesh_PrimitiveMode_07.gltf", aiProcess_ValidateDataStructure);
EXPECT_NE(nullptr, scene); EXPECT_NE(nullptr, scene);
EXPECT_EQ(scene->mMeshes[0]->mNumVertices, 1024); EXPECT_EQ(scene->mMeshes[0]->mNumVertices, 1024u);
for (unsigned int i = 0; i < scene->mMeshes[0]->mNumFaces; ++i) for (unsigned int i = 0; i < scene->mMeshes[0]->mNumFaces; ++i) {
{ EXPECT_EQ(scene->mMeshes[0]->mFaces[i].mNumIndices, 1u);
EXPECT_EQ(scene->mMeshes[0]->mFaces[i].mNumIndices, 1);
EXPECT_EQ(scene->mMeshes[0]->mFaces[i].mIndices[0], i); EXPECT_EQ(scene->mMeshes[0]->mFaces[i].mIndices[0], i);
} }
} }
@ -263,9 +260,9 @@ TEST_F(utglTF2ImportExport, importglTF2PrimitiveModeLines) {
//Lines //Lines
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/glTF2/glTF-Asset-Generator/Mesh_PrimitiveMode/Mesh_PrimitiveMode_08.gltf", aiProcess_ValidateDataStructure); const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/glTF2/glTF-Asset-Generator/Mesh_PrimitiveMode/Mesh_PrimitiveMode_08.gltf", aiProcess_ValidateDataStructure);
EXPECT_NE(nullptr, scene); EXPECT_NE(nullptr, scene);
EXPECT_EQ(scene->mMeshes[0]->mNumVertices, 4); EXPECT_EQ(scene->mMeshes[0]->mNumVertices, 4u);
std::array<int, 5> l1 = {{ 0, 3, 2, 1, 0 }}; std::array<unsigned int, 5> l1 = {{ 0u, 3u, 2u, 1u, 0u }};
EXPECT_EQ(scene->mMeshes[0]->mFaces[0].mNumIndices, 2); EXPECT_EQ(scene->mMeshes[0]->mFaces[0].mNumIndices, 2u);
for (unsigned int i = 0; i < scene->mMeshes[0]->mNumFaces; ++i) for (unsigned int i = 0; i < scene->mMeshes[0]->mNumFaces; ++i)
{ {
EXPECT_EQ(scene->mMeshes[0]->mFaces[i].mIndices[0], l1[i]); EXPECT_EQ(scene->mMeshes[0]->mFaces[i].mIndices[0], l1[i]);
@ -278,9 +275,9 @@ TEST_F(utglTF2ImportExport, importglTF2PrimitiveModeLineLoop) {
//Line loop //Line loop
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/glTF2/glTF-Asset-Generator/Mesh_PrimitiveMode/Mesh_PrimitiveMode_09.gltf", aiProcess_ValidateDataStructure); const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/glTF2/glTF-Asset-Generator/Mesh_PrimitiveMode/Mesh_PrimitiveMode_09.gltf", aiProcess_ValidateDataStructure);
EXPECT_NE(nullptr, scene); EXPECT_NE(nullptr, scene);
EXPECT_EQ(scene->mMeshes[0]->mNumVertices, 4); EXPECT_EQ(scene->mMeshes[0]->mNumVertices, 4u);
std::array<int, 5> l1 = {{ 0, 3, 2, 1, 0 }}; std::array<unsigned int, 5> l1 = {{ 0, 3u, 2u, 1u, 0u }};
EXPECT_EQ(scene->mMeshes[0]->mFaces[0].mNumIndices, 2); EXPECT_EQ(scene->mMeshes[0]->mFaces[0].mNumIndices, 2u);
for (unsigned int i = 0; i < scene->mMeshes[0]->mNumFaces; ++i) for (unsigned int i = 0; i < scene->mMeshes[0]->mNumFaces; ++i)
{ {
EXPECT_EQ(scene->mMeshes[0]->mFaces[i].mIndices[0], l1[i]); EXPECT_EQ(scene->mMeshes[0]->mFaces[i].mIndices[0], l1[i]);
@ -293,11 +290,10 @@ TEST_F(utglTF2ImportExport, importglTF2PrimitiveModeLineStrip) {
//Lines Strip //Lines Strip
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/glTF2/glTF-Asset-Generator/Mesh_PrimitiveMode/Mesh_PrimitiveMode_10.gltf", aiProcess_ValidateDataStructure); const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/glTF2/glTF-Asset-Generator/Mesh_PrimitiveMode/Mesh_PrimitiveMode_10.gltf", aiProcess_ValidateDataStructure);
EXPECT_NE(nullptr, scene); EXPECT_NE(nullptr, scene);
EXPECT_EQ(scene->mMeshes[0]->mNumVertices, 4); EXPECT_EQ(scene->mMeshes[0]->mNumVertices, 4u);
std::array<int, 5> l1 = {{ 0, 3, 2, 1, 0 }}; std::array<unsigned int, 5> l1 = {{ 0u, 3u, 2u, 1u, 0u }};
EXPECT_EQ(scene->mMeshes[0]->mFaces[0].mNumIndices, 2); EXPECT_EQ(scene->mMeshes[0]->mFaces[0].mNumIndices, 2u);
for (unsigned int i = 0; i < scene->mMeshes[0]->mNumFaces; ++i) for (unsigned int i = 0; i < scene->mMeshes[0]->mNumFaces; ++i) {
{
EXPECT_EQ(scene->mMeshes[0]->mFaces[i].mIndices[0], l1[i]); EXPECT_EQ(scene->mMeshes[0]->mFaces[i].mIndices[0], l1[i]);
EXPECT_EQ(scene->mMeshes[0]->mFaces[i].mIndices[1], l1[i + 1]); EXPECT_EQ(scene->mMeshes[0]->mFaces[i].mIndices[1], l1[i + 1]);
} }
@ -308,19 +304,17 @@ TEST_F(utglTF2ImportExport, importglTF2PrimitiveModeTrianglesStrip) {
//Triangles strip //Triangles strip
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/glTF2/glTF-Asset-Generator/Mesh_PrimitiveMode/Mesh_PrimitiveMode_11.gltf", aiProcess_ValidateDataStructure); const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/glTF2/glTF-Asset-Generator/Mesh_PrimitiveMode/Mesh_PrimitiveMode_11.gltf", aiProcess_ValidateDataStructure);
EXPECT_NE(nullptr, scene); EXPECT_NE(nullptr, scene);
EXPECT_EQ(scene->mMeshes[0]->mNumFaces, 2); EXPECT_EQ(scene->mMeshes[0]->mNumFaces, 2u);
EXPECT_EQ(scene->mMeshes[0]->mNumVertices, 4); EXPECT_EQ(scene->mMeshes[0]->mNumVertices, 4u);
std::array<int, 3> f1 = {{ 0, 3, 1 }}; std::array<unsigned int, 3> f1 = {{ 0u, 3u, 1u }};
EXPECT_EQ(scene->mMeshes[0]->mFaces[0].mNumIndices, 3); EXPECT_EQ(scene->mMeshes[0]->mFaces[0].mNumIndices, 3u);
for (int i = 0; i < 3; ++i) for (size_t i = 0; i < 3; ++i) {
{
EXPECT_EQ(scene->mMeshes[0]->mFaces[0].mIndices[i], f1[i]); EXPECT_EQ(scene->mMeshes[0]->mFaces[0].mIndices[i], f1[i]);
} }
std::array<int, 3> f2 = {{ 1, 3, 2 }}; std::array<unsigned int, 3> f2 = {{ 1u, 3u, 2u }};
EXPECT_EQ(scene->mMeshes[0]->mFaces[1].mNumIndices, 3); EXPECT_EQ(scene->mMeshes[0]->mFaces[1].mNumIndices, 3u);
for (int i = 0; i < 3; ++i) for (size_t i = 0; i < 3; ++i) {
{
EXPECT_EQ(scene->mMeshes[0]->mFaces[1].mIndices[i], f2[i]); EXPECT_EQ(scene->mMeshes[0]->mFaces[1].mIndices[i], f2[i]);
} }
} }
@ -330,19 +324,17 @@ TEST_F(utglTF2ImportExport, importglTF2PrimitiveModeTrianglesFan) {
//Triangles fan //Triangles fan
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/glTF2/glTF-Asset-Generator/Mesh_PrimitiveMode/Mesh_PrimitiveMode_12.gltf", aiProcess_ValidateDataStructure); const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/glTF2/glTF-Asset-Generator/Mesh_PrimitiveMode/Mesh_PrimitiveMode_12.gltf", aiProcess_ValidateDataStructure);
EXPECT_NE(nullptr, scene); EXPECT_NE(nullptr, scene);
EXPECT_EQ(scene->mMeshes[0]->mNumVertices, 4); EXPECT_EQ(scene->mMeshes[0]->mNumVertices, 4u);
EXPECT_EQ(scene->mMeshes[0]->mNumFaces, 2); EXPECT_EQ(scene->mMeshes[0]->mNumFaces, 2u);
std::array<int, 3> f1 = {{ 0, 3, 2 }}; std::array<unsigned int, 3> f1 = {{ 0u, 3u, 2u }};
EXPECT_EQ(scene->mMeshes[0]->mFaces[0].mNumIndices, 3); EXPECT_EQ(scene->mMeshes[0]->mFaces[0].mNumIndices, 3u );
for (int i = 0; i < 3; ++i) for (size_t i = 0; i < 3; ++i) {
{
EXPECT_EQ(scene->mMeshes[0]->mFaces[0].mIndices[i], f1[i]); EXPECT_EQ(scene->mMeshes[0]->mFaces[0].mIndices[i], f1[i]);
} }
std::array<int, 3> f2 = {{ 0, 2, 1 }}; std::array<unsigned int, 3> f2 = {{ 0u, 2u, 1u }};
EXPECT_EQ(scene->mMeshes[0]->mFaces[1].mNumIndices, 3); EXPECT_EQ(scene->mMeshes[0]->mFaces[1].mNumIndices, 3u );
for (int i = 0; i < 3; ++i) for (size_t i = 0; i < 3; ++i) {
{
EXPECT_EQ(scene->mMeshes[0]->mFaces[1].mIndices[i], f2[i]); EXPECT_EQ(scene->mMeshes[0]->mFaces[1].mIndices[i], f2[i]);
} }
} }
@ -378,7 +370,8 @@ TEST_F(utglTF2ImportExport, importglTF2FromMemory) {
TEST_F( utglTF2ImportExport, bug_import_simple_skin ) { TEST_F( utglTF2ImportExport, bug_import_simple_skin ) {
Assimp::Importer importer; Assimp::Importer importer;
const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/glTF2/simple_skin/simple_skin.gltf", aiProcess_ValidateDataStructure ); const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/glTF2/simple_skin/simple_skin.gltf",
aiProcess_ValidateDataStructure );
EXPECT_NE( nullptr, scene ); EXPECT_NE( nullptr, scene );
} }