Merge branch 'master' into assimpviewer_dev

pull/1953/head
Kim Kulling 2018-05-13 10:41:16 +02:00 committed by GitHub
commit 1b71c2fd34
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
22 changed files with 308 additions and 215 deletions

1
.gitignore vendored
View File

@ -38,6 +38,7 @@ tools/assimp_cmd/Makefile
# Tests
test/results
test/readlinetest*
# Python
__pycache__

11
CONTRIBUTING.md 100644
View File

@ -0,0 +1,11 @@
#How to contribute
If you want to contribute you can follow these setps:
- Fist create your own clone of assimp
- When you want to fix a bug or add a new feature create a branch on your own fork ( just follow https://help.github.com/articles/creating-a-pull-request-from-a-fork/ )
- Push it to the repo and open a pull request
- A pull request will start our CI-service, which checks if the build works for linux and windows.
It will check for memory leaks, compiler warnings and memory alignment issues. If any of these tests fails: fix it and the tests will be reastarted automatically
- At the end we will perform a code review and merge your branch to the master branch.

View File

@ -208,8 +208,15 @@ OPTION(ASSIMP_BUILD_ALL_IMPORTERS_BY_DEFAULT "default value of all ASSIMP_BUILD_
# macro to add the CMake Option ADD_ASSIMP_IMPORTER_<name> which enables compile of loader
# this way selective loaders can be compiled (reduces filesize + compile time)
MACRO(ADD_ASSIMP_IMPORTER name)
OPTION(ASSIMP_BUILD_${name}_IMPORTER "build the ${name} importer" ${ASSIMP_BUILD_ALL_IMPORTERS_BY_DEFAULT})
IF(ASSIMP_BUILD_${name}_IMPORTER)
IF (ASSIMP_BUILD_ALL_IMPORTERS_BY_DEFAULT)
set(ASSIMP_IMPORTER_ENABLED TRUE)
IF (DEFINED ASSIMP_BUILD_${name}_IMPORTER AND NOT ASSIMP_BUILD_${name}_IMPORTER)
set(ASSIMP_IMPORTER_ENABLED FALSE)
ENDIF ()
ELSE ()
set(ASSIMP_IMPORTER_ENABLED ${ASSIMP_BUILD_${name}_IMPORTER})
ENDIF ()
IF (ASSIMP_IMPORTER_ENABLED)
LIST(APPEND ASSIMP_LOADER_SRCS ${ARGN})
SET(ASSIMP_IMPORTERS_ENABLED "${ASSIMP_IMPORTERS_ENABLED} ${name}")
SET(${name}_SRCS ${ARGN})

View File

@ -1819,9 +1819,12 @@ void ColladaLoader::ConvertPath (aiString& ss)
// Maxon Cinema Collada Export writes "file:///C:\andsoon" with three slashes...
// I need to filter it without destroying linux paths starting with "/somewhere"
if( ss.data[0] == '/' && isalpha( ss.data[1]) && ss.data[2] == ':' )
{
ss.length--;
#if defined( _MSC_VER )
if( ss.data[0] == '/' && isalpha( (unsigned char) ss.data[1]) && ss.data[2] == ':' ) {
#else
if (ss.data[ 0 ] == '/' && isalpha( ss.data[ 1 ] ) && ss.data[ 2 ] == ':') {
#endif
--ss.length;
::memmove( ss.data, ss.data+1, ss.length);
ss.data[ss.length] = 0;
}

View File

@ -115,10 +115,10 @@ public:
// import the metadata
if ( !mMetaData.empty() ) {
const size_t numMeta( mMetaData.size() );
scene->mMetaData = aiMetadata::Alloc( numMeta );
scene->mMetaData = aiMetadata::Alloc(static_cast<unsigned int>( numMeta ) );
for ( size_t i = 0; i < numMeta; ++i ) {
aiString val( mMetaData[ i ].value );
scene->mMetaData->Set( i, mMetaData[ i ].name, val );
scene->mMetaData->Set(static_cast<unsigned int>( i ), mMetaData[ i ].name, val );
}
}

View File

@ -127,7 +127,7 @@ bool DXFImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool
if ( extension.empty() || checkSig ) {
static const char *pTokens[] = { "SECTION", "HEADER", "ENDSEC", "BLOCKS" };
return BaseImporter::SearchFileHeaderForToken(pIOHandler, pFile, pTokens, 4 );
return BaseImporter::SearchFileHeaderForToken(pIOHandler, pFile, pTokens, 4, 32 );
}
return false;

View File

@ -76,11 +76,11 @@ bool DefaultIOSystem::Exists( const char* pFile) const
#ifdef _WIN32
wchar_t fileName16[PATHLIMIT];
bool isUnicode = IsTextUnicode(pFile, static_cast<int>(strlen(pFile)), NULL);
bool isUnicode = IsTextUnicode(pFile, static_cast<int>(strlen(pFile)), NULL) != 0;
if (isUnicode) {
MultiByteToWideChar(CP_UTF8, MB_PRECOMPOSED, pFile, -1, fileName16, PATHLIMIT);
struct _stat64 filestat;
struct __stat64 filestat;
if (0 != _wstat64(fileName16, &filestat)) {
return false;
}
@ -110,7 +110,7 @@ IOStream* DefaultIOSystem::Open( const char* strFile, const char* strMode)
FILE* file;
#ifdef _WIN32
wchar_t fileName16[PATHLIMIT];
bool isUnicode = IsTextUnicode(strFile, static_cast<int>(strlen(strFile)), NULL );
bool isUnicode = IsTextUnicode(strFile, static_cast<int>(strlen(strFile)), NULL) != 0;
if (isUnicode) {
MultiByteToWideChar(CP_UTF8, MB_PRECOMPOSED, strFile, -1, fileName16, PATHLIMIT);
std::string mode8(strMode);
@ -158,7 +158,7 @@ inline static void MakeAbsolutePath (const char* in, char* _out)
{
ai_assert(in && _out);
#if defined( _MSC_VER ) || defined( __MINGW32__ )
bool isUnicode = IsTextUnicode(in, static_cast<int>(strlen(in)), NULL);
bool isUnicode = IsTextUnicode(in, static_cast<int>(strlen(in)), NULL) != 0;
if (isUnicode) {
wchar_t out16[PATHLIMIT];
wchar_t in16[PATHLIMIT];

View File

@ -154,9 +154,9 @@ Exporter::ExportFormatEntry gExporters[] =
aiProcess_JoinIdenticalVertices | aiProcess_Triangulate | aiProcess_SortByPType ),
Exporter::ExportFormatEntry( "glb", "GL Transmission Format (binary)", "glb", &ExportSceneGLB,
aiProcess_JoinIdenticalVertices | aiProcess_Triangulate | aiProcess_SortByPType ),
Exporter::ExportFormatEntry( "gltf2", "GL Transmission Format v. 2", "gltf2", &ExportSceneGLTF2,
Exporter::ExportFormatEntry( "gltf2", "GL Transmission Format v. 2", "gltf", &ExportSceneGLTF2,
aiProcess_JoinIdenticalVertices | aiProcess_Triangulate | aiProcess_SortByPType ),
Exporter::ExportFormatEntry( "glb2", "GL Transmission Format v. 2 (binary)", "glb2", &ExportSceneGLB2,
Exporter::ExportFormatEntry( "glb2", "GL Transmission Format v. 2 (binary)", "glb", &ExportSceneGLB2,
aiProcess_JoinIdenticalVertices | aiProcess_Triangulate | aiProcess_SortByPType ),
#endif

View File

@ -448,8 +448,8 @@ void TokenizeBinary(TokenList& output_tokens, const char* input, unsigned int le
/*Result ignored*/ ReadByte(input, cursor, input + length);
const uint32_t version = ReadWord(input, cursor, input + length);
const bool is64bits = version >= 7500;
while (cursor < input + length)
{
const char *end = input + length;
while (cursor < end ) {
if (!ReadScope(output_tokens, input, cursor, input + length, is64bits)) {
break;
}

View File

@ -108,6 +108,125 @@ void JoinVerticesProcess::Execute( aiScene* pScene)
pScene->mFlags |= AI_SCENE_FLAGS_NON_VERBOSE_FORMAT;
}
namespace {
bool areVerticesEqual(const Vertex &lhs, const Vertex &rhs, bool complex)
{
// A little helper to find locally close vertices faster.
// Try to reuse the lookup table from the last step.
const static float epsilon = 1e-5f;
// Squared because we check against squared length of the vector difference
static const float squareEpsilon = epsilon * epsilon;
// Square compare is useful for animeshes vertexes compare
if ((lhs.position - rhs.position).SquareLength() > squareEpsilon) {
return false;
}
// We just test the other attributes even if they're not present in the mesh.
// In this case they're initialized to 0 so the comparison succeeds.
// By this method the non-present attributes are effectively ignored in the comparison.
if ((lhs.normal - rhs.normal).SquareLength() > squareEpsilon) {
return false;
}
if ((lhs.texcoords[0] - rhs.texcoords[0]).SquareLength() > squareEpsilon) {
return false;
}
if ((lhs.tangent - rhs.tangent).SquareLength() > squareEpsilon) {
return false;
}
if ((lhs.bitangent - rhs.bitangent).SquareLength() > squareEpsilon) {
return false;
}
// Usually we won't have vertex colors or multiple UVs, so we can skip from here
// Actually this increases runtime performance slightly, at least if branch
// prediction is on our side.
if (complex) {
for (int i = 0; i < 8; i++) {
if (i > 0 && (lhs.texcoords[i] - rhs.texcoords[i]).SquareLength() > squareEpsilon) {
return false;
}
if (GetColorDifference(lhs.colors[i], rhs.colors[i]) > squareEpsilon) {
return false;
}
}
}
return true;
}
template<class XMesh>
void updateXMeshVertices(XMesh *pMesh, std::vector<Vertex> &uniqueVertices) {
// replace vertex data with the unique data sets
pMesh->mNumVertices = (unsigned int)uniqueVertices.size();
// ----------------------------------------------------------------------------
// NOTE - we're *not* calling Vertex::SortBack() because it would check for
// presence of every single vertex component once PER VERTEX. And our CPU
// dislikes branches, even if they're easily predictable.
// ----------------------------------------------------------------------------
// Position, if present (check made for aiAnimMesh)
if (pMesh->mVertices)
{
delete [] pMesh->mVertices;
pMesh->mVertices = new aiVector3D[pMesh->mNumVertices];
for (unsigned int a = 0; a < pMesh->mNumVertices; a++) {
pMesh->mVertices[a] = uniqueVertices[a].position;
}
}
// Normals, if present
if (pMesh->mNormals)
{
delete [] pMesh->mNormals;
pMesh->mNormals = new aiVector3D[pMesh->mNumVertices];
for( unsigned int a = 0; a < pMesh->mNumVertices; a++) {
pMesh->mNormals[a] = uniqueVertices[a].normal;
}
}
// Tangents, if present
if (pMesh->mTangents)
{
delete [] pMesh->mTangents;
pMesh->mTangents = new aiVector3D[pMesh->mNumVertices];
for (unsigned int a = 0; a < pMesh->mNumVertices; a++) {
pMesh->mTangents[a] = uniqueVertices[a].tangent;
}
}
// Bitangents as well
if (pMesh->mBitangents)
{
delete [] pMesh->mBitangents;
pMesh->mBitangents = new aiVector3D[pMesh->mNumVertices];
for (unsigned int a = 0; a < pMesh->mNumVertices; a++) {
pMesh->mBitangents[a] = uniqueVertices[a].bitangent;
}
}
// Vertex colors
for (unsigned int a = 0; pMesh->HasVertexColors(a); a++)
{
delete [] pMesh->mColors[a];
pMesh->mColors[a] = new aiColor4D[pMesh->mNumVertices];
for( unsigned int b = 0; b < pMesh->mNumVertices; b++) {
pMesh->mColors[a][b] = uniqueVertices[b].colors[a];
}
}
// Texture coords
for (unsigned int a = 0; pMesh->HasTextureCoords(a); a++)
{
delete [] pMesh->mTextureCoords[a];
pMesh->mTextureCoords[a] = new aiVector3D[pMesh->mNumVertices];
for (unsigned int b = 0; b < pMesh->mNumVertices; b++) {
pMesh->mTextureCoords[a][b] = uniqueVertices[b].texcoords[a];
}
}
}
} // namespace
// ------------------------------------------------------------------------------------------------
// Unites identical vertices in the given mesh
int JoinVerticesProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex)
@ -132,9 +251,6 @@ int JoinVerticesProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex)
static_assert(AI_MAX_VERTICES == 0x7fffffff, "AI_MAX_VERTICES == 0x7fffffff");
std::vector<unsigned int> replaceIndex( pMesh->mNumVertices, 0xffffffff);
// A little helper to find locally close vertices faster.
// Try to reuse the lookup table from the last step.
const static float epsilon = 1e-5f;
// float posEpsilonSqr;
SpatialSort* vertexFinder = NULL;
SpatialSort _vertexFinder;
@ -156,9 +272,6 @@ int JoinVerticesProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex)
// posEpsilonSqr = ComputePositionEpsilon(pMesh);
}
// Squared because we check against squared length of the vector difference
static const float squareEpsilon = epsilon * epsilon;
// Again, better waste some bytes than a realloc ...
std::vector<unsigned int> verticesFound;
verticesFound.reserve(10);
@ -166,6 +279,16 @@ int JoinVerticesProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex)
// Run an optimized code path if we don't have multiple UVs or vertex colors.
// This should yield false in more than 99% of all imports ...
const bool complex = ( pMesh->GetNumColorChannels() > 0 || pMesh->GetNumUVChannels() > 1);
const bool hasAnimMeshes = pMesh->mNumAnimMeshes > 0;
// We'll never have more vertices afterwards.
std::vector<std::vector<Vertex>> uniqueAnimatedVertices;
if (hasAnimMeshes) {
uniqueAnimatedVertices.resize(pMesh->mNumAnimMeshes);
for (unsigned int animMeshIndex = 0; animMeshIndex < pMesh->mNumAnimMeshes; animMeshIndex++) {
uniqueAnimatedVertices[animMeshIndex].reserve(pMesh->mNumVertices);
}
}
// Now check each vertex if it brings something new to the table
for( unsigned int a = 0; a < pMesh->mNumVertices; a++) {
@ -178,74 +301,32 @@ int JoinVerticesProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex)
// check all unique vertices close to the position if this vertex is already present among them
for( unsigned int b = 0; b < verticesFound.size(); b++) {
const unsigned int vidx = verticesFound[b];
const unsigned int uidx = replaceIndex[ vidx];
if( uidx & 0x80000000)
continue;
const Vertex& uv = uniqueVertices[ uidx];
// Position mismatch is impossible - the vertex finder already discarded all non-matching positions
// We just test the other attributes even if they're not present in the mesh.
// In this case they're initialized to 0 so the comparison succeeds.
// By this method the non-present attributes are effectively ignored in the comparison.
if( (uv.normal - v.normal).SquareLength() > squareEpsilon)
continue;
if( (uv.texcoords[0] - v.texcoords[0]).SquareLength() > squareEpsilon)
continue;
if( (uv.tangent - v.tangent).SquareLength() > squareEpsilon)
continue;
if( (uv.bitangent - v.bitangent).SquareLength() > squareEpsilon)
if (!areVerticesEqual(v, uv, complex)) {
continue;
}
// Usually we won't have vertex colors or multiple UVs, so we can skip from here
// Actually this increases runtime performance slightly, at least if branch
// prediction is on our side.
if (complex){
// manually unrolled because continue wouldn't work as desired in an inner loop,
// also because some compilers seem to fail the task. Colors and UV coords
// are interleaved since the higher entries are most likely to be
// zero and thus useless. By interleaving the arrays, vertices are,
// on average, rejected earlier.
if( (uv.texcoords[1] - v.texcoords[1]).SquareLength() > squareEpsilon)
continue;
if( GetColorDifference( uv.colors[0], v.colors[0]) > squareEpsilon)
continue;
if( (uv.texcoords[2] - v.texcoords[2]).SquareLength() > squareEpsilon)
continue;
if( GetColorDifference( uv.colors[1], v.colors[1]) > squareEpsilon)
continue;
if( (uv.texcoords[3] - v.texcoords[3]).SquareLength() > squareEpsilon)
continue;
if( GetColorDifference( uv.colors[2], v.colors[2]) > squareEpsilon)
continue;
if( (uv.texcoords[4] - v.texcoords[4]).SquareLength() > squareEpsilon)
continue;
if( GetColorDifference( uv.colors[3], v.colors[3]) > squareEpsilon)
continue;
if( (uv.texcoords[5] - v.texcoords[5]).SquareLength() > squareEpsilon)
continue;
if( GetColorDifference( uv.colors[4], v.colors[4]) > squareEpsilon)
continue;
if( (uv.texcoords[6] - v.texcoords[6]).SquareLength() > squareEpsilon)
continue;
if( GetColorDifference( uv.colors[5], v.colors[5]) > squareEpsilon)
continue;
if( (uv.texcoords[7] - v.texcoords[7]).SquareLength() > squareEpsilon)
continue;
if( GetColorDifference( uv.colors[6], v.colors[6]) > squareEpsilon)
continue;
if( GetColorDifference( uv.colors[7], v.colors[7]) > squareEpsilon)
if (hasAnimMeshes) {
// If given vertex is animated, then it has to be preserver 1 to 1 (base mesh and animated mesh require same topology)
// NOTE: not doing this totaly breaks anim meshes as they don't have their own faces (they use pMesh->mFaces)
bool breaksAnimMesh = false;
for (unsigned int animMeshIndex = 0; animMeshIndex < pMesh->mNumAnimMeshes; animMeshIndex++) {
const Vertex& animatedUV = uniqueAnimatedVertices[animMeshIndex][ uidx];
Vertex aniMeshVertex(pMesh->mAnimMeshes[animMeshIndex], a);
if (!areVerticesEqual(aniMeshVertex, animatedUV, complex)) {
breaksAnimMesh = true;
break;
}
}
if (breaksAnimMesh) {
continue;
}
}
// we're still here -> this vertex perfectly matches our given vertex
@ -264,6 +345,12 @@ int JoinVerticesProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex)
// no unique vertex matches it up to now -> so add it
replaceIndex[a] = (unsigned int)uniqueVertices.size();
uniqueVertices.push_back( v);
if (hasAnimMeshes) {
for (unsigned int animMeshIndex = 0; animMeshIndex < pMesh->mNumAnimMeshes; animMeshIndex++) {
Vertex aniMeshVertex(pMesh->mAnimMeshes[animMeshIndex], a);
uniqueAnimatedVertices[animMeshIndex].push_back(aniMeshVertex);
}
}
}
}
@ -281,64 +368,10 @@ int JoinVerticesProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex)
);
}
// replace vertex data with the unique data sets
pMesh->mNumVertices = (unsigned int)uniqueVertices.size();
// ----------------------------------------------------------------------------
// NOTE - we're *not* calling Vertex::SortBack() because it would check for
// presence of every single vertex component once PER VERTEX. And our CPU
// dislikes branches, even if they're easily predictable.
// ----------------------------------------------------------------------------
// Position
delete [] pMesh->mVertices;
pMesh->mVertices = new aiVector3D[pMesh->mNumVertices];
for( unsigned int a = 0; a < pMesh->mNumVertices; a++)
pMesh->mVertices[a] = uniqueVertices[a].position;
// Normals, if present
if( pMesh->mNormals)
{
delete [] pMesh->mNormals;
pMesh->mNormals = new aiVector3D[pMesh->mNumVertices];
for( unsigned int a = 0; a < pMesh->mNumVertices; a++) {
pMesh->mNormals[a] = uniqueVertices[a].normal;
}
}
// Tangents, if present
if( pMesh->mTangents)
{
delete [] pMesh->mTangents;
pMesh->mTangents = new aiVector3D[pMesh->mNumVertices];
for( unsigned int a = 0; a < pMesh->mNumVertices; a++) {
pMesh->mTangents[a] = uniqueVertices[a].tangent;
}
}
// Bitangents as well
if( pMesh->mBitangents)
{
delete [] pMesh->mBitangents;
pMesh->mBitangents = new aiVector3D[pMesh->mNumVertices];
for( unsigned int a = 0; a < pMesh->mNumVertices; a++) {
pMesh->mBitangents[a] = uniqueVertices[a].bitangent;
}
}
// Vertex colors
for( unsigned int a = 0; pMesh->HasVertexColors(a); a++)
{
delete [] pMesh->mColors[a];
pMesh->mColors[a] = new aiColor4D[pMesh->mNumVertices];
for( unsigned int b = 0; b < pMesh->mNumVertices; b++) {
pMesh->mColors[a][b] = uniqueVertices[b].colors[a];
}
}
// Texture coords
for( unsigned int a = 0; pMesh->HasTextureCoords(a); a++)
{
delete [] pMesh->mTextureCoords[a];
pMesh->mTextureCoords[a] = new aiVector3D[pMesh->mNumVertices];
for( unsigned int b = 0; b < pMesh->mNumVertices; b++) {
pMesh->mTextureCoords[a][b] = uniqueVertices[b].texcoords[a];
updateXMeshVertices(pMesh, uniqueVertices);
if (hasAnimMeshes) {
for (unsigned int animMeshIndex = 0; animMeshIndex < pMesh->mNumAnimMeshes; animMeshIndex++) {
updateXMeshVertices(pMesh->mAnimMeshes[animMeshIndex], uniqueAnimatedVertices[animMeshIndex]);
}
}

View File

@ -138,28 +138,29 @@ glTF2Exporter::glTF2Exporter(const char* filename, IOSystem* pIOSystem, const ai
}
}
glTF2Exporter::~glTF2Exporter() {
// empty
}
/*
* Copy a 4x4 matrix from struct aiMatrix to typedef mat4.
* Also converts from row-major to column-major storage.
*/
static void CopyValue(const aiMatrix4x4& v, mat4& o)
{
static void CopyValue(const aiMatrix4x4& v, mat4& o) {
o[ 0] = v.a1; o[ 1] = v.b1; o[ 2] = v.c1; o[ 3] = v.d1;
o[ 4] = v.a2; o[ 5] = v.b2; o[ 6] = v.c2; o[ 7] = v.d2;
o[ 8] = v.a3; o[ 9] = v.b3; o[10] = v.c3; o[11] = v.d3;
o[12] = v.a4; o[13] = v.b4; o[14] = v.c4; o[15] = v.d4;
}
static void CopyValue(const aiMatrix4x4& v, aiMatrix4x4& o)
{
static void CopyValue(const aiMatrix4x4& v, aiMatrix4x4& o) {
o.a1 = v.a1; o.a2 = v.a2; o.a3 = v.a3; o.a4 = v.a4;
o.b1 = v.b1; o.b2 = v.b2; o.b3 = v.b3; o.b4 = v.b4;
o.c1 = v.c1; o.c2 = v.c2; o.c3 = v.c3; o.c4 = v.c4;
o.d1 = v.d1; o.d2 = v.d2; o.d3 = v.d3; o.d4 = v.d4;
}
static void IdentityMatrix4(mat4& o)
{
static void IdentityMatrix4(mat4& o) {
o[ 0] = 1; o[ 1] = 0; o[ 2] = 0; o[ 3] = 0;
o[ 4] = 0; o[ 5] = 1; o[ 6] = 0; o[ 7] = 0;
o[ 8] = 0; o[ 9] = 0; o[10] = 1; o[11] = 0;
@ -169,7 +170,9 @@ static void IdentityMatrix4(mat4& o)
inline Ref<Accessor> ExportData(Asset& a, std::string& meshName, Ref<Buffer>& buffer,
unsigned int count, void* data, AttribType::Value typeIn, AttribType::Value typeOut, ComponentType compType, bool isIndices = false)
{
if (!count || !data) return Ref<Accessor>();
if (!count || !data) {
return Ref<Accessor>();
}
unsigned int numCompsIn = AttribType::GetNumComponents(typeIn);
unsigned int numCompsOut = AttribType::GetNumComponents(typeOut);
@ -638,11 +641,11 @@ void ExportSkin(Asset& mAsset, const aiMesh* aimesh, Ref<Mesh>& meshRef, Ref<Buf
Mesh::Primitive& p = meshRef->primitives.back();
Ref<Accessor> vertexJointAccessor = ExportData(mAsset, skinRef->id, bufferRef, aimesh->mNumVertices, vertexJointData, AttribType::VEC4, AttribType::VEC4, ComponentType_FLOAT);
if ( vertexJointAccessor ) {
unsigned int offset = vertexJointAccessor->bufferView->byteOffset;
unsigned int bytesLen = vertexJointAccessor->bufferView->byteLength;
size_t offset = vertexJointAccessor->bufferView->byteOffset;
size_t bytesLen = vertexJointAccessor->bufferView->byteLength;
unsigned int s_bytesPerComp= ComponentTypeSize(ComponentType_UNSIGNED_SHORT);
unsigned int bytesPerComp = ComponentTypeSize(vertexJointAccessor->componentType);
unsigned int s_bytesLen = bytesLen * s_bytesPerComp / bytesPerComp;
size_t s_bytesLen = bytesLen * s_bytesPerComp / bytesPerComp;
Ref<Buffer> buf = vertexJointAccessor->bufferView->buffer;
uint8_t* arrys = new uint8_t[s_bytesLen];
unsigned int i = 0;
@ -728,8 +731,10 @@ void glTF2Exporter::ExportMeshes()
/******************** Normals ********************/
// Normalize all normals as the validator can emit a warning otherwise
for (auto i = 0u; i < aim->mNumVertices; ++i) {
aim->mNormals[i].Normalize();
if ( nullptr != aim->mNormals) {
for ( auto i = 0u; i < aim->mNumVertices; ++i ) {
aim->mNormals[ i ].Normalize();
}
}
Ref<Accessor> n = ExportData(*mAsset, meshId, b, aim->mNumVertices, aim->mNormals, AttribType::VEC3, AttribType::VEC3, ComponentType_FLOAT);
@ -891,6 +896,8 @@ unsigned int glTF2Exporter::ExportNodeHierarchy(const aiNode* n)
{
Ref<Node> node = mAsset->nodes.Create(mAsset->FindUniqueID(n->mName.C_Str(), "node"));
node->name = n->mName.C_Str();
if (!n->mTransformation.IsIdentity()) {
node->matrix.isPresent = true;
CopyValue(n->mTransformation, node->matrix.value);

View File

@ -87,28 +87,15 @@ namespace Assimp
// ------------------------------------------------------------------------------------------------
/** Helper class to export a given scene to an glTF file. */
// ------------------------------------------------------------------------------------------------
class glTF2Exporter
{
class glTF2Exporter {
public:
/// Constructor for a specific scene to export
glTF2Exporter(const char* filename, IOSystem* pIOSystem, const aiScene* pScene,
const ExportProperties* pProperties, bool binary);
~glTF2Exporter();
private:
const char* mFilename;
IOSystem* mIOSystem;
const aiScene* mScene;
const ExportProperties* mProperties;
std::map<std::string, unsigned int> mTexturesByPath;
std::shared_ptr<glTF2::Asset> mAsset;
std::vector<unsigned char> mBodyData;
protected:
void WriteBinaryData(IOStream* outfile, std::size_t sceneLength);
void GetTexSampler(const aiMaterial* mat, glTF2::Ref<glTF2::Texture> texture, aiTextureType tt, unsigned int slot);
void GetMatTexProp(const aiMaterial* mat, unsigned int& prop, const char* propName, aiTextureType tt, unsigned int idx);
void GetMatTexProp(const aiMaterial* mat, float& prop, const char* propName, aiTextureType tt, unsigned int idx);
@ -126,6 +113,15 @@ namespace Assimp
unsigned int ExportNode(const aiNode* node, glTF2::Ref<glTF2::Node>& parent);
void ExportScene();
void ExportAnimations();
private:
const char* mFilename;
IOSystem* mIOSystem;
const aiScene* mScene;
const ExportProperties* mProperties;
std::map<std::string, unsigned int> mTexturesByPath;
std::shared_ptr<glTF2::Asset> mAsset;
std::vector<unsigned char> mBodyData;
};
}

View File

@ -134,6 +134,30 @@ public:
}
}
// ----------------------------------------------------------------------------
/** Extract a particular vertex from a anim mesh and interleave all components */
explicit Vertex(const aiAnimMesh* msh, unsigned int idx) {
ai_assert(idx < msh->mNumVertices);
position = msh->mVertices[idx];
if (msh->HasNormals()) {
normal = msh->mNormals[idx];
}
if (msh->HasTangentsAndBitangents()) {
tangent = msh->mTangents[idx];
bitangent = msh->mBitangents[idx];
}
for (unsigned int i = 0; msh->HasTextureCoords(i); ++i) {
texcoords[i] = msh->mTextureCoords[i][idx];
}
for (unsigned int i = 0; msh->HasVertexColors(i); ++i) {
colors[i] = msh->mColors[i][idx];
}
}
public:
Vertex& operator += (const Vertex& v) {

View File

@ -149,7 +149,8 @@ struct aiMetadata {
mValues[ i ].mType = rhs.mValues[ i ].mType;
switch ( rhs.mValues[ i ].mType ) {
case AI_BOOL:
mValues[ i ].mData = new bool( rhs.mValues[i].mData );
mValues[ i ].mData = new bool;
::memcpy( mValues[ i ].mData, rhs.mValues[ i ].mData, sizeof(bool) );
break;
case AI_INT32: {
int32_t v;

View File

@ -89,4 +89,5 @@ TEST_F( utglTF2ImportExport, importBinaryglTF2FromFileTest ) {
TEST_F( utglTF2ImportExport, exportglTF2FromFileTest ) {
EXPECT_TRUE( exporterTest() );
}
#endif // ASSIMP_BUILD_NO_EXPORT

View File

@ -106,7 +106,8 @@ int Assimp_Export(const char* const* params, unsigned int num)
continue;
}
if (!strncmp( params[i], "-f",2)) {
outf = std::string(params[i]+2);
if ( strncmp( params[ i ], "-fi",3 ))
outf = std::string(params[i]+2);
}
else if ( !strncmp( params[i], "--format=",9)) {
outf = std::string(params[i]+9);

View File

@ -261,7 +261,6 @@ void PrintHorBar()
printf("-----------------------------------------------------------------\n");
}
// ------------------------------------------------------------------------------
// Import a specific file
const aiScene* ImportModel(
@ -390,105 +389,101 @@ int ProcessStandardArguments(
for (unsigned int i = 0; i < num;++i)
{
if (! strcmp(params[i], "-ptv") || ! strcmp(params[i], "--pretransform-vertices")) {
const char *param = params[ i ];
printf( "param = %s\n", param );
if (! strcmp( param, "-ptv") || ! strcmp( param, "--pretransform-vertices")) {
fill.ppFlags |= aiProcess_PreTransformVertices;
}
else if (! strcmp(params[i], "-gsn") || ! strcmp(params[i], "--gen-smooth-normals")) {
else if (! strcmp( param, "-gsn") || ! strcmp( param, "--gen-smooth-normals")) {
fill.ppFlags |= aiProcess_GenSmoothNormals;
}
else if (! strcmp(params[i], "-gn") || ! strcmp(params[i], "--gen-normals")) {
else if (! strcmp( param, "-gn") || ! strcmp( param, "--gen-normals")) {
fill.ppFlags |= aiProcess_GenNormals;
}
else if (! strcmp(params[i], "-jiv") || ! strcmp(params[i], "--join-identical-vertices")) {
else if (! strcmp( param, "-jiv") || ! strcmp( param, "--join-identical-vertices")) {
fill.ppFlags |= aiProcess_JoinIdenticalVertices;
}
else if (! strcmp(params[i], "-rrm") || ! strcmp(params[i], "--remove-redundant-materials")) {
else if (! strcmp( param, "-rrm") || ! strcmp( param, "--remove-redundant-materials")) {
fill.ppFlags |= aiProcess_RemoveRedundantMaterials;
}
else if (! strcmp(params[i], "-fd") || ! strcmp(params[i], "--find-degenerates")) {
else if (! strcmp( param, "-fd") || ! strcmp( param, "--find-degenerates")) {
fill.ppFlags |= aiProcess_FindDegenerates;
}
else if (! strcmp(params[i], "-slm") || ! strcmp(params[i], "--split-large-meshes")) {
else if (! strcmp( param, "-slm") || ! strcmp( param, "--split-large-meshes")) {
fill.ppFlags |= aiProcess_SplitLargeMeshes;
}
else if (! strcmp(params[i], "-lbw") || ! strcmp(params[i], "--limit-bone-weights")) {
else if (! strcmp( param, "-lbw") || ! strcmp( param, "--limit-bone-weights")) {
fill.ppFlags |= aiProcess_LimitBoneWeights;
}
else if (! strcmp(params[i], "-vds") || ! strcmp(params[i], "--validate-data-structure")) {
else if (! strcmp( param, "-vds") || ! strcmp( param, "--validate-data-structure")) {
fill.ppFlags |= aiProcess_ValidateDataStructure;
}
else if (! strcmp(params[i], "-icl") || ! strcmp(params[i], "--improve-cache-locality")) {
else if (! strcmp( param, "-icl") || ! strcmp( param, "--improve-cache-locality")) {
fill.ppFlags |= aiProcess_ImproveCacheLocality;
}
else if (! strcmp(params[i], "-sbpt") || ! strcmp(params[i], "--sort-by-ptype")) {
else if (! strcmp( param, "-sbpt") || ! strcmp( param, "--sort-by-ptype")) {
fill.ppFlags |= aiProcess_SortByPType;
}
else if (! strcmp(params[i], "-lh") || ! strcmp(params[i], "--left-handed")) {
else if (! strcmp( param, "-lh") || ! strcmp( param, "--left-handed")) {
fill.ppFlags |= aiProcess_ConvertToLeftHanded;
}
else if (! strcmp(params[i], "-fuv") || ! strcmp(params[i], "--flip-uv")) {
else if (! strcmp( param, "-fuv") || ! strcmp( param, "--flip-uv")) {
fill.ppFlags |= aiProcess_FlipUVs;
}
else if (! strcmp(params[i], "-fwo") || ! strcmp(params[i], "--flip-winding-order")) {
else if (! strcmp( param, "-fwo") || ! strcmp( param, "--flip-winding-order")) {
fill.ppFlags |= aiProcess_FlipWindingOrder;
}
else if (! strcmp(params[i], "-tuv") || ! strcmp(params[i], "--transform-uv-coords")) {
else if (! strcmp( param, "-tuv") || ! strcmp( param, "--transform-uv-coords")) {
fill.ppFlags |= aiProcess_TransformUVCoords;
}
else if (! strcmp(params[i], "-guv") || ! strcmp(params[i], "--gen-uvcoords")) {
else if (! strcmp( param, "-guv") || ! strcmp( param, "--gen-uvcoords")) {
fill.ppFlags |= aiProcess_GenUVCoords;
}
else if (! strcmp(params[i], "-fid") || ! strcmp(params[i], "--find-invalid-data")) {
else if (! strcmp( param, "-fid") || ! strcmp( param, "--find-invalid-data")) {
fill.ppFlags |= aiProcess_FindInvalidData;
}
else if (! strcmp(params[i], "-fixn") || ! strcmp(params[i], "--fix-normals")) {
else if (! strcmp( param, "-fixn") || ! strcmp( param, "--fix-normals")) {
fill.ppFlags |= aiProcess_FixInfacingNormals;
}
else if (! strcmp(params[i], "-tri") || ! strcmp(params[i], "--triangulate")) {
else if (! strcmp( param, "-tri") || ! strcmp( param, "--triangulate")) {
fill.ppFlags |= aiProcess_Triangulate;
}
else if (! strcmp(params[i], "-cts") || ! strcmp(params[i], "--calc-tangent-space")) {
else if (! strcmp( param, "-cts") || ! strcmp( param, "--calc-tangent-space")) {
fill.ppFlags |= aiProcess_CalcTangentSpace;
}
else if (! strcmp(params[i], "-fi") || ! strcmp(params[i], "--find-instances")) {
else if (! strcmp( param, "-fi") || ! strcmp( param, "--find-instances")) {
fill.ppFlags |= aiProcess_FindInstances;
}
else if (! strcmp(params[i], "-og") || ! strcmp(params[i], "--optimize-graph")) {
else if (! strcmp( param, "-og") || ! strcmp( param, "--optimize-graph")) {
fill.ppFlags |= aiProcess_OptimizeGraph;
}
else if (! strcmp(params[i], "-om") || ! strcmp(params[i], "--optimize-meshes")) {
else if (! strcmp( param, "-om") || ! strcmp( param, "--optimize-meshes")) {
fill.ppFlags |= aiProcess_OptimizeMeshes;
}
else if (! strcmp(params[i], "-db") || ! strcmp(params[i], "--debone")) {
else if (! strcmp( param, "-db") || ! strcmp( param, "--debone")) {
fill.ppFlags |= aiProcess_Debone;
}
else if (! strcmp(params[i], "-sbc") || ! strcmp(params[i], "--split-by-bone-count")) {
else if (! strcmp( param, "-sbc") || ! strcmp( param, "--split-by-bone-count")) {
fill.ppFlags |= aiProcess_SplitByBoneCount;
}
else if (! strncmp(params[i], "-c",2) || ! strncmp(params[i], "--config=",9)) {
else if (! strncmp( param, "-c",2) || ! strncmp( param, "--config=",9)) {
const unsigned int ofs = (params[i][1] == '-' ? 9 : 2);
// use default configurations
if (! strncmp(params[i]+ofs,"full",4)) {
fill.ppFlags |= aiProcessPreset_TargetRealtime_MaxQuality;
}
else if (! strncmp(params[i]+ofs,"default",7)) {
if (!strncmp( param + ofs, "full", 4 )) {
fill.ppFlags |= aiProcessPreset_TargetRealtime_MaxQuality;
} else if (!strncmp( param + ofs, "default", 7 )) {
fill.ppFlags |= aiProcessPreset_TargetRealtime_Quality;
}
else if (! strncmp(params[i]+ofs,"fast",4)) {
} else if (! strncmp( param +ofs,"fast",4)) {
fill.ppFlags |= aiProcessPreset_TargetRealtime_Fast;
}
}
else if (! strcmp(params[i], "-l") || ! strcmp(params[i], "--show-log")) {
} else if (! strcmp( param, "-l") || ! strcmp( param, "--show-log")) {
fill.showLog = true;
}
else if (! strcmp(params[i], "-v") || ! strcmp(params[i], "--verbose")) {
else if (! strcmp( param, "-v") || ! strcmp( param, "--verbose")) {
fill.verbose = true;
}
else if (! strncmp(params[i], "--log-out=",10) || ! strncmp(params[i], "-lo",3)) {
else if (! strncmp( param, "--log-out=",10) || ! strncmp( param, "-lo",3)) {
fill.logFile = std::string(params[i]+(params[i][1] == '-' ? 10 : 3));
if (!fill.logFile.length()) {
fill.logFile = "assimp-log.txt";

View File

@ -2259,7 +2259,7 @@ int CDisplay::RenderTextureView()
const float ny = (float)sRect.bottom;
const float x = (float)sDesc.Width;
const float y = (float)sDesc.Height;
float f = min((nx-30) / x,(ny-30) / y) * (m_fTextureZoom/1000.0f);
float f = std::min((nx-30) / x,(ny-30) / y) * (m_fTextureZoom/1000.0f);
float fHalfX = (nx - (f * x)) / 2.0f;
float fHalfY = (ny - (f * y)) / 2.0f;

View File

@ -275,7 +275,7 @@ bool CMaterialManager::TryLongerPath(char* szTemp,aiString* p_szString)
for (unsigned int i = 0; i < iSizeFound;++i)
info.cFileName[i] = (CHAR)tolower(info.cFileName[i]);
if (0 == memcmp(info.cFileName,szFile2, min(iSizeFound,iSize)))
if (0 == memcmp(info.cFileName,szFile2, std::min(iSizeFound,iSize)))
{
// we have it. Build the full path ...
char* sz = strrchr(szTempB,'*');

View File

@ -45,7 +45,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <windowsx.h>
#include <commdlg.h>
#ifdef __MINGW32__
#include <mmsystem.h>
#else
#include <timeapi.h>
#endif
namespace AssimpView {
@ -1049,9 +1054,9 @@ void DoExport(size_t formatId)
ai_assert(strlen(szFileName) <= MAX_PATH);
// invent a nice default file name
char* sz = max(strrchr(szFileName,'\\'),strrchr(szFileName,'/'));
char* sz = std::max(strrchr(szFileName,'\\'),strrchr(szFileName,'/'));
if (sz) {
strncpy(sz,max(strrchr(g_szFileName,'\\'),strrchr(g_szFileName,'/')),MAX_PATH);
strncpy(sz,std::max(strrchr(g_szFileName,'\\'),strrchr(g_szFileName,'/')),MAX_PATH);
}
}
else {

View File

@ -43,10 +43,15 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "assimp_view.h"
#include <timeapi.h>
#include <assimp/StringUtils.h>
#include <map>
#ifdef __MINGW32__
#include <mmsystem.h>
#else
#include <timeapi.h>
#endif
using namespace std;
namespace AssimpView {

View File

@ -46,6 +46,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define AI_SHADER_COMPILE_FLAGS D3DXSHADER_USE_LEGACY_D3DX9_31_DLL
// Because Dx headers include windef.h with min/max redefinition
#define NOMINMAX
// include resource definitions
#include "resource.h"
@ -177,7 +180,7 @@ type clamp(intype in)
{
// for unsigned types only ...
intype mask = (0x1u << (sizeof(type)*8))-1;
return (type)max((intype)0,min(in,mask));
return (type)std::max((intype)0,std::min(in,mask));
}