From 22bdd2b7a04dd658665c8f99a08dd7880b092ad6 Mon Sep 17 00:00:00 2001 From: Mike Baran Date: Wed, 19 Jan 2022 15:35:36 -0500 Subject: [PATCH 1/4] Don't allow empty URIs as two or more textures could stomp on eachother --- src/meshlabplugins/io_gltf/gltf_loader.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/meshlabplugins/io_gltf/gltf_loader.cpp b/src/meshlabplugins/io_gltf/gltf_loader.cpp index 9a9f95d71..c92cf0194 100644 --- a/src/meshlabplugins/io_gltf/gltf_loader.cpp +++ b/src/meshlabplugins/io_gltf/gltf_loader.cpp @@ -331,6 +331,10 @@ void loadMeshPrimitive( QImage qimg(img.image.data(), img.width, img.height, QImage::Format_RGBA8888); if (!qimg.isNull()){ QImage copy = qimg.copy(); + if (uri.empty()) + { + uri = "texture_" + std::to_string(textureImg); + } m.addTexture(uri, copy); } else { From 4ed4d9729519b52e976abb1eecc9d13beafacfea Mon Sep 17 00:00:00 2001 From: Mike Baran Date: Wed, 19 Jan 2022 15:36:07 -0500 Subject: [PATCH 2/4] Use wedge text coordinates to support multi texturing --- src/meshlabplugins/io_gltf/gltf_loader.cpp | 24 ++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/src/meshlabplugins/io_gltf/gltf_loader.cpp b/src/meshlabplugins/io_gltf/gltf_loader.cpp index c92cf0194..68094cc77 100644 --- a/src/meshlabplugins/io_gltf/gltf_loader.cpp +++ b/src/meshlabplugins/io_gltf/gltf_loader.cpp @@ -405,7 +405,10 @@ void loadMeshPrimitive( cb(progress.progress(), "Loading vertex texcoords"); res = loadAttribute(m, ivp, model, p, TEXCOORD_0, textureImg); if (res) + { mask |= vcg::tri::io::Mask::IOM_VERTTEXCOORD; + mask |= vcg::tri::io::Mask::IOM_WEDGTEXCOORD; + } progress.increment(); @@ -569,6 +572,7 @@ void populateAttr( break; case TEXCOORD_0: m.enable(vcg::tri::io::Mask::IOM_VERTTEXCOORD); + m.enable(vcg::tri::io::Mask::IOM_WEDGTEXCOORD); populateVTextCoords(ivp, array, number, textID); break; break; case INDICES: @@ -647,18 +651,26 @@ void populateTriangles( CMeshO::FaceIterator fi = vcg::tri::Allocator::AddFaces(m.cm, triNumber); for (unsigned int i = 0; i < triNumber*3; i+=3, ++fi) { - fi->V(0) = ivp[triArray[i]]; - fi->V(1) = ivp[triArray[i+1]]; - fi->V(2) = ivp[triArray[i+2]]; + for (int j = 0; j < 3; ++j) { + fi->V(j) = ivp[triArray[i+j]]; + + fi->WT(j).u() = fi->V(j)->T().u(); + fi->WT(j).v() = fi->V(j)->T().v(); + fi->WT(j).n() = fi->V(j)->T().N(); + } } } else { CMeshO::FaceIterator fi = vcg::tri::Allocator::AddFaces(m.cm, ivp.size()/3); for (unsigned int i = 0; i < ivp.size(); i+=3, ++fi) { - fi->V(0) = ivp[i]; - fi->V(1) = ivp[i+1]; - fi->V(2) = ivp[i+2]; + for (int j = 0; j < 3; ++j) { + fi->V(j) = ivp[i+j]; + + fi->WT(j).u() = fi->V(j)->T().u(); + fi->WT(j).v() = fi->V(j)->T().v(); + fi->WT(j).n() = fi->V(j)->T().N(); + } } } } From 518abb15904ce3cccdc4b760e9b1c7d5c9dd6335 Mon Sep 17 00:00:00 2001 From: Mike Baran Date: Thu, 20 Jan 2022 16:53:39 -0500 Subject: [PATCH 3/4] Don't reassign textureImg, when the texture already exists --- src/meshlabplugins/io_gltf/gltf_loader.cpp | 26 +++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/src/meshlabplugins/io_gltf/gltf_loader.cpp b/src/meshlabplugins/io_gltf/gltf_loader.cpp index 68094cc77..0ec01f626 100644 --- a/src/meshlabplugins/io_gltf/gltf_loader.cpp +++ b/src/meshlabplugins/io_gltf/gltf_loader.cpp @@ -326,16 +326,28 @@ void loadMeshPrimitive( std::string uri = img.uri; uri = std::regex_replace(uri, std::regex("\\%20"), " "); + bool textureAlreadyExists = false; if (img.image.size() > 0) { if (img.bits == 8 || img.component == 4) { QImage qimg(img.image.data(), img.width, img.height, QImage::Format_RGBA8888); if (!qimg.isNull()){ QImage copy = qimg.copy(); - if (uri.empty()) - { + if (uri.empty()) { uri = "texture_" + std::to_string(textureImg); } - m.addTexture(uri, copy); + + QImage existingTexture = m.getTexture(uri); + if (existingTexture.isNull()) { + m.addTexture(uri, copy); + } + else { + //use the existing texture index + auto it = std::find(m.cm.textures.begin(), m.cm.textures.end(), uri); + textureAlreadyExists = it != m.cm.textures.end(); + if (textureAlreadyExists) { + textureImg = it - m.cm.textures.begin(); + } + } } else { m.cm.textures.push_back(uri); @@ -349,8 +361,12 @@ void loadMeshPrimitive( //set to load later (could be format non-supported by tinygltf) m.cm.textures.push_back(uri); } - //set the id of the texture: we need it when set uv coords - textureImg = m.cm.textures.size()-1; + + if (!textureAlreadyExists) + { + //set the id of the texture: we need it when set uv coords + textureImg = m.cm.textures.size() - 1; + } } //vector of vertex pointers added to the mesh //this vector is modified only when adding vertex position attributes From bec1c61d06d6eafd47384e5f7fc7dc13c3828e29 Mon Sep 17 00:00:00 2001 From: alemuntoni Date: Fri, 21 Jan 2022 17:10:34 +0100 Subject: [PATCH 4/4] fix adding wedges --- src/meshlabplugins/io_gltf/gltf_loader.cpp | 56 +++++++++++++--------- 1 file changed, 34 insertions(+), 22 deletions(-) diff --git a/src/meshlabplugins/io_gltf/gltf_loader.cpp b/src/meshlabplugins/io_gltf/gltf_loader.cpp index 0ec01f626..e6d896a15 100644 --- a/src/meshlabplugins/io_gltf/gltf_loader.cpp +++ b/src/meshlabplugins/io_gltf/gltf_loader.cpp @@ -300,7 +300,8 @@ void loadMeshPrimitive( progress.setStep(oldStep/GLTF_ATTR_STR.size()+1); int textureImg = -1; //id of the texture associated to the material - bool vCol = false; //used if a material has a base color for all the primitive + bool vCol = false; // used if a material has a base color for all the primitive + bool vTex = false; // used if a material has a texture vcg::Color4b col; //the base color, to be set to all the vertices if (p.material >= 0) { //if the primitive has a material @@ -321,6 +322,7 @@ void loadMeshPrimitive( } } if (textureImg != -1) { //if we found a texture + vTex = true; const tinygltf::Image& img = model.images[model.textures[textureImg].source]; //add the path of the texture to the mesh std::string uri = img.uri; @@ -389,11 +391,17 @@ void loadMeshPrimitive( //if the mesh has a base color, set it to vertex colors if (vCol) { mask |= vcg::tri::io::Mask::IOM_VERTCOLOR; - m.enable(vcg::tri::io::Mask::IOM_VERTCOLOR); + m.updateDataMask(MeshModel::MM_VERTCOLOR); for (auto v : ivp) v->C() = col; } + // if the mesh has a texture, enable texcoords to the mesh + if (vTex) { + m.updateDataMask(MeshModel::MM_VERTTEXCOORD); + m.updateDataMask(MeshModel::MM_WEDGTEXCOORD); + } + if (cb) cb(progress.progress(), "Loading vertex normals"); //load all the other vertex attributes (ivp is not modified by these calls) @@ -414,15 +422,14 @@ void loadMeshPrimitive( if (cb) cb(progress.progress(), "Loading vertex colors"); res = loadAttribute(m, ivp, model, p, COLOR_0); - if (res) + if (res) { mask |= vcg::tri::io::Mask::IOM_VERTCOLOR; + } progress.increment(); if (cb) cb(progress.progress(), "Loading vertex texcoords"); res = loadAttribute(m, ivp, model, p, TEXCOORD_0, textureImg); - if (res) - { - mask |= vcg::tri::io::Mask::IOM_VERTTEXCOORD; + if (res) { mask |= vcg::tri::io::Mask::IOM_WEDGTEXCOORD; } progress.increment(); @@ -434,6 +441,15 @@ void loadMeshPrimitive( loadAttribute(m, ivp, model, p, INDICES); progress.increment(); + // if vTex was true, it means that we loaded texcoords, that have been transfered from vertex to + // wedges when loading triangle indices. Therefore, we can remove vertex texcoords and leave + // only wedges, which are the only that can be rendered with multiple textures in meshlab + // TODO: remove this mechanism whenever vertex texcoords allow to render multiple textures in + // vcg. + if (vTex) { + m.clearDataMask(MeshModel::MM_VERTTEXCOORD); + } + if (cb) cb(progress.progress(), "Loaded all attributes of current mesh"); @@ -585,12 +601,8 @@ void populateAttr( populateVNormals(ivp, array, number); break; case COLOR_0: populateVColors(ivp, array, number, textID); break; - break; case TEXCOORD_0: - m.enable(vcg::tri::io::Mask::IOM_VERTTEXCOORD); - m.enable(vcg::tri::io::Mask::IOM_WEDGTEXCOORD); populateVTextCoords(ivp, array, number, textID); break; - break; case INDICES: populateTriangles(m, ivp, array, number/3); break; } @@ -667,12 +679,12 @@ void populateTriangles( CMeshO::FaceIterator fi = vcg::tri::Allocator::AddFaces(m.cm, triNumber); for (unsigned int i = 0; i < triNumber*3; i+=3, ++fi) { - for (int j = 0; j < 3; ++j) { - fi->V(j) = ivp[triArray[i+j]]; - - fi->WT(j).u() = fi->V(j)->T().u(); - fi->WT(j).v() = fi->V(j)->T().v(); - fi->WT(j).n() = fi->V(j)->T().N(); + for (int j = 0; j < 3; ++j) { + fi->V(j) = ivp[triArray[i+j]]; + + fi->WT(j).u() = fi->V(j)->T().u(); + fi->WT(j).v() = fi->V(j)->T().v(); + fi->WT(j).n() = fi->V(j)->T().N(); } } } @@ -680,12 +692,12 @@ void populateTriangles( CMeshO::FaceIterator fi = vcg::tri::Allocator::AddFaces(m.cm, ivp.size()/3); for (unsigned int i = 0; i < ivp.size(); i+=3, ++fi) { - for (int j = 0; j < 3; ++j) { - fi->V(j) = ivp[i+j]; - - fi->WT(j).u() = fi->V(j)->T().u(); - fi->WT(j).v() = fi->V(j)->T().v(); - fi->WT(j).n() = fi->V(j)->T().N(); + for (int j = 0; j < 3; ++j) { + fi->V(j) = ivp[i+j]; + + fi->WT(j).u() = fi->V(j)->T().u(); + fi->WT(j).v() = fi->V(j)->T().v(); + fi->WT(j).n() = fi->V(j)->T().N(); } } }