現(xiàn)與工程實(shí)踐)
做網(wǎng)格參數(shù)化的人繞不開(kāi)的一個(gè)名字就是LSCMLeast Squares Conformal Maps最小二乘保角參數(shù)化。我最早接觸它是在做紋理映射的時(shí)候把一個(gè)三維人頭模型展開(kāi)到二維平面再用棋盤(pán)格紋理貼回去如果參數(shù)化做得好棋盤(pán)格幾乎不變形做得不好臉上到處是拉伸和扭曲。LSCM就是那個(gè)能把“角度畸變”壓到最低的經(jīng)典算法2002年由Bruno Lévy等人提出直到今天它仍然是UV展開(kāi)、網(wǎng)格重建、重網(wǎng)格化、形態(tài)分析等一堆下游工作的默認(rèn)起點(diǎn)之一。這篇內(nèi)容會(huì)從LSCM的核心數(shù)學(xué)思想講起把“為什么是最小二乘”“為什么叫保角”“離散網(wǎng)格上怎么落地”這幾件事徹底說(shuō)透再帶著你用C/Eigen從零搭一個(gè)可運(yùn)行的實(shí)現(xiàn)最后聊一聊我在實(shí)際項(xiàng)目中踩過(guò)的坑。適合正在做幾何處理、想搞懂參數(shù)化原理的開(kāi)發(fā)者也適合只是想在項(xiàng)目里快速接入U(xiǎn)V展開(kāi)功能、但不想只會(huì)調(diào)庫(kù)的同學(xué)。1. 為什么網(wǎng)格參數(shù)化繞不開(kāi)LSCM1.1 參數(shù)化到底解決的什么問(wèn)題參數(shù)化的本質(zhì)很簡(jiǎn)單給定一張三維曲面網(wǎng)格我們要為它找到一個(gè)二維參數(shù)域上的坐標(biāo)通常叫UV坐標(biāo)使得從三維到二維的映射盡可能“保真”。什么叫保真不同場(chǎng)景定義不同。紋理映射希望角度不變因?yàn)榻嵌茸兞思y理圖案會(huì)歪斜重新網(wǎng)格化希望面積盡量均勻因?yàn)槊娣e畸變會(huì)直接改變采樣密度物理仿真里的殼結(jié)構(gòu)展開(kāi)甚至要求邊長(zhǎng)都不變那是等距映射。但現(xiàn)實(shí)中絕大部分網(wǎng)格都有非零高斯曲率比如球面、人臉、衣服曲面它們無(wú)論如何都無(wú)法無(wú)畸變地展開(kāi)成一個(gè)平面。這一點(diǎn)由Gauss-Bonnet定理從根上決定了平面域總曲率為零而曲面總曲率由拓?fù)錄Q定兩者不相等就必然產(chǎn)生畸變。既然無(wú)法做到所有度量都完美保持那就必須選擇“優(yōu)先保什么”。LSCM選擇的是保角度也就是共形映射。這個(gè)選擇非常聰明角度畸變是最容易被人眼感知的畸變之一而且在所有可微映射中共形映射對(duì)面積和邊長(zhǎng)的扭曲方式也相對(duì)“溫和”它允許局部縮放但縮放比例各向同性像一個(gè)橡皮膜被均勻拉伸——不會(huì)出現(xiàn)“某個(gè)方向被拉長(zhǎng)、另一個(gè)方向被壓扁”的剪應(yīng)力感。所以LSCM最合適的定位是當(dāng)你需要把三維表面攤平又不希望紋理圖案被歪斜、變形、撕裂時(shí)它幾乎是第一選擇。1.2 三類(lèi)參數(shù)化算法里L(fēng)SCM的位置參數(shù)化算法主流可以分三類(lèi)等距映射、保面積映射、共形映射。等距映射要求所有邊長(zhǎng)和角度同時(shí)保持約束最強(qiáng)對(duì)一般網(wǎng)格幾乎無(wú)解只能把畸變攤到整個(gè)面上代表有ARAP盡可能剛體這類(lèi)迭代算法。保面積映射只要求面積不變角度可以歪常見(jiàn)于面積加權(quán)類(lèi)方法。共形映射只要求角度不變?cè)试S均勻縮放代表就是LSCM、ABF、共形映射族。類(lèi)型保角度保面積保邊長(zhǎng)典型算法適用場(chǎng)景等距是是是ARAP、彈簧模型形狀近似可展平的薄殼類(lèi)保面積否是否面積加權(quán)參數(shù)化面積均勻采樣、部分仿真共形是否否LSCM、ABF、DCP紋理映射、UV展開(kāi)、重網(wǎng)格化從這個(gè)表可以看出LSCM不是萬(wàn)能的它能很好地保持角度但不保證面積比例和邊長(zhǎng)比例。如果用來(lái)做直接建模、加工類(lèi)項(xiàng)目后期還需要根據(jù)面積畸變做補(bǔ)償。但作為通用UV展開(kāi)手段它兼顧了效果、速度、實(shí)現(xiàn)門(mén)檻三者的平衡——這也是我至今仍然在很多項(xiàng)目里默認(rèn)先用LSCM打底的原因。2. LSCM的數(shù)學(xué)原理從Cauchy-Riemann到最小二乘2.1 共形映射的連續(xù)版本要理解LSCM得先理解復(fù)分析里的共形映射。設(shè)二維平面上一個(gè)映射寫(xiě)成復(fù)函數(shù)形式 φ u i v其中 (u, v) 就是參數(shù)坐標(biāo)。這個(gè)映射共形的充要條件是滿(mǎn)足Cauchy-Riemann方程組?u/?x ?v/?y?u/?y -?v/?x這兩個(gè)式子表達(dá)了一個(gè)幾何直覺(jué)參數(shù)域里的局部小正方形經(jīng)過(guò)映射之后對(duì)應(yīng)到原表面仍然是一個(gè)“局部旋轉(zhuǎn)等比例縮放”的正方形而不是被壓扁或拉長(zhǎng)的矩形。用生活化的方式理解你在橡皮膜上畫(huà)滿(mǎn)方格共形映射相當(dāng)于你均勻拉扯橡皮膜每個(gè)方格還是方格只是整體可能變大變小、旋轉(zhuǎn)了一定角度。這個(gè)Cauchy-Riemann條件還能寫(xiě)成更簡(jiǎn)潔的復(fù)形式。如果定義復(fù)梯度算子 ?/?z? (?/?x i?/?y)/2那么共形條件等價(jià)于 ?φ/?z? 0。也就是說(shuō)共形映射是復(fù)平面上“最圓潤(rùn)”的那類(lèi)映射它沒(méi)有剪切畸變只有縮放。但現(xiàn)實(shí)是一個(gè)任意三維曲面網(wǎng)格幾乎不可能找到嚴(yán)格滿(mǎn)足Cauchy-Riemann方程的平面參數(shù)化。因?yàn)槿S網(wǎng)格的高斯曲率分布是任意且離散的想把它散開(kāi)成平面必然在局部產(chǎn)生扭曲。所以LSCM做了一個(gè)關(guān)鍵妥協(xié)——不要求每個(gè)點(diǎn)都嚴(yán)格共形而是最小化共形條件的違反程度。2.2 從“嚴(yán)格共形”到“最小二乘”的關(guān)鍵一步LSCM把Cauchy-Riemann方程的兩個(gè)等式改造成一個(gè)能量函數(shù)E_LSCM(φ) ∫_Ω ( ?u/?x - ?v/?y )2 ( ?u/?y ?v/?x )2 dxdy這個(gè)積分的意義很直白如果映射嚴(yán)格共形兩項(xiàng)都為零能量為零如果映射有角度畸變能量是一個(gè)正數(shù)數(shù)值越大畸變?cè)絿?yán)重。LSCM要做的就是找到UV坐標(biāo)讓這個(gè)能量盡可能小。為什么用平方而不是絕對(duì)值因?yàn)槠椒揭院竽芰亢瘮?shù)變成UV坐標(biāo)的二次型二次型的極值問(wèn)題可以直接通過(guò)求解線(xiàn)性方程組得到。這是整個(gè)算法最漂亮的地方一個(gè)看似復(fù)雜的幾何畸變問(wèn)題被轉(zhuǎn)換成了一次稀疏線(xiàn)性系統(tǒng)求解。接下來(lái)的問(wèn)題是這個(gè)二次型在離散三角形網(wǎng)格上長(zhǎng)什么樣答案是把每個(gè)三角形上的梯度算出來(lái)然后組裝成一個(gè)全局的稀疏矩陣。對(duì)每個(gè)三角形它的“梯度矩陣”可以預(yù)先算好再乘上三角形面積加權(quán)最后拼成大矩陣。這就是LSCM全部的實(shí)現(xiàn)核心。2.3 兩個(gè)固定點(diǎn)背后的自由度二次型最小化還有一個(gè)隱患如果沒(méi)有任何約束UV坐標(biāo)存在大量的平凡自由度。你可以把所有UV平移一段距離能量不變旋轉(zhuǎn)一個(gè)角度能量不變整體縮放能量也不變。也就是說(shuō)解不唯一。這就像你問(wèn)“怎么把一個(gè)正方形放在桌面上最穩(wěn)”如果沒(méi)有任何約束答案有無(wú)窮多放左邊、放右邊、轉(zhuǎn)個(gè)角度、放大縮小都行。LSCM的做法是在網(wǎng)格上固定兩個(gè)頂點(diǎn)的UV坐標(biāo)比如固定頂點(diǎn) p0 和 p1讓它們的UV分別等于 (0,0) 和 (1,0)。為什么是兩個(gè)點(diǎn)因?yàn)閺?fù)平面上的相似變換正好有4個(gè)實(shí)自由度平移2個(gè)x、y方向、旋轉(zhuǎn)1個(gè)、縮放1個(gè)。固定兩個(gè)點(diǎn)提供了4個(gè)約束方程剛好把自由度全部消除。實(shí)際操作中固定點(diǎn)的選擇會(huì)影響結(jié)果的質(zhì)量如果兩個(gè)點(diǎn)靠得太近或者恰好落在同一個(gè)退化三角形上求解出來(lái)的參數(shù)化可能非常不穩(wěn)定。一般我會(huì)選網(wǎng)格包圍盒上距離最遠(yuǎn)的兩個(gè)頂點(diǎn)來(lái)固定這能讓縮放尺度盡量貼近網(wǎng)格整體尺寸減少數(shù)值問(wèn)題。3. 從原理到代碼數(shù)值實(shí)現(xiàn)的關(guān)鍵細(xì)節(jié)3.1 局部坐標(biāo)與梯度組裝先確認(rèn)輸入一個(gè)三角網(wǎng)格頂點(diǎn)數(shù)組和三角形索引數(shù)組。每個(gè)三角形有三個(gè)三維頂點(diǎn) p0、p1、p2。要在這個(gè)三角形上計(jì)算2D梯度得先在局部建立一組正交基把三個(gè)頂點(diǎn)投影到平面上。我常用的做法是令 e1 p1 - p0令 e2 p2 - p0局部坐標(biāo)第一個(gè)點(diǎn) p0 設(shè)為 (0, 0)第二個(gè)點(diǎn) p1 設(shè)為 (|e1|, 0)第三個(gè)點(diǎn) p2 的局部坐標(biāo)為 ( (e1·e2)/|e1|, |e1×e2|/|e1| )這樣得到的是三角形在自身切平面上的二維表示。然后計(jì)算這個(gè)三角形上的梯度算子矩陣 D_t它是一個(gè) 2×3 矩陣作用在三個(gè)頂點(diǎn)的標(biāo)量值上得到該標(biāo)量場(chǎng)的平面梯度。具體表達(dá)式可以用面積坐標(biāo)推導(dǎo)這里直接給出常見(jiàn)形式設(shè)局部三角形面積為 A三個(gè)局部點(diǎn)坐標(biāo)分別為 (x0,y0)、(x1,y1)、(x2,y2)則梯度算子?f/?x [(y1-y2)f0 (y2-y0)f1 (y0-y1)f2] / (2A)?f/?y [(x2-x1)f0 (x0-x2)f1 (x1-x0)f2] / (2A)把這個(gè)式子寫(xiě)成矩陣 D_t每個(gè)三角形的LSCM能量貢獻(xiàn)就是E_t A_t · | D_t · (u 或 v) |2 的組合把u、v交錯(cuò)排成一個(gè)未知量向量 x [u0, v0, u1, v1, ..., un, vn]每個(gè)三角形會(huì)貢獻(xiàn)一個(gè)小的稠密矩陣最后疊加成全局稀疏矩陣 M。目標(biāo)變成min x? M x再加上固定點(diǎn)的約束把對(duì)應(yīng)行和列刪掉移項(xiàng)到右邊就變成一個(gè)標(biāo)準(zhǔn)的最小二乘問(wèn)題 A x b。如果你只想要一套能跑的代碼到這里基本就夠了——理解了這個(gè)流程你已經(jīng)能自己寫(xiě)出LSCM。3.2 矩陣結(jié)構(gòu)與稀疏求解LSCM組出來(lái)的大矩陣 M 是一個(gè) 2n×2n 的稀疏半正定矩陣n是頂點(diǎn)數(shù)。由于每個(gè)三角形只連接三個(gè)頂點(diǎn)非零元非常有限老實(shí)的做法是用稀疏矩陣存儲(chǔ)避免稠密矩陣把內(nèi)存炸掉。求解時(shí)一般用稀疏Cholesky分解。Eigen里對(duì)應(yīng)的類(lèi)是SimplicialLDLT或SimplicialLLT也可以用SuiteSparse的CHOLMOD。對(duì)于十萬(wàn)頂點(diǎn)的網(wǎng)格這類(lèi)直接法通常幾秒到幾十秒就能出結(jié)果速度可以接受。如果網(wǎng)格更大或者需要實(shí)時(shí)預(yù)覽可以用共軛梯度法配合預(yù)條件子但要注意共軛梯度法需要矩陣正定——這引出了下一個(gè)關(guān)鍵問(wèn)題。3.3 負(fù)權(quán)重與正定性陷阱LSCM組出來(lái)的二次型矩陣不一定正定。原因在于當(dāng)三角形是鈍角三角形時(shí)標(biāo)準(zhǔn)余切權(quán)重會(huì)出現(xiàn)負(fù)值。雖然LSCM采用的是梯度平方形式而不是直接寫(xiě)出余切權(quán)重但兩者在代數(shù)上等價(jià)負(fù)權(quán)重問(wèn)題一樣存在。負(fù)權(quán)重會(huì)導(dǎo)致什么矩陣可能變成病態(tài)的甚至不是半正定的。解出來(lái)的UV坐標(biāo)可能飛出去也就是產(chǎn)生極大的坐標(biāo)值、嚴(yán)重的三角形翻轉(zhuǎn)。一個(gè)很典型的癥狀是同一套代碼在高質(zhì)量的均勻網(wǎng)格上解出來(lái)的UV非常漂亮換成一個(gè)帶大量細(xì)長(zhǎng)三角形的掃描網(wǎng)格后UV直接亂掉。處理方式有幾種。第一在網(wǎng)格預(yù)處理階段做各向同性重網(wǎng)格化把鈍角三角形清理掉這是最有效的辦法。第二對(duì)負(fù)權(quán)重三角形做裁剪或重新加權(quán)比如把負(fù)權(quán)重截?cái)酁榱阍贇w一化但這會(huì)稍微偏離原始LSCM能量需要在實(shí)現(xiàn)中明確記錄。第三檢查求解器是否返回成功如果矩陣不正定及時(shí)報(bào)錯(cuò)而不是硬算。我在實(shí)際項(xiàng)目中遇到最多的情況是網(wǎng)格本身質(zhì)量很差LSCM解出來(lái)UV亂飛很多人第一反應(yīng)是調(diào)求解器參數(shù)其實(shí)根本問(wèn)題在網(wǎng)格質(zhì)量。先把網(wǎng)格修好LSCM就會(huì)恢復(fù)穩(wěn)定。4. 實(shí)操全流程用C/Eigen從零搭一個(gè)LSCM4.1 預(yù)處理網(wǎng)格檢查與切割輸入網(wǎng)格不是隨便拿過(guò)來(lái)就能展開(kāi)。LSCM只適用于拓?fù)錇閳A盤(pán)genus 0帶一條邊界的網(wǎng)格。如果你的模型是封閉的球面拓?fù)浔仨毾惹懈畛鲆粭l路徑把它變成帶邊界拓?fù)?。切割位置的選擇非常影響展平效果。我習(xí)慣把接縫放在曲率變化大的地方比如頭部的耳朵后面、下頜線(xiàn)或者根據(jù)應(yīng)用需求讓用戶(hù)手動(dòng)指定切割路徑。接縫不要放在視覺(jué)中心區(qū)域否則紋理接縫會(huì)非常明顯。預(yù)處理清單檢查網(wǎng)格流形性每條邊最多被兩個(gè)三角形共享檢查三角形方向一致性所有三角形法向指向同一側(cè)如果封閉網(wǎng)格用Dijkstra或最短路徑生成切割線(xiàn)形成單邊界拓?fù)溆?jì)算連通分量LSCM只能處理單一連通分量4.2 核心實(shí)現(xiàn)與代碼下面是一段可運(yùn)行的Eigen實(shí)現(xiàn)核心邏輯。我把它簡(jiǎn)化到LSCM的主干部分幫助你對(duì)照理解。#include Eigen/Sparse #include Eigen/Dense #include vector struct Mesh { std::vectorEigen::Vector3d verts; std::vectorEigen::Vector3i tris; }; // 組裝 LSCM 稀疏矩陣 M并返回固定點(diǎn)約束 void build_lscm_system(const Mesh mesh, Eigen::SparseMatrixdouble M, Eigen::VectorXd b, int fixed0, int fixed1) { int n (int)mesh.verts.size(); int rows 2 * n; std::vectorEigen::Tripletdouble triplets; // 目標(biāo)向量 x [u0,v0, u1,v1, ...] // 每三角形的局部坐標(biāo)與梯度 for (auto tri : mesh.tris) { Eigen::Vector3d p0 mesh.verts[tri[0]]; Eigen::Vector3d p1 mesh.verts[tri[1]]; Eigen::Vector3d p2 mesh.verts[tri[2]]; Eigen::Vector3d e1 p1 - p0; Eigen::Vector3d e2 p2 - p0; double len1 e1.norm(); double len2 e2.norm(); double cosA e1.dot(e2) / (len1 * len2); double sinA e1.cross(e2).norm() / (len1 * len2); // 局部2D坐標(biāo) Eigen::Vector2d q0(0.0, 0.0); Eigen::Vector2d q1(len1, 0.0); Eigen::Vector2d q2(len2 * cosA, len2 * sinA); double A 0.5 * (q1.x()*q2.y() - q2.x()*q1.y()); // 有向面積 // 梯度算子 2x3 Eigen::Matrixdouble,2,3 D; D q1.y()-q2.y(), q2.y()-q0.y(), q0.y()-q1.y(), q2.x()-q1.x(), q0.x()-q2.x(), q1.x()-q0.x(); D / (2.0 * A); // LSCM能量對(duì)u和v分別二次型再組合 // 每個(gè)三角形的貢獻(xiàn)A * |D u|^2 A * |D v|^2 交叉項(xiàng) // 這里直接組裝到全局稀疏矩陣 Eigen::Matrixdouble,3,3 M_loc A * D.transpose() * D; // 對(duì)應(yīng)三角形三個(gè)頂點(diǎn)的u,v索引 int idx[3] { tri[0]*2, tri[1]*2, tri[2]*2 }; for (int ii0; ii3; ii) { for (int jj0; jj3; jj) { // u-u 塊 triplets.emplace_back(idx[ii], idx[jj], M_loc(ii,jj)); // v-v 塊 triplets.emplace_back(idx[ii]1, idx[jj]1, M_loc(ii,jj)); } } // 交叉項(xiàng)來(lái)自Cauchy-Riemann (展開(kāi)后的 -?u/?x ?v/?y ?u/?y ?v/?x) // 完整推導(dǎo)可參考LSCM原論文這里略去交叉項(xiàng)以體現(xiàn)核心組裝思路 // 真實(shí)生產(chǎn)環(huán)境中需要補(bǔ)全否則能量不完整 } // 固定兩個(gè)頂點(diǎn): 把對(duì)應(yīng)行/列移到右邊 // 簡(jiǎn)化做法刪除固定點(diǎn)行/列求解后可填回 // 這里用“移動(dòng)變量法”示意 M.resize(rows, rows); M.setFromTriplets(triplets.begin(), triplets.end()); b.resize(rows); b.setZero(); // 注意此處只是系統(tǒng)組裝骨架實(shí)際求解時(shí)需處理固定點(diǎn)約束 }上面代碼里我把交叉項(xiàng)略去了因?yàn)橥暾归_(kāi)公式較長(zhǎng)。真正生產(chǎn)級(jí)實(shí)現(xiàn)需要補(bǔ)全交叉項(xiàng)否則能量只在“角度完全保持”時(shí)正確但梯度方向會(huì)錯(cuò)。一個(gè)快速核對(duì)方法把每個(gè)三角形的6×6局部矩陣完整算出來(lái)再全局組裝而不是只放D?D。4.3 后處理與結(jié)果驗(yàn)證求解出UV之后第一時(shí)間要做的不是直接拿去貼紋理而是先驗(yàn)證結(jié)果質(zhì)量。我的習(xí)慣是三個(gè)步驟第一步看行列式。對(duì)每個(gè)三角形計(jì)算從三維坐標(biāo)到UV坐標(biāo)的2×2 Jacobian矩陣的行列式。如果行列式出現(xiàn)負(fù)值說(shuō)明該三角形在參數(shù)域里發(fā)生了翻轉(zhuǎn)。LSCM本身不能保證無(wú)翻轉(zhuǎn)出現(xiàn)少量翻轉(zhuǎn)可以接受但大面積翻轉(zhuǎn)就是出問(wèn)題了。第二步看能量值。把每個(gè)三角形的共形能量累加起來(lái)得到一個(gè)全局能量值。這個(gè)數(shù)值本身沒(méi)有絕對(duì)意義但可以用來(lái)對(duì)比不同參數(shù)化參數(shù)的效果。第三步做可視化。把UV坐標(biāo)畫(huà)成二維三角形網(wǎng)格直接肉眼看有沒(méi)有翻轉(zhuǎn)、重疊、極度拉伸的區(qū)域。如果配合棋盤(pán)格紋理貼回模型更能直觀看出角度畸變分布。5. 常見(jiàn)問(wèn)題與排查技巧實(shí)錄5.1 解出來(lái)的UV大面積翻轉(zhuǎn)這種情況最多的原因就是固定點(diǎn)選擇不當(dāng)或者網(wǎng)格質(zhì)量差。先檢查三角形最小角度如果網(wǎng)格里大量存在小于10度的細(xì)長(zhǎng)三角形LSCM的數(shù)值穩(wěn)定性會(huì)非常差。我的處理順序是先做網(wǎng)格清理和重網(wǎng)格化如果網(wǎng)格質(zhì)量沒(méi)問(wèn)題再換固定點(diǎn)方案還是不行就考慮改用ARAP或Tutte嵌入做初始化再用LSCM迭代收尾。在工程上很少有一個(gè)LSCM單發(fā)到底就能完美處理所有網(wǎng)格的情況通常需要和其他算法配合。5.2 結(jié)果沒(méi)有翻轉(zhuǎn)但紋理拉伸嚴(yán)重這時(shí)候問(wèn)題可能不是角度畸變而是面積畸變。LSCM只保證角度盡量一致面積會(huì)被不均勻地縮放。高曲率區(qū)域會(huì)被壓縮得很小低曲率區(qū)域又會(huì)被放大。紋理顯示時(shí)小面積區(qū)域會(huì)因?yàn)榧y素密度過(guò)高而顯得糊。解決方案有兩條路一是接受共形展開(kāi)在后處理里用各向異性過(guò)濾或多級(jí)紋理緩解二是先跑LSCM再以它作為初始解跑幾輪面積補(bǔ)償?shù)热缰鸩郊由厦娣e正則項(xiàng)。很多工業(yè)級(jí)UV展開(kāi)工具實(shí)際采用的就是“LSCM打底 面積補(bǔ)償”的組合。5.3 矩陣求解慢或者內(nèi)存爆炸十萬(wàn)頂點(diǎn)以?xún)?nèi)的網(wǎng)格用Eigen SimplicialLDLT完全沒(méi)問(wèn)題。再往上比如百萬(wàn)頂點(diǎn)規(guī)模建議改用共軛梯度法配合不完全Cholesky預(yù)條件子。另外不要忘了LSCM矩陣是對(duì)稱(chēng)的存儲(chǔ)時(shí)用SparseMatrix 加RowMajor標(biāo)記組裝時(shí)用Triplet批量插入這些細(xì)節(jié)對(duì)性能影響很大。還有一個(gè)小技巧固定點(diǎn)約束不要用“直接刪行刪列”的方式處理那樣會(huì)破壞矩陣結(jié)構(gòu)的對(duì)稱(chēng)性。更優(yōu)雅的方法是使用拉格朗日乘子或者把對(duì)應(yīng)行設(shè)為單位行、對(duì)應(yīng)列乘到右邊保持稀疏求解的高效性。不過(guò)從實(shí)現(xiàn)簡(jiǎn)單角度刪行刪列其實(shí)也夠用只是矩陣重排稍微麻煩。5.4 常見(jiàn)問(wèn)題速查表現(xiàn)象可能原因處理建議UV坐標(biāo)飛出去正定性破壞、固定點(diǎn)不佳重網(wǎng)格化、換固定點(diǎn)大面積翻轉(zhuǎn)網(wǎng)格質(zhì)量差各向同性重網(wǎng)格化局部過(guò)度拉伸面積畸變LSCM面積正則求解報(bào)錯(cuò)矩陣不正定啟用預(yù)條件子或換求解器紋理接縫明顯切割線(xiàn)位置不好把接縫放到視覺(jué)盲區(qū)6. 一點(diǎn)個(gè)人體會(huì)我自己在項(xiàng)目里用LSCM最多的時(shí)候是做人臉建模和服裝曲面展平。踩過(guò)最深的坑就是“以為L(zhǎng)SCM只是解一個(gè)線(xiàn)性系統(tǒng)所以什么問(wèn)題都能交給它”。實(shí)際上LSCM的成功率高度依賴(lài)預(yù)處理網(wǎng)格要干凈拓?fù)湟_切割要合理。那些看起來(lái)神奇的UV展開(kāi)效果背后往往是精細(xì)的預(yù)處理流程和多次驗(yàn)證。如果你正在學(xué)習(xí)這一塊我的建議是不要只盯著代碼跑通而是親手做一遍能量推導(dǎo)把Cauchy-Riemann方程展開(kāi)成二次型算出每個(gè)三角形的局部矩陣再全局組裝。這個(gè)過(guò)程做完一遍比你看十篇綜述都有用。之后無(wú)論是擴(kuò)展到ARAP、擬共形映射還是用到深度學(xué)習(xí)里的可微參數(shù)化層你都會(huì)比別人理解深一層。