Merge branch 'master' into fix-multiUV-export

pull/2572/head
Kim Kulling 2019-07-28 09:37:00 +02:00 committed by GitHub
commit 7d74a3354d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
45 changed files with 2154 additions and 753 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

@ -331,7 +331,7 @@ ADD_ASSIMP_EXPORTER( ASSBIN
Assbin/AssbinExporter.cpp
)
ADD_ASSIMP_IMPORTER( ASSXML
ADD_ASSIMP_EXPORTER( ASSXML
Assxml/AssxmlExporter.h
Assxml/AssxmlExporter.cpp
)
@ -810,6 +810,14 @@ ADD_ASSIMP_IMPORTER( MMD
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
# 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

View File

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

View File

@ -5,8 +5,6 @@ Open Asset Import Library (assimp)
Copyright (c) 2006-2019, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,
@ -43,7 +41,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/** @file Implementation of the Collada loader */
#ifndef ASSIMP_BUILD_NO_COLLADA_IMPORTER
#include "ColladaLoader.h"
@ -65,8 +62,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "math.h"
#include <algorithm>
#include <numeric>
#include <memory>
using namespace Assimp;
namespace Assimp {
using namespace Assimp::Formatter;
static const aiImporterDesc desc = {
@ -111,7 +110,7 @@ ColladaLoader::~ColladaLoader() {
// Returns whether the class can handle the format of the given file.
bool ColladaLoader::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const {
// check file extension
std::string extension = GetExtension(pFile);
const std::string extension = GetExtension(pFile);
if (extension == "dae") {
return true;
@ -126,7 +125,7 @@ bool ColladaLoader::CanRead( const std::string& pFile, IOSystem* pIOHandler, boo
if (!pIOHandler) {
return true;
}
const char* tokens[] = {"<collada"};
static const char* tokens[] = {"<collada"};
return SearchFileHeaderForToken(pIOHandler,pFile,tokens,1);
}
@ -134,8 +133,7 @@ bool ColladaLoader::CanRead( const std::string& pFile, IOSystem* pIOHandler, boo
}
// ------------------------------------------------------------------------------------------------
void ColladaLoader::SetupProperties(const Importer* pImp)
{
void ColladaLoader::SetupProperties(const Importer* pImp) {
noSkeletonMesh = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_NO_SKELETON_MESHES,0) != 0;
ignoreUpDirection = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_COLLADA_IGNORE_UP_DIRECTION,0) != 0;
useColladaName = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_COLLADA_USE_COLLADA_NAMES,0) != 0;
@ -143,8 +141,7 @@ void ColladaLoader::SetupProperties(const Importer* pImp)
// ------------------------------------------------------------------------------------------------
// Get file extension list
const aiImporterDesc* ColladaLoader::GetInfo () const
{
const aiImporterDesc* ColladaLoader::GetInfo () const {
return &desc;
}
@ -167,12 +164,13 @@ void ColladaLoader::InternReadFile( const std::string& pFile, aiScene* pScene, I
// parse the input file
ColladaParser parser( pIOHandler, pFile);
if( !parser.mRootNode)
if( !parser.mRootNode) {
throw DeadlyImportError( "Collada: File came out empty. Something is wrong here.");
}
// reserve some storage to avoid unnecessary reallocs
newMats.reserve(parser.mMaterialLibrary.size()*2);
mMeshes.reserve(parser.mMeshLibrary.size()*2);
newMats.reserve(parser.mMaterialLibrary.size()*2u);
mMeshes.reserve(parser.mMeshLibrary.size()*2u);
mCameras.reserve(parser.mCameraLibrary.size());
mLights.reserve(parser.mLightLibrary.size());
@ -192,19 +190,20 @@ void ColladaLoader::InternReadFile( const std::string& pFile, aiScene* pScene, I
0, 0, parser.mUnitSize, 0,
0, 0, 0, 1);
if( !ignoreUpDirection ) {
// Convert to Y_UP, if different orientation
if( parser.mUpDirection == ColladaParser::UP_X)
pScene->mRootNode->mTransformation *= aiMatrix4x4(
0, -1, 0, 0,
1, 0, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1);
else if( parser.mUpDirection == ColladaParser::UP_Z)
pScene->mRootNode->mTransformation *= aiMatrix4x4(
1, 0, 0, 0,
0, 0, 1, 0,
0, -1, 0, 0,
0, 0, 0, 1);
// Convert to Y_UP, if different orientation
if( parser.mUpDirection == ColladaParser::UP_X) {
pScene->mRootNode->mTransformation *= aiMatrix4x4(
0, -1, 0, 0,
1, 0, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1);
} else if( parser.mUpDirection == ColladaParser::UP_Z) {
pScene->mRootNode->mTransformation *= aiMatrix4x4(
1, 0, 0, 0,
0, 0, 1, 0,
0, -1, 0, 0,
0, 0, 0, 1);
}
}
// Store scene metadata
@ -212,8 +211,7 @@ void ColladaLoader::InternReadFile( const std::string& pFile, aiScene* pScene, I
const size_t numMeta(parser.mAssetMetaData.size());
pScene->mMetaData = aiMetadata::Alloc(static_cast<unsigned int>(numMeta));
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);
}
}
@ -233,9 +231,8 @@ void ColladaLoader::InternReadFile( const std::string& pFile, aiScene* pScene, I
// store all animations
StoreAnimations( pScene, parser);
// If no meshes have been loaded, it's probably just an animated skeleton.
if (!pScene->mNumMeshes) {
if ( 0u == pScene->mNumMeshes) {
if (!noSkeletonMesh) {
SkeletonMeshBuilder hero(pScene);
@ -246,8 +243,7 @@ void ColladaLoader::InternReadFile( const std::string& pFile, aiScene* pScene, I
// ------------------------------------------------------------------------------------------------
// Recursively constructs a scene node for the given parser node and returns it.
aiNode* ColladaLoader::BuildHierarchy( const ColladaParser& pParser, const Collada::Node* pNode)
{
aiNode* ColladaLoader::BuildHierarchy( const ColladaParser& pParser, const Collada::Node* pNode) {
// create a node for it
aiNode* node = new aiNode();
@ -265,15 +261,13 @@ aiNode* ColladaLoader::BuildHierarchy( const ColladaParser& pParser, const Colla
node->mNumChildren = static_cast<unsigned int>(pNode->mChildren.size()+instances.size());
node->mChildren = new aiNode*[node->mNumChildren];
for( size_t a = 0; a < pNode->mChildren.size(); a++)
{
for( size_t a = 0; a < pNode->mChildren.size(); ++a) {
node->mChildren[a] = BuildHierarchy( pParser, pNode->mChildren[a]);
node->mChildren[a]->mParent = node;
}
// ... and finally the resolved node instances
for( size_t a = 0; a < instances.size(); a++)
{
for( size_t a = 0; a < instances.size(); ++a) {
node->mChildren[pNode->mChildren.size() + a] = BuildHierarchy( pParser, instances[a]);
node->mChildren[pNode->mChildren.size() + a]->mParent = node;
}
@ -286,20 +280,19 @@ aiNode* ColladaLoader::BuildHierarchy( const ColladaParser& pParser, const Colla
// construct lights
BuildLightsForNode(pParser, pNode, node);
return node;
}
// ------------------------------------------------------------------------------------------------
// Resolve node instances
void ColladaLoader::ResolveNodeInstances( const ColladaParser& pParser, const Collada::Node* pNode,
std::vector<const Collada::Node*>& resolved)
{
std::vector<const Collada::Node*>& resolved) {
// reserve enough storage
resolved.reserve(pNode->mNodeInstances.size());
// ... and iterate through all nodes to be instanced as children of pNode
for (const auto &nodeInst: pNode->mNodeInstances)
{
for (const auto &nodeInst: pNode->mNodeInstances) {
// find the corresponding node in the library
const ColladaParser::NodeLibrary::const_iterator itt = pParser.mNodeLibrary.find(nodeInst.mNode);
const Collada::Node* nd = itt == pParser.mNodeLibrary.end() ? NULL : (*itt).second;
@ -307,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
// 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.
if (!nd) {
if (nullptr == nd) {
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);
else {
} else {
// attach this node to the list of children
resolved.push_back(nd);
}
@ -323,12 +315,12 @@ void ColladaLoader::ResolveNodeInstances( const ColladaParser& pParser, const Co
// ------------------------------------------------------------------------------------------------
// Resolve UV channels
void ColladaLoader::ApplyVertexToEffectSemanticMapping(Collada::Sampler& sampler,
const Collada::SemanticMappingTable& table)
{
const Collada::SemanticMappingTable& table) {
std::map<std::string, Collada::InputSemanticMapEntry>::const_iterator it = table.mMap.find(sampler.mUVChannel);
if (it != table.mMap.end()) {
if (it->second.mType != Collada::IT_Texcoord)
if (it->second.mType != Collada::IT_Texcoord) {
ASSIMP_LOG_ERROR("Collada: Unexpected effect input mapping");
}
sampler.mUVId = it->second.mSet;
}
@ -336,14 +328,11 @@ void ColladaLoader::ApplyVertexToEffectSemanticMapping(Collada::Sampler& sampler
// ------------------------------------------------------------------------------------------------
// Builds lights for the given node and references them
void ColladaLoader::BuildLightsForNode( const ColladaParser& pParser, const Collada::Node* pNode, aiNode* pTarget)
{
for( const Collada::LightInstance& lid : pNode->mLights)
{
void ColladaLoader::BuildLightsForNode( const ColladaParser& pParser, const Collada::Node* pNode, aiNode* pTarget) {
for( const Collada::LightInstance& lid : pNode->mLights) {
// find the referred light
ColladaParser::LightLibrary::const_iterator srcLightIt = pParser.mLightLibrary.find( lid.mLight);
if( srcLightIt == pParser.mLightLibrary.end())
{
if( srcLightIt == pParser.mLightLibrary.end()) {
ASSIMP_LOG_WARN_F("Collada: Unable to find light for ID \"" , lid.mLight , "\". Skipping.");
continue;
}
@ -365,8 +354,7 @@ void ColladaLoader::BuildLightsForNode( const ColladaParser& pParser, const Coll
if (out->mType == aiLightSource_AMBIENT) {
out->mColorDiffuse = out->mColorSpecular = aiColor3D(0, 0, 0);
out->mColorAmbient = srcLight->mColor*srcLight->mIntensity;
}
else {
} else {
// collada doesn't differentiate between these color types
out->mColorDiffuse = out->mColorSpecular = srcLight->mColor*srcLight->mIntensity;
out->mColorAmbient = aiColor3D(0, 0, 0);
@ -374,27 +362,24 @@ void ColladaLoader::BuildLightsForNode( const ColladaParser& pParser, const Coll
// convert falloff angle and falloff exponent in our representation, if given
if (out->mType == aiLightSource_SPOT) {
out->mAngleInnerCone = AI_DEG_TO_RAD( srcLight->mFalloffAngle );
// ... some extension magic.
if (srcLight->mOuterAngle >= ASSIMP_COLLADA_LIGHT_ANGLE_NOT_SET*(1-1e-6f))
{
if (srcLight->mOuterAngle >= ASSIMP_COLLADA_LIGHT_ANGLE_NOT_SET*(1-1e-6f)) {
// ... some deprecation magic.
if (srcLight->mPenumbraAngle >= ASSIMP_COLLADA_LIGHT_ANGLE_NOT_SET*(1-1e-6f))
{
if (srcLight->mPenumbraAngle >= ASSIMP_COLLADA_LIGHT_ANGLE_NOT_SET*(1-1e-6f)) {
// Need to rely on falloff_exponent. I don't know how to interpret it, so I need to guess ....
// epsilon chosen to be 0.1
out->mAngleOuterCone = std::acos(std::pow(0.1f,1.f/srcLight->mFalloffExponent))+
out->mAngleInnerCone;
}
else {
} else {
out->mAngleOuterCone = out->mAngleInnerCone + AI_DEG_TO_RAD( srcLight->mPenumbraAngle );
if (out->mAngleOuterCone < out->mAngleInnerCone)
std::swap(out->mAngleInnerCone,out->mAngleOuterCone);
}
} else {
out->mAngleOuterCone = AI_DEG_TO_RAD( srcLight->mOuterAngle );
}
else out->mAngleOuterCone = AI_DEG_TO_RAD( srcLight->mOuterAngle );
}
// add to light list
@ -404,14 +389,11 @@ void ColladaLoader::BuildLightsForNode( const ColladaParser& pParser, const Coll
// ------------------------------------------------------------------------------------------------
// Builds cameras for the given node and references them
void ColladaLoader::BuildCamerasForNode( const ColladaParser& pParser, const Collada::Node* pNode, aiNode* pTarget)
{
for( const Collada::CameraInstance& cid : pNode->mCameras)
{
void ColladaLoader::BuildCamerasForNode( const ColladaParser& pParser, const Collada::Node* pNode, aiNode* pTarget) {
for( const Collada::CameraInstance& cid : pNode->mCameras) {
// find the referred light
ColladaParser::CameraLibrary::const_iterator srcCameraIt = pParser.mCameraLibrary.find( cid.mCamera);
if( srcCameraIt == pParser.mCameraLibrary.end())
{
if( srcCameraIt == pParser.mCameraLibrary.end()) {
ASSIMP_LOG_WARN_F("Collada: Unable to find camera for ID \"" , cid.mCamera , "\". Skipping.");
continue;
}
@ -435,8 +417,9 @@ void ColladaLoader::BuildCamerasForNode( const ColladaParser& pParser, const Col
// ... but for the rest some values are optional
// and we need to compute the others in any combination.
if (srcCamera->mAspect != 10e10f)
if (srcCamera->mAspect != 10e10f) {
out->mAspect = srcCamera->mAspect;
}
if (srcCamera->mHorFov != 10e10f) {
out->mHorizontalFOV = srcCamera->mHorFov;
@ -445,8 +428,7 @@ void ColladaLoader::BuildCamerasForNode( const ColladaParser& pParser, const Col
out->mAspect = std::tan(AI_DEG_TO_RAD(srcCamera->mHorFov)) /
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 *
std::tan(AI_DEG_TO_RAD(srcCamera->mVerFov) * 0.5f)));
}
@ -461,77 +443,69 @@ void ColladaLoader::BuildCamerasForNode( const ColladaParser& pParser, const Col
// ------------------------------------------------------------------------------------------------
// Builds meshes for the given node and references them
void ColladaLoader::BuildMeshesForNode( const ColladaParser& pParser, const Collada::Node* pNode, aiNode* pTarget)
{
void ColladaLoader::BuildMeshesForNode( const ColladaParser& pParser, const Collada::Node* pNode, aiNode* pTarget) {
// accumulated mesh references by this node
std::vector<size_t> newMeshRefs;
newMeshRefs.reserve(pNode->mMeshes.size());
// add a mesh for each subgroup in each collada mesh
for( const Collada::MeshInstance& mid : pNode->mMeshes)
{
const Collada::Mesh* srcMesh = NULL;
const Collada::Controller* srcController = NULL;
for( const Collada::MeshInstance& mid : pNode->mMeshes) {
const Collada::Mesh* srcMesh = nullptr;
const Collada::Controller* srcController = nullptr;
// find the referred mesh
ColladaParser::MeshLibrary::const_iterator srcMeshIt = pParser.mMeshLibrary.find( mid.mMeshOrController);
if( srcMeshIt == pParser.mMeshLibrary.end())
{
if( srcMeshIt == pParser.mMeshLibrary.end()) {
// if not found in the mesh-library, it might also be a controller referring to a mesh
ColladaParser::ControllerLibrary::const_iterator srcContrIt = pParser.mControllerLibrary.find( mid.mMeshOrController);
if( srcContrIt != pParser.mControllerLibrary.end())
{
if( srcContrIt != pParser.mControllerLibrary.end()) {
srcController = &srcContrIt->second;
srcMeshIt = pParser.mMeshLibrary.find( srcController->mMeshId);
if( srcMeshIt != pParser.mMeshLibrary.end())
if( srcMeshIt != pParser.mMeshLibrary.end()) {
srcMesh = srcMeshIt->second;
}
}
if( !srcMesh)
{
if( nullptr == srcMesh) {
ASSIMP_LOG_WARN_F( "Collada: Unable to find geometry for ID \"", mid.mMeshOrController, "\". Skipping." );
continue;
}
} else
{
} else {
// ID found in the mesh library -> direct reference to an unskinned mesh
srcMesh = srcMeshIt->second;
}
// build a mesh for each of its subgroups
size_t vertexStart = 0, faceStart = 0;
for( size_t sm = 0; sm < srcMesh->mSubMeshes.size(); ++sm)
{
for( size_t sm = 0; sm < srcMesh->mSubMeshes.size(); ++sm) {
const Collada::SubMesh& submesh = srcMesh->mSubMeshes[sm];
if( submesh.mNumFaces == 0)
if( submesh.mNumFaces == 0) {
continue;
}
// find material assigned to this submesh
std::string meshMaterial;
std::map<std::string, Collada::SemanticMappingTable >::const_iterator meshMatIt = mid.mMaterials.find( submesh.mMaterial);
const Collada::SemanticMappingTable* table = NULL;
if( meshMatIt != mid.mMaterials.end())
{
const Collada::SemanticMappingTable* table = nullptr;
if( meshMatIt != mid.mMaterials.end()) {
table = &meshMatIt->second;
meshMaterial = table->mMatName;
}
else
{
} else {
ASSIMP_LOG_WARN_F( "Collada: No material specified for subgroup <", submesh.mMaterial, "> in geometry <",
mid.mMeshOrController, ">." );
if( !mid.mMaterials.empty() )
if( !mid.mMaterials.empty() ) {
meshMaterial = mid.mMaterials.begin()->second.mMatName;
}
}
// OK ... here the *real* fun starts ... we have the vertex-input-to-effect-semantic-table
// given. The only mapping stuff which we do actually support is the UV channel.
std::map<std::string, size_t>::const_iterator matIt = mMaterialIndexByName.find( meshMaterial);
unsigned int matIdx;
if( matIt != mMaterialIndexByName.end())
unsigned int matIdx = 0;
if( matIt != mMaterialIndexByName.end()) {
matIdx = static_cast<unsigned int>(matIt->second);
else
matIdx = 0;
}
if (table && !table->mMap.empty() ) {
std::pair<Collada::Effect*, aiMaterial*>& mat = newMats[matIdx];
@ -553,9 +527,7 @@ void ColladaLoader::BuildMeshesForNode( const ColladaParser& pParser, const Coll
std::map<ColladaMeshIndex, size_t>::const_iterator dstMeshIt = mMeshIndexByID.find( index);
if( dstMeshIt != mMeshIndexByID.end()) {
newMeshRefs.push_back( dstMeshIt->second);
}
else
{
} else {
// else we have to add the mesh to the collection and store its newly assigned index at the node
aiMesh* dstMesh = CreateMesh( pParser, srcMesh, submesh, srcController, vertexStart, faceStart);
@ -567,22 +539,18 @@ void ColladaLoader::BuildMeshesForNode( const ColladaParser& pParser, const Coll
// assign the material index
dstMesh->mMaterialIndex = matIdx;
if(dstMesh->mName.length == 0)
{
if(dstMesh->mName.length == 0) {
dstMesh->mName = mid.mMeshOrController;
}
}
}
}
}
// now place all mesh references we gathered in the target node
pTarget->mNumMeshes = static_cast<unsigned int>(newMeshRefs.size());
if( newMeshRefs.size())
{
struct UIntTypeConverter
{
unsigned int operator()(const size_t& v) const
{
if( newMeshRefs.size()) {
struct UIntTypeConverter {
unsigned int operator()(const size_t& v) const {
return static_cast<unsigned int>(v);
}
};
@ -594,25 +562,27 @@ void ColladaLoader::BuildMeshesForNode( const ColladaParser& pParser, const Coll
// ------------------------------------------------------------------------------------------------
// Find mesh from either meshes or morph target meshes
aiMesh *ColladaLoader::findMesh(std::string meshid)
{
for (unsigned int i = 0; i < mMeshes.size(); i++)
if (std::string(mMeshes[i]->mName.data) == meshid)
aiMesh *ColladaLoader::findMesh(std::string meshid) {
for (unsigned int i = 0; i < mMeshes.size(); ++i ) {
if (std::string(mMeshes[i]->mName.data) == meshid) {
return mMeshes[i];
}
}
for (unsigned int i = 0; i < mTargetMeshes.size(); i++)
if (std::string(mTargetMeshes[i]->mName.data) == meshid)
for (unsigned int i = 0; i < mTargetMeshes.size(); ++i ) {
if (std::string(mTargetMeshes[i]->mName.data) == meshid) {
return mTargetMeshes[i];
return NULL;
}
}
return nullptr;
}
// ------------------------------------------------------------------------------------------------
// Creates a mesh for the given ColladaMesh face subset and returns the newly created mesh
aiMesh* ColladaLoader::CreateMesh( const ColladaParser& pParser, const Collada::Mesh* pSrcMesh, const Collada::SubMesh& pSubMesh,
const Collada::Controller* pSrcController, size_t pStartVertex, size_t pStartFace)
{
aiMesh* dstMesh = new aiMesh;
const Collada::Controller* pSrcController, size_t pStartVertex, size_t pStartFace) {
std::unique_ptr<aiMesh> dstMesh(new aiMesh);
dstMesh->mName = pSrcMesh->mName;
@ -629,24 +599,21 @@ aiMesh* ColladaLoader::CreateMesh( const ColladaParser& pParser, const Collada::
// normals, if given. HACK: (thom) Due to the glorious Collada spec we never
// know if we have the same number of normals as there are positions. So we
// also ignore any vertex attribute if it has a different count
if( pSrcMesh->mNormals.size() >= pStartVertex + numVertices)
{
if( pSrcMesh->mNormals.size() >= pStartVertex + numVertices) {
dstMesh->mNormals = new aiVector3D[numVertices];
std::copy( pSrcMesh->mNormals.begin() + pStartVertex, pSrcMesh->mNormals.begin() +
pStartVertex + numVertices, dstMesh->mNormals);
}
// tangents, if given.
if( pSrcMesh->mTangents.size() >= pStartVertex + numVertices)
{
if( pSrcMesh->mTangents.size() >= pStartVertex + numVertices) {
dstMesh->mTangents = new aiVector3D[numVertices];
std::copy( pSrcMesh->mTangents.begin() + pStartVertex, pSrcMesh->mTangents.begin() +
pStartVertex + numVertices, dstMesh->mTangents);
}
// bitangents, if given.
if( pSrcMesh->mBitangents.size() >= pStartVertex + numVertices)
{
if( pSrcMesh->mBitangents.size() >= pStartVertex + numVertices) {
dstMesh->mBitangents = new aiVector3D[numVertices];
std::copy( pSrcMesh->mBitangents.begin() + pStartVertex, pSrcMesh->mBitangents.begin() +
pStartVertex + numVertices, dstMesh->mBitangents);
@ -654,13 +621,12 @@ aiMesh* ColladaLoader::CreateMesh( const ColladaParser& pParser, const Collada::
// same for texturecoords, as many as we have
// empty slots are not allowed, need to pack and adjust UV indexes accordingly
for( size_t a = 0, real = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; a++)
{
if( pSrcMesh->mTexCoords[a].size() >= pStartVertex + numVertices)
{
for( size_t a = 0, real = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++a ) {
if( pSrcMesh->mTexCoords[a].size() >= pStartVertex + numVertices) {
dstMesh->mTextureCoords[real] = new aiVector3D[numVertices];
for( size_t b = 0; b < numVertices; ++b)
for( size_t b = 0; b < numVertices; ++b) {
dstMesh->mTextureCoords[real][b] = pSrcMesh->mTexCoords[a][pStartVertex+b];
}
dstMesh->mNumUVComponents[real] = pSrcMesh->mNumUVComponents[a];
++real;
@ -668,10 +634,8 @@ aiMesh* ColladaLoader::CreateMesh( const ColladaParser& pParser, const Collada::
}
// same for vertex colors, as many as we have. again the same packing to avoid empty slots
for( size_t a = 0, real = 0; a < AI_MAX_NUMBER_OF_COLOR_SETS; a++)
{
if( pSrcMesh->mColors[a].size() >= pStartVertex + numVertices)
{
for( size_t a = 0, real = 0; a < AI_MAX_NUMBER_OF_COLOR_SETS; ++a ) {
if( pSrcMesh->mColors[a].size() >= pStartVertex + numVertices) {
dstMesh->mColors[real] = new aiColor4D[numVertices];
std::copy( pSrcMesh->mColors[a].begin() + pStartVertex, pSrcMesh->mColors[a].begin() + pStartVertex + numVertices,dstMesh->mColors[real]);
++real;
@ -682,14 +646,14 @@ aiMesh* ColladaLoader::CreateMesh( const ColladaParser& pParser, const Collada::
size_t vertex = 0;
dstMesh->mNumFaces = static_cast<unsigned int>(pSubMesh.mNumFaces);
dstMesh->mFaces = new aiFace[dstMesh->mNumFaces];
for( size_t a = 0; a < dstMesh->mNumFaces; ++a)
{
for( size_t a = 0; a < dstMesh->mNumFaces; ++a) {
size_t s = pSrcMesh->mFaceSize[ pStartFace + a];
aiFace& face = dstMesh->mFaces[a];
face.mNumIndices = static_cast<unsigned int>(s);
face.mIndices = new unsigned int[s];
for( size_t b = 0; b < s; ++b)
for( size_t b = 0; b < s; ++b) {
face.mIndices[b] = static_cast<unsigned int>(vertex++);
}
}
// create morph target meshes if any
@ -697,14 +661,12 @@ aiMesh* ColladaLoader::CreateMesh( const ColladaParser& pParser, const Collada::
std::vector<float> targetWeights;
Collada::MorphMethod method = Collada::Normalized;
for(std::map<std::string, Collada::Controller>::const_iterator it = pParser.mControllerLibrary.begin();
it != pParser.mControllerLibrary.end(); it++)
{
for(std::map<std::string, Collada::Controller>::const_iterator it = pParser.mControllerLibrary.begin();
it != pParser.mControllerLibrary.end(); it++) {
const Collada::Controller &c = it->second;
const Collada::Mesh* baseMesh = pParser.ResolveLibraryReference( pParser.mMeshLibrary, c.mMeshId);
if (c.mType == Collada::Morph && baseMesh->mName == pSrcMesh->mName)
{
if (c.mType == Collada::Morph && baseMesh->mName == pSrcMesh->mName) {
const Collada::Accessor& targetAccessor = pParser.ResolveLibraryReference( pParser.mAccessorLibrary, c.mMorphTarget);
const Collada::Accessor& weightAccessor = pParser.ResolveLibraryReference( pParser.mAccessorLibrary, c.mMorphWeight);
const Collada::Data& targetData = pParser.ResolveLibraryReference( pParser.mDataLibrary, targetAccessor.mSource);
@ -713,34 +675,34 @@ aiMesh* ColladaLoader::CreateMesh( const ColladaParser& pParser, const Collada::
// take method
method = c.mMethod;
if (!targetData.mIsStringArray)
if (!targetData.mIsStringArray) {
throw DeadlyImportError( "target data must contain id. ");
if (weightData.mIsStringArray)
}
if (weightData.mIsStringArray) {
throw DeadlyImportError( "target weight data must not be textual ");
}
for (unsigned int i = 0; i < targetData.mStrings.size(); ++i)
{
for (unsigned int i = 0; i < targetData.mStrings.size(); ++i) {
const Collada::Mesh* targetMesh = pParser.ResolveLibraryReference(pParser.mMeshLibrary, targetData.mStrings.at(i));
aiMesh *aimesh = findMesh(targetMesh->mName);
if (!aimesh)
{
if (targetMesh->mSubMeshes.size() > 1)
if (!aimesh) {
if (targetMesh->mSubMeshes.size() > 1) {
throw DeadlyImportError( "Morhing target mesh must be a single");
}
aimesh = CreateMesh(pParser, targetMesh, targetMesh->mSubMeshes.at(0), NULL, 0, 0);
mTargetMeshes.push_back(aimesh);
}
targetMeshes.push_back(aimesh);
}
for (unsigned int i = 0; i < weightData.mValues.size(); ++i)
for (unsigned int i = 0; i < weightData.mValues.size(); ++i) {
targetWeights.push_back(weightData.mValues.at(i));
}
}
}
if (targetMeshes.size() > 0 && targetWeights.size() == targetMeshes.size())
{
if (targetMeshes.size() > 0 && targetWeights.size() == targetMeshes.size()) {
std::vector<aiAnimMesh*> animMeshes;
for (unsigned int i = 0; i < targetMeshes.size(); i++)
{
for (unsigned int i = 0; i < targetMeshes.size(); ++i ) {
aiMesh* targetMesh = targetMeshes.at(i);
aiAnimMesh *animMesh = aiCreateAnimMesh(targetMesh);
float weight = targetWeights[i];
@ -753,13 +715,13 @@ aiMesh* ColladaLoader::CreateMesh( const ColladaParser& pParser, const Collada::
: aiMorphingMethod_MORPH_NORMALIZED;
dstMesh->mAnimMeshes = new aiAnimMesh*[animMeshes.size()];
dstMesh->mNumAnimMeshes = static_cast<unsigned int>(animMeshes.size());
for (unsigned int i = 0; i < animMeshes.size(); i++)
for (unsigned int i = 0; i < animMeshes.size(); ++i ) {
dstMesh->mAnimMeshes[i] = animMeshes.at(i);
}
}
// create bones if given
if( pSrcController && pSrcController->mType == Collada::Skin)
{
if( pSrcController && pSrcController->mType == Collada::Skin) {
// resolve references - joint names
const Collada::Accessor& jointNamesAcc = pParser.ResolveLibraryReference( pParser.mAccessorLibrary, pSrcController->mJointNameSource);
const Collada::Data& jointNames = pParser.ResolveLibraryReference( pParser.mDataLibrary, jointNamesAcc.mSource);
@ -790,15 +752,13 @@ aiMesh* ColladaLoader::CreateMesh( const ColladaParser& pParser, const Collada::
weightStartPerVertex.resize(pSrcController->mWeightCounts.size(),pSrcController->mWeights.end());
IndexPairVector::const_iterator pit = pSrcController->mWeights.begin();
for( size_t a = 0; a < pSrcController->mWeightCounts.size(); ++a)
{
for( size_t a = 0; a < pSrcController->mWeightCounts.size(); ++a) {
weightStartPerVertex[a] = pit;
pit += pSrcController->mWeightCounts[a];
}
// now for each vertex put the corresponding vertex weights into each bone's weight collection
for( size_t a = pStartVertex; a < pStartVertex + numVertices; ++a)
{
for( size_t a = pStartVertex; a < pStartVertex + numVertices; ++a) {
// which position index was responsible for this vertex? that's also the index by which
// the controller assigns the vertex weights
size_t orgIndex = pSrcMesh->mFacePosIndices[a];
@ -806,12 +766,13 @@ aiMesh* ColladaLoader::CreateMesh( const ColladaParser& pParser, const Collada::
IndexPairVector::const_iterator iit = weightStartPerVertex[orgIndex];
size_t pairCount = pSrcController->mWeightCounts[orgIndex];
for( size_t b = 0; b < pairCount; ++b, ++iit)
{
size_t jointIndex = iit->first;
size_t vertexIndex = iit->second;
ai_real weight = ReadFloat( weightsAcc, weights, vertexIndex, 0);
for( size_t b = 0; b < pairCount; ++b, ++iit) {
const size_t jointIndex = iit->first;
const size_t vertexIndex = iit->second;
ai_real weight = 1.0f;
if (!weights.mValues.empty()) {
weight = ReadFloat(weightsAcc, weights, vertexIndex, 0);
}
// one day I gonna kill that XSI Collada exporter
if( weight > 0.0f)
@ -826,19 +787,21 @@ aiMesh* ColladaLoader::CreateMesh( const ColladaParser& pParser, const Collada::
// count the number of bones which influence vertices of the current submesh
size_t numRemainingBones = 0;
for( std::vector<std::vector<aiVertexWeight> >::const_iterator it = dstBones.begin(); it != dstBones.end(); ++it)
if( it->size() > 0)
numRemainingBones++;
for( std::vector<std::vector<aiVertexWeight> >::const_iterator it = dstBones.begin(); it != dstBones.end(); ++it) {
if( it->size() > 0) {
++numRemainingBones;
}
}
// create bone array and copy bone weights one by one
dstMesh->mNumBones = static_cast<unsigned int>(numRemainingBones);
dstMesh->mBones = new aiBone*[numRemainingBones];
size_t boneCount = 0;
for( size_t a = 0; a < numBones; ++a)
{
for( size_t a = 0; a < numBones; ++a) {
// omit bones without weights
if( dstBones[a].size() == 0)
if( dstBones[a].empty() ) {
continue;
}
// create bone with its weights
aiBone* bone = new aiBone;
@ -884,108 +847,101 @@ 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
// find-by-name method to associate nodes with bones.
const Collada::Node* bnode = FindNode( pParser.mRootNode, bone->mName.data);
if( !bnode)
if( !bnode) {
bnode = FindNodeBySID( pParser.mRootNode, bone->mName.data);
}
// assign the name that we would have assigned for the source node
if( bnode)
if( bnode) {
bone->mName.Set( FindNameForNode( bnode));
else
} else {
ASSIMP_LOG_WARN_F( "ColladaLoader::CreateMesh(): could not find corresponding node for joint \"", bone->mName.data, "\"." );
}
// and insert bone
dstMesh->mBones[boneCount++] = bone;
}
}
return dstMesh;
return dstMesh.release();
}
// ------------------------------------------------------------------------------------------------
// 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());
if( mMeshes.size() > 0)
{
pScene->mMeshes = new aiMesh*[mMeshes.size()];
std::copy( mMeshes.begin(), mMeshes.end(), pScene->mMeshes);
mMeshes.clear();
if( mMeshes.empty() ) {
return;
}
pScene->mMeshes = new aiMesh*[mMeshes.size()];
std::copy( mMeshes.begin(), mMeshes.end(), pScene->mMeshes);
mMeshes.clear();
}
// ------------------------------------------------------------------------------------------------
// 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());
if( mCameras.size() > 0)
{
pScene->mCameras = new aiCamera*[mCameras.size()];
std::copy( mCameras.begin(), mCameras.end(), pScene->mCameras);
mCameras.clear();
if( mCameras.empty() ) {
return;
}
pScene->mCameras = new aiCamera*[mCameras.size()];
std::copy( mCameras.begin(), mCameras.end(), pScene->mCameras);
mCameras.clear();
}
// ------------------------------------------------------------------------------------------------
// 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());
if( mLights.size() > 0)
{
pScene->mLights = new aiLight*[mLights.size()];
std::copy( mLights.begin(), mLights.end(), pScene->mLights);
mLights.clear();
if( mLights.empty() ) {
return;
}
pScene->mLights = new aiLight*[mLights.size()];
std::copy( mLights.begin(), mLights.end(), pScene->mLights);
mLights.clear();
}
// ------------------------------------------------------------------------------------------------
// 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());
if( mTextures.size() > 0)
{
pScene->mTextures = new aiTexture*[mTextures.size()];
std::copy( mTextures.begin(), mTextures.end(), pScene->mTextures);
mTextures.clear();
if( mTextures.empty() ) {
return;
}
pScene->mTextures = new aiTexture*[mTextures.size()];
std::copy( mTextures.begin(), mTextures.end(), pScene->mTextures);
mTextures.clear();
}
// ------------------------------------------------------------------------------------------------
// 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());
if (newMats.size() > 0) {
pScene->mMaterials = new aiMaterial*[newMats.size()];
for (unsigned int i = 0; i < newMats.size();++i)
pScene->mMaterials[i] = newMats[i].second;
newMats.clear();
if (newMats.empty() ) {
return;
}
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
void ColladaLoader::StoreAnimations( aiScene* pScene, const ColladaParser& pParser)
{
void ColladaLoader::StoreAnimations( aiScene* pScene, const ColladaParser& pParser) {
// recursively collect all animations from the collada scene
StoreAnimations( pScene, pParser, &pParser.mAnims, "");
// 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
for( size_t a = 0; a < mAnims.size(); ++a)
{
for( size_t a = 0; a < mAnims.size(); ++a) {
aiAnimation* templateAnim = mAnims[a];
if( templateAnim->mNumChannels == 1)
{
if( templateAnim->mNumChannels == 1) {
// search for other single-channel-anims with the same duration
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];
if( other->mNumChannels == 1 && other->mDuration == templateAnim->mDuration &&
other->mTicksPerSecond == templateAnim->mTicksPerSecond )
@ -1916,19 +1872,23 @@ const Collada::Node* ColladaLoader::FindNode( const Collada::Node* pNode, const
// ------------------------------------------------------------------------------------------------
// 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
{
if( pNode->mSID == pSID)
return pNode;
const Collada::Node* ColladaLoader::FindNodeBySID( const Collada::Node* pNode, const std::string& pSID) const {
if (nullptr == pNode) {
return nullptr;
}
for( size_t a = 0; a < pNode->mChildren.size(); ++a)
{
const Collada::Node* node = FindNodeBySID( pNode->mChildren[a], pSID);
if( node)
return node;
}
if (pNode->mSID == pSID) {
return pNode;
}
return NULL;
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;
}
// ------------------------------------------------------------------------------------------------
@ -1962,4 +1922,6 @@ std::string ColladaLoader::FindNameForNode( const Collada::Node* pNode)
}
}
} // Namespace Assimp
#endif // !! ASSIMP_BUILD_NO_DAE_IMPORTER

View File

@ -47,10 +47,6 @@ namespace Assimp {
aiAnimMesh *aiCreateAnimMesh(const aiMesh *mesh)
{
aiAnimMesh *animesh = new aiAnimMesh;
animesh->mVertices = NULL;
animesh->mNormals = NULL;
animesh->mTangents = NULL;
animesh->mBitangents = NULL;
animesh->mNumVertices = mesh->mNumVertices;
if (mesh->mVertices) {
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 ExportSceneFBXA(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
@ -179,7 +180,11 @@ Exporter::ExportFormatEntry gExporters[] =
#endif
#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
};

View File

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

View File

@ -420,11 +420,6 @@ namespace Assimp {
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->mLookAt = aiVector3D(1.0f, 0.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) {
return true;
}
}
else if (ok) {
} else if (ok) {
if (v.SquareLength() > zero_epsilon) {
return true;
}
@ -1253,10 +1247,10 @@ namespace Assimp {
ai_assert(count_faces);
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::map<unsigned int, unsigned int> translateIndexMap;
if (process_weights) {
if (process_weights || mesh.GetBlendShapes().size() > 0) {
reverseMapping.resize(count_vertices);
}
@ -1413,8 +1407,10 @@ namespace Assimp {
unsigned int count = 0;
const unsigned int* outIndices = mesh.ToOutputVertexIndex(index, count);
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;
if (animMesh->mNormals != nullptr) {
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);
}
@ -1733,9 +1738,8 @@ namespace Assimp {
}
void FBXConverter::TrySetTextureProperties(aiMaterial* out_mat, const TextureMap& textures,
const std::string& propName,
aiTextureType target, const MeshGeometry* const mesh)
{
const std::string& propName,
aiTextureType target, const MeshGeometry* const mesh) {
TextureMap::const_iterator it = textures.find(propName);
if (it == textures.end()) {
return;

View File

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

View File

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

View File

@ -1850,7 +1850,10 @@ void FBXExporter::WriteObjects ()
// this should be the same as the bone's mOffsetMatrix.
// 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;
if (b && ! tr.Equal(b->mOffsetMatrix, epsilon)) {
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
void ParseVectorDataArray(std::vector<unsigned int>& out, const Element& el)
@ -1280,7 +1279,6 @@ float ParseTokenAsFloat(const Token& t)
return i;
}
// ------------------------------------------------------------------------------------------------
// wrapper around ParseTokenAsInt() with ParseError handling
int ParseTokenAsInt(const Token& t)
@ -1293,8 +1291,6 @@ int ParseTokenAsInt(const Token& t)
return i;
}
// ------------------------------------------------------------------------------------------------
// wrapper around ParseTokenAsInt64() with ParseError handling
int64_t ParseTokenAsInt64(const Token& t)

View File

@ -118,7 +118,7 @@ void ObjFileParser::parseFile( IOStreamBuffer<char> &streamBuffer ) {
size_t lastFilePos( 0 );
std::vector<char> buffer;
while ( streamBuffer.getNextDataLine( buffer, '\0' ) ) {
while ( streamBuffer.getNextDataLine( buffer, '\\' ) ) {
m_DataIt = buffer.begin();
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.Y = (int32_t)v.y;
n.Z = (int32_t)v.z;
out = t;
::memcpy( &out, &t, sizeof(int32_t));
//out = t;
}
// UNREAL vertex decompression

View File

@ -5,8 +5,6 @@ Open Asset Import Library (assimp)
Copyright (c) 2006-2019, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,
@ -60,7 +58,7 @@ extern "C" {
*
* Cameras have a representation in the node graph and can be animated.
* An important aspect is that the camera itself is also part of the
* scenegraph. This means, any values such as the look-at vector are not
* scene-graph. This means, any values such as the look-at vector are not
* *absolute*, they're <b>relative</b> to the coordinate system defined
* by the node which corresponds to the camera. This allows for camera
* animations. For static cameras parameters like the 'look-at' or 'up' vectors

View File

@ -142,7 +142,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/** @brief Specifies the maximum angle that may be between two vertex tangents
* that their tangents and bi-tangents are smoothed.
*
* This applies to the CalcTangentSpace-Step. The angle is specified
* This applies to the CalcTangentSpace-Step. TFvhe angle is specified
* in degrees. The maximum value is 175.
* Property type: float. Default value: 45 degrees
*/
@ -981,8 +981,12 @@ enum aiComponent
#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"

View File

@ -274,6 +274,8 @@ def hasattr_silent(object, name):
"""
try:
if not object:
return False
return hasattr(object, name)
except AttributeError:
return False

3
test/.gitignore vendored 100644
View File

@ -0,0 +1,3 @@
# Ignore Unit Test Output files
*_out.*

View File

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

Binary file not shown.

View File

@ -1,24 +0,0 @@
ply
format ascii 1.0
comment Created by Open Asset Import Library - http://assimp.sf.net (v4.1.649942190)
element vertex 8
property float x
property float y
property float z
element face 6
property list uchar int vertex_index
end_header
0 0 0
0 0 1
0 1 1
0 1 0
1 0 0
1 0 1
1 1 1
1 1 0
4 0 1 2 3
4 7 6 5 4
4 0 4 5 1
4 1 5 6 2
4 2 6 7 3
4 3 7 4 0

View File

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

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
All rights reserved.
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
All rights reserved.
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
All rights reserved.
Redistribution and use of this software in source and binary forms,
@ -53,20 +51,20 @@ using namespace Assimp;
class utAssbinImportExport : public AbstractImportExportBase {
public:
virtual bool importerTest() {
Assimp::Importer importer;
bool importerTest() override {
Importer importer;
const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/OBJ/spider.obj", aiProcess_ValidateDataStructure );
Exporter exporter;
EXPECT_EQ( aiReturn_SUCCESS, exporter.Export( scene, "assbin", ASSIMP_TEST_MODELS_DIR "/OBJ/spider_test.assbin" ) );
const aiScene *newScene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/OBJ/spider_test.assbin", aiProcess_ValidateDataStructure );
EXPECT_EQ( aiReturn_SUCCESS, exporter.Export( scene, "assbin", ASSIMP_TEST_MODELS_DIR "/OBJ/spider_out.assbin" ) );
const aiScene *newScene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/OBJ/spider_out.assbin", aiProcess_ValidateDataStructure );
return newScene != nullptr;
}
};
TEST_F( utAssbinImportExport, exportAssbin3DFromFileTest ) {
Assimp::Importer importer;
Importer importer;
const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/OBJ/spider.obj", aiProcess_ValidateDataStructure );
EXPECT_NE( nullptr, scene );
}

View File

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

View File

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

View File

@ -70,10 +70,10 @@ TEST_F( utFBXImporterExporter, importBareBoxWithoutColorsAndTextureCoords ) {
Assimp::Importer importer;
const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/FBX/box.fbx", aiProcess_ValidateDataStructure );
EXPECT_NE( nullptr, scene );
EXPECT_EQ(scene->mNumMeshes, 1);
EXPECT_EQ(scene->mNumMeshes, 1u);
aiMesh* mesh = scene->mMeshes[0];
EXPECT_EQ(mesh->mNumFaces, 12);
EXPECT_EQ(mesh->mNumVertices, 36);
EXPECT_EQ(mesh->mNumFaces, 12u);
EXPECT_EQ(mesh->mNumVertices, 36u);
}
TEST_F(utFBXImporterExporter, importCubesWithNoNames) {
@ -85,13 +85,13 @@ TEST_F(utFBXImporterExporter, importCubesWithNoNames) {
const auto root = scene->mRootNode;
ASSERT_STREQ(root->mName.C_Str(), "RootNode");
ASSERT_TRUE(root->mChildren);
ASSERT_EQ(root->mNumChildren, 2);
ASSERT_EQ(root->mNumChildren, 2u);
const auto child0 = root->mChildren[0];
ASSERT_TRUE(child0);
ASSERT_STREQ(child0->mName.C_Str(), "RootNode001");
ASSERT_TRUE(child0->mChildren);
ASSERT_EQ(child0->mNumChildren, 1);
ASSERT_EQ(child0->mNumChildren, 1u);
const auto child00 = child0->mChildren[0];
ASSERT_TRUE(child00);
@ -101,7 +101,7 @@ TEST_F(utFBXImporterExporter, importCubesWithNoNames) {
ASSERT_TRUE(child1);
ASSERT_STREQ(child1->mName.C_Str(), "RootNode002");
ASSERT_TRUE(child1->mChildren);
ASSERT_EQ(child1->mNumChildren, 1);
ASSERT_EQ(child1->mNumChildren, 1u);
const auto child10 = child1->mChildren[0];
ASSERT_TRUE(child10);
@ -117,13 +117,13 @@ TEST_F(utFBXImporterExporter, importCubesWithUnicodeDuplicatedNames) {
const auto root = scene->mRootNode;
ASSERT_STREQ(root->mName.C_Str(), "RootNode");
ASSERT_TRUE(root->mChildren);
ASSERT_EQ(root->mNumChildren, 2);
ASSERT_EQ(root->mNumChildren, 2u);
const auto child0 = root->mChildren[0];
ASSERT_TRUE(child0);
ASSERT_STREQ(child0->mName.C_Str(), "Cube2");
ASSERT_TRUE(child0->mChildren);
ASSERT_EQ(child0->mNumChildren, 1);
ASSERT_EQ(child0->mNumChildren, 1u);
const auto child00 = child0->mChildren[0];
ASSERT_TRUE(child00);
@ -133,7 +133,7 @@ TEST_F(utFBXImporterExporter, importCubesWithUnicodeDuplicatedNames) {
ASSERT_TRUE(child1);
ASSERT_STREQ(child1->mName.C_Str(), "Cube3");
ASSERT_TRUE(child1->mChildren);
ASSERT_EQ(child1->mNumChildren, 1);
ASSERT_EQ(child1->mNumChildren, 1u);
const auto child10 = child1->mChildren[0];
ASSERT_TRUE(child10);
@ -149,13 +149,13 @@ TEST_F(utFBXImporterExporter, importCubesComplexTransform) {
const auto root = scene->mRootNode;
ASSERT_STREQ(root->mName.C_Str(), "RootNode");
ASSERT_TRUE(root->mChildren);
ASSERT_EQ(root->mNumChildren, 2);
ASSERT_EQ(root->mNumChildren, 2u);
const auto child0 = root->mChildren[0];
ASSERT_TRUE(child0);
ASSERT_STREQ(child0->mName.C_Str(), "Cube2");
ASSERT_TRUE(child0->mChildren);
ASSERT_EQ(child0->mNumChildren, 1);
ASSERT_EQ(child0->mNumChildren, 1u);
const auto child00 = child0->mChildren[0];
ASSERT_TRUE(child00);
@ -177,35 +177,36 @@ TEST_F(utFBXImporterExporter, importCubesComplexTransform) {
"Cube1001_$AssimpFbx$_ScalingPivotInverse",
"Cube1001"
};
for (size_t i = 0; i < chain_length; ++i)
{
for (size_t i = 0; i < chain_length; ++i) {
ASSERT_TRUE(parent->mChildren);
ASSERT_EQ(parent->mNumChildren, 1);
ASSERT_EQ(parent->mNumChildren, 1u);
auto node = parent->mChildren[0];
ASSERT_TRUE(node);
ASSERT_STREQ(node->mName.C_Str(), chainStr[i]);
parent = node;
}
ASSERT_EQ(0, parent->mNumChildren) << "Leaf node";
ASSERT_EQ(0u, parent->mNumChildren) << "Leaf node";
}
TEST_F( utFBXImporterExporter, importPhongMaterial ) {
Assimp::Importer importer;
const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/FBX/phong_cube.fbx", aiProcess_ValidateDataStructure );
EXPECT_NE( nullptr, scene );
EXPECT_EQ( (unsigned int)1, scene->mNumMaterials );
EXPECT_EQ( 1u, scene->mNumMaterials );
const aiMaterial *mat = scene->mMaterials[0];
EXPECT_NE( nullptr, mat );
float f; aiColor3D c;
float f;
aiColor3D c;
// phong_cube.fbx has all properties defined
EXPECT_EQ( mat->Get(AI_MATKEY_COLOR_DIFFUSE, c), aiReturn_SUCCESS );
EXPECT_EQ( c, aiColor3D(0.5, 0.25, 0.25) );
EXPECT_EQ( mat->Get(AI_MATKEY_COLOR_SPECULAR, c), aiReturn_SUCCESS );
EXPECT_EQ( c, aiColor3D(0.25, 0.25, 0.5) );
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( f, 10.0 );
EXPECT_EQ( f, 10.0f );
EXPECT_EQ( mat->Get(AI_MATKEY_COLOR_AMBIENT, c), aiReturn_SUCCESS );
EXPECT_EQ( c, aiColor3D(0.125, 0.25, 0.25) );
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( c, aiColor3D(0.75, 0.5, 0.25) );
EXPECT_EQ( mat->Get(AI_MATKEY_OPACITY, f), aiReturn_SUCCESS );
EXPECT_EQ( f, 0.5 );
EXPECT_EQ( f, 0.5f );
}
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);
EXPECT_NE(nullptr, scene);
EXPECT_EQ(1, scene->mNumMaterials);
EXPECT_EQ(1u, scene->mNumMaterials);
aiMaterial *mat = scene->mMaterials[0];
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));
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_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);
EXPECT_NE(nullptr, scene);
EXPECT_EQ(1, scene->mNumMaterials);
EXPECT_EQ(1u, scene->mNumMaterials);
aiMaterial *mat = scene->mMaterials[0];
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_STREQ(path.C_Str(), "paper.png");
ASSERT_EQ(1, scene->mNumTextures);
ASSERT_EQ(1u, scene->mNumTextures);
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";
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -205,8 +205,8 @@ protected:
::Assimp::Exporter exporter;
const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/OBJ/spider.obj", aiProcess_ValidateDataStructure );
EXPECT_NE( nullptr, scene );
EXPECT_EQ( aiReturn_SUCCESS, exporter.Export( scene, "obj", ASSIMP_TEST_MODELS_DIR "/OBJ/spider_test.obj" ) );
EXPECT_EQ( aiReturn_SUCCESS, exporter.Export( scene, "objnomtl", ASSIMP_TEST_MODELS_DIR "/OBJ/spider_nomtl_test.obj" ) );
EXPECT_EQ( aiReturn_SUCCESS, exporter.Export( scene, "obj", ASSIMP_TEST_MODELS_DIR "/OBJ/spider_out.obj" ) );
EXPECT_EQ( aiReturn_SUCCESS, exporter.Export( scene, "objnomtl", ASSIMP_TEST_MODELS_DIR "/OBJ/spider_nomtl_out.obj" ) );
return true;
}
@ -263,7 +263,7 @@ TEST_F( utObjImportExport, issue809_vertex_color_Test ) {
#ifndef ASSIMP_BUILD_NO_EXPORT
::Assimp::Exporter exporter;
EXPECT_EQ( aiReturn_SUCCESS, exporter.Export( scene, "obj", ASSIMP_TEST_MODELS_DIR "/OBJ/test.obj" ) );
EXPECT_EQ( aiReturn_SUCCESS, exporter.Export( scene, "obj", ASSIMP_TEST_MODELS_DIR "/OBJ/test_out.obj" ) );
#endif // ASSIMP_BUILD_NO_EXPORT
}
@ -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);
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

@ -71,7 +71,7 @@ public:
Exporter exporter;
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/PLY/cube.ply", aiProcess_ValidateDataStructure);
EXPECT_NE(nullptr, scene);
EXPECT_EQ(aiReturn_SUCCESS, exporter.Export(scene, "ply", ASSIMP_TEST_MODELS_DIR "/PLY/cube_test.ply"));
EXPECT_EQ(aiReturn_SUCCESS, exporter.Export(scene, "ply", ASSIMP_TEST_MODELS_DIR "/PLY/cube_out.ply"));
return true;
}

View File

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

View File

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

View File

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

View File

@ -5,8 +5,6 @@ Open Asset Import Library (assimp)
Copyright (c) 2006-2019, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,
@ -55,17 +53,23 @@ class utglTF2ImportExport : public AbstractImportExportBase {
public:
virtual bool importerTest() {
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 );
if ( !scene ) return false;
if (!scene) {
return false;
}
EXPECT_TRUE( scene->HasMaterials() );
if ( !scene->HasMaterials() ) return false;
if (!scene->HasMaterials()) {
return false;
}
const aiMaterial *material = scene->mMaterials[0];
aiString path;
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_EQ( modes[0], aiTextureMapMode_Mirror );
EXPECT_EQ( modes[1], aiTextureMapMode_Clamp );
@ -75,7 +79,8 @@ public:
virtual bool binaryImporterTest() {
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;
}
@ -83,7 +88,8 @@ public:
virtual bool exporterTest() {
Assimp::Importer importer;
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_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) {
Assimp::Importer importer;
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_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) {
Assimp::Importer importer;
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_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
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_EQ(scene->mMeshes[0]->mNumVertices, 1024);
for (unsigned int i = 0; i < scene->mMeshes[0]->mNumFaces; ++i)
{
EXPECT_EQ(scene->mMeshes[0]->mFaces[i].mNumIndices, 1);
EXPECT_EQ(scene->mMeshes[0]->mNumVertices, 1024u);
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].mIndices[0], i);
}
}
@ -137,12 +144,11 @@ TEST_F(utglTF2ImportExport, importglTF2PrimitiveModeLinesWithoutIndices) {
//Lines without indices
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_EQ(scene->mMeshes[0]->mNumVertices, 8);
for (unsigned int i = 0; i < scene->mMeshes[0]->mNumFaces; ++i)
{
EXPECT_EQ(scene->mMeshes[0]->mFaces[i].mNumIndices, 2);
EXPECT_EQ(scene->mMeshes[0]->mFaces[i].mIndices[0], i*2);
EXPECT_EQ(scene->mMeshes[0]->mFaces[i].mIndices[1], i*2 + 1);
EXPECT_EQ(scene->mMeshes[0]->mNumVertices, 8u);
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].mIndices[0], i*2u);
EXPECT_EQ(scene->mMeshes[0]->mFaces[i].mIndices[1], i*2u + 1u);
}
}
@ -151,15 +157,14 @@ TEST_F(utglTF2ImportExport, importglTF2PrimitiveModeLinesLoopWithoutIndices) {
//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);
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 }};
EXPECT_EQ(scene->mMeshes[0]->mFaces[0].mNumIndices, 2);
for (unsigned int i = 0; i < scene->mMeshes[0]->mNumFaces; ++i)
{
EXPECT_EQ(scene->mMeshes[0]->mFaces[i].mNumIndices, 2);
std::array<unsigned int, 5> l1 = {{ 0u, 1u, 2u, 3u, 0u }};
EXPECT_EQ(scene->mMeshes[0]->mFaces[0].mNumIndices, 2u);
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].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
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_EQ(scene->mMeshes[0]->mNumVertices, 5);
EXPECT_EQ(scene->mMeshes[0]->mNumVertices, 5u);
EXPECT_EQ(scene->mMeshes[0]->mFaces[0].mNumIndices, 2);
for (unsigned int i = 0; i < scene->mMeshes[0]->mNumFaces; ++i)
{
EXPECT_EQ(scene->mMeshes[0]->mFaces[i].mNumIndices, 2);
EXPECT_EQ(scene->mMeshes[0]->mFaces[0].mNumIndices, 2u);
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].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
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_EQ(scene->mMeshes[0]->mNumFaces, 2);
EXPECT_EQ(scene->mMeshes[0]->mNumVertices, 4);
std::array<int, 3> f1 = {{ 0, 1, 2 }};
EXPECT_EQ(scene->mMeshes[0]->mFaces[0].mNumIndices, 3);
for (int i = 0; i < 3; ++i)
{
EXPECT_EQ(scene->mMeshes[0]->mNumFaces, 2u);
EXPECT_EQ(scene->mMeshes[0]->mNumVertices, 4u);
std::array<unsigned int, 3> f1 = {{ 0u, 1u, 2u }};
EXPECT_EQ(scene->mMeshes[0]->mFaces[0].mNumIndices, 3u);
for (unsigned int i = 0; i < 3; ++i) {
EXPECT_EQ(scene->mMeshes[0]->mFaces[0].mIndices[i], f1[i]);
}
std::array<int, 3> f2 = {{ 2, 1, 3 }};
EXPECT_EQ(scene->mMeshes[0]->mFaces[1].mNumIndices, 3);
for (int i = 0; i < 3; ++i)
{
std::array<unsigned int, 3> f2 = {{ 2u, 1u, 3u }};
EXPECT_EQ(scene->mMeshes[0]->mFaces[1].mNumIndices, 3u);
for (size_t i = 0; i < 3; ++i) {
EXPECT_EQ(scene->mMeshes[0]->mFaces[1].mIndices[i], f2[i]);
}
}
@ -206,19 +208,17 @@ TEST_F(utglTF2ImportExport, importglTF2PrimitiveModeTrianglesFanWithoutIndices)
//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);
EXPECT_NE(nullptr, scene);
EXPECT_EQ(scene->mMeshes[0]->mNumFaces, 2);
EXPECT_EQ(scene->mMeshes[0]->mNumVertices, 4);
std::array<int, 3> f1 = {{ 0, 1, 2 }};
EXPECT_EQ(scene->mMeshes[0]->mFaces[0].mNumIndices, 3);
for (int i = 0; i < 3; ++i)
{
EXPECT_EQ(scene->mMeshes[0]->mNumFaces, 2u);
EXPECT_EQ(scene->mMeshes[0]->mNumVertices, 4u);
std::array<unsigned int, 3> f1 = {{ 0u, 1u, 2u }};
EXPECT_EQ(scene->mMeshes[0]->mFaces[0].mNumIndices, 3u);
for (size_t i = 0; i < 3; ++i) {
EXPECT_EQ(scene->mMeshes[0]->mFaces[0].mIndices[i], f1[i]);
}
std::array<int, 3> f2 = {{ 0, 2, 3 }};
EXPECT_EQ(scene->mMeshes[0]->mFaces[1].mNumIndices, 3);
for (int i = 0; i < 3; ++i)
{
std::array<unsigned int, 3> f2 = {{ 0u, 2u, 3u }};
EXPECT_EQ(scene->mMeshes[0]->mFaces[1].mNumIndices, 3u);
for (size_t i = 0; i < 3; ++i) {
EXPECT_EQ(scene->mMeshes[0]->mFaces[1].mIndices[i], f2[i]);
}
}
@ -228,19 +228,17 @@ TEST_F(utglTF2ImportExport, importglTF2PrimitiveModeTrianglesWithoutIndices) {
//Triangles without indices
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_EQ(scene->mMeshes[0]->mNumFaces, 2);
EXPECT_EQ(scene->mMeshes[0]->mNumVertices, 6);
std::array<int, 3> f1 = {{ 0, 1, 2 }};
EXPECT_EQ(scene->mMeshes[0]->mFaces[0].mNumIndices, 3);
for (int i = 0; i < 3; ++i)
{
EXPECT_EQ(scene->mMeshes[0]->mNumFaces, 2u);
EXPECT_EQ(scene->mMeshes[0]->mNumVertices, 6u);
std::array<unsigned int, 3> f1 = {{ 0u, 1u, 2u }};
EXPECT_EQ(scene->mMeshes[0]->mFaces[0].mNumIndices, 3u);
for (size_t i = 0; i < 3; ++i) {
EXPECT_EQ(scene->mMeshes[0]->mFaces[0].mIndices[i], f1[i]);
}
std::array<int, 3> f2 = {{ 3, 4, 5 }};
EXPECT_EQ(scene->mMeshes[0]->mFaces[1].mNumIndices, 3);
for (int i = 0; i < 3; ++i)
{
std::array<unsigned int, 3> f2 = {{ 3u, 4u, 5u }};
EXPECT_EQ(scene->mMeshes[0]->mFaces[1].mNumIndices, 3u);
for (size_t i = 0; i < 3; ++i) {
EXPECT_EQ(scene->mMeshes[0]->mFaces[1].mIndices[i], f2[i]);
}
}
@ -250,10 +248,9 @@ TEST_F(utglTF2ImportExport, importglTF2PrimitiveModePoints) {
//Line loop
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_EQ(scene->mMeshes[0]->mNumVertices, 1024);
for (unsigned int i = 0; i < scene->mMeshes[0]->mNumFaces; ++i)
{
EXPECT_EQ(scene->mMeshes[0]->mFaces[i].mNumIndices, 1);
EXPECT_EQ(scene->mMeshes[0]->mNumVertices, 1024u);
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].mIndices[0], i);
}
}
@ -263,9 +260,9 @@ TEST_F(utglTF2ImportExport, importglTF2PrimitiveModeLines) {
//Lines
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_EQ(scene->mMeshes[0]->mNumVertices, 4);
std::array<int, 5> l1 = {{ 0, 3, 2, 1, 0 }};
EXPECT_EQ(scene->mMeshes[0]->mFaces[0].mNumIndices, 2);
EXPECT_EQ(scene->mMeshes[0]->mNumVertices, 4u);
std::array<unsigned int, 5> l1 = {{ 0u, 3u, 2u, 1u, 0u }};
EXPECT_EQ(scene->mMeshes[0]->mFaces[0].mNumIndices, 2u);
for (unsigned int i = 0; i < scene->mMeshes[0]->mNumFaces; ++i)
{
EXPECT_EQ(scene->mMeshes[0]->mFaces[i].mIndices[0], l1[i]);
@ -278,9 +275,9 @@ TEST_F(utglTF2ImportExport, importglTF2PrimitiveModeLineLoop) {
//Line loop
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_EQ(scene->mMeshes[0]->mNumVertices, 4);
std::array<int, 5> l1 = {{ 0, 3, 2, 1, 0 }};
EXPECT_EQ(scene->mMeshes[0]->mFaces[0].mNumIndices, 2);
EXPECT_EQ(scene->mMeshes[0]->mNumVertices, 4u);
std::array<unsigned int, 5> l1 = {{ 0, 3u, 2u, 1u, 0u }};
EXPECT_EQ(scene->mMeshes[0]->mFaces[0].mNumIndices, 2u);
for (unsigned int i = 0; i < scene->mMeshes[0]->mNumFaces; ++i)
{
EXPECT_EQ(scene->mMeshes[0]->mFaces[i].mIndices[0], l1[i]);
@ -293,11 +290,10 @@ TEST_F(utglTF2ImportExport, importglTF2PrimitiveModeLineStrip) {
//Lines Strip
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_EQ(scene->mMeshes[0]->mNumVertices, 4);
std::array<int, 5> l1 = {{ 0, 3, 2, 1, 0 }};
EXPECT_EQ(scene->mMeshes[0]->mFaces[0].mNumIndices, 2);
for (unsigned int i = 0; i < scene->mMeshes[0]->mNumFaces; ++i)
{
EXPECT_EQ(scene->mMeshes[0]->mNumVertices, 4u);
std::array<unsigned int, 5> l1 = {{ 0u, 3u, 2u, 1u, 0u }};
EXPECT_EQ(scene->mMeshes[0]->mFaces[0].mNumIndices, 2u);
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[1], l1[i + 1]);
}
@ -308,19 +304,17 @@ TEST_F(utglTF2ImportExport, importglTF2PrimitiveModeTrianglesStrip) {
//Triangles strip
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_EQ(scene->mMeshes[0]->mNumFaces, 2);
EXPECT_EQ(scene->mMeshes[0]->mNumVertices, 4);
std::array<int, 3> f1 = {{ 0, 3, 1 }};
EXPECT_EQ(scene->mMeshes[0]->mFaces[0].mNumIndices, 3);
for (int i = 0; i < 3; ++i)
{
EXPECT_EQ(scene->mMeshes[0]->mNumFaces, 2u);
EXPECT_EQ(scene->mMeshes[0]->mNumVertices, 4u);
std::array<unsigned int, 3> f1 = {{ 0u, 3u, 1u }};
EXPECT_EQ(scene->mMeshes[0]->mFaces[0].mNumIndices, 3u);
for (size_t i = 0; i < 3; ++i) {
EXPECT_EQ(scene->mMeshes[0]->mFaces[0].mIndices[i], f1[i]);
}
std::array<int, 3> f2 = {{ 1, 3, 2 }};
EXPECT_EQ(scene->mMeshes[0]->mFaces[1].mNumIndices, 3);
for (int i = 0; i < 3; ++i)
{
std::array<unsigned int, 3> f2 = {{ 1u, 3u, 2u }};
EXPECT_EQ(scene->mMeshes[0]->mFaces[1].mNumIndices, 3u);
for (size_t i = 0; i < 3; ++i) {
EXPECT_EQ(scene->mMeshes[0]->mFaces[1].mIndices[i], f2[i]);
}
}
@ -330,19 +324,17 @@ TEST_F(utglTF2ImportExport, importglTF2PrimitiveModeTrianglesFan) {
//Triangles fan
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_EQ(scene->mMeshes[0]->mNumVertices, 4);
EXPECT_EQ(scene->mMeshes[0]->mNumFaces, 2);
std::array<int, 3> f1 = {{ 0, 3, 2 }};
EXPECT_EQ(scene->mMeshes[0]->mFaces[0].mNumIndices, 3);
for (int i = 0; i < 3; ++i)
{
EXPECT_EQ(scene->mMeshes[0]->mNumVertices, 4u);
EXPECT_EQ(scene->mMeshes[0]->mNumFaces, 2u);
std::array<unsigned int, 3> f1 = {{ 0u, 3u, 2u }};
EXPECT_EQ(scene->mMeshes[0]->mFaces[0].mNumIndices, 3u );
for (size_t i = 0; i < 3; ++i) {
EXPECT_EQ(scene->mMeshes[0]->mFaces[0].mIndices[i], f1[i]);
}
std::array<int, 3> f2 = {{ 0, 2, 1 }};
EXPECT_EQ(scene->mMeshes[0]->mFaces[1].mNumIndices, 3);
for (int i = 0; i < 3; ++i)
{
std::array<unsigned int, 3> f2 = {{ 0u, 2u, 1u }};
EXPECT_EQ(scene->mMeshes[0]->mFaces[1].mNumIndices, 3u );
for (size_t i = 0; i < 3; ++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 ) {
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 );
}