First: the Channel class:Imports MTV3D65
Public Class cChannel
#Region " Declarations "
Private Randomizer As Random = New Random()
Private PixelArray(,) As Single
Private Size As Integer
Public Structure tCELL
Public x As Single
Public y As Single
Public color1 As Single
Public color2 As Single
Public distanceToMapCenter As Single
End Structure
Public Structure tDISTANCE_BUFFER
Public distance As Single
Public cell As Integer
End Structure
#End Region
#Region " New "
Public Sub New(ByVal nSize As Integer)
Size = nSize
ReDim PixelArray(nSize + 1, nSize + 1)
End Sub
#End Region
#Region " Functions & Properties "
Public Sub SetPixel(ByVal x As Integer, ByVal y As Integer, ByVal pixel As Single)
PixelArray(x, y) = pixel
End Sub
'#########################################################################
Public Sub FillWith(ByVal pixel As Single)
For x = 0 To Size - 1
For y = 0 To Size - 1
PixelArray(x, y) = pixel
Next
Next
End Sub
'#########################################################################
Public Sub SetPixelWrap(ByRef x As Integer, ByRef y As Integer, ByVal pixel As Single)
WrapCoordinates(x, y)
PixelArray(x, y) = pixel
End Sub
'#########################################################################
Public Sub WrapCoordinates(ByRef x As Integer, ByRef y As Integer)
If (x < 0) Then x *= -1
If (y < 0) Then y *= -1
If (x >= Size) Then x = Size - (x Mod Size) - 1
If (y >= Size) Then y = Size - (y Mod Size) - 1
End Sub
'#########################################################################
Public Sub GetColorLimits(ByRef min As Single, ByRef max As Single)
For x = 0 To Size - 1
For y = 0 To Size - 1
If (PixelArray(x, y) < min) Then
min = PixelArray(x, y)
ElseIf (PixelArray(x, y) > max) Then
max = PixelArray(x, y)
End If
Next
Next
End Sub
'#########################################################################
Public ReadOnly Property GetSize() As Single
Get
Return Size
End Get
End Property
'#########################################################################
Public ReadOnly Property GetPixel(ByVal x As Integer, ByVal y As Integer) As Single
Get
Return PixelArray(x, y)
End Get
End Property
'#########################################################################
Public Function GetPixelWrap(ByRef x As Integer, ByRef y As Integer) As Single
WrapCoordinates(x, y)
Return PixelArray(x, y)
End Function
'#########################################################################
Public ReadOnly Property GetPixelRGBA(ByVal x As Integer, ByVal y As Integer) As Integer
Get
Return Globals.RGBA(PixelArray(x, y), PixelArray(x, y), PixelArray(x, y), 1.0F)
End Get
End Property
'#########################################################################
Public Function InterpolateRGB(ByVal x As TV_COLOR, ByVal y As TV_COLOR, ByVal s As Single) As TV_COLOR
Dim n As TV_COLOR = New TV_COLOR()
n.r = x.r + s * (y.r - x.r)
n.g = x.g + s * (y.g - x.g)
n.b = x.b + s * (y.b - x.b)
Return n
End Function
'#########################################################################
Public Function InterpolateLinear(ByVal x0 As Single, ByVal x1 As Single, ByVal s As Single) As Single
Return x0 + s * (x1 - x0)
End Function
'#########################################################################
Public Function RGBA2TV3D(ByVal r As Integer, ByVal g As Integer, ByVal b As Integer, ByVal a As Integer) As TV_COLOR
Return Globals.DecodeRGBA(Globals.RGBA256(r, g, b, a))
End Function
'#########################################################################
'public Function Color2TV3D(Color tColor) as TV_COLOR
' Return Globals.DecodeRGBA(Globals.RGBA256(Convert.ToInt32(tColor.R), Convert.ToInt32(tColor.G), Convert.ToInt32(tColor.B), Convert.ToInt32(tColor.A)))
' End Function
'#########################################################################
'public Function Color TV3D2Color(TV_COLOR tColor)
' Return Color.FromArgb((Int())(tColor.a * 255), (Int())(tColor.r * 255), (Int())(tColor.g * 255), (Int())(tColor.b * 255))
' End Function
#End Region
#Region " Smooth "
Public Sub Smooth(ByVal nPasses As Integer, ByVal fFactor As Single)
Dim faNewPixels(Size, Size) As Single
Dim x, y, i, l, n, px, py As Integer
Dim dMax, h, hi, di, dh As Single
Dim hl As Single = 0.0F
Dim T As Single = fFactor / Size
'# Moore Neighborhood
Dim vaNeighborhood(8) As TV_2DVECTOR
vaNeighborhood(0) = New TV_2DVECTOR(-1, 1)
vaNeighborhood(1) = New TV_2DVECTOR(1, 0)
vaNeighborhood(2) = New TV_2DVECTOR(1, 1)
vaNeighborhood(3) = New TV_2DVECTOR(0, -1)
vaNeighborhood(4) = New TV_2DVECTOR(0, 1)
vaNeighborhood(5) = New TV_2DVECTOR(-1, -1)
vaNeighborhood(6) = New TV_2DVECTOR(-1, 0)
vaNeighborhood(7) = New TV_2DVECTOR(-1, 1)
For i = 0 To nPasses - 1
For x = 0 To Size - 1
For y = 0 To Size - 1
h = GetPixel(x, y)
dMax = 0.0F
For n = 0 To 7
hi = GetPixelWrap(x + vaNeighborhood(n).x, y + vaNeighborhood(n).y)
di = h - hi
If (di > dMax) Then
dMax = di
l = n
End If
Next
If (0 < dMax And dMax <= T) Then
dh = 0.5F * dMax
h -= dh
SetPixel(x, y, h)
px = x + vaNeighborhood(l).x
py = y + vaNeighborhood(l).y
WrapCoordinates(px, py)
hl = dh + GetPixel(px, py)
SetPixel(px, py, hl)
End If
Next
Next
Next
End Sub
#End Region
#Region " Normalize "
Public Sub Normalize()
Dim min As Single = 0.0F
Dim max As Single = 0.0F
GetColorLimits(min, max)
For x = 0 To Size - 1
For y = 0 To Size - 1
PixelArray(x, y) = (PixelArray(x, y) - min) / (max - min)
Next
Next
End Sub
#End Region
#Region " Add Erosion "
Public Sub AddErosion(ByVal nPasses As Integer, ByVal fFactor As Single)
Dim x As Integer = 0
Dim y As Integer = 0
Dim px As Integer = 0
Dim py As Integer = 0
Dim i As Integer = 0
Dim n As Integer = 0
Dim l As Integer = 0
Dim dMax, h, hi, di, dh As Single
Dim T As Single = fFactor / Size
Dim hl As Single = 0.0F
'# Moore Neighborhood
Dim vaNeighborhood(8) As TV_2DVECTOR
vaNeighborhood(0) = New TV_2DVECTOR(-1, 1)
vaNeighborhood(1) = New TV_2DVECTOR(1, 0)
vaNeighborhood(2) = New TV_2DVECTOR(1, 1)
vaNeighborhood(3) = New TV_2DVECTOR(0, -1)
vaNeighborhood(4) = New TV_2DVECTOR(0, 1)
vaNeighborhood(5) = New TV_2DVECTOR(-1, -1)
vaNeighborhood(6) = New TV_2DVECTOR(-1, 0)
vaNeighborhood(7) = New TV_2DVECTOR(-1, 1)
For i = 0 To nPasses - 1
For x = 0 To Size - 1
For y = 0 To Size - 1
h = GetPixel(x, y)
dMax = 0.0F
For n = 0 To 7
hi = GetPixelWrap(x + vaNeighborhood(n).x, y + vaNeighborhood(n).y)
di = h - hi
If (di > dMax) Then
dMax = di
l = n
End If
Next
If (0 < dMax And dMax <= T) Then
dh = 0.5F * dMax
h -= dh
SetPixel(x, y, h)
px = x + vaNeighborhood(l).x
py = y + vaNeighborhood(l).y
WrapCoordinates(px, py)
hl = dh + GetPixel(px, py)
SetPixel(px, py, hl)
End If
Next
Next
Next
End Sub
#End Region
#Region " Perturb "
Public Sub Perturb(ByVal pNoiseMap As cChannel, ByVal fMagnitude As Single)
Dim faNewPixels(Size, Size) As Single
Dim x, y, x_coord_lo, x_coord_hi, y_coord_lo, y_coord_hi As Integer
Dim p, x_coord, x_frac, y_coord, y_frac, val1, val2 As Single
For x = 0 To Size - 1
For y = 0 To Size - 1
p = fMagnitude * (pNoiseMap.GetPixel(x, y) - 0.5F)
x_coord = x + Size * p
x_coord_lo = x_coord
x_coord_hi = x_coord_lo + 1
x_frac = x_coord - x_coord_lo
y_coord = y + Size * p
y_coord_lo = y_coord
y_coord_hi = y_coord_lo + 1
y_frac = y_coord - y_coord_lo
val1 = Cosine_Interpolate(GetPixelWrap(x_coord_lo, y_coord_lo), GetPixelWrap(x_coord_hi, y_coord_lo), x_frac)
val2 = Cosine_Interpolate(GetPixelWrap(x_coord_lo, y_coord_hi), GetPixelWrap(x_coord_hi, y_coord_hi), x_frac)
faNewPixels(x, y) = Cosine_Interpolate(val1, val2, y_frac)
Next
Next
PixelArray = faNewPixels
End Sub
#End Region
#Region " Generate Midpoint Displacement Map "
Public Sub GenerateMidpointDisplacementMap(ByVal fPersitence As Single)
'# Diamond Square Algorithm
Dim n As Integer = 2
Dim avg, c As Single
Dim ulx, uly, dimm As Integer
Dim s, i, j, x, y As Integer
While Math.Pow(2, n) < Size - 1
n += 1
End While
dimm = 1 << (n - 2)
'# seed the first few array values with reasonable numbers
For j = 0 To 4
For i = 0 To 4
PixelArray(dimm * i, dimm * j) = 0.75F + (Randomizer.NextDouble() * 2 - 1) / 8
Next
Next
'# run the algorithm
c = 1.0F
For s = 2 To n - 1
c *= fPersitence
dimm = (1 << (n - s))
For j = 0 To (1 << s) - 1
For i = 0 To (1 << s) - 1
uly = j * dimm
ulx = i * dimm
y = (1 << (n - s - 1)) + j * (1 << (n - s))
x = (1 << (n - s - 1)) + i * (1 << (n - s))
avg = 0
avg += PixelArray(ulx, uly)
avg += PixelArray(ulx + dimm, uly)
avg += PixelArray(ulx, uly + dimm)
avg += PixelArray(ulx + dimm, uly + dimm)
avg /= 4
PixelArray(x, y) = avg + c * (Randomizer.NextDouble() * 2 - 1)
Next
Next
dimm = (1 << (n - s - 1))
For j = 0 To (1 << (s + 1))
For i = 0 To (1 << (s + 1))
If ((i + j) Mod 2 = 0) Then Continue For
y = j * dimm
x = i * dimm
avg = 0
avg += PixelArray(IIf((x - dimm >= 0), (x - dimm), (x - dimm + (1 << n))), y)
avg += PixelArray(x, IIf((y - dimm >= 0), (y - dimm), (y - dimm + (1 << n))))
avg += PixelArray(IIf((x + dimm <= (1 << n)), (x + dimm), (x + dimm - (1 << n))), y)
avg += PixelArray(x, IIf((y + dimm <= (1 << n)), (y + dimm), (y + dimm - (1 << n))))
avg /= 4
PixelArray(x, y) = avg + c * (Randomizer.NextDouble() * 2 - 1)
Next
Next
Next
Normalize()
End Sub
#End Region
#Region " Save To Texture "
Public Sub SaveToTexture(ByVal sFilename As String)
Dim nTextureID As Integer = TextureFactory.CreateTexture(Size, Size, False)
TextureFactory.LockTexture(nTextureID, False)
For x = 0 To Size - 1
For y = 0 To Size - 1
TextureFactory.SetPixel(nTextureID, x, y, GetPixelRGBA(x, y))
Next
Next
TextureFactory.UnlockTexture(nTextureID, False)
TextureFactory.SaveTexture(nTextureID, sFilename, MTV3D65.CONST_TV_IMAGEFORMAT.TV_IMAGE_BMP)
TextureFactory.DeleteTexture(nTextureID)
End Sub
#End Region
#Region " Create From Texture "
Public Sub CreateFromTexture(ByVal sFilename As String)
Dim nTextureID As Integer = TextureFactory.LoadTexture(sFilename, "", Size, Size)
TextureFactory.LockTexture(nTextureID, False)
For x = 0 To Size - 1
For y = 0 To Size - 1
PixelArray(x, y) = Globals.DecodeRGBA(TextureFactory.GetPixel(nTextureID, x, y)).r
Next
Next
TextureFactory.UnlockTexture(nTextureID, False)
TextureFactory.DeleteTexture(nTextureID)
End Sub
#End Region
#Region " Multiply With "
Public Sub MultiplyWith(ByVal pRight As cChannel)
If Not (pRight.Size = Size) Then Return
For x = 0 To Size - 1
For y = 0 To Size - 1
PixelArray(x, y) *= pRight.PixelArray(x, y)
Next
Next
End Sub
#End Region
#Region " Combine With "
Public Sub CombineWith(ByVal pRight As cChannel, ByVal fRightOpacity As Single)
If Not (pRight.Size = Size) Then Return
Dim fLeftOpacity As Single = 1.0F - fRightOpacity
For x = 0 To Size - 1
For y = 0 To Size - 1
PixelArray(x, y) = PixelArray(x, y) * fLeftOpacity + pRight.PixelArray(x, y) * fRightOpacity
Next
Next
End Sub
#End Region
#Region " Generate Voronoi Map "
Public Sub GenerateVoronoiMap(ByVal pRedChannel As cChannel, ByVal pGreenChannel As cChannel, ByVal pBlueChannel As cChannel, ByVal c1 As Single, ByVal c2 As Single, ByVal nCellCount As Integer)
Dim faDistanceBuffer(pRedChannel.GetSize(), pRedChannel.GetSize()) As tDISTANCE_BUFFER
Dim fTotalMinDistance As Single = Single.MaxValue
Dim fTotalMaxDistance As Single = Single.MinValue
Dim d1, d2 As Single
Dim fDistance As Single = 0.0F
Dim vaPointBuffer(nCellCount) As tCELL
Dim i, x, y As Integer
For i = 0 To nCellCount - 1
vaPointBuffer(i).x = Randomizer.NextDouble() * pRedChannel.GetSize()
vaPointBuffer(i).y = Randomizer.NextDouble() * pRedChannel.GetSize()
vaPointBuffer(i).color1 = Randomizer.NextDouble()
vaPointBuffer(i).distanceToMapCenter = Math.Sqrt(Math.Pow(vaPointBuffer(i).x - pRedChannel.GetSize() / 2, 2) + Math.Pow(vaPointBuffer(i).y - pRedChannel.GetSize() / 2, 2))
'for (n = 0 n < nCellCount n++)
' '# Die eigene Zelle überspringen
' If( n != i ) Then
' vaPointBuffer(i).color2 = (float)m_pRandomizer.Next(0, 2) % 2
' End If
'Next
Next
For x = 0 To pRedChannel.GetSize() - 1
For y = 0 To pRedChannel.GetSize() - 1
d1 = Single.MaxValue
d2 = Single.MaxValue
For i = 0 To nCellCount - 1
'# a² = b² + c² = Pythagoras (bzw. Euclidean distance metric)
fDistance = Math.Sqrt(Math.Pow(vaPointBuffer(i).x - x, 2) + Math.Pow(vaPointBuffer(i).y - y, 2))
If (fDistance < d1) Then
d2 = d1
d1 = fDistance
faDistanceBuffer(x, y).cell = i
ElseIf (fDistance < d2) Then
d2 = fDistance
End If
Next
faDistanceBuffer(x, y).distance = c1 * d1 + c2 * d2
If (faDistanceBuffer(x, y).distance < fTotalMinDistance) Then
fTotalMinDistance = faDistanceBuffer(x, y).distance
ElseIf (faDistanceBuffer(x, y).distance > fTotalMaxDistance) Then
fTotalMaxDistance = faDistanceBuffer(x, y).distance
End If
Next
Next
d1 = Single.MaxValue
d2 = Single.MinValue
For i = 0 To nCellCount - 1
If (vaPointBuffer(i).distanceToMapCenter < d1) Then
d1 = vaPointBuffer(i).distanceToMapCenter
ElseIf (vaPointBuffer(i).distanceToMapCenter > d2) Then
d2 = vaPointBuffer(i).distanceToMapCenter
End If
Next
For i = 0 To nCellCount - 1
vaPointBuffer(i).color2 = 1.0F - (vaPointBuffer(i).distanceToMapCenter - d1) / (d2 - d1)
Next
For x = 0 To pRedChannel.GetSize() - 1
For y = 0 To pRedChannel.GetSize() - 1
'# Normalisieren
pRedChannel.SetPixel(x, y, (faDistanceBuffer(x, y).distance - fTotalMinDistance) / (fTotalMaxDistance - fTotalMinDistance))
pGreenChannel.SetPixel(x, y, vaPointBuffer(faDistanceBuffer(x, y).cell).color1)
pBlueChannel.SetPixel(x, y, vaPointBuffer(faDistanceBuffer(x, y).cell).color2)
Next
Next
End Sub
#End Region
End Class