• Advertisement

Archived

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

procedural asteroids

This topic is 5006 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

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 this post


Link to post
Share on other sites
Advertisement
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 this post


Link to post
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 this post


Link to post
Share on other sites
Guest Anonymous Poster
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 this post


Link to post
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 this post


Link to post
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 this post


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

Share this post


Link to post
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 this post


Link to post
Share on other sites
Guest Anonymous Poster
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 this post


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

vertex += normal * distance


Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Yeah. You can get some interesting shapes by applying several layers of noise and recalculating the normals between each one, although you can sometimes end up with self-intersecting meshes.

Share this post


Link to post
Share on other sites
For my 3D first person asteroids shooter game Close Approach at each level (and each time the same level is played) the game procedurally generates a different asteroid mesh using fractal algorithms. (all the asteroids in one level are the same) This was done by generating a 2D height grid with fractals, and then appling this as fractal noise over the vertices of a standard sphere mesh.

It''s not the perfect solution, you still end up with spherical surfaces at the north and south poles of the sphere, but it was cheap and cheerful.

If I ever get round to improving the asteroids in the game, I would take into account the fact that most asteroids, because of their small mass and gravity aren''t necessarily spherical in shape, e.g. Eros is more potato shaped. I''d probably model this by merging 2, 3, 4 of my previous asteroid shapes into one asteroid to make odd-looking but more realistic asteroid shapes.

With a spherical mesh having a noisy surface, I did encounter problems trying to texture map the surface, e.g. faces that were sloped more at right angles to a perfect sphere''s surface did result in texture stretching when applying a mesh texture (cylindrical). If anybody has any solutions for this problem I would be interested to hear them.

Share this post


Link to post
Share on other sites

  • Advertisement