这是我的第一篇博客,在这里我首先对具有开元思想的人表示感谢,是你们的奉献才能让我慢慢的入门。
在常规的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坐标的计算即为三角形为最小单位,所以运算速度会较以点为单位的计算方式好些。