Seams in texture mapping a sphere (using cube mapping and dodecahedra)

Started by
-1 comments, last by quasar3d 14 years, 11 months ago
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.

This topic is closed to new replies.

Advertisement