Fast 2D Blobby Objects/Metaballs with Max2D


Tweet blitzmax blitzmax-ng code-archives effects blitzmax-dx rated
(Posted 2 months ago) RonTek

The main idea of producing blobby objects is that you first of all generate the combined energy fields - officially known as an isosurface - and then you interpret that surface by rendering only at a certain threshold. In my example above I simply took a paint program, a flood fill tool with a treshhold of 5 pixel values, and clicked on the image in several places. What this shows you is that if you vary the threshold you vary how much energy needs to be present in order to make a perimeter.

The very simple final sourcecode is below, no strings attached. As it stands it generates blob fields that occupy a 512x512 space. It can also do 256x256 and 128x128, but any size other than that you'll have to work out the balldivider and lineardivider values - I'm sure there is a formulae that would generate them properly but I couldn't figure it out.

Author: ImaginaryHuman, Bot Builder

Image

Strict

Type Blob
Field X,Y,r,g,b
Const size=128, sizehalf=64
Global img:TImage

Function Init()
Local divider:Float
If size=128 Then divider=64 '8x8
If size=256 Then divider=256 '16x16
If size=512 Then divider=1024 '32x32
Local lineardivider:Float
If size=128 Then lineardivider=0.5
If size=256 Then lineardivider=1
If size=512 Then lineardivider=2

'Render the gradient image
For Local r:Float=1 To size-1 Step 0.5
Local level:Float=r
level:*level
level=level/divider
SetColor level,level,level 'For blobby gradient shape
DrawOval r/2,r/2,size-r,size-r
Next

AutoMidHandle True
img=CreateImage(size,size,1,FILTEREDIMAGE)
GrabImage(img,0,0,0)
End Function
End Type



Type HumpingBlob Extends blob
Global List:TList
Field vx#,vy#

Method New()
If List=Null Then List=New TList
List.Addlast(Self)
End Method

Function Update()
For Local b:HumpingBlob=EachIn list
For Local b2:HumpingBlob=EachIn list
If b2<>b And (b2.x<>b.x Or b.x<>b2.x) Then
Local dx#=b2.x-b.x, dy#=b2.y-b.y, d1#=Sqr(dx*dx+dy*dy)
If d1<64 Then
d1=.01*(d1-40)/d1
dx:*d1
dy:*d1
b.vx:+dx
b2.vx:-dx
b.vy:+dy
b2.vy:-dy
EndIf
EndIf
Next
b.x:+b.vx
b.y:+b.vy
If b.x<20 Or b.x>780 Or b.y<20 Or b.y>580 Then
b.y=Rand(30,570)
b.x=Rand(30,770)
b.vx=Rnd(-1,1)
b.vy=Rnd(-1,1)
EndIf
b.vx=b.vx*.99'+Rnd(-.5,.5)
b.vy=b.vy*.99'+Rnd(-.5,.5)
SetColor b.r,b.g,b.b
DrawImage img,b.x,b.y
Next
End Function
End Type

Graphics 800,600
blob.init
Cls

SeedRnd MilliSecs()

'Set the drawing mode
SetBlend LIGHTBLEND

For Local i=0 To 100
Local g:HumpingBlob=New HumpingBlob
g.x=Rand(10,800)
g.y=Rand(10,600)
g.vx=Rnd(-1,1)
g.vy=Rnd(-1,1)
g.r=Rand(128,255)
g.g=Rand(128,255)
g.b=Rand(128,255)
Next

'Keep drawing the image until you press Escape
Repeat
Cls
HumpingBlob.update
Flip
Until KeyHit(KEY_ESCAPE)

Reply To Topic (minimum 10 characters)

Please log in to reply