I'm trying to uniformly texture map a sphere using an icosahedron as its basis (I'm pretty sure the latter is unimportant in this case). I'm texture mapping a planetoid, which means this isn't strictly cube mapping - I'm just trying to texture map the sphere in such a way that there would be not visible discrepancies when viewed from close up or afar. I'm using the good old cube projection to do the actual mapping:
//'R' is the normal (eg normalized position vector for a point)
if((fabs(R.x) >= fabs(R.y)) && (fabs(R.x) >= fabs(R.z)))
{
if(R.x > 0.0)
{
S = 1.0 - (R.z / R.x+ 1.0) * 0.5;
T = (R.y / R.x+ 1.0) * 0.5;
}
else if(R.x < 0.0)
{
S = 1.0 - (R.z / R.x+ 1.0) * 0.5;
T = 1.0 - (R.y / R.x + 1.0) * 0.5;
}
}
else if((fabs(R.y) >= fabs(R.x)) && (fabs(R.y) >= fabs(R.z)))
{
if(R.y > 0.0)
{
S = (R.x / R.y + 1.0) * 0.5;
T = 1.0 - (R.z / R.y + 1.0) * 0.5;;
}
else if(R.y < 0.0)
{
S = 1.0 - (R.x / R.y + 1.0) * 0.5;
T = (R.z / R.y + 1.0) * 0.5;;
}
}
else if((fabs(R.z) >= fabs(R.x)) && (fabs(R.z) >= fabs(R.y)))
{
if(R.z > 0.0)
{
S = (R.x / R.z + 1.0) * 0.5;
T = (R.y / R.z + 1.0) * 0.5;
}
else if (R.z < 0.0)
{
S = (R.x / R.z + 1.0) * 0.5;
T = 1.0 - (R.y / R.z+1) * 0.5;
}
}
Since I'm scaling the texture coordinates, however, I get nasty seams over the triangles that project their vertices onto two different sides of the cube. Eg, when scaling the texture by 20, I might get texture coordinates S1 = 19.8 for one point and S2 = 0.1 for another point on the same triangle. This causes the texture to be quite nastily warped and looks like a "seam" when the entire sphere is rendered.
I've tried the following quick hack to ninja my way past this, but it's not working 100% reliably - there are cases where the test fails and there's always one seam (I believe running from one pole to the other) that I cannot get rid of. Mind you that the seam is not straight and I'm having trouble figuring out where it projects from.
//scale texture by 20
const TReal GLOBAL_TEX_SCALE = 20.0;
//use half of the scale to test for wrapping
const TReal GLOBAL_TEX_SCALE_HALF = GLOBAL_TEX_SCALE * 0.5;
//do a component-wise test of each point against each other point in the triangle:
//
//'tris' is the triangle set;
//'tris.t' is a pair of texture coordinates;
//'tris.t.c' is the u/v component
for(DWORD c = 0; c < 2; c++)
{
if(fabs (tris[iNumMeshes].t[0].c[c] - tris[iNumMeshes].t[1].c[c]) > GLOBAL_TEX_SCALE_HALF)
(tris[iNumMeshes].t[0].c[c] > tris[iNumMeshes].t[1].c[c] ? (tris[iNumMeshes].t[1].c[c] += GLOBAL_TEX_SCALE) : (tris[iNumMeshes].t[0].c[c] += GLOBAL_TEX_SCALE));
if(fabs (tris[iNumMeshes].t[0].c[c] - tris[iNumMeshes].t[2].c[c]) > GLOBAL_TEX_SCALE_HALF)
(tris[iNumMeshes].t[0].c[c] > tris[iNumMeshes].t[2].c[c] ? (tris[iNumMeshes].t[2].c[c] += GLOBAL_TEX_SCALE) : (tris[iNumMeshes].t[0].c[c] += GLOBAL_TEX_SCALE));
if(fabs (tris[iNumMeshes].t[2].c[c] - tris[iNumMeshes].t[1].c[c]) > GLOBAL_TEX_SCALE_HALF)
(tris[iNumMeshes].t[2].c[c] > tris[iNumMeshes].t[1].c[c] ? (tris[iNumMeshes].t[1].c[c] += GLOBAL_TEX_SCALE) : (tris[iNumMeshes].t[2].c[c] += GLOBAL_TEX_SCALE));
}
I'm not even sure if this is the best way to seamlessly and uniformly texture map a sphere - apart from the seams I'm still noticing a level of convergence at the corners of the faces of the icosahedron. If anyone can suggest a better method that would handle seams, poles and would not be too evil to implement, I'd really appreciate it. For now, however, I'm trying to get this working properly.