9
\$\begingroup\$

Imagine you are working on a 3D adaptation of the classical video game Asteroids. Your task is to write an algorithm that can create a random 3D asteroid.

This is a popularity contest, not code golf. Write nice code and create interesting results. Add other cool features if you want.

Rules:

  • Your algorithm must actually create the model, not just load it from an external source or similar.
  • The results must be (pseudo-)random. Running the algorithm several times must create different results.
  • Real-time capability is desirable, but not necessary.
  • Low or high polygon count? Realistic or stylized? You decide...
  • The output must be a mesh, either in memory or as a file such as Wavefront OBJ. In either case you need to render it in some way.
  • Explain your algorithm, so that everybody can learn from it.
  • Show some images of your results.
\$\endgroup\$

1 Answer 1

30
\$\begingroup\$

Blender + Python

Blender's built-in Python scripting is perfect for this sort of thing.

GIF animation of a spinning asteroid

Open a Python console and paste in the following:

import bpy
import random

def asteroid():
    bpy.ops.mesh.primitive_ico_sphere_add()
    bpy.ops.object.mode_set(mode='EDIT')
    bpy.ops.mesh.faces_shade_smooth()
    bpy.ops.mesh.select_mode(type='VERT')
    bpy.ops.mesh.select_random()
    bpy.ops.transform.resize(value=(random.uniform(1.1,1.4),random.uniform(1.1,1.4),random.uniform(1.1,1.4)))
    bpy.ops.mesh.select_all(action='SELECT')
    bpy.ops.mesh.subdivide(smoothness=1)
    bpy.ops.mesh.select_random()
    bpy.ops.transform.resize(value=(random.uniform(1.05,1.15),random.uniform(1.05,1.15),random.uniform(1.05,1.15)))
    bpy.ops.mesh.select_all(action='SELECT')
    bpy.ops.mesh.subdivide(smoothness=1)
    bpy.ops.mesh.select_random()
    bpy.ops.transform.resize(value=(random.uniform(0.92,1.05),random.uniform(0.92,1.05),random.uniform(0.92,1.05)))
    bpy.ops.mesh.select_all(action='SELECT')
    bpy.ops.mesh.subdivide(smoothness=1)
    stretch = random.uniform(0.9,1.5)
    bpy.ops.transform.resize(value=(stretch,1,1))
    bpy.ops.transform.rotate(value=(random.uniform(-1.57,1.57)), axis=(random.uniform(-1.57,1.57),random.uniform(-1.57,1.57),random.uniform(-1.57,1.57)))
    bpy.ops.object.mode_set(mode='OBJECT')

asteroid()

An asteroid will then be created at the position of your 3D cursor:

Wireframe render of asteroid 3D model

Want another asteroid? Move the 3D cursor somewhere else and then type asteroid() into the Python console again (or just Enter to repeat the last line entered).

To make it look more like a piece of space rock and less like a blob of plastic, you need to apply a suitable material. The following procedural material works quite well. I used a diffuse colour of #635C5B, and #8D887F in the marble texture.

Space rock material settings

How it works:

  1. Start by creating a simple icosahedron (bpy.ops.mesh.primitive_ico_sphere_add()).
  2. Enter edit mode (bpy.ops.object.mode_set(mode='EDIT')) and apply smooth shading so that the individual facets blend into one another (bpy.ops.mesh.faces_shade_smooth()).
  3. Select a random subset of the object's vertices (bpy.ops.mesh.select_random()).
  4. Scale them randomly in the X, Y and Z directions (bpy.ops.transform.resize()).
  5. Select the whole object (bpy.ops.mesh.select_all(action='SELECT')) and apply smooth subdivision to add new vertices by interpolating smoothly across the deformed object (bpy.ops.mesh.subdivide(smoothness=1)).
  6. (Repeat steps 3–5 a couple more times.)
  7. Stretch the object in the X direction to make it a bit less spherical (bpy.ops.transform.resize(value=(stretch,1,1)))
  8. Apply a random rotation transform (bpy.ops.transform.rotate())
  9. Finally, exit edit mode and leave the object selected (bpy.ops.object.mode_set(mode='OBJECT')).

More examples:

Asteroid 1Asteroid 2Asteroid 3Asteroid 4

\$\endgroup\$
2
  • 3
    \$\begingroup\$ Holy Bajeezus! . \$\endgroup\$ Mar 13, 2014 at 1:42
  • \$\begingroup\$ Wow that is great! \$\endgroup\$
    – user7467
    Mar 19, 2021 at 14:01

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.