- BUGFIX: ColladaLoader handles multiple UVs/VColors correctly now. Thanks to Ingrater to point it out.
- ScenePreprocessor will now detect 3D UV channels with all-empty third component. git-svn-id: https://assimp.svn.sourceforge.net/svnroot/assimp/trunk@400 67173fc5-114c-0410-ac8e-9d2fd5bffc1fpull/1/head
parent
e8386dc837
commit
d6aacefa1e
|
@ -319,8 +319,12 @@ struct Mesh
|
||||||
mNumUVComponents[i] = 2;
|
mNumUVComponents[i] = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string mVertexID; // just to check if there's some sophisticated addressing involved... which we don't support, and therefore should warn about.
|
// just to check if there's some sophisticated addressing involved...
|
||||||
std::vector<InputChannel> mPerVertexData; // Vertex data addressed by vertex indices
|
// which we don't support, and therefore should warn about.
|
||||||
|
std::string mVertexID;
|
||||||
|
|
||||||
|
// Vertex data addressed by vertex indices
|
||||||
|
std::vector<InputChannel> mPerVertexData;
|
||||||
|
|
||||||
// actual mesh data, assembled on encounter of a <p> element. Verbose format, not indexed
|
// actual mesh data, assembled on encounter of a <p> element. Verbose format, not indexed
|
||||||
std::vector<aiVector3D> mPositions;
|
std::vector<aiVector3D> mPositions;
|
||||||
|
@ -332,9 +336,12 @@ struct Mesh
|
||||||
|
|
||||||
unsigned int mNumUVComponents[AI_MAX_NUMBER_OF_TEXTURECOORDS];
|
unsigned int mNumUVComponents[AI_MAX_NUMBER_OF_TEXTURECOORDS];
|
||||||
|
|
||||||
// Faces. Stored are only the number of vertices for each face. 1 == point, 2 == line, 3 == triangle, 4+ == poly
|
// Faces. Stored are only the number of vertices for each face.
|
||||||
|
// 1 == point, 2 == line, 3 == triangle, 4+ == poly
|
||||||
std::vector<size_t> mFaceSize;
|
std::vector<size_t> mFaceSize;
|
||||||
// Position indices for all faces in the sequence given in mFaceSize - necessary for bone weight assignment
|
|
||||||
|
// Position indices for all faces in the sequence given in mFaceSize -
|
||||||
|
// necessary for bone weight assignment
|
||||||
std::vector<size_t> mFacePosIndices;
|
std::vector<size_t> mFacePosIndices;
|
||||||
|
|
||||||
// Submeshes in this mesh, each with a given material
|
// Submeshes in this mesh, each with a given material
|
||||||
|
|
|
@ -506,7 +506,7 @@ void ColladaLoader::BuildMeshesForNode( const ColladaParser& pParser, const Coll
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
// Creates a mesh for the given ColladaMesh face subset and returns the newly created mesh
|
// Creates a mesh for the given ColladaMesh face subset and returns the newly created mesh
|
||||||
aiMesh* ColladaLoader::CreateMesh( const ColladaParser& pParser, const Collada::Mesh* pSrcMesh, const Collada::SubMesh& pSubMesh,
|
aiMesh* ColladaLoader::CreateMesh( const ColladaParser& pParser, const Collada::Mesh* pSrcMesh, const Collada::SubMesh& pSubMesh,
|
||||||
const Collada::Controller* pSrcController, size_t pStartVertex, size_t pStartFace)
|
const Collada::Controller* pSrcController, size_t pStartVertex, size_t pStartFace)
|
||||||
{
|
{
|
||||||
aiMesh* dstMesh = new aiMesh;
|
aiMesh* dstMesh = new aiMesh;
|
||||||
|
|
||||||
|
@ -547,25 +547,28 @@ aiMesh* ColladaLoader::CreateMesh( const ColladaParser& pParser, const Collada::
|
||||||
}
|
}
|
||||||
|
|
||||||
// same for texturecoords, as many as we have
|
// same for texturecoords, as many as we have
|
||||||
for( size_t a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; a++)
|
// empty slots are not allowed, need to pack and adjust UV indexes accordingly
|
||||||
|
for( size_t a = 0, real = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; a++)
|
||||||
{
|
{
|
||||||
if( pSrcMesh->mTexCoords[a].size() == pSrcMesh->mPositions.size())
|
if( pSrcMesh->mTexCoords[a].size() == pSrcMesh->mPositions.size())
|
||||||
{
|
{
|
||||||
dstMesh->mTextureCoords[a] = new aiVector3D[numVertices];
|
dstMesh->mTextureCoords[real] = new aiVector3D[numVertices];
|
||||||
for( size_t b = 0; b < numVertices; ++b)
|
for( size_t b = 0; b < numVertices; ++b)
|
||||||
dstMesh->mTextureCoords[a][b] = pSrcMesh->mTexCoords[a][pStartVertex+b];
|
dstMesh->mTextureCoords[real][b] = pSrcMesh->mTexCoords[a][pStartVertex+b];
|
||||||
|
|
||||||
dstMesh->mNumUVComponents[a] = pSrcMesh->mNumUVComponents[a];
|
dstMesh->mNumUVComponents[real] = pSrcMesh->mNumUVComponents[a];
|
||||||
|
++real;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// same for vertex colors, as many as we have
|
// same for vertex colors, as many as we have. again the same packing to avoid empty slots
|
||||||
for( size_t a = 0; a < AI_MAX_NUMBER_OF_COLOR_SETS; a++)
|
for( size_t a = 0, real = 0; a < AI_MAX_NUMBER_OF_COLOR_SETS; a++)
|
||||||
{
|
{
|
||||||
if( pSrcMesh->mColors[a].size() == pSrcMesh->mPositions.size())
|
if( pSrcMesh->mColors[a].size() == pSrcMesh->mPositions.size())
|
||||||
{
|
{
|
||||||
dstMesh->mColors[a] = new aiColor4D[numVertices];
|
dstMesh->mColors[real] = new aiColor4D[numVertices];
|
||||||
std::copy( pSrcMesh->mColors[a].begin() + pStartVertex, pSrcMesh->mColors[a].begin() + pStartVertex + numVertices, dstMesh->mColors[a]);
|
std::copy( pSrcMesh->mColors[a].begin() + pStartVertex, pSrcMesh->mColors[a].begin() + pStartVertex + numVertices,dstMesh->mColors[real]);
|
||||||
|
++real;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -866,12 +869,12 @@ void ColladaLoader::CreateAnimation( aiScene* pScene, const ColladaParser& pPars
|
||||||
}
|
}
|
||||||
|
|
||||||
// determine which transform step is affected by this channel
|
// determine which transform step is affected by this channel
|
||||||
entry.mTransformIndex = -1;
|
entry.mTransformIndex = 0xffffffff;
|
||||||
for( size_t a = 0; a < srcNode->mTransforms.size(); ++a)
|
for( size_t a = 0; a < srcNode->mTransforms.size(); ++a)
|
||||||
if( srcNode->mTransforms[a].mID == entry.mTransformId)
|
if( srcNode->mTransforms[a].mID == entry.mTransformId)
|
||||||
entry.mTransformIndex = a;
|
entry.mTransformIndex = a;
|
||||||
|
|
||||||
if( entry.mTransformIndex == -1)
|
if( entry.mTransformIndex == 0xffffffff)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
entry.mChannel = &(*cit);
|
entry.mChannel = &(*cit);
|
||||||
|
@ -1075,20 +1078,19 @@ void ColladaLoader::AddTexture ( Assimp::MaterialHelper& mat, const ColladaParse
|
||||||
// UV source index ... if we didn't resolve the mapping it is actually just
|
// UV source index ... if we didn't resolve the mapping it is actually just
|
||||||
// a guess but it works in most cases. We search for the frst occurence of a
|
// a guess but it works in most cases. We search for the frst occurence of a
|
||||||
// number in the channel name. We assume it is the zero-based index into the
|
// number in the channel name. We assume it is the zero-based index into the
|
||||||
// UV channel array of all corresponding meshes.
|
// UV channel array of all corresponding meshes. It could also be one-based
|
||||||
|
// for some exporters, but we won't care of it unless someone complains about.
|
||||||
if (sampler.mUVId != 0xffffffff)
|
if (sampler.mUVId != 0xffffffff)
|
||||||
map = sampler.mUVId;
|
map = sampler.mUVId;
|
||||||
else {
|
else {
|
||||||
map = 0xffffffff;
|
map = -1;
|
||||||
for (std::string::const_iterator it = sampler.mUVChannel.begin();
|
for (std::string::const_iterator it = sampler.mUVChannel.begin();it != sampler.mUVChannel.end(); ++it){
|
||||||
it != sampler.mUVChannel.end(); ++it)
|
|
||||||
{
|
|
||||||
if (IsNumeric(*it)) {
|
if (IsNumeric(*it)) {
|
||||||
map = strtol10(&(*it));
|
map = strtol10(&(*it));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (0xffffffff == map) {
|
if (-1 == map) {
|
||||||
DefaultLogger::get()->warn("Collada: unable to determine UV channel for texture");
|
DefaultLogger::get()->warn("Collada: unable to determine UV channel for texture");
|
||||||
map = 0;
|
map = 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1800,6 +1800,18 @@ void ColladaParser::ReadInputChannel( std::vector<InputChannel>& poChannels)
|
||||||
if( attrOffset > -1)
|
if( attrOffset > -1)
|
||||||
channel.mOffset = mReader->getAttributeValueAsInt( attrOffset);
|
channel.mOffset = mReader->getAttributeValueAsInt( attrOffset);
|
||||||
|
|
||||||
|
// read set if texture coordinates
|
||||||
|
if(channel.mType == IT_Texcoord || channel.mType == IT_Color){
|
||||||
|
int attrSet = TestAttribute("set");
|
||||||
|
if(attrSet > -1){
|
||||||
|
attrSet = mReader->getAttributeValueAsInt( attrSet);
|
||||||
|
if(attrSet < 0)
|
||||||
|
ThrowException( boost::str( boost::format( "Invalid index \"%i\" for set attribute") % (channel.mIndex+1)));
|
||||||
|
|
||||||
|
channel.mIndex = attrSet;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// store, if valid type
|
// store, if valid type
|
||||||
if( channel.mType != IT_Invalid)
|
if( channel.mType != IT_Invalid)
|
||||||
poChannels.push_back( channel);
|
poChannels.push_back( channel);
|
||||||
|
@ -1816,7 +1828,7 @@ void ColladaParser::ReadPrimitives( Mesh* pMesh, std::vector<InputChannel>& pPer
|
||||||
// determine number of indices coming per vertex
|
// determine number of indices coming per vertex
|
||||||
// find the offset index for all per-vertex channels
|
// find the offset index for all per-vertex channels
|
||||||
size_t numOffsets = 1;
|
size_t numOffsets = 1;
|
||||||
size_t perVertexOffset = -1; // invalid value
|
size_t perVertexOffset = 0xffffffff; // invalid value
|
||||||
BOOST_FOREACH( const InputChannel& channel, pPerIndexChannels)
|
BOOST_FOREACH( const InputChannel& channel, pPerIndexChannels)
|
||||||
{
|
{
|
||||||
numOffsets = std::max( numOffsets, channel.mOffset+1);
|
numOffsets = std::max( numOffsets, channel.mOffset+1);
|
||||||
|
@ -1946,7 +1958,7 @@ void ColladaParser::ReadPrimitives( Mesh* pMesh, std::vector<InputChannel>& pPer
|
||||||
for( size_t b = 0; b < numPoints; b++)
|
for( size_t b = 0; b < numPoints; b++)
|
||||||
{
|
{
|
||||||
// read all indices for this vertex. Yes, in a hacky static array
|
// read all indices for this vertex. Yes, in a hacky static array
|
||||||
assert( numOffsets < 20);
|
assert( numOffsets < 20 && perVertexOffset < 20);
|
||||||
static size_t vindex[20];
|
static size_t vindex[20];
|
||||||
for( size_t offsets = 0; offsets < numOffsets; ++offsets)
|
for( size_t offsets = 0; offsets < numOffsets; ++offsets)
|
||||||
vindex[offsets] = *idx++;
|
vindex[offsets] = *idx++;
|
||||||
|
@ -2017,8 +2029,9 @@ void ColladaParser::ExtractDataObjectFromChannel( const InputChannel& pInput, si
|
||||||
break;
|
break;
|
||||||
case IT_Texcoord: // up to 4 texture coord sets are fine, ignore the others
|
case IT_Texcoord: // up to 4 texture coord sets are fine, ignore the others
|
||||||
if( pInput.mIndex < AI_MAX_NUMBER_OF_TEXTURECOORDS) {
|
if( pInput.mIndex < AI_MAX_NUMBER_OF_TEXTURECOORDS) {
|
||||||
|
|
||||||
pMesh->mTexCoords[pInput.mIndex].push_back( aiVector3D( obj[0], obj[1], obj[2]));
|
pMesh->mTexCoords[pInput.mIndex].push_back( aiVector3D( obj[0], obj[1], obj[2]));
|
||||||
if (0 != acc.mSubOffset[2]) /* hack ... consider cleaner solution */
|
if (0 != acc.mSubOffset[2] || 0 != acc.mSubOffset[3]) /* hack ... consider cleaner solution */
|
||||||
pMesh->mNumUVComponents[pInput.mIndex]=3;
|
pMesh->mNumUVComponents[pInput.mIndex]=3;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
@ -121,17 +121,31 @@ void ScenePreprocessor::ProcessMesh (aiMesh* mesh)
|
||||||
if( !mesh->mNumUVComponents[i])
|
if( !mesh->mNumUVComponents[i])
|
||||||
mesh->mNumUVComponents[i] = 2;
|
mesh->mNumUVComponents[i] = 2;
|
||||||
|
|
||||||
|
aiVector3D* p = mesh->mTextureCoords[i], *end = p+mesh->mNumVertices;
|
||||||
|
|
||||||
// Ensure unsued components are zeroed. This will make 1D texture channels work
|
// Ensure unsued components are zeroed. This will make 1D texture channels work
|
||||||
// as if they were 2D channels .. just in case an application doesn't handle
|
// as if they were 2D channels .. just in case an application doesn't handle
|
||||||
// this case
|
// this case
|
||||||
if (2 == mesh->mNumUVComponents[i]) {
|
if (2 == mesh->mNumUVComponents[i]) {
|
||||||
for (aiVector3D* p = mesh->mTextureCoords[i], *end = p+mesh->mNumVertices; p != end; ++p)
|
for (; p != end; ++p)
|
||||||
p->z = 0.f;
|
p->z = 0.f;
|
||||||
}
|
}
|
||||||
else if (1 == mesh->mNumUVComponents[i]) {
|
else if (1 == mesh->mNumUVComponents[i]) {
|
||||||
for (aiVector3D* p = mesh->mTextureCoords[i], *end = p+mesh->mNumVertices; p != end; ++p)
|
for (; p != end; ++p)
|
||||||
p->z = p->y = 0.f;
|
p->z = p->y = 0.f;
|
||||||
}
|
}
|
||||||
|
else if (3 == mesh->mNumUVComponents[i]) {
|
||||||
|
|
||||||
|
// Really 3D coordinates? Check whether the third coordinate is != 0 for at least one element
|
||||||
|
for (; p != end; ++p) {
|
||||||
|
if (p->z != 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (p == end) {
|
||||||
|
DefaultLogger::get()->warn("ScenePreprocessor: UVs are declared to be 3D but they're obviously not. Reverting to 2D.");
|
||||||
|
mesh->mNumUVComponents[i] = 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue