Nebula generator

Download Latest version: 0.1
Includes PDF manual.

Edit: posted first release.


Hey all. Long time blenderhead who just decided to join. Looking forward to learn.

Cutting to the chase, I’ve been trying to generate more realistically looking, traversable nebulae, because what I’ve done so far are just sort of diffuse colored clouds that bear no actual resemblance to the gorgeous stuff that you get from pictures, so I’m working on a python script that will generate a particle cloud (each particle as a volume of gas) and imitate the structures we see in a nebula.

This is my approach, in a nutshell:

  1. Generate the cloud using the voronoi() group and vTurbulence to further separate points. (I get a more or less uniform distribution of points, but with those rich voronoi tendrils :smiley: )

  2. Assume that the particles are very heavy, then start moving them according as if gravity attracted them to each other.

  3. There should be a process that prevents a ‘black hole’. I could add ‘novas’ that send particles away whenever it gets crowded.

  4. ‘Freeze’ the system, put the points in a NMesh, give it a Halo tex with a radius that’s somewhat less than the average distance between particles. The end result should be a multiple-colored nebula, so I may end up using multiple meshes and textures.

Now for the harsh truth: I haven’t put half of what I just described to code yet %| , so I can’t post any code yet (also, it’s not too late to move it to C :P.) I thought this would be the best place to ask for comments, criticism and suggestions.

Well, I think I’m moving the project to C/C++, if only because I realized that an interpreted language is not an ideal choice if you intend to have a bazillion particles all influencing each other as they move through space. I’m researching optimal data structures and algorithms (noise, particle movement, particle raytracing) for this (maybe a a blender texture plugin version.)

This only means that the skybox generator is becoming faster and therefore that the nebulae can be more detailed, not that it is not going to play well with Blender. In fact, there are a few ways this project can work with Blender.

  • It could produce a skybox.
  • It could be a texture plugin. Actually I like the previous option better; all I could gain from running inside blender, such as using the lights in the scene to illuminate the nebula, appear to be pipe dreams–the plugin API doesn’t seem to provide access to scene data. And I’m not sure that I can make my vertex data persistent enough.
  • I can write it as a two-part project to save myself from writing the raytracer, and give users the 3d clouds to play with. The C part could generate the points and evolve the system, then write them to a file. Then a Python loader would bring it to Blender and create several separate meshes for rendering with the Unified. The advantage of this one is that it gives us 3d clouds we could move through.

I think I’m sticking with option C (C plus Python, no pun intended.)

For what it’s worth, here’s the original, non-running python code. I don’t think it’s very useful as is (the Evolve function is not complete), but if anyone can do anything with it, you’re welcome to.


import Blender, math, types
from Blender import Material, NMesh, Noise, Object, Scene, Window


# ====== constants
invNorQ	= (2*math.pi)**0.5	# inverse of normal sigma=1 mu=1 quofficient
norQ	= 1.0 / invNorQ		# actual quofficient
G		= 6.67*10**-11		# universal gravitational constant


# ====== probability distributons
def Normal(x):
	"""
		This is the actual normal distribution
	"""
	global norQ
	return norQ*math.exp(-x*x/2.0)

# ====== distance calculation
def distance(p1, p2):
	return		((p1[0]-p2[0])*(p1[0]-p2[0]) \
			+	 (p1[1]-p2[1])*(p1[1]-p2[1]) \
			+	 (p1[2]-p2[2])*(p1[2]-p2[2])) ** 0.5


# ====== nebulae creation+evolution functions
def add(a,b): return a+b

def Evolve(mesh, speeds, evolutions):
	"""
		This function uses vectorial gravity to evolve the system
		through mutual attraction between particles iteratively:
		
					G m1 m2 (^v1-^v2) / |^v1-^v2|**3
		
		However, we'll assign a sufficiently large enough mass to
		each point that will cause the system to evolve quickly
		
		G = 6.67x10**-11, factoring it out from the equation
		makes every particle extremely heavy, and being there
		no friction, it makes'em move pretty fast. Assuming that the
		mass of each particle is G**(-1/2), the final equation is:

					^v1 - ^v2 / |^v1 - ^v2| ** 3
					
		In the future, this may use a search-optimized kD tree, but
		the brute force method will have to do for now.
	"""
	for e in range(evolutions):
		for i in range(len(mesh)):
			accel = (0,0,0)
			for j in range(len(mesh)):
				speeds[i]	= map(add, [0.5*coord for coord in accel], speeds[i])
				dist		= distance(mesh[j], mesh[i])
				dist3		= dist*dist*dist
				#gravec		= map(add, 


def MakeNebula(maxD, totalPoints=100, evolveIter=10):
	"""
		We use a voronoi distance to displace the point and
		use normalized multiplicative turbulence to generate unique,
		sort of wispy, uniformly distributed points.
		Then we evolve the system using gravity.
	"""
	pointsPerDimension = totalPoints**(1.0/3.0)
	# prepare randomization
	Noise.setRandomSeed(0)
	# create object and mesh
	meshObj = Object.New("Mesh", "Nebula")
	mesh = NMesh.New("Nebula.mesh")
	meshObj.link(mesh)
	# add random vertexes
	step, cnt	= float(maxD+0.01)/pointsPerDimension, 0
	speeds		= []
	x = -maxD/2
	while x < maxD/2:
		y = -maxD/2
		while y < maxD/2:
			z = -maxD/2
			while z < maxD/2:
				cnt += 1
				xt, yt, zt	= [Normal(coord) for coord in Noise.vTurbulence((x,y,x,), 1, 1)]
				xv, yv, zv	= [coord+0.5 for coord in Noise.voronoi((x,y,z,))[1][2]]
				xf, yf, zf	= xv*xt, yv*yt, zv*zt
				speeds.append((xt, yt, zt,))
				mesh.verts.append(NMesh.Vert(xf, yf, zf))
				mesh.update()
				z += step
			y += step
		Window.DrawProgressBar(0.25, "Adding points")
		x += step
	# once created, evolve them
	Evolve(mesh.verts, speeds, evolveIter)
	#mat			=	Material.New("Nebula.mat")
	#mat.mode	=	Material.Modes["HALO"]		| Material.Modes["ZTRANSP"]		\
	#			|	Material.Modes["TRACEABLE"]	| Material.Modes["HALOSHADE"]	\
	#			|	Material.Modes["SHADOW"]	| Material.Modes["VCOL_PAINT"]
	#mat.alpha		= 0.0625
	#mat.add			= 0.25
	#mat.haloSize	= step*3.5
	# and put it in current scene	
	Scene.GetCurrent().link(meshObj)

#MakeNebula(20, 5000)
print Vector(3,2,1) + Vector(1,2,3)

What I’m looking for now is an effective clustering algorithm that works on ‘density’ so I can make dense groups ‘explode’.

Hi
This would be a usefull tool in any form, hope it goes well, thanks for the work :slight_smile:

Ken

Just wondering how this project was going? It would be useful, there is a way to use the Time IPO and a particle system to make a 3D cloud now but it lacks the complex structure you’d find in a real nebula.

I just wish you could use more then one texture on a halo.

Thanx for the interest. Right now I have a working script for Blender 2.37a that creates structures that resemble planetary nebulae somewhat. It’s still at very early stages, but I’ll try to post an initial (alpha) version with a standard control interface and a few pics tomorrow, with a short pdf manual if I can.

Keep up the good work!

–Ralph

Thanks for the effort, it’d be really cool if you can pull this off.

This may not be the way you where going with this but something else that would be cool is to have an object made up of verts that would be shaped like a nebula. I think with halos and careful use of verts and particles some really awesome nebulae could be made with interesting effects.

The thing is to split the verts into groups so that you can have a different halo texture for each segment, like pillars vs clouds and also proto stars. But I’m just thinking out loud, looking forward to testing your script.

@Sonic TH: I was contemplating automating material creation in the future, but I don’t know yet whether to go for realism or artistic freedom, or even if it’s possible to offer both. Well, I’m going to be using this utility often myself, so it’s likely that I’ll end up figuring out what way makes it more useful and work in that direction.

Ok, here’s a first release. It’s very premature, but it’s enough to start playing with it.

Here’s the package, including a 'quick ‘n dirty’ manual: MakeNebula.zip (version 0.1)

Here’s a render out of clouds generated with it:

http://img227.imageshack.us/img227/8104/nebulasample15iu.jpg

Features planned (although who knows) for feature releases:

  • Automatic halo texture generation
  • Multiple material simulation and textures
  • Selection of spectrography options (simulating actual telescope photography)
  • More accurate physics modeling
  • Supernovas (simulated explosions in points of higher concentrations)

BTW – who knows a better site for hosting zips like this? Geocities runs out of bandwidth in a second :frowning:

Well here’s one that I’ve used and seen used before but the file will be deleted after it becomes inactive for x many days. Don’t remember how long have to check on the site. Once you get it to a final version this wouldn’t be the best place but for testing it should work fine.

http://www.zupload.com/index.php

That first render looks interesting can’t wait to try it out.

Well I ran it this morning and it seems to work like a charm. I’ll have to play around with it to see if I can get a good render to post. I’ve been messing around with a hand made halo nebula this week (as seen in my sig) but this gives a much more interesting shape which even at 500,000 iterations took only minutes. Rendering of course takes a bit longer(1,500,000 verts/halos). I was wondering what setting you used for the demo pics? Did you add a particle system or just halos?

What I had been doing was fractal sub-dividing a mesh then using select random to thin/shape it and halo particles with a cloud texture added to make it look more like a cloud.

Also it seems to work in 2.40alpha2 build of blender but I still have python 2.3 installed along with 2.4 so not sure if it really works with python 2.4 or not.

How did you manage to get 2.4x to work on python 2.3.x? I haven’t been able to. :o Anyway, if the Blender.* modules in 2.4x allow this to run, then so should Python 2.4.x – the standard library functions I’m using pretty much stayed the same. At any rate, thanks for testing and for the heads up! :slight_smile:

The fractal+randomness idea is good–maybe I’ll add something along those lines as a third algorithm. Right now my particles only know to dance to their feverish, turbulent mutual attraction :wink:

The demo shots were made with three or four points clouds 30000 to 100000 points each. I don’t recall the exact settings, but the turbulence variation (I think those two have the most influence in shaping the cloud) was probably over 1.5 for the red cloud and less than 1 for the black strand. I leave the mean at 0, or close to 0. I usually end up scaling down to a 20% or even less to get the points closer. To avoid large blobs, I set the camera clipstart over 0.5, or even as much as 2, depending on the mesh.

Hmm, thanks for the tips I’ll be messing around with it some more this weekend no doubt. Gotta say this is really cool.

I have found 2 errors so far, I’m guessing neither will be a surprise since you said in the PDF that they aren’t really working but here they are:

First error is when using the Thorough algorithm.

Trackback <most recent call last>:
  File "<string>", line 522, in ButtonEventHandler
  File "<string>", line 462, in MakeNebula
  File "<string>", line 287, in Evolve_Cuadratic
NameError: global name 'turbScale' is not defined

Second happened when I pushed the ProbBranch to max.

Traceback <most recent call last>:
  File "<string>", line 522, in ButtonEventHandler
  File "<string>", line 426, in MakeNebula
ZeroDivisionError: float division

I typed that in by hand as it’s on another computer and cut N paste would be a hassle so you might wanna double check those tracebacks with your own results. But I am SURE that’s Cuadratic and not Quadratic.

I had a thought but not sure if it would be practical or not. If you could make lines that connect the vertexes, maybe along the path they grew in. The only reason I suggest that is it’d then be possible to make use of blender’s grow and shrink selection tools. I had thought on my hand made cloud that this could be a good way to split it up into parts like a center mass and extending arms. Then give each part a different texture to make it look more like a real cloud. Select random is good too but it’s not as good for selecting a group and using the circle select doesn’t look as random.

[EDIT] Almost forgot about the python thing, I installed 2.4 and set the path to it but left 2.3 where it is, this could screw me up I’m guessing but I didn’t want to remove 2.3 incase I wanted to use scripts that don’t work with 2.4 yet. It seems like WinXP won’t change the path from 2.3 to 2.4 but not going into that, as long as it works I’m not going to mess with it again. [/EDIT]

LOL, “Cuadratic” is my Spanish (first language) butting in. Fixed to keep good form. Dang, why didn’t Python catch that one? :smiley:

I think I’ve got the two bugs you reported squashed. I’ve also added an extra parameter (particle mass) to play with, and I’m working on a (toggleable) evolution edges addition. They can be very useful. I’ll post the updated release as soon as I can.

Ok, here’s the updated script for 0.1.2 (full release next week):

http://z08.zupload.com/download.php?file=getfile&filepath=3064

Added:

  • Adjustable particle mass in kg
  • Wireframe edges (toggle)
  • Initial force of explosion
  • bug fixes

Enjoy :wink:

Awesome, downloading now.

I’m not sure if this is really that good of a shot (I don’t want to discredit your cool script) but I thought I’d post a few renderings:
http://img204.imageshack.us/img204/2761/nebgenneb018yb.th.jpghttp://img204.imageshack.us/img204/5046/nebgenneb027oz.th.jpg

Couldn’t decide on a good view so I just did a panorama:
(Note the color depth has been tweaked for a smaller file size)

WARNING 300K+ HI-RES IMAGE
http://img204.imageshack.us/img204/2175/nebgenneb00pan4pb.jpg

I’ve found I get better results just tweaking halo size without using particles and it renders faster of course. Also a side note, the last two settings “Mean” and “Variation” are pretty much interchangeable. But I think variation would become way more important once/if there are different types of turbulence.

I’m sorry if I’m getting you off course here but I wanted to ask about other kinds of nebulae, like say the ever cool cat’s eye or a dying star (which isn’t really a nebula but still). I was thinking if you did add something like that, maybe something like a type selection option would be useful.

Oh and one more idea, A LOT of scripts need this but don’t have it, yours is not overly complex as far as tweaks goes (yet) but it would be nice to be able to load/save settings for repeat use or to share with others. I think you can use blender’s text editing to that end but not really sure how you’d do it. Of course you know way more about python then I, so just a thought there.

Hmm, there seems to be an intermittent error with the edges, I tried it three and the first time with default settings got a console error instantly. The second time with other settings got it towards the end and the third time with default settings, again got it towards the end.

Seems to be the same traceback every time:

Traceback <most recent call last>:
  File "<string>", line 580, in ButtonEventHandler
  File "<string>", line 513, in MakeNebula
AttributeError: addEdgesData

Ok well I’ll have to eat my hat now, that error seems to only happen in blender 2.4alpha2. In 2.37a it works fine over and over. One note though, not sure if it’s just me again but it seems to tend to produce really long chains a lot. (with or without lines) By chains I mean clouds that end up going off in a line. Not sure if it’s just my settings or not but didn’t seem to happen as much before. Maybe that’s just the branching kicking in though.

Sorry about the false alarm on that last error, it’s most likely blender as others have reported bugs that prevent scripts from working.

[EDIT]Yeah the branching value does seem to play a part, an interesting thing to try is to goto edit mode and press the PKEY then select “All Loose Parts” seems to split the cloud up in an interesting way, by each branch of verts. Also one other note, in the console, it’s saying

Memoryblock free: attempt to free NULL pointer

, as it only happens with edges on thought I’d mention it. [/EDIT]

Wow,I really enjoy this script.I did a small cloud test,nothing really special,but with some more tweeking im sure to get some nice results.
here’s the link.

http://blender.isoserv.com/uploads/CLOUDY.avi

Thanx for sharing :slight_smile:

@Sonic TH: No worries about sidetracking me. Given your efforts to create realistic-looking nebulae, you’re giving me the feedback I need to improve this thing, including some very desirable features I’ve already put in my ‘to do’ list. Wish I had more time to work on this.

The new parameters add some variety too: ExplForce (force of initial explosion) and massMul (weight of each ‘mother cloud’ in kg) can add some variety. (I’ve been setting massMul to smaller weights (in the range of 0.1 to 15000) to see how differently it behaves, and I get ‘angelhair’ that could be interpreted as smoke.)

@tomiko: cool! And you did exactly the thing I originally started writing this for–flying through the clouds! Well, that’s real ‘fitness for purpose’ testing!