@@ -210,39 +210,6 @@ struct MeshTexture {
210210 };
211211 typedef cList<SeamVertex,const SeamVertex&,1 ,256 ,uint32_t > SeamVertices;
212212
213- // used to iterate vertex labels
214- struct PatchIndex {
215- bool bIndex;
216- union {
217- uint32_t idxPatch;
218- uint32_t idxSeamVertex;
219- };
220- };
221- typedef CLISTDEF0 (PatchIndex) PatchIndices;
222- struct VertexPatchIterator {
223- uint32_t idx;
224- uint32_t idxPatch;
225- const SeamVertex::Patches* pPatches;
226- inline VertexPatchIterator (const PatchIndex& patchIndex, const SeamVertices& seamVertices) : idx(NO_ID) {
227- if (patchIndex.bIndex ) {
228- pPatches = &seamVertices[patchIndex.idxSeamVertex ].patches ;
229- } else {
230- idxPatch = patchIndex.idxPatch ;
231- pPatches = NULL ;
232- }
233- }
234- inline operator uint32_t () const {
235- return idxPatch;
236- }
237- inline bool Next () {
238- if (pPatches == NULL )
239- return (idx++ == NO_ID);
240- if (++idx >= pPatches->size ())
241- return false ;
242- idxPatch = (*pPatches)[idx].idxPatch ;
243- return true ;
244- }
245- };
246213
247214 // used to sample seam edges
248215 typedef TAccumulator<Color> AccumColor;
@@ -289,12 +256,12 @@ struct MeshTexture {
289256 #if TEXOPT_FACEOUTLIER != TEXOPT_FACEOUTLIER_NA
290257 bool FaceOutlierDetection (FaceDataArr& faceDatas, float fOutlierThreshold ) const ;
291258 #endif
292-
259+
293260 void CreateVirtualFaces (const FaceDataViewArr& facesDatas, FaceDataViewArr& virtualFacesDatas, VirtualFaceIdxsArr& virtualFaces, unsigned minCommonCameras=2 , float thMaxNormalDeviation=25 .f) const ;
294261 IIndexArr SelectBestView (const FaceDataArr& faceDatas, FIndex fid, unsigned minCommonCameras, float ratioAngleToQuality) const ;
295262
296263 bool FaceViewSelection (unsigned minCommonCameras, float fOutlierThreshold , float fRatioDataSmoothness , int nIgnoreMaskLabel, const IIndexArr& views);
297-
264+
298265 void CreateSeamVertices ();
299266 void GlobalSeamLeveling ();
300267 void LocalSeamLeveling ();
@@ -623,7 +590,7 @@ IIndexArr MeshTexture::SelectBestView(const FaceDataArr& faceDatas, FIndex fid,
623590{
624591 ASSERT (!faceDatas.empty ());
625592 #if 1
626-
593+
627594 // compute scores based on the view quality and its angle to the face normal
628595 float maxQuality = 0 ;
629596 for (const FaceData& faceData: faceDatas)
@@ -647,7 +614,7 @@ IIndexArr MeshTexture::SelectBestView(const FaceDataArr& faceDatas, FIndex fid,
647614 });
648615
649616 #else
650-
617+
651618 // sort qualityPodium in relation to faceDatas[index].quality decreasing
652619 IIndexArr qualityPodium(faceDatas.size());
653620 std::iota(qualityPodium.begin(), qualityPodium.end(), 0);
@@ -685,7 +652,7 @@ IIndexArr MeshTexture::SelectBestView(const FaceDataArr& faceDatas, FIndex fid,
685652 scorePodium.Sort([&scores](IIndex i, IIndex j) {
686653 return scores[i] < scores[j];
687654 });
688-
655+
689656 #endif
690657 IIndexArr cameras (MINF (minCommonCameras, faceDatas.size ()));
691658 FOREACH (i, cameras)
@@ -700,7 +667,7 @@ static bool IsFaceVisible(const MeshTexture::FaceDataArr& faceDatas, const IInde
700667 for (IIndex camId : cameraList) {
701668 if (cfCam == camId) {
702669 if (++camFoundCounter == cameraList.size ())
703- return true ;
670+ return true ;
704671 break ;
705672 }
706673 }
@@ -1136,7 +1103,7 @@ bool MeshTexture::FaceViewSelection(unsigned minCommonCameras, float fOutlierThr
11361103
11371104 graph.clear ();
11381105 }
1139-
1106+
11401107 // create the graph of faces: each vertex is a face and the edges are the edges shared by the faces
11411108 FOREACH (idxFace, faces) {
11421109 MAYBEUNUSED const Mesh::FIndex idx ((Mesh::FIndex)boost::add_vertex (graph));
@@ -1364,45 +1331,26 @@ void MeshTexture::GlobalSeamLeveling()
13641331 ASSERT (!seamVertices.empty ());
13651332 const unsigned numPatches (texturePatches.size ()-1 );
13661333
1367- // find the patch ID for each vertex
1368- PatchIndices patchIndices (vertices.size ());
1369- patchIndices.Memset (0 );
1334+ // assign a row index within the solution vector x to each vertex/patch
1335+ ASSERT (vertices.size () < static_cast <VIndex>(std::numeric_limits<MatIdx>::max ()));
1336+ typedef std::unordered_map<uint32_t ,MatIdx> VertexPatch2RowMap;
1337+ cList<VertexPatch2RowMap> vertpatch2rows (vertices.size ());
1338+
1339+ // find the patch IDs for each vertex
13701340 FOREACH (f, faces) {
13711341 const uint32_t idxPatch (mapIdxPatch[components[f]]);
1342+ if (idxPatch == numPatches)
1343+ continue ;
13721344 const Face& face = faces[f];
13731345 for (int v=0 ; v<3 ; ++v)
1374- patchIndices[face[v]].idxPatch = idxPatch;
1375- }
1376- FOREACH (i, seamVertices) {
1377- const SeamVertex& seamVertex = seamVertices[i];
1378- ASSERT (!seamVertex.patches .empty ());
1379- PatchIndex& patchIndex = patchIndices[seamVertex.idxVertex ];
1380- patchIndex.bIndex = true ;
1381- patchIndex.idxSeamVertex = i;
1346+ vertpatch2rows[face[v]][idxPatch] = 0 ;
13821347 }
13831348
1384- // assign a row index within the solution vector x to each vertex/patch
1385- ASSERT (vertices.size () < static_cast <VIndex>(std::numeric_limits<MatIdx>::max ()));
1349+ // assign a row to each vertex/patch
13861350 MatIdx rowsX (0 );
1387- typedef std::unordered_map<uint32_t ,MatIdx> VertexPatch2RowMap;
1388- cList<VertexPatch2RowMap> vertpatch2rows (vertices.size ());
1389- FOREACH (i, vertices) {
1390- const PatchIndex& patchIndex = patchIndices[i];
1391- VertexPatch2RowMap& vertpatch2row = vertpatch2rows[i];
1392- if (patchIndex.bIndex ) {
1393- // vertex is part of multiple patches
1394- const SeamVertex& seamVertex = seamVertices[patchIndex.idxSeamVertex ];
1395- ASSERT (seamVertex.idxVertex == i);
1396- for (const SeamVertex::Patch& patch: seamVertex.patches ) {
1397- ASSERT (patch.idxPatch != numPatches);
1398- vertpatch2row[patch.idxPatch ] = rowsX++;
1399- }
1400- } else
1401- if (patchIndex.idxPatch < numPatches) {
1402- // vertex is part of only one patch
1403- vertpatch2row[patchIndex.idxPatch ] = rowsX++;
1404- }
1405- }
1351+ FOREACH (i, vertices)
1352+ for (auto & [idxPatch, row] : vertpatch2rows[i])
1353+ row = rowsX++;
14061354
14071355 // fill Tikhonov's Gamma matrix (regularization constraints)
14081356 const float lambda (0 .1f );
@@ -1412,24 +1360,17 @@ void MeshTexture::GlobalSeamLeveling()
14121360 FOREACH (v, vertices) {
14131361 adjVerts.Empty ();
14141362 scene.mesh .GetAdjVertices (v, adjVerts);
1415- VertexPatchIterator itV (patchIndices[v], seamVertices);
1416- while (itV.Next ()) {
1417- const uint32_t idxPatch (itV);
1418- if (idxPatch == numPatches)
1419- continue ;
1420- const MatIdx col (vertpatch2rows[v].at (idxPatch));
1363+ for (const auto & [idxPatch, col] : vertpatch2rows[v]) {
1364+ ASSERT (idxPatch < numPatches);
14211365 for (const VIndex vAdj: adjVerts) {
14221366 if (v >= vAdj)
14231367 continue ;
1424- VertexPatchIterator itVAdj (patchIndices[vAdj], seamVertices);
1425- while (itVAdj.Next ()) {
1426- const uint32_t idxPatchAdj (itVAdj);
1427- if (idxPatch == idxPatchAdj) {
1428- const MatIdx colAdj (vertpatch2rows[vAdj].at (idxPatchAdj));
1429- rows.emplace_back (rowsGamma, col, lambda);
1430- rows.emplace_back (rowsGamma, colAdj, -lambda);
1431- ++rowsGamma;
1432- }
1368+ const auto itVAdj (vertpatch2rows[vAdj].find (idxPatch));
1369+ if (itVAdj != vertpatch2rows[vAdj].end ()) {
1370+ const MatIdx colAdj (itVAdj->second );
1371+ rows.emplace_back (rowsGamma, col, lambda);
1372+ rows.emplace_back (rowsGamma, colAdj, -lambda);
1373+ ++rowsGamma;
14331374 }
14341375 }
14351376 }
@@ -1899,29 +1840,21 @@ void MeshTexture::LocalSeamLeveling()
18991840 if (idxVertPatch0 == SeamVertex::Patches::NO_INDEX)
19001841 continue ;
19011842 const SeamVertex::Patch& patch0 = seamVertex0.patches [idxVertPatch0];
1902- const TexCoord p0 (patch0.proj - offset);
1843+ const TexCoord p0 (patch0.proj - offset);
19031844 // for each edge of this vertex belonging to this patch...
19041845 for (const SeamVertex::Patch::Edge& edge0: patch0.edges ) {
19051846 // select the same edge leaving from the adjacent vertex
19061847 const SeamVertex& seamVertex1 = seamVertices[edge0.idxSeamVertex ];
1907- const uint32_t idxVertPatch0Adj (seamVertex1.patches .Find (idxPatch));
1908- ASSERT (idxVertPatch0Adj != SeamVertex::Patches::NO_INDEX);
1909- const SeamVertex::Patch& patch0Adj = seamVertex1.patches [idxVertPatch0Adj];
1910- const TexCoord p0Adj (patch0Adj.proj -offset);
1911- // find the other patch sharing the same edge (edge with same adjacent vertex)
1912- FOREACH (idxVertPatch1, seamVertex0.patches ) {
1913- if (idxVertPatch1 == idxVertPatch0)
1914- continue ;
1915- const SeamVertex::Patch& patch1 = seamVertex0.patches [idxVertPatch1];
1916- const uint32_t idxEdge1 (patch1.edges .Find (edge0.idxSeamVertex ));
1917- if (idxEdge1 == SeamVertex::Patch::Edges::NO_INDEX)
1848+ const SeamVertex::Patch& patch0Adj = seamVertex1.patches [seamVertex1.patches .Find (idxPatch)];
1849+ const TexCoord p0Adj (patch0Adj.proj - offset);
1850+ // find the other patch sharing the same edge
1851+ for (const SeamVertex::Patch& patch1: seamVertex0.patches ) {
1852+ if (patch1.idxPatch == idxPatch)
19181853 continue ;
1919- const TexCoord& p1 (patch1.proj );
1854+ if (patch1.edges .Find (edge0.idxSeamVertex ) == SeamVertex::Patch::Edges::NO_INDEX)
1855+ continue ; // edge not shared with this patch
19201856 // select the same edge belonging to the second patch leaving from the adjacent vertex
1921- const uint32_t idxVertPatch1Adj (seamVertex1.patches .Find (patch1.idxPatch ));
1922- ASSERT (idxVertPatch1Adj != SeamVertex::Patches::NO_INDEX);
1923- const SeamVertex::Patch& patch1Adj = seamVertex1.patches [idxVertPatch1Adj];
1924- const TexCoord& p1Adj (patch1Adj.proj );
1857+ const SeamVertex::Patch& patch1Adj = seamVertex1.patches [seamVertex1.patches .Find (patch1.idxPatch )];
19251858 // this is an edge separating two (valid) patches;
19261859 // draw it on this patch as the mean color of the two patches
19271860 const Image8U3& image1 (images[texturePatches[patch1.idxPatch ].label ].image );
@@ -1939,17 +1872,15 @@ void MeshTexture::LocalSeamLeveling()
19391872 : image(_image), mask(_mask), image0(_image0), image1(_image1),
19401873 p0(_p0), p0Dir(_p0Adj-_p0), p1(_p1), p1Dir(_p1Adj-_p1), length((float )norm(p0Dir)) {}
19411874 inline void operator ()(const ImageRef& pt) {
1942- const float l ((float )norm (TexCoord (pt)-p0)/length);
19431875 // compute mean color
1944- const TexCoord samplePos0 (p0 + p0Dir * l);
1945- const Color color0 (image0.sample <Sampler,Color>(sampler, samplePos0));
1946- const TexCoord samplePos1 (p1 + p1Dir * l);
1947- const Color color1 (image1.sample <Sampler,Color>(sampler, samplePos1)/255 .f );
1876+ const float l ((float )norm (TexCoord (pt)-p0)/length);
1877+ const Color color0 (image0.sample <Sampler,Color>(sampler, p0 + p0Dir * l));
1878+ const Color color1 (image1.sample <Sampler,Color>(sampler, p1 + p1Dir * l)/255 .f );
19481879 image (pt) = Color ((color0 + color1) * 0 .5f );
19491880 // set mask edge also
19501881 mask (pt) = border;
19511882 }
1952- } data (image, mask, imageOrg, image1, p0, p0Adj, p1, p1Adj );
1883+ } data (image, mask, imageOrg, image1, p0, p0Adj, patch1. proj , patch1Adj. proj );
19531884 Image32F3::DrawLine (p0, p0Adj, data);
19541885 // skip remaining patches,
19551886 // as a manifold edge is shared by maximum two face (one in each patch), which we found already
@@ -1964,7 +1895,7 @@ void MeshTexture::LocalSeamLeveling()
19641895 const Image8U3& img (images[texturePatches[patch.idxPatch ].label ].image );
19651896 accumColor.Add (img.sample <Sampler,Color>(sampler, patch.proj )/255 .f , 1 .f );
19661897 }
1967- const ImageRef pt (ROUND2INT (patch0. proj -offset ));
1898+ const ImageRef pt (ROUND2INT (p0 ));
19681899 image (pt) = accumColor.Normalized ();
19691900 mask (pt) = border;
19701901 }
@@ -2142,7 +2073,7 @@ void MeshTexture::GenerateTexture(bool bGlobalSeamLeveling, bool bLocalSeamLevel
21422073 // try again with a bigger texture
21432074 textureSize *= 2 ;
21442075 if (maxTextureSize > 0 )
2145- textureSize = MAXF (textureSize, maxTextureSize);
2076+ textureSize = MINF (textureSize, maxTextureSize);
21462077 unplacedRects.JoinRemove (newPlacedRects);
21472078 }
21482079 }
0 commit comments