|
|
||
|
Totalistic Cellular AutomataCreate unique, continually varying tiled images
Continuing this short series on the use of cellular automata for creation of algorithmic images, this sample demonstrates using the Totalistic form. A Totalistic cellular automata differs from other the other forms of the algorithm by summing the contribution from surrounding cells, and using modular arithmetic to provide the result. About The Totalistic Cellular Automata AlgorithmAs described in the article Crystal Model Cellular Automata article, a cellular automata is essentially a grid of cells whose state varies with each step through the automation. In this case, the rule that is applied to modify the state between steps is as follows:
As ever, this technique sounds rather simple and it is hard to imagine it producing particularly complex results. And in practice, if you start with a grid where all of the cells have the same state then that is true. However, if the initial state is seeded with random values then complex and organised results emerge rapidly. This is associated with the "magic" step of discarding the whole portion of the result, which introduces considerable complexity into the mathematics. One of the effects of taking only the fractional portion of the result is that if the rate factor is around 0.5 then many cells will undergo a radical change in state with each step of the automata. This differs from the more natural evolution of states which occur in the Catalytic and Crystal model automatas presented elsewhere in the article, and can result in flashing, depending upon how the colours in the palette are arranged. The technique can therefore be better suited for creation of static environments rather than evolving or animated ones. ImplementationAs with the other cellular automata samples, the implementation uses a 256 Colour DIB Section to store the result. This is used both for manipulating the state and rendering at the same time, which means animation can be performed in realtime on many systems. The main part of the implementation makes the DIB Section memory look like a VB array, then loops through each cell, performing the algorithm given above. The code for this is as follows:
Public Sub Step()
Dim x As Long
Dim y As Long
Dim tSALast As SAFEARRAY2D
Dim tSA As SAFEARRAY2D
Dim bDibLast() As Byte
Dim bDibNext() As Byte
Dim lTot As Long
Dim iX As Long
Dim iY As Long
Dim i As Long
Dim j As Long
Dim lMid As Long
With tSALast
.cbElements = 1
.cDims = 2
.Bounds(0).lLbound = 0
.Bounds(0).cElements = m_cDibLast.Height
.Bounds(1).lLbound = 0
.Bounds(1).cElements = m_cDibLast.BytesPerScanLine()
.pvData = m_cDibLast.DIBSectionBitsPtr
End With
CopyMemory ByVal VarPtrArray(bDibLast()), VarPtr(tSALast), 4
With tSA
.cbElements = 1
.cDims = 2
.Bounds(0).lLbound = 0
.Bounds(0).cElements = m_cDib.Height
.Bounds(1).lLbound = 0
.Bounds(1).cElements = m_cDib.BytesPerScanLine()
.pvData = m_cDib.DIBSectionBitsPtr
End With
CopyMemory ByVal VarPtrArray(bDibNext()), VarPtr(tSA), 4
' Run the cellular automata step:
lMid = m_lStates \ 2
For x = 0 To m_cDib.Width - 1
For y = 0 To m_cDib.Height - 1
lTot = 0
Dim fTot As Double
For iX = -1 To 1
i = x + iX
If (i < 0) Then i = m_cDib.Width - 1
If (i >= m_cDib.Width) Then i = 0
For iY = -1 To 1
j = y + iY
If (j < 0) Then j = m_cDib.Height - 1
If (j >= m_cDib.Height) Then j = 0
fTot = fTot + bDibLast(i, j)
Next iY
Next iX
fTot = fTot / (9# * m_lStates)
fTot = fTot + m_fRate
fTot = fTot - Int(fTot)
bDibNext(i, j) = fTot * m_lStates
Next y
Next x
' Copy New -> Old
m_cDib.PaintPicture m_cDibLast.hdc
' Clear the temporary array descriptor
CopyMemory ByVal VarPtrArray(bDibNext), 0&, 4
CopyMemory ByVal VarPtrArray(bDibLast), 0&, 4
End Sub
To make the output look interesting, each of the states is assigned a colour from a gradient palette. The palette is arranged so that there is a linear gradient from a dark colour to a light colour and back again over the 256 states:
Public Property Let States(ByVal lStates As Long)
m_lStates = lStates
ReDim lColor(0 To m_lStates - 1) As Long
Dim i As Long, j As Long
Dim rS As Long, gS As Long, bS As Long
Dim rE As Long, gE As Long, bE As Long
' Get the RGB components of the dark and light colours:
rS = m_lColorDark And &HFF&
gS = (m_lColorDark And &HFF00&) \ &H100&
bS = (m_lColorDark And &HFF0000) \ &H10000
rE = m_lColorLight And &HFF&
gE = (m_lColorLight And &HFF00&) \ &H100&
bE = (m_lColorLight And &HFF0000) \ &H10000
' Generate the palette:
Dim lMid As Long
lMid = States \ 2
For i = 0 To lMid
lColor(i) = RGB( _
rS + (i * (rE - rS)) \ lMid, _
gS + (i * (gE - gS)) \ lMid, _
bS + (i * (bE - bS)) \ lMid _
)
Next i
j = i
For i = lMid + 1 To m_lStates - 1
lColor(i) = lColor(j)
j = j - 1
Next i
' Set this palette into the DIB Sections:
m_cDib.SetPalette lColor
m_cDibLast.SetPalette lColor
End Property
Sample OutputSome images which were generated using this technique are displayed below. These effects were generated by varying the rate factor: ![]() ![]() ![]() ![]() ![]() ![]() ConclusionThis article has demonstrated how to implement a simple Totalistic Cellular Automata and provided sample code to play with.
|
|
|
|
||