Jump to content
  • Advertisement
Sign in to follow this  
keyofrassilon

icosahedron

This topic is 5487 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Ive spent what seems like a week on this and found varoius threads on the subject but am still in the dark about texturing such a beast. I have sourcecode I grabbed from various places here and on the net and have this thus far for my texture mapping but it doesnt work. 1) It stretches the texture too far on the X axis, distorting the look of the texture and doesnt even meet at the meridian. I used some kind of ugly hack someone here mentioned in another thread but it stretches the last portion of the texture across to meet at the meridian and looks terrible. so I disabled it. 2) I really have no clue what is going on in the coding at this point and wonder if someone could point out a better method... Heres a snippit:
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 = 0.99;
	}
	if (texU1 - texU2 > 0.2 || texU3 - texU2 > 0.2){
		texAdd2 = 0.99;
	}
	if (texU1 - texU3 > 0.2 || texU2 - texU3 > 0.2){
		texAdd3 = 0.99;
	}


	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, 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, 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, texV);
		glVertex3f (point.x, point.y, point.z);
	glEnd();
}


void Icosahedron::GetTextureCoord(Vector3f *normal, float *targetU, float *targetV){
   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 * PI) / 2);
	}
	else {
		*targetU = atan(normalisedX / normalisedZ);
		if (normalisedZ < 0){
			*targetU += PI;
		}
	}
	if (*targetU < 0){
	   *targetU += 2 * PI;
	}

   *targetU /= 2 * PI;
   *targetV = (-normal->y + 1) / 2;
}







Thanks! EDIT: I did a quick hack to my project to output a screenshot so you could see the artifacts that the texturing method I currently use does... Example Picture [Edited by - keyofrassilon on September 7, 2004 10:20:23 PM]

Share this post


Link to post
Share on other sites
Advertisement
I had the same problems with a sphere. Make sure you generate triangle strips that cover the surface completely, so the last triangle doesn't have the tex coords from 0.9 to 0.0

Share this post


Link to post
Share on other sites
Thats what I thought as well but when I unbind the texture there is no missing triangles that I can see. Im pretty certain the problem lies in my texturing coordinates unless thats what you mean by triangle strips.

Heres my complete class if that sheds any more light on the problem. I know Im no expert at trig so Im sure Im going about this the hard way or something.


class Icosahedron {
public:
Icosahedron();
~Icosahedron();

void Init(GLdouble m_radius, int subdivisions);

private:
void Normalize(float v[3]);
void DrawTriangle(float *v1, float *v2, float *v3);
void Subdivide(float *v1, float *v2, float *v3, long depth);
void GetTextureCoord(Vector3f *normal, float *targetU, float *targetV);

GLuint displayList;
GLfloat radius;
};

// ******************** CLASS IMPLEMENTATION ********************


GLfloat vdata[12][3] = {
{-X_BASE,0.0,Z_BASE},{X_BASE,0.0,Z_BASE},{-X_BASE,0.0,-Z_BASE},{X_BASE,0.0,-Z_BASE},
{0.0,Z_BASE,X_BASE},{0.0,Z_BASE,-X_BASE},{0.0,-Z_BASE,X_BASE},{0.0,-Z_BASE,-X_BASE},
{Z_BASE,X_BASE,0.0},{-Z_BASE,X_BASE,0.0},{Z_BASE,-X_BASE,0.0},{-Z_BASE,-X_BASE,0.0}};

GLuint tindices[20][3] = {
{1,4,0},{4,9,0},{4,5,9},{8,5,4},{1,8,4},
{1,10,8},{10,3,8},{8,3,5},{3,2,5},{3,7,2},
{3,10,7},{10,6,7},{6,11,7},{6,0,11},{6,1,0},
{10,1,6},{11,0,9},{2,11,9},{5,2,9},{11,2,7}};

Icosahedron::Icosahedron() {
}

Icosahedron::~Icosahedron() {
}

void Icosahedron::Init(GLdouble m_radius, int subdivisions) {
radius = m_radius;
if (radius == 0) return;
glPushMatrix();
glEnable(GL_NORMALIZE);
glScaled(radius, radius, radius);


for (int i = 0; i < 20; i++) {
Subdivide(&vdata[tindices[0]][0], &vdata[tindices[1]][0], &vdata[tindices[2]][0], subdivisions);
}
glDisable(GL_NORMALIZE);
glPopMatrix();
}


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 = 0.99;
}
if (texU1 - texU2 > 0.2 || texU3 - texU2 > 0.2){
texAdd2 = 0.99;
}
if (texU1 - texU3 > 0.2 || texU2 - texU3 > 0.2){
texAdd3 = 0.99;
}


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, 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, 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, texV);
glVertex3f (point.x, point.y, point.z);
glEnd();
}


void Icosahedron::GetTextureCoord(Vector3f *normal, float *targetU, float *targetV){
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 * PI) / 2);
}
else {
*targetU = atan(normalisedX / normalisedZ);
if (normalisedZ < 0){
*targetU += PI;
}
}
if (*targetU < 0){
*targetU += 2 * PI;
}

*targetU /= 2 * PI;
*targetV = (-normal->y + 1) / 2;
}


void Icosahedron::Normalize(float v[3]) {
GLfloat d = (float)sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
if (d == 0.0) return;
v[0] /= d; v[1] /= d; v[2] /= d;
}

void Icosahedron::Subdivide(float *v1, float *v2, float *v3, long depth) {
GLfloat v12[3], v23[3], v31[3];
GLint i;

if (depth == 0) {
DrawTriangle(v1, v2, v3);
return;
}
for (i = 0; i < 3; i++) {
v12 = v1+v2;
v23 = v2+v3;
v31 = v3+v1;
}
Normalize(v12);
Normalize(v23);
Normalize(v31);
Subdivide(v1, v12, v31, depth-1);
Subdivide(v2, v23, v12, depth-1);
Subdivide(v3, v31, v23, depth-1);
Subdivide(v12, v23, v31, depth-1);
}



Heres a few more shots. The first one using an earth texture also shows how the continents appear stretched on the X axis.

Earth Shot

I watched my sphere rotate all the way round and never saw any missing triangles. I can only conclude I have bogus texture coordinates.

No Texture

Share this post


Link to post
Share on other sites
Thanks! Thats originally where I got most of my code but still to no avail. At the end he mentioned he used a counting method but I have no idea what he did so that could be the problem... In any event I found a better solution although I prefer the icosahedron...Someday I hope to implement some sort of lod to the sphere creating a procedural planet. Thats far in the future as Im still learning the basics.


void drawSphere (float R, int u, int v, float px, float py, float pz, float rot) {
int i,j;
float dx, dy, X, Y, Z, alpha=0, beta=0;
float X1, X2, X3;
float Y1, Y2, Y3;
float Z1, Z2, Z3;
float xs, ys, zs;
float len;

dx = (2.0 * PI) / (float) u;
dy = PI / (float) v;

glPushMatrix();
glRotatef( rot, 0.0, 1.0, 0.0 );
for (i=0; i<u; i++) {
alpha = 0.0;
for (j=0; j<v; j++) {
X = sin (alpha) * cos (beta) * R;
Y = cos (alpha) * R;
Z = sin (alpha) * sin (beta) * R;

X1 = sin (alpha + dy) * cos (beta) * R;
Y1 = cos (alpha + dy) * R;
Z1 = sin (alpha + dy) * sin (beta) * R;

X2 = sin (alpha + dy) * cos (beta + dx) * R;
Y2 = cos (alpha + dy) * R;
Z2 = sin (alpha + dy) * sin (beta + dx) * R;

X3 = sin (alpha) * cos (beta + dx) * R;
Y3 = cos (alpha) * R;
Z3 = sin (alpha) * sin (beta + dx) * R;

glBegin (GL_TRIANGLES);
xs=X;ys=Y;zs=Z; len=sqrt(xs*xs + ys*ys + zs*zs);
glNormal3f (xs/len, ys/len, zs/len);
glTexCoord2f (beta / (2.0*PI), alpha / PI);
glVertex3f (X + px, Y + py, Z + pz);

xs=X2;ys=Y2;zs=Z2; len=sqrt(xs*xs + ys*ys + zs*zs);
glNormal3f (xs/len, ys/len, zs/len);
glTexCoord2f ((beta + dx) / (2.0*PI), (alpha + dy) / PI);
glVertex3f (X2 + px, Y2 + py, Z2 + pz);

xs=X1;ys=Y1;zs=Z1; len=sqrt(xs*xs + ys*ys + zs*zs);
glNormal3f (xs/len, ys/len, zs/len);
glTexCoord2f (beta / (2.0*PI), (alpha + dy) / PI);
glVertex3f (X1 + px, Y1 + py, Z1 + pz);
glEnd();

glBegin (GL_TRIANGLES);
xs=X;ys=Y;zs=Z; len=sqrt(xs*xs + ys*ys + zs*zs);
glNormal3f (xs/len, ys/len, zs/len);
glTexCoord2f (beta / (2.0*PI), alpha / PI);
glVertex3f (X + px, Y + py, Z + pz);

xs=X3;ys=Y3;zs=Z3; len=sqrt(xs*xs + ys*ys + zs*zs);
glNormal3f (xs/len, ys/len, zs/len);
glTexCoord2f ((beta + dx) / (2.0*PI), alpha / PI);
glVertex3f (X3 + px, Y3 + py, Z3 + pz);

xs=X2;ys=Y2;zs=Z2; len=sqrt(xs*xs + ys*ys + zs*zs);
glNormal3f (xs/len, ys/len, zs/len);
glTexCoord2f ((beta + dx) / (2.0*PI), (alpha + dy) / PI);
glVertex3f (X2 + px, Y2 + py, Z2 + pz);
glEnd();

alpha+=dy;
};
beta+=dx;
};
glPopMatrix();
//glLoadIdentity();
}





The only problem Im having with this is something really stupid. Positioning the sphere and rotating it on its axis.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!