Patch Interpolator Example
The following is source code for a triangular and quadrilateral patch interpolator
// Triangular patch interpolator
Point3 Patch::interp(PatchMesh *pMesh, float pu, float pv, float pw)
{
// It had better be a triangular patch!
assert(type == PATCH_TRI);
Point3 p;
PatchVert *vp = pMesh->verts;
PatchVec *vecp = pMesh->vecs;
float pu2 = pu * pu;
float pu3 = pu2 * pu;
float pu4 = pu3 * pu;
float pv2 = pv * pv;
float pv3 = pv2 * pv;
float pv4 = pv3 * pv;
float pw2 = pw * pw;
float pw3 = pw2 * pw;
float pw4 = pw3 * pw;
// Hold on to your hats -- Here it comes!
p = vp[v[0]].p * pw4 +
aux[0] * 4.0f * pu * pw3 +
aux[1] * 6.0f * pu2 * pw2 +
aux[2] * 4.0f * pu3 * pw +
vp[v[1]].p * pu4 +
aux[3] * 4.0f * pv * pu3 +
aux[4] * 6.0f * pu2 * pv2 +
aux[5] * 4.0f * pv3 * pu +
vp[v[2]].p * pv4 +
aux[6] * 4.0f * pw * pv3 +
aux[7] * 6.0f * pv2 * pw2 +
aux[8] * 4.0f * pw3 * pv +
vecp[interior[0]].p * 12.0f * pu * pv * pw2 +
vecp[interior[1]].p * 12.0f * pu2 * pv * pw +
vecp[interior[2]].p * 12.0f * pu * pv2 * pw;
return p;
}
// Quadrilateral patch interpolator
Point3 Patch::interp(PatchMesh *pMesh, float pu, float pv)
{
// It had better be a quad patch!
assert(type == PATCH_QUAD);
Point3 p;
PatchVert *vp = pMesh->verts;
PatchVec *vecp = pMesh->vecs;
float pu2 = pu * pu;
float pu1 = 1.0f - pu;
float pu12 = pu1 * pu1;
float u0 = pu12 * pu1;
float u1 = 3.0f * pu * pu12;
float u2 = 3.0f * pu2 * pu1;
float u3 = pu2 * pu;
float pv2 = pv * pv;
float pv1 = 1.0f - pv;
float pv12 = pv1 * pv1;
float v0 = pv12 * pv1;
float v1 = 3.0f * pv * pv12;
float v2 = 3.0f * pv2 * pv1;
float v3 = pv2 * pv;
// Hold on to your hats -- Here it comes!
p = vp[v[0]].p * u0 * v0 +
vecp[vec[7]].p * u1 * v0 +
vecp[vec[6]].p * u2 * v0 +
vp[v[3]].p * u3 * v0 +
vecp[vec[0]].p * u0 * v1 +
vecp[interior[0]].p * u1 * v1 +
vecp[interior[3]].p * u2 * v1 +
vecp[vec[5]].p * u3 * v1 +
vecp[vec[1]].p * u0 * v2 +
vecp[interior[1]].p * u1 * v2 +
vecp[interior[2]].p * u2 * v2 +
vecp[vec[4]].p * u3 * v2 +
vp[v[1]].p * u0 * v3 +
vecp[vec[2]].p * u1 * v3 +
vecp[vec[3]].p * u2 * v3 +
vp[v[2]].p * u3 * v3;
return p;
}
Building the vertices are just a matter of looping through your patches and then running through each patches UV space to get the corresponding point on the surface. Below is a sample showing the basics.
float fpd = (float)patchDivs;
for(px = 0; px < numPatches; ++px)
{
Patch &p = patches[px];
switch(p.type)
{
case PATCH_TRI:
{
for(intax = patchDivs - 1; ax > 0; --ax)
{
for(int bx = 1; bx < ax; ++bx)
{
float u = (float)bx / fpd;
float v = (float)(patchDivs - ax) / fpd;
float w = 1.0f - u - v; // Barycentric validity guaranteed!
mesh.setVert(vert++, p.interp(this, u, v, w));
}
}
}
break;
case PATCH_QUAD:
{
for(intu = 1; u < patchDivs; ++u)
{
float fu = (float)u / fpd;
for(int v = 1; v < patchDivs; ++v)
{
float fv = (float)v / fpd;
mesh.setVert(vert++, p.interp(this, fu, fv));
}
}
}
break;
}
}