Ich habe letztlich einen Code verfasst der die Mandelbrotmenge in Quaternionen berechnet, stat wie normalerweise in den Komplexen Zahlen.
Allerdings ist der Rendervorgang etwas langsam.
Das Mandelbrot wird auf die Koordinaten x,y,z und w gerechnet woraus dann ein 3D schnitt gezeigt wird.
Mit den Tasten Hoch/Runter,Links/Rechts,A/Y Bewegt man sich.
Mit den Tasten S/X kann man sich durch die w-Achse bewegen
BlitzMax: [AUSKLAPPEN] [EINKLAPPEN] SuperStrict
Const GWIDTH:Int = 400, GHEIGHT:Int = 300 Const stp:Byte = 2
Global GWIDTH2:Float = GWIDTH / 2.0, GHEIGHT2:Float = GHEIGHT / 2.0
Graphics GWIDTH, GHEIGHT
Const Res:Int = 100 Global Voxel:Byte[Res, Res, Res, Res]
Global CamX:Float, CamY:Float, CamZ:Float, CamW:Float Global CamYaw:Float CamX = Res / 3 CamY = Res / 2 CamZ = 0 CamW = Res / 2
Const CamSpeed:Float = 4
Global Light:Int
Global Res2:Int = Res / 2 Local Res5:Float = Res / 4
Print "" Print "Calculate Mandelbrot" For Local x:Int = 0 Until Res For Local y:Int = 0 Until Res For Local z:Int = 0 Until Res For Local w:Int = 0 Until Res If Mandelbrot4D(100, (x - Res2) / Res5, (y - Res2) / Res5, (z - Res2) / Res5, (w - Res2) / Res5) Then Voxel[x, y, z, w] = 1 Next Next Next Print x + "/" + Res Next
Print "Compute Light" For Local x:Int = 0 Until Res For Local y:Int = 0 Until Res For Local z:Int = 0 Until Res For Local w:Int = 0 Until Res If voxel[x, y, z, w] > 0 If GetVoxel(x - 1, y, z, w) > 0 Then Light:+1 If GetVoxel(x - 1, y - 1, z, w) > 0 Then Light:+1 If GetVoxel(x - 1, y - 1, z - 1, w) > 0 Then Light:+1 If GetVoxel(x, y - 1, z, w) > 0 Then Light:+1 If GetVoxel(x, y - 1, z - 1, w) > 0 Then Light:+1 If GetVoxel(x, y, z - 1, w) > 0 Then Light:+1 If GetVoxel(x - 1, y, z - 1, w) > 0 Then Light:+1 voxel[x, y, z, w] = 255 - (25 * Light) Light = 0 EndIf Next Next Next Next
Print "Finished"
Global millis:Int
While Not KeyHit(KEY_ESCAPE) If KeyDown(KEY_A) CamX:+Cos(CamYaw + 90) * CamSpeed CamZ:+Sin(CamYaw + 90) * CamSpeed End If If KeyDown(KEY_Y) CamX:-Cos(CamYaw + 90) * CamSpeed CamZ:-Sin(CamYaw + 90) * CamSpeed End If CamY:+(KeyDown(KEY_DOWN) - KeyDown(KEY_UP)) * CamSpeed CamYaw:+(KeyDown(KEY_LEFT) - KeyDown(KEY_RIGHT)) * CamSpeed * 5 CamW:+(KeyDown(KEY_S) - KeyDown(KEY_X)) millis = MilliSecs() Render() DrawText "Render Time: " + (MilliSecs() - millis) + "ms", 0, 0 Flip 0 Cls Wend
Function Render() For Local x:Int = 0 Until GWIDTH Step stp For Local y:Int = 0 Until GHEIGHT Step stp Local PickX:Float = CamX Local PickY:Float = CamY Local PickZ:Float = CamZ Local PickSX:Float = (x - GWIDTH2) / GWIDTH2 Local PickSY:Float = (y - GHEIGHT2) / GHEIGHT2 Local PickSZ:Float = 1 Local Dist:Float = Sqr(PickSX * PickSX + PickSZ * PickSZ) Local winkel:Float = ATan2(PickSZ, PickSX) + CamYaw PickSX = Cos(winkel) * Dist PickSZ = Sin(winkel) * Dist For Local n:Int = 0 To Res2 PickX:+PickSX PickY:+PickSY PickZ:+PickSZ If GetVoxel(PickX, PickY, PickZ, CamW) > 0 SetColor voxel[PickX, PickY, PickZ, CamW], voxel[PickX, PickY, PickZ, CamW], voxel[PickX, PickY, PickZ, CamW] DrawRect x, y, stp, stp Exit End If Next Next Next End Function
Function GetVoxel:Byte(x:Int, y:Int, z:Int, w:Int = 50) If x >= 0 And x < Res And y >= 0 And y < Res And z >= 0 And z < Res Return Voxel[x, y, z, w] EndIf Return 0 End Function
Function Mandelbrot4D:Byte(Iterationen:Int, x:Float, y:Float, z:Float, w:Float, a:Float=0, b:Float=0, c:Float=0, d:Float=0) Local a1:Float, b1:Float, c1:Float, d1:Float Local itr:Int = 0 Repeat If itr = Iterationen Then Return 1 a1 = a * a - b * b - c * c - d * d + x b1 = 2 * a * b + y c1 = 2 * a * c + z d1 = 2 * a * d + w a = a1 b = b1 c = c1 d = d1 itr:+1 Until a * a + b * b + c * c + d * d >= 4 Return 0 End Function
Da man mit einem 4D-Array keine sehr grosse Auflösung hinbekommt, hier noch eine Version in der die w-Achse nicht berechnet wird BlitzMax: [AUSKLAPPEN] [EINKLAPPEN] SuperStrict
Const GWIDTH:Int = 400, GHEIGHT:Int = 300 Const stp:Byte = 2
Global GWIDTH2:Float = GWIDTH / 2, GHEIGHT2:Float = GHEIGHT / 2
Graphics GWIDTH, GHEIGHT
Const Res:Int = 300 Global Voxel:Byte[Res, Res, Res]
Global CamX:Float, CamY:Float, CamZ:Float, CamW:Float Global CamYaw:Float CamX = Res / 3 CamY = Res / 2 CamZ = 0 CamW = Res / 2
Const CamSpeed:Float = 4
Global Light:Int
Global Res2:Int = Res / 2 Local Res5:Float = Res / 4
DrawText "Calculate Mandelbrot", 0, 0 Flip 0 For Local x:Int = 0 Until Res For Local y:Int = 0 Until Res For Local z:Int = 0 Until Res If Mandelbrot4D(100, (x - Res2) / Res5, (y - Res2) / Res5, (z - Res2) / Res5, 0) Then Voxel[x, y, z] = 1 Next Next Print x + "/" + Res Next
DrawText "Compute Light", 0, 15 Flip 0 For Local x:Int = 0 Until Res For Local y:Int = 0 Until Res For Local z:Int = 0 Until Res If voxel[x, y, z] > 0 If GetVoxel(x - 1, y, z) > 0 Then Light:+1 If GetVoxel(x - 1, y - 1, z) > 0 Then Light:+1 If GetVoxel(x - 1, y - 1, z - 1) > 0 Then Light:+1 If GetVoxel(x, y - 1, z) > 0 Then Light:+1 If GetVoxel(x, y - 1, z - 1) > 0 Then Light:+1 If GetVoxel(x, y, z - 1) > 0 Then Light:+1 If GetVoxel(x - 1, y, z - 1) > 0 Then Light:+1 voxel[x, y, z] = 255 - (25 * Light) Light = 0 EndIf Next Next Print x + "/" + Res Next
Print "Finished"
Global millis:Int
While Not KeyHit(KEY_ESCAPE) If KeyDown(KEY_A) CamX:+Cos(CamYaw + 90) * CamSpeed CamZ:+Sin(CamYaw + 90) * CamSpeed End If If KeyDown(KEY_Y) CamX:-Cos(CamYaw + 90) * CamSpeed CamZ:-Sin(CamYaw + 90) * CamSpeed End If CamY:+(KeyDown(KEY_DOWN) - KeyDown(KEY_UP)) * CamSpeed CamYaw:+(KeyDown(KEY_LEFT) - KeyDown(KEY_RIGHT)) * CamSpeed * 2 CamW:+(KeyDown(KEY_S) - KeyDown(KEY_X)) millis = MilliSecs() Render() DrawText "Render Time: " + (MilliSecs() - millis) + "ms", 0, 0 Flip 0 Cls Wend
Function Render() For Local x:Int = 0 Until GWIDTH Step stp For Local y:Int = 0 Until GHEIGHT Step stp Local PickX:Float = CamX Local PickY:Float = CamY Local PickZ:Float = CamZ Local PickSX:Float = (x - GWIDTH2) / GWIDTH2 Local PickSY:Float = (y - GHEIGHT2) / GHEIGHT2 Local PickSZ:Float = 1 Local Dist:Float = Sqr(PickSX * PickSX + PickSZ * PickSZ) Local winkel:Float = ATan2(PickSZ, PickSX) + CamYaw PickSX = Cos(winkel) * Dist PickSZ = Sin(winkel) * Dist For Local n:Int = 0 To Res2 PickX:+PickSX PickY:+PickSY PickZ:+PickSZ If GetVoxel(PickX, PickY, PickZ) > 0 SetColor voxel[PickX, PickY, PickZ], voxel[PickX, PickY, PickZ], voxel[PickX, PickY, PickZ] DrawRect x, y, stp, stp Exit End If Next Next Next End Function
Function GetVoxel:Byte(x:Int, y:Int, z:Int) If x >= 0 And x < Res And y >= 0 And y < Res And z >= 0 And z < Res Return Voxel[x, y, z] EndIf Return 0 End Function
Function Mandelbrot4D:Byte(Iterationen:Int, x:Float, y:Float, z:Float, w:Float, a:Float=0, b:Float=0, c:Float=0, d:Float=0) Local a1:Float, b1:Float, c1:Float, d1:Float Local itr:Int = 0 Repeat If itr = Iterationen Then Return 1 a1 = a * a - b * b - c * c - d * d + x b1 = 2 * a * b + y c1 = 2 * a * c + z d1 = 2 * a * d + w a = a1 b = b1 c = c1 d = d1 itr:+1 Until a * a + b * b + c * c + d * d >= 4 Return 0 End Function
Viel Spass!
|