几何部分 loop 细分部分不正常

我在几何部分第二章 loop 面细分的时候,在 cube 细分达不到文档的要求,面是平滑了,但是八个顶点突出。


这是一次细分,可以看到八个顶点明显

这是四次细分,八个顶点更为明显
我觉得应该是新顶点计算有问题,我的实现如下:

if (v->is_new)
        {
            Eigen::Vector3f V1AddV2 = Eigen::Vector3f::Zero();
            Eigen::Vector3f V3AddV4 = Eigen::Vector3f::Zero();
            Eigen::Vector3f V1V2V3V4 = Eigen::Vector3f::Zero();
            Halfedge* h = v->halfedge;
            do
            {
                if(h->edge->is_new)
                {
                    V1V2V3V4 += h->inv->from->pos;
                }
                h = h->inv->next;
            } while (h != v->halfedge);
            V1AddV2 = 2.0f * v->pos;
            V3AddV4 = V1V2V3V4 - V1AddV2;//不知道为啥这里要减去 V3AddV4 才第一次 cube 正常,之后就不正常,别的物体不正常。
            v->new_pos = 3.0f/8.0f * V1AddV2 + 1.0f/8.0f * V3AddV4;
        }

方法是在 split 生成的新点坐标正好是 1/2(V1+V2),就可以作为一个整体来计算 V1+V2 和 V3+V4,通过对一个新顶点周围顶点对 split 产生的新边遍历求坐标和(图中红色顶点的另外四个虚线的点的坐标和),正好是 V1+V2+V3+V4,V1+V2 是它中点新顶点坐标的两倍,然后这俩求差就可以得到 V3+V4;我觉得这么计算没有问题。但是遇到了怪异的现象:
1.V3AddV4 = V1V2V3V4 - V1AddV2;我把后面减去的 V1+V2 换成 V3+V4(这个显然是错误的),cube 第一次细分和文档一摸一样,但是后续细分错误,其他的 cow 和兔子错误,尖锐和凹陷明显。
2.V3AddV4 = V1V2V3V4 - V1AddV2;仍然用这个,cube 细分错误,但是兔子和 cow 细分正确,他们的表面仔细检查十分平滑,没有突起和凹陷。


想知道是什么原因导致的部分正确,按理说要正确就全部正确吗。

if (n == 3)
                {
                    v->new_pos = (1.0f - (9.0f / 16.0f)) * v->pos + (3.0f / 16.0f) * Eneighbors;
                }
                else
                {
                    // For other vertices, apply the general rule based on degree
                    v->new_pos = (1.0f - (3.0f / 8.0f)) * v->pos + (0.375f / n) * Eneighbors;
                }

Eneighbor 是通过 do {}while 遍历求出来的临近所有顶点的坐标和
这是我处理旧顶点的方式,和文档计算一摸一样,我觉得不是这个的问题导致细分错误。
另外在进行一次 loop 后,我会把所有的顶点和边全部置为旧的,这个操作也没问题。

曲面细分对于 cube 有个整体往回缩的趋势,八个顶点突出考虑是因为旧顶点坐标计算错了往回缩的不够多。可能要看下更新顺序问题?比如要在对每条边分裂之前先计算旧顶点新坐标。
对于新顶点的计算,如果你是将所有边分裂完之后再用你现在的算法,你应该注意到由于旁边的边已经分裂,在半边网络数据里产生了新顶点,公式里的 v3 和 v4 两个顶点与新顶点已经不邻接,你的 V3addV4 可能变成了相邻的两个新顶点相加,你应该在分裂前就计算。