Archived

This topic is now archived and is closed to further replies.

procedural asteroids

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

Recommended Posts

I''m looking into ways of generating (at load time) a series of asteroids for my dissertation project, I''ve looked through the faq and searched on google but am still unsure where to begin. I''ve read up on planetary generation using ROAM (though I don''t need LOD, the asteroids will only ever be displayed at a fixed distance from the screen.) I found a site that used a heightmap to generate a planet (I''ve since lost the link, I was at that point too tired to remember to bookmark the page!), though the basic idea was to multiply the vertex positions by the ''height'' stored in the heightmap. I''ve been working along with the heightmap idea and implemented a (very poor) perlin noise generator, which needs considerable work before it''s useful. Does anyone else have any suggestions as to what else I could look at? I''d prefer for the entire generation process to be procedural, from the geometry to the textures.

Share on other sites
As I see it you''ve got two options - in order to generate procedural geometry/textures you''re gonna have to use a noise algorithm, so you can either program this yourself (ie. finish your noise implmentation), or use another program to generate procedural textures which you can use as a height map/texture.

I would recommend trying to finish your own noise implementation. I have a couple of links that have good tutorials if you want them. Once you''ve got this running, you could apply it to a spherical terrain. Its probably not worth going into a level-of-detail scheme unless its a significant part of your project, so you could perhaps just generate points on a sphere using spherical coordinates, convert them to cartesian and then apply 3D noise.

Just my recomendations anyway.

Share on other sites
Yeah, if you could post up those links I''d be most appreciative, I''ve found quite a few, but the wonky bit of code that I currently call my noise algorithim is horribly slow and well, not very pretty.

Share on other sites
If you dont need your noise implementation for something else I can recommend Paul Bourkes planet generation, http://astronomy.swin.edu.au/~pbourke/terrain/planets/ . He also desribes howto make procedual sphere''s, http://astronomy.swin.edu.au/~pbourke/modelling/sphere/ . I used the surface refinment method he describes and applied the above algorithm and it looks rather nice. If you are gonna try it use something with more faces then the tetrahedron he uses, like a octrahedon or something like that.

Share on other sites
I''ve looked into Bourkes generation and decided it''s a good route to take, however, having implemented it, I''m getting a debug assertation failure in dbgheap.c when deleting the array I used to generate the sphere.

int CreateNSphere(int iterations){	facet3 *f = new facet3;	int i, it;	double a;	Vector3 p[6];	p[0].x = p[1].x = 0;	p[2].x = p[5].x = -1;	p[3].x = p[4].x = 1;	p[0].y = p[1].y = 0;	p[2].y = p[3].y = -1;	p[4].y = p[5].y = 1;	p[0].z = 1;	p[1].z = -1;	p[2].z = p[3].z = p[4].z = p[5].z = 0;	Vector3 pa, pb, pc;	int nt, ntold = 0;	a = 1 / sqrt(2.0);	for (i=0; i<6; i++) {		p[i].x *= a;		p[i].y *= a;	}	f[0].p[0] = p[0]; f[0].p[1] = p[3]; f[0].p[2] = p[4];	f[1].p[0] = p[0]; f[1].p[1] = p[4]; f[1].p[2] = p[5];	f[2].p[0] = p[0]; f[2].p[1] = p[5]; f[2].p[2] = p[2];	f[3].p[0] = p[0]; f[3].p[1] = p[2]; f[3].p[2] = p[3];	f[4].p[0] = p[1]; f[4].p[1] = p[4]; f[4].p[2] = p[3];	f[5].p[0] = p[1]; f[5].p[1] = p[5]; f[5].p[2] = p[4];	f[6].p[0] = p[1]; f[6].p[1] = p[2]; f[6].p[2] = p[5];	f[7].p[0] = p[1]; f[7].p[1] = p[3]; f[7].p[2] = p[2];	nt = 8;	if (iterations < 1)		return nt;	for (it = 0; it<iterations; it++)	{		ntold = nt;		for (i = 0; i<ntold; i++)		{			pa.x = (f[i].p[0].x + f[i].p[1].x) /2;			pa.y = (f[i].p[0].y + f[i].p[1].y) /2;			pa.z = (f[i].p[0].z + f[i].p[1].z) /2;			pb.x = (f[i].p[1].x + f[i].p[2].x) /2;			pb.y = (f[i].p[1].y + f[i].p[2].y) /2;			pb.z = (f[i].p[1].z + f[i].p[2].z) /2;			pc.x = (f[i].p[2].x + f[i].p[0].x) /2;			pc.y = (f[i].p[2].y + f[i].p[0].y) /2;			pc.z = (f[i].p[2].z + f[i].p[0].z) /2;			pa.normalize();			pb.normalize();			pc.normalize();			f[nt].p[0] = f[i].p[0]; f[nt].p[1] = pa; f[nt].p[2] = pc; nt++;			f[nt].p[0] = pa; f[nt].p[1] = f[i].p[1]; f[nt].p[2] = pb; nt++;			f[nt].p[0] = pb; f[nt].p[1] = f[i].p[2]; f[nt].p[2] = pc; nt++;			f[i].p[0] = pa;			f[i].p[1] = pb;			f[i].p[2] = pc;		}	}	nface = nt;	int j, k, niter = 1;	double r, r1, r2, r3, dp, scale, offset;	double len = 0;	Vector3 colour;	Vector3 px, p1, p2, p3, n;	for (i = 0; i < 3; i++)	{		for (j = 0; j < nface; j++)		{			f[j].p[i].normalize();			f[j].c[i] = 0;		}	}	niter = iterationdepth;	srand(seedvalue);	for (i = 0; i < niter; i++)	{		n.x = rand() - 0.5;		n.y = rand() - 0.5;		n.z = rand() - 0.5;		n.normalize();		offset = rand() - 0.5;		for (j = 0; j < nface; j++)		{			for (k = 0; k < 3; k++)			{				px = f[j].p[k];				if((dp = n*px) > 0)					f[j].c[k]++;				else					f[j].c[k]--;			}		}	}	for (j = 0; j < nface; j++)	{		for (k = 0; k < 3; k++)		{			f[j].p[k].normalize();			scale = 1 + deltaheight * f[j].c[k];			f[j].p[k].x *= scale;			f[j].p[k].y *= scale;			f[j].p[k].z *= scale;		}	}	radiusmin = 1;	radiusmax = 1;	for (i = 0; i < nface; i++)	{		for (k = 0; k < 3; k++)		{			r = vectorMag(f[i].p[k]);			radiusmin = MIN(radiusmin, r);			radiusmax = MAX(radiusmax, r);		}	}	radiusmin -= deltaheight;	radiusmax += deltaheight;	glNewList(1, GL_COMPILE);	glBegin(GL_TRIANGLES);	for (i = 0; i < nface; i++)	{		p1 = f[i].p[0];		r1 = vectorMag(p1);		p2 = f[i].p[1];		r2 = vectorMag(p2);		p3 = f[i].p[2];		r3 = vectorMag(p3);		colour = getColour(r1, radiusmin, radiusmax);		glColor4f(colour.x, colour.y, colour.z, 1.0);		glNormal3f(p1.x, p1.y, p1.z);		glVertex3f(p1.x, p1.y, p1.z);		colour = getColour(r2, radiusmin, radiusmax);		glColor4f(colour.x, colour.y, colour.z, 1.0);		glNormal3f(p2.x, p2.y, p2.z);		glVertex3f(p2.x, p2.y, p2.z);		colour = getColour(r3, radiusmin, radiusmax);		glColor4f(colour.x, colour.y, colour.z, 1.0);		glNormal3f(p3.x, p3.y, p3.z);		glVertex3f(p3.x, p3.y, p3.z);	}	glEnd();	glEndList();	delete[] f;	return 0;}

That''s the code, it''s pretty much a direct work through of Bourkes code for generating a sphere and putting it in a display list. The major difference is I use my own vector class for the facet struct, rather than his XYZ struct.

If anyone could shine some light on possible problems, I''d be most appreciative.

Share on other sites
You only seem to be allocating a single facet3 rather than an array of them which will cause an error because your pairing new and delete[] rather than new[] and delete[].

Share on other sites
*sigh* it''s so frustrating when something so simple stops you dead, thanks for that

Share on other sites
Ok, next couple of questions...

Looking at creating a bumped surface, I''ve looked at Bourkes planet generation, his PovRay idea for asteroids and Elias''s planet generation which is very similar (in fact nearly the same) as Bourkes.

With the planet generation, my random vector only ever seems to point in one direction, which means that I get a variety of coloured strips and some change in shape, but only along one axis of the sphere. So it starts at blue and shifts to red on the opposite side.

With Bourkes asteroid approach, the bulges it creates are coloured, but the shape of the mesh does not alter to match. I think this is down to something I''m not doing with the vertices, but I can''t figure out quite what.

// bulges, dodgy, colours work, but no change in mesh!!!		int bulges = 30;	double bulge_rmin = 0.3,bulge_rmax = 0.7;	double bulge_dmin = -0.075,bulge_dmax = 0.075;	double bscale, radius, length;	float d;	Vector3 norm;	for (k = 0; k < bulges; k++)	{		i = rand() % nface;		j = rand() % 3;		n = f[i].p[j];		bscale  = bulge_dmin + ((rand() % 10) / 10) * (bulge_dmax - bulge_dmin);		radius = bulge_rmin + ((rand() % 10) / 10) * (bulge_rmax - bulge_rmin);			for (i = 0; i < nface; i++)		{			norm.zero();			norm += f[i].p[0]; norm += f[i].p[1]; norm += f[i].p[2];			norm.normalize();			for (int x = 0; x < 3; x++)			{				if((d = vectorDistance(n, f[i].p[x])) >= radius)					continue;				length = bscale * 0.5 * (1 + cos(d  * PI / radius));				f[i].p[x].x += norm.x * length;				f[i].p[x].y += norm.y * length;				f[i].p[x].z += norm.z * length;				f[i].c[x] += 10;			}		}	}

Share on other sites
I''m currently working on procedural planet and asteroid generation, although mainly for eye-candy purposes.

I''m using basic Perlin noise functions, the main difference is that I use the 3D position of the vertex as input to the noise function. This avoids the distortion seen when using polar coordinates.

Geometry:
I use a standard lattitude/longitude sphere model (to make texture generation easier). For each vertex, I perturb it along the normal by a few octaves of Perlin noise. This only generates one type of asteroid - a roughened sphere, however it can look quite good with largish bumps.

Texture:
Because the sphere geometry is simple, it is trivial to map vertices to texture coordinates and (more importantly) vice-versa. For each pixel in the texture, I determine the 3D position of it on the object by bilinear interpolation of the 4 vertices around it. I then use more Perlin noise for the texture. Because I''m using the x,y,z coordinates of where the texture ends up on the object, I dont get the distortion at the poles you see when using standard u,v mapping.

Share on other sites
ok, is this how you perturb along a normal?

vertex += normal * distance

1. 1
Rutin
71
2. 2
3. 3
4. 4
5. 5

• 21
• 10
• 33
• 20
• 9
• Forum Statistics

• Total Topics
633428
• Total Posts
3011822
• Who's Online (See full list)

There are no registered users currently online

×