commit
4a2df57241
|
@ -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;
|
||||
}
|
||||
|
|
@ -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 */
|
|
@ -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
|
|
@ -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;
|
||||
}
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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
|
||||
};
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
@ -1414,7 +1408,6 @@ namespace Assimp {
|
|||
const unsigned int* outIndices = mesh.ToOutputVertexIndex(index, count);
|
||||
for (unsigned int k = 0; k < count; k++) {
|
||||
unsigned int index = translateIndexMap[outIndices[k]];
|
||||
|
||||
animMesh->mVertices[index] += vertex;
|
||||
if (animMesh->mNormals != nullptr) {
|
||||
animMesh->mNormals[index] += normal;
|
||||
|
@ -1733,9 +1726,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;
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -627,7 +627,7 @@ public:
|
|||
return content;
|
||||
}
|
||||
|
||||
uint32_t ContentLength() const {
|
||||
uint64_t ContentLength() const {
|
||||
return contentLength;
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
|
|
@ -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.
|
@ -1,6 +1,6 @@
|
|||
ply
|
||||
format ascii 1.0
|
||||
comment Created by Open Asset Import Library - http://assimp.sf.net (v4.1.649942190)
|
||||
comment Created by Open Asset Import Library - http://assimp.sf.net (v4.1.993695325)
|
||||
element vertex 8
|
||||
property float x
|
||||
property float y
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -5,8 +5,6 @@ Open Asset Import Library (assimp)
|
|||
|
||||
Copyright (c) 2006-2019, assimp team
|
||||
|
||||
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use of this software in source and binary forms,
|
||||
|
@ -53,8 +51,8 @@ using namespace Assimp;
|
|||
|
||||
class utAssbinImportExport : public AbstractImportExportBase {
|
||||
public:
|
||||
virtual bool importerTest() {
|
||||
Assimp::Importer importer;
|
||||
bool importerTest() override {
|
||||
Importer importer;
|
||||
const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/OBJ/spider.obj", aiProcess_ValidateDataStructure );
|
||||
|
||||
Exporter exporter;
|
||||
|
@ -66,7 +64,7 @@ public:
|
|||
};
|
||||
|
||||
TEST_F( utAssbinImportExport, exportAssbin3DFromFileTest ) {
|
||||
Assimp::Importer importer;
|
||||
Importer importer;
|
||||
const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/OBJ/spider.obj", aiProcess_ValidateDataStructure );
|
||||
EXPECT_NE( nullptr, scene );
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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]);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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];
|
||||
|
||||
|
|
|
@ -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,28 @@ void SortByPTypeProcessTest::SetUp()
|
|||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void SortByPTypeProcessTest::TearDown()
|
||||
{
|
||||
//delete process0;
|
||||
delete process1;
|
||||
delete scene;
|
||||
void SortByPTypeProcessTest::TearDown() {
|
||||
delete mProcess1;
|
||||
delete mScene;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
//TEST_F(SortByPTypeProcessTest, DeterminePTypeStep()
|
||||
//{
|
||||
// process0->Execute(scene);
|
||||
//
|
||||
// for (unsigned int i = 0; i < 10; ++i)
|
||||
// {
|
||||
// aiMesh* mesh = scene->mMeshes[i];
|
||||
// EXPECT_TRUE(mesh->mPrimitiveTypes == result[i]);
|
||||
// }
|
||||
//}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
TEST_F(SortByPTypeProcessTest, SortByPTypeStep)
|
||||
{
|
||||
// process0->Execute(scene);
|
||||
|
||||
// and another small test for ScenePreprocessor
|
||||
ScenePreprocessor s(scene);
|
||||
TEST_F(SortByPTypeProcessTest, SortByPTypeStep) {
|
||||
ScenePreprocessor s(mScene);
|
||||
s.ProcessScene();
|
||||
for (unsigned int m = 0; m< 10;++m)
|
||||
EXPECT_EQ(result[m], scene->mMeshes[m]->mPrimitiveTypes);
|
||||
EXPECT_EQ(result[m], mScene->mMeshes[m]->mPrimitiveTypes);
|
||||
|
||||
process1->Execute(scene);
|
||||
mProcess1->Execute(mScene);
|
||||
|
||||
unsigned int idx = 0;
|
||||
for (unsigned int m = 0,real = 0; m< 10;++m)
|
||||
{
|
||||
for (unsigned int n = 0; n < 4;++n)
|
||||
{
|
||||
for (unsigned int m = 0,real = 0; m< 10;++m) {
|
||||
for (unsigned int n = 0; n < 4;++n) {
|
||||
if ((idx = num[m][n]))
|
||||
{
|
||||
EXPECT_TRUE(real < scene->mNumMeshes);
|
||||
EXPECT_TRUE(real < mScene->mNumMeshes);
|
||||
|
||||
aiMesh* mesh = scene->mMeshes[real];
|
||||
aiMesh* mesh = mScene->mMeshes[real];
|
||||
|
||||
EXPECT_TRUE(NULL != mesh);
|
||||
EXPECT_EQ(AI_PRIMITIVE_TYPE_FOR_N_INDICES(n+1), mesh->mPrimitiveTypes);
|
||||
|
@ -218,8 +198,7 @@ TEST_F(SortByPTypeProcessTest, SortByPTypeStep)
|
|||
EXPECT_TRUE(NULL != mesh->mTextureCoords[0]);
|
||||
|
||||
EXPECT_TRUE(mesh->mNumFaces == idx);
|
||||
for (unsigned int f = 0; f < mesh->mNumFaces;++f)
|
||||
{
|
||||
for (unsigned int f = 0; f < mesh->mNumFaces;++f) {
|
||||
aiFace& face = mesh->mFaces[f];
|
||||
EXPECT_TRUE(face.mNumIndices == (n+1) || (3 == n && face.mNumIndices > 3));
|
||||
}
|
||||
|
@ -228,4 +207,3 @@ TEST_F(SortByPTypeProcessTest, SortByPTypeStep)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue