Advertisement

[Request for help] Texture mapping a subdivided icosahedron

Started by September 27, 2002 04:55 AM
21 comments, last by IainC 22 years, 5 months ago
And maybe you should replace :

  if (normalisedZ < 0){  *targetU += PI;}  
with:
  if (normalisedZ < 0){  *targetU = PI - *targetU;}  
vincoof:

I don't think so. The equations to that point should leave the values in the range 0 -> PI/2 */* -PI/2 -> PI/2 */* -PI/2 -> 0 where */* indicates that value change at the functions tangents. By then adding PI to the middle section you get a distribution of 0 -> PI/2 */* PI/2 -> 3PI/2 */* -PI/2 -> 0. Then adding 2PI if the value is < 0 maps the distribution to 0 -> PI/2 */* PI/2 -> 3PI/2 */* 3PI/2 -> 2PI.

Your proposed modification would leave the distribution as 0 -> PI/2 */* 3PI/2 -> PI/2 */* 3PI/2 -> 0, reversing the texture on one side of the planet and adding extra seams either side.

At least I *think* that's what would happen!

Enigma

EDIT: spelling

[edited by - enigma on September 27, 2002 12:13:16 PM]
Advertisement
Aw sorry I made a mistake. Thanks for poiiting it out. It was too hurried.
I meant :

  if (normalisedX < 0){  *targetU = PI - *targetU;}  
Almost!

Now I have (with Enigma''s function):



Vincoof - I couldn''t quite see where you meant to put that line - doing this gives me more bizarreness:


  	float normalisedX = 0;	float normalisedZ = -1;	if (((normal->x * normal->x) + (normal->z * normal->z)) > 0){		normalisedX = sqrt((normal->x * normal->x) / ((normal->x * normal->x) + (normal->z * normal->z)));		if (normal->x < 0){			normalisedX = -normalisedX;		}		normalisedZ = sqrt((normal->z * normal->z) / ((normal->x * normal->x) + (normal->z * normal->z)));		if (normal->z < 0){			normalisedZ = -normalisedZ;		}	}	if (normalisedZ == 0){		*targetU = ((normalisedX * ASE_PI) / 2);	} else if (normalisedX < 0){		*targetU = ASE_PI - *targetU;	} else {		*targetU = atan(normalisedX / normalisedZ);		if (normalisedZ < 0){			*targetU += ASE_PI;			//*targetU = ASE_PI - *targetU;		}		if (*targetU < 0){			*targetU += 2 * ASE_PI;		}	}	*targetU /= 2 * ASE_PI;	*targetV = (-normal->y + 1) / 2;  


So the only problem that remains is correcting those two seams; would it make it easier if I went for square textures instead? As I realised that that''s going to be what I need to do eventually anyway.... (DOH)

If I followed your explanation correcting I''m suspecting that all I need do to change to square textures is change the last line from
  *targetV = (-normal->y + 1) / 2;  
to
  *targetV = -normal->y / 2;  


I tried to fiddle Enigma''s function so that the seams were corrected, but got nowhere

Thanks again for your continued help guys.

Brgds
I.
[size="2"]www.coldcity.com code, art, life
I''m not sure what you mean by ''square textures''. In what way is your current texture not square? (I realize the image is a rectangle, but assumed that you would have stretched it to a square texture).

The first seam (zigzagging line) exists because the texture coordinates around the planet are distributed as follows: The first X coordinate is zero or a small positive fraction. The X coordinates then increase linearly around the planet until we reach the point we started. Unfortunately the point we started has a texture coordinate which is about zero so we get a steep drop in coordinates here. What we wanted was to wrap around from one edge of the image to the other, but OpenGL doesn''t know this and instead draws nearly the entire texture ''backwards''. The solution is to spot the seam and give the initial vertex different texture coords according to which polygon it is part of. For the first polygon you give it the normal X coordinate. For the final polygon you give it the X coordinate + 1.

Without going through your source codes more thoroughly than I''ve had time to thus far, I can''t say how to implement this in you class.

As for the second seam - It shouldn''t be there! something has gone wrong! I''ll have a look at it and hopefully I''ll have an answer sometime tomorrow.

Enigma
My modification should be used with Enigma''s previous method.
Anyhow I''m glad that the current method is correct (well, almost).

Now that the seams are here, it''s probably the most difficult part. To be honest, I don''t know a "simple" method. The only one I would dare using is detecting the polygons that are responsible of the seams and apply specific texture coordinates on them.
Advertisement
That looks so dang cool

Post a pic of the final product when it lines up the way you like it!

[edited by - Waverider on September 27, 2002 7:32:50 PM]
It's not what you're taught, it's what you learn.
Enigma: Please ignore my "square texture" tangent, I''m totally confusing the issue and inventing problems where there are none. The reason for the zigzag seam is obvious (now you''ve pointed it out!) - I''ll work on fixing that.

Waverider: I will I think it looks pretty cool in its messed-up incarnations

There is a point to all this, incidentally - eventually this thing won''t even be texturemapped, but to do what I want to I need a way of reliably getting UVs onto a two-dimensional grid, so perfecting it with something as visual as a texture seemed the way to go.

From that you''ve probably figured out I''m working on procedural planets and the 2D grid is actually a noise function that returns the same values when given the same inputs (so no storage of the noise required).

The Icosahedron class below is a simplification of what I''m actually using, which already includes LOD, but the tex coord generation still applies.

Thanks again all,
I.
[size="2"]www.coldcity.com code, art, life
Well, here''s a (pretty horrible) hack that''ll fix the seams:

  void Icosahedron::DrawTriangle(float *v1, float *v2, float *v3) {	Vector3f point;	GLfloat texU, texV;	GLfloat texU1, texU2, texU3;	GLfloat texAdd1 = 0;	GLfloat texAdd2 = 0;	GLfloat texAdd3 = 0;	// determine if triangle spans	point.Set (v1[0], v1[1], v1[2]);	GetTextureCoord (&point, &texU1, &texV);	point.Set (v2[0], v2[1], v2[2]);	GetTextureCoord (&point, &texU2, &texV);	point.Set (v3[0], v3[1], v3[2]);	GetTextureCoord (&point, &texU3, &texV);	if (texU2 - texU1 > 0.2 || texU3 - texU1 > 0.2){		texAdd1 = 1;	}	if (texU1 - texU2 > 0.2 || texU3 - texU2 > 0.2){		texAdd2 = 1;	}	if (texU1 - texU3 > 0.2 || texU2 - texU3 > 0.2){		texAdd3 = 1;	}	glBegin(GL_TRIANGLES);	point.Set (v1[0], v1[1], v1[2]);	glNormal3f (point.x, point.y, point.z);		// (Points are already normalised)	GetTextureCoord (&point, &texU, &texV);	glTexCoord2f(texU + texAdd1, texV);	glVertex3f (point.x, point.y, point.z);	point.Set (v2[0], v2[1], v2[2]);	glNormal3f (point.x, point.y, point.z);	GetTextureCoord (&point, &texU, &texV);	glTexCoord2f(texU + texAdd2, texV);	glVertex3f (point.x, point.y, point.z);	point.Set (v3[0], v3[1], v3[2]);	glNormal3f (point.x, point.y, point.z);	GetTextureCoord (&point, &texU, &texV);	glTexCoord2f(texU + texAdd3, texV);	glVertex3f (point.x, point.y, point.z);	glEnd();}  


It could be optimised, but since it''s such a hack there''s no point. The value 0.2 is just a value < 1 that is guarenteed to be greater that the difference between any two correct texture coordinates.

It does work - I''ve just spent the last hour hacking various bits of old code together to get a simple OpenGL app to display it. It fixes both problems - I still don''t know what caused the second one but nevermind!

Enigma
Just spotted what was causing the second seam. In the GetTextureCoord method, this:

  if (normalisedZ == 0){   *targetU = ((normalisedX * PI) / 2);}else {   *targetU = atan(normalisedX / normalisedZ);   if (normalisedZ < 0){      *targetU += PI;   }   if (*targetU < 0){      *targetU += 2 * PI;   }}  

should have been:

  if (normalisedZ == 0){   *targetU = ((normalisedX * PI) / 2);}else {   *targetU = atan(normalisedX / normalisedZ);   if (normalisedZ < 0){      *targetU += PI;   }}if (*targetU < 0){   *targetU += 2 * PI;}  

The first if will set targetU to +/- PI/2. The -PI/2 should then have been transformed to 3PI/2 by adding 2PI, but I put the code to add 2PI inside the else clause so for this one case it didn''t get executed.

Enigma

This topic is closed to new replies.

Advertisement