issue_1973

added support for CustomData(Layer) to support multiple (texture) UV mappings
added unittest with sample model
This commit is contained in:
CwTCwT
2018-06-09 15:45:09 +02:00
parent cd0fe21464
commit 85b0026c92
12 changed files with 707 additions and 17 deletions

View File

@@ -54,6 +54,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "BlenderIntermediate.h"
#include "BlenderModifier.h"
#include "BlenderBMesh.h"
#include "BlenderCustomData.h"
#include <assimp/StringUtils.h>
#include <assimp/scene.h>
#include <assimp/importerdesc.h>
@@ -1021,6 +1022,36 @@ void BlenderImporter::ConvertMesh(const Scene& /*in*/, const Object* /*obj*/, co
}
}
// TODO should we create the TextureUVMapping map in Convert<Material> to prevent redundant processing?
// create texture <-> uvname mapping for all materials
// key is texture number, value is data *
typedef std::map<uint32_t, const MLoopUV *> TextureUVMapping;
// key is material number, value is the TextureUVMapping for the material
typedef std::map<uint32_t, TextureUVMapping> MaterialTextureUVMappings;
MaterialTextureUVMappings matTexUvMappings;
const uint32_t maxMat = static_cast<const uint32_t>(mesh->mat.size());
for (uint32_t m = 0; m < maxMat; ++m)
{
// get material by index
const std::shared_ptr<Material> pMat = mesh->mat[m];
TextureUVMapping texuv;
const uint32_t maxTex = sizeof(pMat->mtex) / sizeof(pMat->mtex[0]);
for (uint32_t t = 0; t < maxTex; ++t)
{
if (pMat->mtex[t] && pMat->mtex[t]->uvname[0])
{
// get the CustomData layer for given uvname and correct type
const MLoopUV *pLoop = static_cast<const MLoopUV*>(getCustomDataLayerData(mesh->ldata, CD_MLOOPUV, pMat->mtex[t]->uvname));
if (pLoop)
{
texuv.insert(std::make_pair(t, pLoop));
}
}
}
matTexUvMappings.insert(std::make_pair(m, texuv));
}
// collect texture coordinates, they're stored in a separate per-face buffer
if (mesh->mtface || mesh->mloopuv) {
if (mesh->totface > static_cast<int> ( mesh->mtface.size())) {
@@ -1028,8 +1059,17 @@ void BlenderImporter::ConvertMesh(const Scene& /*in*/, const Object* /*obj*/, co
}
for (std::vector<aiMesh*>::iterator it = temp->begin()+old; it != temp->end(); ++it) {
ai_assert((*it)->mNumVertices && (*it)->mNumFaces);
(*it)->mTextureCoords[0] = new aiVector3D[(*it)->mNumVertices];
const auto itMatTexUvMapping = matTexUvMappings.find((*it)->mMaterialIndex);
if (itMatTexUvMapping == matTexUvMappings.end()) {
// default behaviour like before
(*it)->mTextureCoords[0] = new aiVector3D[(*it)->mNumVertices];
}
else {
// create texture coords for every mapped tex
for (uint32_t i = 0; i < itMatTexUvMapping->second.size(); ++i) {
(*it)->mTextureCoords[i] = new aiVector3D[(*it)->mNumVertices];
}
}
(*it)->mNumFaces = (*it)->mNumVertices = 0;
}
@@ -1051,13 +1091,35 @@ void BlenderImporter::ConvertMesh(const Scene& /*in*/, const Object* /*obj*/, co
aiMesh* const out = temp[ mat_num_to_mesh_idx[ v.mat_nr ] ];
const aiFace& f = out->mFaces[out->mNumFaces++];
aiVector3D* vo = &out->mTextureCoords[0][out->mNumVertices];
for (unsigned int j = 0; j < f.mNumIndices; ++j,++vo,++out->mNumVertices) {
const MLoopUV& uv = mesh->mloopuv[v.loopstart + j];
vo->x = uv.uv[0];
vo->y = uv.uv[1];
const auto itMatTexUvMapping = matTexUvMappings.find(v.mat_nr);
if (itMatTexUvMapping == matTexUvMappings.end()) {
// old behavior
aiVector3D* vo = &out->mTextureCoords[0][out->mNumVertices];
for (unsigned int j = 0; j < f.mNumIndices; ++j, ++vo, ++out->mNumVertices) {
const MLoopUV& uv = mesh->mloopuv[v.loopstart + j];
vo->x = uv.uv[0];
vo->y = uv.uv[1];
}
}
else {
// create textureCoords for every mapped tex
for (uint32_t m = 0; m < itMatTexUvMapping->second.size(); ++m) {
const MLoopUV *tm = itMatTexUvMapping->second[m];
aiVector3D* vo = &out->mTextureCoords[m][out->mNumVertices];
uint32_t j = 0;
for (; j < f.mNumIndices; ++j, ++vo) {
const MLoopUV& uv = tm[v.loopstart + j];
vo->x = uv.uv[0];
vo->y = uv.uv[1];
}
// only update written mNumVertices in last loop
// TODO why must the numVertices be incremented here?
if (m == itMatTexUvMapping->second.size() - 1)
{
out->mNumVertices += j;
}
}
}
}
}