通常,Bezier曲面用作具有16个控制点的双三次曲面片。但是,在3dsMax中,可以隐藏内部边缘以进行编辑并计算automatically(它的默认状态)。只剩下12个控制点,这使得编辑更简单。
来自Primitives3D sample project的XNA代码(简化):
void CreatePatchVertices(Vector3[] patch, int tessellation)
{
Debug.Assert(patch.Length == 16);
for (int i = 0; i <= tessellation; i++)
{
float ti = (float)i / tessellation;
for (int j = 0; j <= tessellation; j++)
{
float tj = (float)j / tessellation;
// Perform four horizontal bezier interpolations
// between the control points of this patch.
Vector3 p1 = Bezier(patch[0], patch[1], patch[2], patch[3], ti);
Vector3 p2 = Bezier(patch[4], patch[5], patch[6], patch[7], ti);
Vector3 p3 = Bezier(patch[8], patch[9], patch[10], patch[11], ti);
Vector3 p4 = Bezier(patch[12], patch[13], patch[14], patch[15], ti);
// Perform a vertical interpolation between the results of the
// previous horizontal interpolations, to compute the position.
Vector3 position = Bezier(p1, p2, p3, p4, tj);
// Perform another four bezier interpolations between the control
// points, but this time vertically rather than horizontally.
Vector3 q1 = Bezier(patch[0], patch[4], patch[8], patch[12], tj);
Vector3 q2 = Bezier(patch[1], patch[5], patch[9], patch[13], tj);
Vector3 q3 = Bezier(patch[2], patch[6], patch[10], patch[14], tj);
Vector3 q4 = Bezier(patch[3], patch[7], patch[11], patch[15], tj);
// Compute vertical and horizontal tangent vectors.
Vector3 tangentA = BezierTangent(p1, p2, p3, p4, tj);
Vector3 tangentB = BezierTangent(q1, q2, q3, q4, ti);
// Cross the two tangent vectors to compute the normal.
Vector3 normal = Vector3.Cross(tangentA, tangentB);
normal.Normalize();
// Create the vertex.
AddVertex(position, normal);
}
}
}
在此示例中,如何自动计算向量5,6,9和10(patch[5]
等),就像在3dsMax中一样?
答案 0 :(得分:2)
这个答案必须是多余的,但我想提请你注意构建名为 Coons patches 的贝塞尔曲面的另一种方法。 Coons补丁明确只使用边界曲线,转换为双三次补丁非常简单。
我之所以推荐这个,是因为它是为了精确地推断汽车设计中典型的边界特征线而开发的,用于自动计算内部点(用于双三次贝塞尔曲面片)或曲面细分。
给出四条边界曲线bu0,bu1,bv0,bv1;
bu0, bu1 // boundaries in u direction u <- [0, 1]
bv0, bv1 // in v direction v <- [0, 1]
// bu0, bu1, bv0, bv1 are arrays of bezier coefficients
可以通过首先独立地评估u和v方向上的规则曲面,以及u和v两者中的双线性插值来评估coons补片表面上的内部点和点。
// In matrix form, so that you can reduce it all together
⎡ ⎤
ruled_u = [ (1-u) u ] ⎜ bv0(v) ⎟
⎜ bv1(v) ⎟
⎣ ⎦
// Similarly
⎡ ⎤
ruled_v = [ (1-v) v ] ⎜ bu0(u) ⎟
⎜ bu1(u) ⎟
⎣ ⎦
// Assuming cubic bezier curves as boundary, if you select appropriate control point
// instead of bv0(u) etc, i.e. bv0[1] for u = 1/3 and bv0[2] for u = 2/3, we can convert
// a coons patch into a bicubic patch, instead of evaluating the point on surface directly
⎡ ⎤ ⎡ ⎤
bilinear_uv = [ (1-u) u ] ⎜ bu0(0) bu0(1) ⎟ ⎜ (1 - v) ⎟
⎜ bu1(0) bu1(1) ⎟ ⎜ v ⎟
⎣ ⎦ ⎣ ⎦
// Then the 'interior' point at u and v is
Coons (u, v) = ruled_u + ruled_v - bilinear_uv
在coons补丁上,内部控制点可以计算为
Coons(1/3, 1/3)
Coons(1/3, 2/3)
Coons(2/3, 1/3)
Coons(2/3, 2/3)
在上述方程式中只选择bv0 [1]为1/3而不是bv0(1/3)等。
在Coons补丁中,插值感觉比仅仅线性插值边界控制点更自然。也是更正确的&#39;在我的经验中。在镶嵌细分之后,不仅在美学上而且在参数上也是如此。
最近,我必须在LCH色彩空间中生成近似sRGB色域的贝塞尔曲面。它只是一个变形和扭曲的RGB立方体。 我所拥有的只是补丁的边界。使用刚刚线性插值时内部值是错误的。 最后,coons补丁到目前为止给出的误差最小。
以下是来自固定浣熊斑块的生成的双三次曲面的样本。
答案 1 :(得分:0)
看起来3ds Max构造了一个平行四边形以获得内部点。
patch[5] = patch[0] + (patch[1] - patch[0]) + (patch[4] - patch[0]);
patch[5] = patch[1] + patch[4] - patch[0];
整个功能:
void CreatePatchVertices(Vector3[] s, int tessellation, bool isMirrored)
{
Debug.Assert(s.Length == 16);
for (int i = 0; i <= tessellation; i++)
{
float ti = (float)i / tessellation;
for (int j = 0; j <= tessellation; j++)
{
float tj = (float)j / tessellation;
// Compute automatic interior edges.
s[5] = s[1] + s[4] - s[0];
s[6] = s[2] + s[7] - s[3];
s[9] = s[8] + s[13] - s[12];
s[10] = s[11] + s[14] - s[15];
// Perform four horizontal bezier interpolations
// between the control points of this patch.
Vector3 p1 = Bezier(s[0], s[1], s[2], s[3], ti);
Vector3 p2 = Bezier(s[4], s[5], s[6], s[7], ti);
Vector3 p3 = Bezier(s[8], s[9], s[10], s[11], ti);
Vector3 p4 = Bezier(s[12], s[13], s[14], s[15], ti);
// Perform a vertical interpolation between the results of the
// previous horizontal interpolations, to compute the position.
Vector3 position = Bezier(p1, p2, p3, p4, tj);
// Perform another four bezier interpolations between the control
// points, but this time vertically rather than horizontally.
Vector3 q1 = Bezier(s[0], s[4], s[8], s[12], tj);
Vector3 q2 = Bezier(s[1], s[5], s[9], s[13], tj);
Vector3 q3 = Bezier(s[2], s[6], s[10], s[14], tj);
Vector3 q4 = Bezier(s[3], s[7], s[11], s[15], tj);
// Compute vertical and horizontal tangent vectors.
Vector3 tangentA = BezierTangent(p1, p2, p3, p4, tj);
Vector3 tangentB = BezierTangent(q1, q2, q3, q4, ti);
// Cross the two tangent vectors to compute the normal.
Vector3 normal = Vector3.Cross(tangentA, tangentB);
normal.Normalize();
// Create the vertex.
AddVertex(position, normal);
}
}
}
这是具有自动内部点的茶壶原语在3ds Max和Primitives3D样本中的样子: