我正在细分网格的三角形,正如你猜测的那样,我需要这些新顶点的权重值。目前我正在使用线性插值(Vnew.weight[i] = (V1.weight[i] + V2.weight[i]) * 0.5
),但似乎我无法获得正确的值。
您是否知道使用插值权重的更好解决方案?
编辑:
正确的知道,我正在使用LBS,并通过取中间点将一个三角形分成两个三角形。一旦从文件中读取三角形信息(我使用SMD
文件),就会完成此除法。
我认为问题是权重因为,在休息姿势(没有任何皮肤)一切都很好。但是当姿势开始应用并且完成蒙皮时,会出现一些疯狂的三角形和洞。当我仔细观察这些“疯狂三角形”时,它们的顶点随着网格一起移动,但与其他顶点不够快。
这是分割过程的代码,并插入顶点,法线,UV和权重
int pi=0;
while (1)
{
// Some control, and decleration
for (int w = 0; w < 3; w++)
{
// Some declerations
Vert v;
// Values are read from file into Cert v
// Using boneIndex2[] and boneWeight2[] because GLSL 1.30 does
// not support shader storage buffer object, and I need just
// 8 indices most for now.
v.boneIndex2[0] = 0;
v.boneIndex2[1] = 0;
v.boneIndex2[2] = 0;
v.boneIndex2[3] = 0;
v.boneWeight2[0] = 0;
v.boneWeight2[1] = 0;
v.boneWeight2[2] = 0;
v.boneWeight2[3] = 0;
m.vert.push_back(v);
pi++;
}
// Dividing the triangle
Vert a = m.vert[pi - 2];
Vert b = m.vert[pi - 1];
Vert v;
// Interpolate position
v.pos[0] = (a.pos[0] + b.pos[0]) / 2;
v.pos[1] = (a.pos[1] + b.pos[1]) / 2;
v.pos[2] = (a.pos[2] + b.pos[2]) / 2;
// Interpolate normal
v.norm[0] = (a.norm[0] + b.norm[0]) / 2;
v.norm[1] = (a.norm[1] + b.norm[1]) / 2;
v.norm[2] = (a.norm[2] + b.norm[2]) / 2;
// Interpolate UV
v.uv[0] = (a.uv[0] + b.uv[0]) / 2;
v.uv[1] = (a.uv[1] + b.uv[1]) / 2;
// Assign bone indices
// The new vertex should be treated by each bone of Vert a, and b
v.boneIndex[0] = a.boneIndex[0];
v.boneIndex[1] = a.boneIndex[1];
v.boneIndex[2] = a.boneIndex[2];
v.boneIndex[3] = a.boneIndex[3];
v.boneIndex2[0] = b.boneIndex[0];
v.boneIndex2[1] = b.boneIndex[1];
v.boneIndex2[2] = b.boneIndex[2];
v.boneIndex2[3] = b.boneIndex[3];
// Interpolate weights
float we[4];
we[0] = (a.boneWeight[0] + b.boneWeight[0]) / 2;
we[1] = (a.boneWeight[1] + b.boneWeight[1]) / 2;
we[2] = (a.boneWeight[2] + b.boneWeight[2]) / 2;
we[3] = (a.boneWeight[3] + b.boneWeight[3]) / 2;
// Assign weights
v.boneWeight[0] = we[0];
v.boneWeight[1] = we[1];
v.boneWeight[2] = we[2];
v.boneWeight[3] = we[3];
v.boneWeight2[0] = we[0];
v.boneWeight2[1] = we[1];
v.boneWeight2[2] = we[2];
v.boneWeight2[3] = we[3];
// Push new vertex
m.vert.push_back(v);
pi++;
// Push new faces
m.face.push_back(Face(pi - 4, pi - 1, pi - 2));
m.face.push_back(Face(pi - 4, pi - 3, pi - 1));
} // End of while(1)
答案 0 :(得分:2)
您正在混合可能属于不同骨骼的权重(即,如果骨骼索引不相等)。
相反,从两个顶点收集所有影响骨骼的索引。如果只有一个顶点指向任何骨骼,请使用此重量的一半。如果两个顶点都引用骨骼,请使用插补方法。然后,选择具有最高权重的四个骨骼并重新标准化为1的总和。
这是一个例子。考虑您有两个具有这些骨骼索引和权重的顶点:
v1 v2
index | weight index | weight
------+-------- ------+--------
0 | 0.2 2 | 0.1
1 | 0.5 3 | 0.6
2 | 0.1 4 | 0.2
3 | 0.2 5 | 0.1
首先要构建关节权重表:
index | weight
------+--------
0 | 0.2 / 2 = 0.1
1 | 0.5 / 2 = 0.25
2 | (0.1 + 0.1) / 2 = 0.1
3 | (0.2 + 0.6) / 2 = 0.4
4 | 0.2 / 2 = 0.1
5 | 0.1 / 2 = 0.05
对wrt权重进行排序并挑选四个最大值:
index | weight
------+--------
3 | 0.4 *
1 | 0.25 *
0 | 0.1 *
2 | 0.1 *
4 | 0.1
5 | 0.05
这些权重总和为0.85。因此,将权重除以0.85以得到最终权重和指数:
index | weight
------+--------
3 | 0.47
1 | 0.29
0 | 0.12
2 | 0.12
另一种选择是扩展您的结构以使用更多(静态八个或动态)骨骼。但它可能不值得努力。