Merge branch 'master' into fix_gltf2_export_componentType_error
commit
327a43c26f
|
@ -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})
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -874,7 +874,7 @@ void Converter::ConvertModel( const Model& model, aiNode& nd, const aiMatrix4x4&
|
|||
|
||||
const MeshGeometry* const mesh = dynamic_cast< const MeshGeometry* >( geo );
|
||||
if ( mesh ) {
|
||||
const std::vector<unsigned int>& indices = ConvertMesh( *mesh, model, node_global_transform );
|
||||
const std::vector<unsigned int>& indices = ConvertMesh( *mesh, model, node_global_transform, nd);
|
||||
std::copy( indices.begin(), indices.end(), std::back_inserter( meshes ) );
|
||||
}
|
||||
else {
|
||||
|
@ -891,7 +891,7 @@ void Converter::ConvertModel( const Model& model, aiNode& nd, const aiMatrix4x4&
|
|||
}
|
||||
|
||||
std::vector<unsigned int> Converter::ConvertMesh( const MeshGeometry& mesh, const Model& model,
|
||||
const aiMatrix4x4& node_global_transform )
|
||||
const aiMatrix4x4& node_global_transform, aiNode& nd)
|
||||
{
|
||||
std::vector<unsigned int> temp;
|
||||
|
||||
|
@ -915,17 +915,17 @@ std::vector<unsigned int> Converter::ConvertMesh( const MeshGeometry& mesh, cons
|
|||
const MatIndexArray::value_type base = mindices[ 0 ];
|
||||
for( MatIndexArray::value_type index : mindices ) {
|
||||
if ( index != base ) {
|
||||
return ConvertMeshMultiMaterial( mesh, model, node_global_transform );
|
||||
return ConvertMeshMultiMaterial( mesh, model, node_global_transform, nd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// faster code-path, just copy the data
|
||||
temp.push_back( ConvertMeshSingleMaterial( mesh, model, node_global_transform ) );
|
||||
temp.push_back( ConvertMeshSingleMaterial( mesh, model, node_global_transform, nd) );
|
||||
return temp;
|
||||
}
|
||||
|
||||
aiMesh* Converter::SetupEmptyMesh( const MeshGeometry& mesh )
|
||||
aiMesh* Converter::SetupEmptyMesh( const MeshGeometry& mesh, aiNode& nd)
|
||||
{
|
||||
aiMesh* const out_mesh = new aiMesh();
|
||||
meshes.push_back( out_mesh );
|
||||
|
@ -940,15 +940,19 @@ aiMesh* Converter::SetupEmptyMesh( const MeshGeometry& mesh )
|
|||
if ( name.length() ) {
|
||||
out_mesh->mName.Set( name );
|
||||
}
|
||||
else
|
||||
{
|
||||
out_mesh->mName = nd.mName;
|
||||
}
|
||||
|
||||
return out_mesh;
|
||||
}
|
||||
|
||||
unsigned int Converter::ConvertMeshSingleMaterial( const MeshGeometry& mesh, const Model& model,
|
||||
const aiMatrix4x4& node_global_transform )
|
||||
const aiMatrix4x4& node_global_transform, aiNode& nd)
|
||||
{
|
||||
const MatIndexArray& mindices = mesh.GetMaterialIndices();
|
||||
aiMesh* const out_mesh = SetupEmptyMesh( mesh );
|
||||
aiMesh* const out_mesh = SetupEmptyMesh(mesh, nd);
|
||||
|
||||
const std::vector<aiVector3D>& vertices = mesh.GetVertices();
|
||||
const std::vector<unsigned int>& faces = mesh.GetFaceIndexCounts();
|
||||
|
@ -1072,7 +1076,7 @@ unsigned int Converter::ConvertMeshSingleMaterial( const MeshGeometry& mesh, con
|
|||
}
|
||||
|
||||
std::vector<unsigned int> Converter::ConvertMeshMultiMaterial( const MeshGeometry& mesh, const Model& model,
|
||||
const aiMatrix4x4& node_global_transform )
|
||||
const aiMatrix4x4& node_global_transform, aiNode& nd)
|
||||
{
|
||||
const MatIndexArray& mindices = mesh.GetMaterialIndices();
|
||||
ai_assert( mindices.size() );
|
||||
|
@ -1083,7 +1087,7 @@ std::vector<unsigned int> Converter::ConvertMeshMultiMaterial( const MeshGeometr
|
|||
for( MatIndexArray::value_type index : mindices ) {
|
||||
if ( had.find( index ) == had.end() ) {
|
||||
|
||||
indices.push_back( ConvertMeshMultiMaterial( mesh, model, index, node_global_transform ) );
|
||||
indices.push_back( ConvertMeshMultiMaterial( mesh, model, index, node_global_transform, nd) );
|
||||
had.insert( index );
|
||||
}
|
||||
}
|
||||
|
@ -1093,9 +1097,10 @@ std::vector<unsigned int> Converter::ConvertMeshMultiMaterial( const MeshGeometr
|
|||
|
||||
unsigned int Converter::ConvertMeshMultiMaterial( const MeshGeometry& mesh, const Model& model,
|
||||
MatIndexArray::value_type index,
|
||||
const aiMatrix4x4& node_global_transform )
|
||||
const aiMatrix4x4& node_global_transform,
|
||||
aiNode& nd)
|
||||
{
|
||||
aiMesh* const out_mesh = SetupEmptyMesh( mesh );
|
||||
aiMesh* const out_mesh = SetupEmptyMesh(mesh, nd);
|
||||
|
||||
const MatIndexArray& mindices = mesh.GetMaterialIndices();
|
||||
const std::vector<aiVector3D>& vertices = mesh.GetVertices();
|
||||
|
|
|
@ -172,23 +172,23 @@ private:
|
|||
// ------------------------------------------------------------------------------------------------
|
||||
// MeshGeometry -> aiMesh, return mesh index + 1 or 0 if the conversion failed
|
||||
std::vector<unsigned int> ConvertMesh(const MeshGeometry& mesh, const Model& model,
|
||||
const aiMatrix4x4& node_global_transform);
|
||||
const aiMatrix4x4& node_global_transform, aiNode& nd);
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
aiMesh* SetupEmptyMesh(const MeshGeometry& mesh);
|
||||
aiMesh* SetupEmptyMesh(const MeshGeometry& mesh, aiNode& nd);
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
unsigned int ConvertMeshSingleMaterial(const MeshGeometry& mesh, const Model& model,
|
||||
const aiMatrix4x4& node_global_transform);
|
||||
const aiMatrix4x4& node_global_transform, aiNode& nd);
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
std::vector<unsigned int> ConvertMeshMultiMaterial(const MeshGeometry& mesh, const Model& model,
|
||||
const aiMatrix4x4& node_global_transform);
|
||||
const aiMatrix4x4& node_global_transform, aiNode& nd);
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
unsigned int ConvertMeshMultiMaterial(const MeshGeometry& mesh, const Model& model,
|
||||
MatIndexArray::value_type index,
|
||||
const aiMatrix4x4& node_global_transform);
|
||||
const aiMatrix4x4& node_global_transform, aiNode& nd);
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
static const unsigned int NO_MATERIAL_SEPARATION = /* std::numeric_limits<unsigned int>::max() */
|
||||
|
|
|
@ -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]);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -114,14 +114,13 @@ static const std::string MaterialExt = ".mtl";
|
|||
ObjExporter::ObjExporter(const char* _filename, const aiScene* pScene, bool noMtl)
|
||||
: filename(_filename)
|
||||
, pScene(pScene)
|
||||
, vp()
|
||||
, vn()
|
||||
, vt()
|
||||
, vc()
|
||||
, mVpMap()
|
||||
, vp()
|
||||
, useVc(false)
|
||||
, mVnMap()
|
||||
, mVtMap()
|
||||
, mVcMap()
|
||||
, mVpMap()
|
||||
, mMeshes()
|
||||
, endl("\n") {
|
||||
// make sure that all formatting happens using the standard, C locale and not the user's current locale
|
||||
|
@ -268,27 +267,22 @@ void ObjExporter::WriteGeometryFile(bool noMtl) {
|
|||
AddNode(pScene->mRootNode, mBase);
|
||||
|
||||
// write vertex positions with colors, if any
|
||||
mVpMap.getVectors( vp );
|
||||
mVcMap.getColors( vc );
|
||||
if ( vc.empty() ) {
|
||||
mVpMap.getKeys( vp );
|
||||
if ( !useVc ) {
|
||||
mOutput << "# " << vp.size() << " vertex positions" << endl;
|
||||
for ( const aiVector3D& v : vp ) {
|
||||
mOutput << "v " << v.x << " " << v.y << " " << v.z << endl;
|
||||
for ( const vertexData& v : vp ) {
|
||||
mOutput << "v " << v.vp.x << " " << v.vp.y << " " << v.vp.z << endl;
|
||||
}
|
||||
} else {
|
||||
mOutput << "# " << vp.size() << " vertex positions and colors" << endl;
|
||||
size_t colIdx = 0;
|
||||
for ( const aiVector3D& v : vp ) {
|
||||
if ( colIdx < vc.size() ) {
|
||||
mOutput << "v " << v.x << " " << v.y << " " << v.z << " " << vc[ colIdx ].r << " " << vc[ colIdx ].g << " " << vc[ colIdx ].b << endl;
|
||||
}
|
||||
++colIdx;
|
||||
for ( const vertexData& v : vp ) {
|
||||
mOutput << "v " << v.vp.x << " " << v.vp.y << " " << v.vp.z << " " << v.vc.r << " " << v.vc.g << " " << v.vc.b << endl;
|
||||
}
|
||||
}
|
||||
mOutput << endl;
|
||||
|
||||
// write uv coordinates
|
||||
mVtMap.getVectors(vt);
|
||||
mVtMap.getKeys(vt);
|
||||
mOutput << "# " << vt.size() << " UV coordinates" << endl;
|
||||
for(const aiVector3D& v : vt) {
|
||||
mOutput << "vt " << v.x << " " << v.y << " " << v.z << endl;
|
||||
|
@ -296,7 +290,7 @@ void ObjExporter::WriteGeometryFile(bool noMtl) {
|
|||
mOutput << endl;
|
||||
|
||||
// write vertex normals
|
||||
mVnMap.getVectors(vn);
|
||||
mVnMap.getKeys(vn);
|
||||
mOutput << "# " << vn.size() << " vertex normals" << endl;
|
||||
for(const aiVector3D& v : vn) {
|
||||
mOutput << "vn " << v.x << " " << v.y << " " << v.z << endl;
|
||||
|
@ -337,54 +331,15 @@ void ObjExporter::WriteGeometryFile(bool noMtl) {
|
|||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
int ObjExporter::vecIndexMap::getIndex(const aiVector3D& vec) {
|
||||
vecIndexMap::dataType::iterator vertIt = vecMap.find(vec);
|
||||
// vertex already exists, so reference it
|
||||
if(vertIt != vecMap.end()){
|
||||
return vertIt->second;
|
||||
}
|
||||
vecMap[vec] = mNextIndex;
|
||||
int ret = mNextIndex;
|
||||
mNextIndex++;
|
||||
return ret;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void ObjExporter::vecIndexMap::getVectors( std::vector<aiVector3D>& vecs ) {
|
||||
vecs.resize(vecMap.size());
|
||||
for(vecIndexMap::dataType::iterator it = vecMap.begin(); it != vecMap.end(); ++it){
|
||||
vecs[it->second-1] = it->first;
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
int ObjExporter::colIndexMap::getIndex( const aiColor4D& col ) {
|
||||
colIndexMap::dataType::iterator vertIt = colMap.find( col );
|
||||
// vertex already exists, so reference it
|
||||
if ( vertIt != colMap.end() ) {
|
||||
return vertIt->second;
|
||||
}
|
||||
colMap[ col ] = mNextIndex;
|
||||
int ret = mNextIndex;
|
||||
mNextIndex++;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void ObjExporter::colIndexMap::getColors( std::vector<aiColor4D> &colors ) {
|
||||
colors.resize( colMap.size() );
|
||||
for ( colIndexMap::dataType::iterator it = colMap.begin(); it != colMap.end(); ++it ) {
|
||||
colors[ it->second - 1 ] = it->first;
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void ObjExporter::AddMesh(const aiString& name, const aiMesh* m, const aiMatrix4x4& mat) {
|
||||
mMeshes.push_back(MeshInstance() );
|
||||
MeshInstance& mesh = mMeshes.back();
|
||||
|
||||
if ( nullptr != m->mColors[ 0 ] ) {
|
||||
useVc = true;
|
||||
}
|
||||
|
||||
mesh.name = std::string( name.data, name.length );
|
||||
mesh.matname = GetMaterialName(m->mMaterialIndex);
|
||||
|
||||
|
@ -410,7 +365,13 @@ void ObjExporter::AddMesh(const aiString& name, const aiMesh* m, const aiMatrix4
|
|||
const unsigned int idx = f.mIndices[a];
|
||||
|
||||
aiVector3D vert = mat * m->mVertices[idx];
|
||||
face.indices[a].vp = mVpMap.getIndex(vert);
|
||||
|
||||
if ( nullptr != m->mColors[ 0 ] ) {
|
||||
aiColor4D col4 = m->mColors[ 0 ][ idx ];
|
||||
face.indices[a].vp = mVpMap.getIndex({vert, aiColor3D(col4.r, col4.g, col4.b)});
|
||||
} else {
|
||||
face.indices[a].vp = mVpMap.getIndex({vert, aiColor3D(0,0,0)});
|
||||
}
|
||||
|
||||
if (m->mNormals) {
|
||||
aiVector3D norm = aiMatrix3x3(mat) * m->mNormals[idx];
|
||||
|
@ -419,13 +380,6 @@ void ObjExporter::AddMesh(const aiString& name, const aiMesh* m, const aiMatrix4
|
|||
face.indices[a].vn = 0;
|
||||
}
|
||||
|
||||
if ( nullptr != m->mColors[ 0 ] ) {
|
||||
aiColor4D col4 = m->mColors[ 0 ][ idx ];
|
||||
face.indices[ a ].vc = mVcMap.getIndex( col4 );
|
||||
} else {
|
||||
face.indices[ a ].vc = 0;
|
||||
}
|
||||
|
||||
if ( m->mTextureCoords[ 0 ] ) {
|
||||
face.indices[a].vt = mVtMap.getIndex(m->mTextureCoords[0][idx]);
|
||||
} else {
|
||||
|
|
|
@ -77,13 +77,12 @@ private:
|
|||
FaceVertex()
|
||||
: vp()
|
||||
, vn()
|
||||
, vt()
|
||||
, vc() {
|
||||
, vt() {
|
||||
// empty
|
||||
}
|
||||
|
||||
// one-based, 0 means: 'does not exist'
|
||||
unsigned int vp, vn, vt, vc;
|
||||
unsigned int vp, vn, vt;
|
||||
};
|
||||
|
||||
struct Face {
|
||||
|
@ -106,66 +105,80 @@ private:
|
|||
private:
|
||||
std::string filename;
|
||||
const aiScene* const pScene;
|
||||
std::vector<aiVector3D> vp, vn, vt;
|
||||
|
||||
struct vertexData {
|
||||
aiVector3D vp;
|
||||
aiColor3D vc; // OBJ does not support 4D color
|
||||
};
|
||||
|
||||
std::vector<aiVector3D> vn, vt;
|
||||
std::vector<aiColor4D> vc;
|
||||
std::vector<vertexData> vp;
|
||||
bool useVc;
|
||||
|
||||
struct aiVectorCompare {
|
||||
bool operator() (const aiVector3D& a, const aiVector3D& b) const {
|
||||
if(a.x < b.x) return true;
|
||||
if(a.x > b.x) return false;
|
||||
if(a.y < b.y) return true;
|
||||
if(a.y > b.y) return false;
|
||||
if(a.z < b.z) return true;
|
||||
struct vertexDataCompare {
|
||||
bool operator() ( const vertexData& a, const vertexData& b ) const {
|
||||
// position
|
||||
if (a.vp.x < b.vp.x) return true;
|
||||
if (a.vp.x > b.vp.x) return false;
|
||||
if (a.vp.y < b.vp.y) return true;
|
||||
if (a.vp.y > b.vp.y) return false;
|
||||
if (a.vp.z < b.vp.z) return true;
|
||||
if (a.vp.z > b.vp.z) return false;
|
||||
|
||||
// color
|
||||
if (a.vc.r < b.vc.r) return true;
|
||||
if (a.vc.r > b.vc.r) return false;
|
||||
if (a.vc.g < b.vc.g) return true;
|
||||
if (a.vc.g > b.vc.g) return false;
|
||||
if (a.vc.b < b.vc.b) return true;
|
||||
if (a.vc.b > b.vc.b) return false;
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
struct aiColor4Compare {
|
||||
bool operator() ( const aiColor4D& a, const aiColor4D& b ) const {
|
||||
if ( a.r < b.r ) return true;
|
||||
if ( a.r > b.r ) return false;
|
||||
if ( a.g < b.g ) return true;
|
||||
if ( a.g > b.g ) return false;
|
||||
if ( a.b < b.b ) return true;
|
||||
if ( a.b > b.b ) return false;
|
||||
if ( a.a < b.a ) return true;
|
||||
if ( a.a > b.a ) return false;
|
||||
struct aiVectorCompare {
|
||||
bool operator() (const aiVector3D& a, const aiVector3D& b) const {
|
||||
if(a.x < b.x) return true;
|
||||
if(a.x > b.x) return false;
|
||||
if(a.y < b.y) return true;
|
||||
if(a.y > b.y) return false;
|
||||
if(a.z < b.z) return true;
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
class vecIndexMap {
|
||||
template <class T, class Compare = std::less<T>>
|
||||
class indexMap {
|
||||
int mNextIndex;
|
||||
typedef std::map<aiVector3D, int, aiVectorCompare> dataType;
|
||||
typedef std::map<T, int, Compare> dataType;
|
||||
dataType vecMap;
|
||||
|
||||
public:
|
||||
vecIndexMap()
|
||||
indexMap()
|
||||
: mNextIndex(1) {
|
||||
// empty
|
||||
}
|
||||
|
||||
int getIndex(const aiVector3D& vec);
|
||||
void getVectors( std::vector<aiVector3D>& vecs );
|
||||
int getIndex(const T& key) {
|
||||
typename dataType::iterator vertIt = vecMap.find(key);
|
||||
// vertex already exists, so reference it
|
||||
if(vertIt != vecMap.end()){
|
||||
return vertIt->second;
|
||||
}
|
||||
return vecMap[key] = mNextIndex++;
|
||||
};
|
||||
|
||||
void getKeys( std::vector<T>& keys ) {
|
||||
keys.resize(vecMap.size());
|
||||
for(typename dataType::iterator it = vecMap.begin(); it != vecMap.end(); ++it){
|
||||
keys[it->second-1] = it->first;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
class colIndexMap {
|
||||
int mNextIndex;
|
||||
typedef std::map<aiColor4D, int, aiColor4Compare> dataType;
|
||||
dataType colMap;
|
||||
|
||||
public:
|
||||
colIndexMap()
|
||||
: mNextIndex( 1 ) {
|
||||
// empty
|
||||
}
|
||||
|
||||
int getIndex( const aiColor4D& col );
|
||||
void getColors( std::vector<aiColor4D> &colors );
|
||||
};
|
||||
|
||||
vecIndexMap mVpMap, mVnMap, mVtMap;
|
||||
colIndexMap mVcMap;
|
||||
indexMap<aiVector3D, aiVectorCompare> mVnMap, mVtMap;
|
||||
indexMap<vertexData, vertexDataCompare> mVpMap;
|
||||
std::vector<MeshInstance> mMeshes;
|
||||
|
||||
// this endl() doesn't flush() the stream
|
||||
|
|
|
@ -194,16 +194,16 @@ PlyExporter::PlyExporter(const char* _filename, const aiScene* pScene, bool bina
|
|||
|
||||
for (unsigned int n = PLY_EXPORT_HAS_COLORS, c = 0; (components & n) && c != AI_MAX_NUMBER_OF_COLOR_SETS; n <<= 1, ++c) {
|
||||
if (!c) {
|
||||
mOutput << "property " << typeName << " r" << endl;
|
||||
mOutput << "property " << typeName << " g" << endl;
|
||||
mOutput << "property " << typeName << " b" << endl;
|
||||
mOutput << "property " << typeName << " a" << endl;
|
||||
mOutput << "property " << "uchar" << " red" << endl;
|
||||
mOutput << "property " << "uchar" << " green" << endl;
|
||||
mOutput << "property " << "uchar" << " blue" << endl;
|
||||
mOutput << "property " << "uchar" << " alpha" << endl;
|
||||
}
|
||||
else {
|
||||
mOutput << "property " << typeName << " r" << c << endl;
|
||||
mOutput << "property " << typeName << " g" << c << endl;
|
||||
mOutput << "property " << typeName << " b" << c << endl;
|
||||
mOutput << "property " << typeName << " a" << c << endl;
|
||||
mOutput << "property " << "uchar" << " red" << c << endl;
|
||||
mOutput << "property " << "uchar" << " green" << c << endl;
|
||||
mOutput << "property " << "uchar" << " blue" << c << endl;
|
||||
mOutput << "property " << "uchar" << " alpha" << c << endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -288,13 +288,13 @@ void PlyExporter::WriteMeshVerts(const aiMesh* m, unsigned int components)
|
|||
for (unsigned int n = PLY_EXPORT_HAS_COLORS, c = 0; (components & n) && c != AI_MAX_NUMBER_OF_COLOR_SETS; n <<= 1, ++c) {
|
||||
if (m->HasVertexColors(c)) {
|
||||
mOutput <<
|
||||
" " << m->mColors[c][i].r <<
|
||||
" " << m->mColors[c][i].g <<
|
||||
" " << m->mColors[c][i].b <<
|
||||
" " << m->mColors[c][i].a;
|
||||
" " << (int)(m->mColors[c][i].r * 255) <<
|
||||
" " << (int)(m->mColors[c][i].g * 255) <<
|
||||
" " << (int)(m->mColors[c][i].b * 255) <<
|
||||
" " << (int)(m->mColors[c][i].a * 255);
|
||||
}
|
||||
else {
|
||||
mOutput << " -1.0 -1.0 -1.0 -1.0";
|
||||
mOutput << " 0 0 0";
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -85,8 +85,6 @@ void SortByPTypeProcess::SetupProperties(const Importer* pImp)
|
|||
// Update changed meshes in all nodes
|
||||
void UpdateNodes(const std::vector<unsigned int>& replaceMeshIndex, aiNode* node)
|
||||
{
|
||||
// std::vector<unsigned int>::const_iterator it;
|
||||
|
||||
if (node->mNumMeshes)
|
||||
{
|
||||
unsigned int newSize = 0;
|
||||
|
@ -133,10 +131,8 @@ void UpdateNodes(const std::vector<unsigned int>& replaceMeshIndex, aiNode* node
|
|||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Executes the post processing step on the given imported data.
|
||||
void SortByPTypeProcess::Execute( aiScene* pScene)
|
||||
{
|
||||
if (!pScene->mNumMeshes)
|
||||
{
|
||||
void SortByPTypeProcess::Execute( aiScene* pScene) {
|
||||
if ( 0 == pScene->mNumMeshes) {
|
||||
ASSIMP_LOG_DEBUG("SortByPTypeProcess skipped, there are no meshes");
|
||||
return;
|
||||
}
|
||||
|
@ -152,42 +148,38 @@ void SortByPTypeProcess::Execute( aiScene* pScene)
|
|||
|
||||
std::vector<unsigned int> replaceMeshIndex(pScene->mNumMeshes*4,UINT_MAX);
|
||||
std::vector<unsigned int>::iterator meshIdx = replaceMeshIndex.begin();
|
||||
for (unsigned int i = 0; i < pScene->mNumMeshes;++i)
|
||||
{
|
||||
for (unsigned int i = 0; i < pScene->mNumMeshes; ++i) {
|
||||
aiMesh* const mesh = pScene->mMeshes[i];
|
||||
ai_assert(0 != mesh->mPrimitiveTypes);
|
||||
|
||||
// if there's just one primitive type in the mesh there's nothing to do for us
|
||||
unsigned int num = 0;
|
||||
if (mesh->mPrimitiveTypes & aiPrimitiveType_POINT)
|
||||
{
|
||||
if (mesh->mPrimitiveTypes & aiPrimitiveType_POINT) {
|
||||
++aiNumMeshesPerPType[0];
|
||||
++num;
|
||||
}
|
||||
if (mesh->mPrimitiveTypes & aiPrimitiveType_LINE)
|
||||
{
|
||||
if (mesh->mPrimitiveTypes & aiPrimitiveType_LINE) {
|
||||
++aiNumMeshesPerPType[1];
|
||||
++num;
|
||||
}
|
||||
if (mesh->mPrimitiveTypes & aiPrimitiveType_TRIANGLE)
|
||||
{
|
||||
if (mesh->mPrimitiveTypes & aiPrimitiveType_TRIANGLE) {
|
||||
++aiNumMeshesPerPType[2];
|
||||
++num;
|
||||
}
|
||||
if (mesh->mPrimitiveTypes & aiPrimitiveType_POLYGON)
|
||||
{
|
||||
if (mesh->mPrimitiveTypes & aiPrimitiveType_POLYGON) {
|
||||
++aiNumMeshesPerPType[3];
|
||||
++num;
|
||||
}
|
||||
|
||||
if (1 == num)
|
||||
{
|
||||
if (!(configRemoveMeshes & mesh->mPrimitiveTypes))
|
||||
{
|
||||
*meshIdx = (unsigned int) outMeshes.size();
|
||||
if (1 == num) {
|
||||
if (!(configRemoveMeshes & mesh->mPrimitiveTypes)) {
|
||||
*meshIdx = static_cast<unsigned int>( outMeshes.size() );
|
||||
outMeshes.push_back(mesh);
|
||||
} else {
|
||||
delete mesh;
|
||||
pScene->mMeshes[ i ] = nullptr;
|
||||
bAnyChanges = true;
|
||||
}
|
||||
else bAnyChanges = true;
|
||||
|
||||
meshIdx += 4;
|
||||
continue;
|
||||
|
@ -195,14 +187,13 @@ void SortByPTypeProcess::Execute( aiScene* pScene)
|
|||
bAnyChanges = true;
|
||||
|
||||
// reuse our current mesh arrays for the submesh
|
||||
// with the largest numer of primitives
|
||||
// with the largest number of primitives
|
||||
unsigned int aiNumPerPType[4] = {0,0,0,0};
|
||||
aiFace* pFirstFace = mesh->mFaces;
|
||||
aiFace* const pLastFace = pFirstFace + mesh->mNumFaces;
|
||||
|
||||
unsigned int numPolyVerts = 0;
|
||||
for (;pFirstFace != pLastFace; ++pFirstFace)
|
||||
{
|
||||
for (;pFirstFace != pLastFace; ++pFirstFace) {
|
||||
if (pFirstFace->mNumIndices <= 3)
|
||||
++aiNumPerPType[pFirstFace->mNumIndices-1];
|
||||
else
|
||||
|
|
|
@ -758,7 +758,7 @@ void glTF2Exporter::ExportMeshes()
|
|||
if (c)
|
||||
p.attributes.color.push_back(c);
|
||||
}
|
||||
|
||||
|
||||
/*************** Vertices indices ****************/
|
||||
if (aim->mNumFaces > 0) {
|
||||
std::vector<IndicesType> indices;
|
||||
|
@ -890,6 +890,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);
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
g cube
|
||||
|
||||
v 0.0 0.0 0.0 124 110 120
|
||||
v 0.0 0.0 1.0 24 0 121
|
||||
v 0.0 1.0 0.0 4 0 44
|
||||
v 0.0 1.0 1.0 224 0 10
|
||||
v 1.0 0.0 0.0 24 200 25
|
||||
v 1.0 0.0 1.0 124 10 56
|
||||
v 1.0 1.0 0.0 78 10 50
|
||||
v 1.0 1.0 1.0 23 0 200
|
||||
v 0.0 0.0 0.0 0.48627 0.43137 0.47059
|
||||
v 0.0 0.0 1.0 0.09412 0.00000 0.47451
|
||||
v 0.0 1.0 0.0 0.01569 0.00000 0.17255
|
||||
v 0.0 1.0 1.0 0.87843 0.00000 0.03922
|
||||
v 1.0 0.0 0.0 0.09412 0.78431 0.09804
|
||||
v 1.0 0.0 1.0 0.48627 0.03922 0.21961
|
||||
v 1.0 1.0 0.0 0.30588 0.03922 0.19608
|
||||
v 1.0 1.0 1.0 0.09020 0.00000 0.78431
|
||||
|
||||
vn 0.0 0.0 1.0
|
||||
vn 0.0 0.0 -1.0
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
g cube
|
||||
|
||||
v 0.0 0.0 0.0 0.0 0.0 0.0
|
||||
v 0.0 0.0 1.0 1.0 0.6 0.3
|
||||
v 0.0 1.0 0.0 0.0 0.0 0.0
|
||||
v 0.0 1.0 1.0 0.3 0.6 1.0
|
||||
v 1.0 0.0 0.0 0.0 0.0 0.0
|
||||
v 1.0 0.0 1.0 1.0 0.6 0.3
|
||||
v 1.0 1.0 0.0 0.0 0.0 0.0
|
||||
v 1.0 1.0 1.0 0.3 0.6 1.0
|
||||
|
||||
vn 0.0 0.0 1.0
|
||||
vn 0.0 0.0 -1.0
|
||||
vn 0.0 1.0 0.0
|
||||
vn 0.0 -1.0 0.0
|
||||
vn 1.0 0.0 0.0
|
||||
vn -1.0 0.0 0.0
|
||||
|
||||
f 1//2 7//2 5//2
|
||||
f 1//2 3//2 7//2
|
||||
f 1//6 4//6 3//6
|
||||
f 1//6 2//6 4//6
|
||||
f 3//3 8//3 7//3
|
||||
f 3//3 4//3 8//3
|
||||
f 5//5 7//5 8//5
|
||||
f 5//5 8//5 6//5
|
||||
f 1//4 5//4 6//4
|
||||
f 1//4 6//4 2//4
|
||||
f 2//1 6//1 8//1
|
||||
f 2//1 8//1 4//1
|
|
@ -267,6 +267,28 @@ TEST_F( utObjImportExport, issue809_vertex_color_Test ) {
|
|||
#endif // ASSIMP_BUILD_NO_EXPORT
|
||||
}
|
||||
|
||||
TEST_F( utObjImportExport, issue1923_vertex_color_Test ) {
|
||||
::Assimp::Importer importer;
|
||||
const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/OBJ/cube_with_vertexcolors_uni.obj", aiProcess_ValidateDataStructure );
|
||||
EXPECT_NE( nullptr, scene );
|
||||
|
||||
scene = importer.GetOrphanedScene();
|
||||
|
||||
#ifndef ASSIMP_BUILD_NO_EXPORT
|
||||
::Assimp::Exporter exporter;
|
||||
const aiExportDataBlob* blob = exporter.ExportToBlob( scene, "obj");
|
||||
EXPECT_NE( nullptr, blob );
|
||||
|
||||
const aiScene *sceneReImport = importer.ReadFileFromMemory( blob->data, blob->size, aiProcess_ValidateDataStructure );
|
||||
EXPECT_NE( nullptr, scene );
|
||||
|
||||
SceneDiffer differ;
|
||||
EXPECT_TRUE( differ.isEqual( scene, sceneReImport ) );
|
||||
#endif // ASSIMP_BUILD_NO_EXPORT
|
||||
|
||||
delete scene;
|
||||
}
|
||||
|
||||
TEST_F( utObjImportExport, issue1453_segfault ) {
|
||||
static const std::string ObjModel =
|
||||
"v 0.0 0.0 0.0\n"
|
||||
|
|
Loading…
Reference in New Issue