关于laplacian坐标的编译

这是我的第一篇博客,在这里我首先对具有开元思想的人表示感谢,是你们的奉献才能让我慢慢的入门。

  在常规的laplacian坐标计算中,都习惯性的以顶点为单位,根据laplacian坐标的公式计算,虽然都可以计算出来但是计算量较大。这里提出的laplacian坐标计算方法最小单位为三角形或者四边形,在目前的扫描文件中通常都是用的三角形,故文中的代码都以三角形进行探讨。

static void LaplacianMatrix(SystemData *sys)
{
    float v1[3], v2[3], v3[3], v4[3], no[3];
    float w2, w3, w4;
    int i, j, fi;
    bool has_4_vert;
    unsigned int idv1, idv2, idv3, idv4;

    for (fi = 0; fi < sys->total_faces; fi++) {          //****所有面的个数****
        const unsigned int *vidf = sys->faces[fi];

        idv1 = vidf[0];
        idv2 = vidf[1];
        idv3 = vidf[2];
        idv4 = vidf[3];                                   //****面中各个顶点对应顶点的序列****

        has_4_vert = vidf[3] ? 1 : 0;                      //****判断是四边形还是三边形***
        if (has_4_vert) {
            normal_quad_v3(no, sys->co[idv1], sys->co[idv2], sys->co[idv3], sys->co[idv4]);
            add_v3_v3(sys->no[idv4], no);
            i = 4;
        }
        else {
            normal_tri_v3(no, sys->co[idv1], sys->co[idv2], sys->co[idv3]);     //****计算三角形的法线****
            i = 3;
        }
        add_v3_v3(sys->no[idv1], no);                                            //****点的法线与面的法线相加****
        add_v3_v3(sys->no[idv2], no);
        add_v3_v3(sys->no[idv3], no);

        for (j = 0; j < i; j++) {
            idv1 = vidf[j];
            idv2 = vidf[(j + 1) % i];
            idv3 = vidf[(j + 2) % i];
            idv4 = has_4_vert ? vidf[(j + 3) % i] : 0;

            copy_v3_v3(v1, sys->co[idv1]);
            copy_v3_v3(v2, sys->co[idv2]);
            copy_v3_v3(v3, sys->co[idv3]);
            if (has_4_vert) {
                copy_v3_v3(v4, sys->co[idv4]);
            }

            if (has_4_vert) {

                w2 = (cotan_weight(v4, v1, v2) + cotan_weight(v3, v1, v2)) / 2.0f;
                w3 = (cotan_weight(v2, v3, v1) + cotan_weight(v4, v1, v3)) / 2.0f;
                w4 = (cotan_weight(v2, v4, v1) + cotan_weight(v3, v4, v1)) / 2.0f;

                sys->delta[idv1][0] -= v4[0] * w4;
                sys->delta[idv1][1] -= v4[1] * w4;
                sys->delta[idv1][2] -= v4[2] * w4;

                nlRightHandSideAdd(0, idv1, -v4[0] * w4);
                nlRightHandSideAdd(1, idv1, -v4[1] * w4);
                nlRightHandSideAdd(2, idv1, -v4[2] * w4);

                nlMatrixAdd(idv1, idv4, -w4);
            }
            else {
                w2 = cotan_weight(v3, v1, v2);                        //****非顶点的夹角,为laplacian坐标的计算做准备****
                w3 = cotan_weight(v2, v3, v1);
                w4 = 0.0f;
            }

            sys->delta[idv1][0] += v1[0] * (w2 + w3 + w4);           //****计算laplacian坐标的规律,中心点以外的两个顶点夹角的正切值,相加与当前中心点,相减于另外两个顶点****
            sys->delta[idv1][1] += v1[1] * (w2 + w3 + w4);           //****于对角正切值的乘积,是以三角形为计算中心****
            sys->delta[idv1][2] += v1[2] * (w2 + w3 + w4);

            sys->delta[idv1][0] -= v2[0] * w2;
            sys->delta[idv1][1] -= v2[1] * w2;
            sys->delta[idv1][2] -= v2[2] * w2;

            sys->delta[idv1][0] -= v3[0] * w3;
            sys->delta[idv1][1] -= v3[1] * w3;
            sys->delta[idv1][2] -= v3[2] * w3;

            nlMatrixAdd(idv1, idv2, -w2);
            nlMatrixAdd(idv1, idv3, -w3);
            nlMatrixAdd(idv1, idv1, w2 + w3 + w4);

        }
    }
}

  上面laplacian坐标的计算即为三角形为最小单位,所以运算速度会较以点为单位的计算方式好些。

posted @ 2016-01-18 17:01  逐风者的祝福  阅读(312)  评论(0编辑  收藏  举报