実装イメージ:曲面をグリッドで評価して、点群と比べる (u, v) のグリッドを固定すると、テッセレーションは制御点と重みについての滑らかな式になる。分岐も argmax も通らないので、点群 との距離をそのまま backward できる。 パッチ数(平均 2546) 4 = 1 方向の制御点の数(3 次で固定) r = 評価するグリッドの細かさ dP, w_raw = decoder(slat) # デコーダ:SLAT から変位 (N, 4, 4, 3) と重み (N, 4, 4) を予測 dP = scatter_mean(dP, shared_id) # 共有する境界の点は、予測を平均して 1 つに # N = w_raw = scatter_mean(w_raw, shared_id) 初期位置(quad の 4 隅から補間)に変位を足す w = F.softplus(w_raw) # 重みは正に保つ Bu = bernstein(torch.linspace(0, 1, r)) # (r, 4):グリッドの r 点での基底 4 個の値。学習しない定数 num = torch.einsum("ui,vj,nij,nijk->nuvk", Bu, Bu, w, P) # S(u, v) の分子 den = torch.einsum("ui,vj,nij->nuv", Bu, Bu, w) # S(u, v) の分母 V = num / den[..., None] # (N, r, r, 3):S(u, v) をグリッドで評価した座標(メッシュの頂点) X = sample_points(V, faces_fixed) # 三角形のつなぎ方は固定 loss = chamfer(X, Y_gt) + reg(P, w, V) # reg:正則化(G1・Laplacian)と VAE の KL loss.backward() # → 制御点 → デコーダ → エンコーダ P = P0 + torch.tanh(dP) # 論文の記述をもとにした概念的な疑似コード。学習中にグリッド r は 4×4 → 16×16、比較に使う点数は 16K → 100K へ段階的に増やす § 2 DreamCAD · 実装イメージ 16 / 50