Wellensimulation

Übersicht BlitzBasic Codearchiv

Neue Antwort erstellen

Noobody

Betreff: Wellensimulation

BeitragMi, Feb 11, 2009 21:12
Antworten mit Zitat
Benutzer-Profile anzeigen
Vor einiger Zeit bin ich über einen kleinen, aber feinen Artikel über Echtzeit - Simulation von Wasserwellen am Computer gestossen - den habe ich natürlich gleich umgesetzt.

Vom Code gibt es zwei Versionen: Eine Edition mit Arrays und eine mit Banks. Die mit Arrays ist natürlich schneller, jedoch hielt ich die Bank - Version komfortabler, falls es mal jemand in ein Spiel einbauen möchte, wo es unter Umständen auch mehrere Wasserflächen geben soll.

Arrayversion: BlitzBasic: [AUSKLAPPEN]
Global WATERSIZE = 256

Graphics WATERSIZE, WATERSIZE, 0, 2
SetBuffer BackBuffer()

Global Damping# = 0.002, ReadBuffer
Dim Buffer( WATERSIZE, WATERSIZE, 1 )
Dim Obstacle( WATERSIZE, WATERSIZE )
Const PENSIZE = 2

Timer = CreateTimer( 60 )

While Not KeyHit( 1 )
Cls

T = MilliSecs()
ProcessWater()
ReadBuffer = Not ReadBuffer
RenderWater()
Text 0, 0, MilliSecs() - T

If MouseDown( 1 ) Then SpillWater( MouseX(), MouseY(), 12, 10 )

If MouseDown( 2 ) Then
For X = MouseX() - PENSIZE To MouseX() + PENSIZE
For Y = MouseY() - PENSIZE To MouseY() + PENSIZE
If RectsOverlap( 0, 0, WATERSIZE, WATERSIZE, X, Y, 1, 1 ) Then Obstacle( X, Y ) = True
Next
Next
EndIf

Flip 0
WaitTimer Timer
Wend
End

Function ProcessWater()
For Y = 2 To WATERSIZE - 3
For X = 2 To WATERSIZE - 3
If Not Obstacle( X, Y ) Then
Local Value# = Buffer( X - 2, Y, ReadBuffer ) + Buffer( X + 2, Y, ReadBuffer )
Value# = Value# + Buffer( X - 1, Y, ReadBuffer ) + Buffer( X + 1, Y, ReadBuffer )
Value# = Value# + Buffer( X, Y - 2, ReadBuffer ) + Buffer( X, Y + 2, ReadBuffer )
Value# = Value# + Buffer( X, Y - 1, ReadBuffer ) + Buffer( X, Y + 1, ReadBuffer )
Value# = Value# + Buffer( X - 1, Y - 1, ReadBuffer ) + Buffer( X - 1, Y + 1, ReadBuffer )
Value# = Value# + Buffer( X + 1, Y - 1, ReadBuffer ) + Buffer( X + 1, Y + 1, ReadBuffer )

Value# = Value#/6.
Value# = Value# - Buffer( X, Y, Not ReadBuffer )
Value# = Value# - Value#*Damping#

If Value# < -127 Then Value# = -127 ElseIf Value# > 127 Then Value# = 127

Buffer( X, Y, Not ReadBuffer ) = Value#
Else
Curr = Buffer( X, Y, ReadBuffer )
Prev = Buffer( X, Y, Not ReadBuffer )

Buffer( X, Y, ReadBuffer ) = Prev
Buffer( X, Y, Not ReadBuffer ) = Curr
EndIf
Next
Next
End Function

Function RenderWater()
LockBuffer BackBuffer()

For X = 0 To WATERSIZE - 1
For Y = 0 To WATERSIZE - 1
RGB = ( Buffer( X, Y, ReadBuffer ) + 128 )*$010101

If Not Obstacle( X, Y ) Then WritePixelFast X, Y, RGB
Next
Next

UnlockBuffer BackBuffer()
End Function

Function SpillWater( CenterX, CenterY, Radius, Depth )
For X = CenterX - Radius To CenterX + Radius
For Y = CenterY - Radius To CenterY + Radius
If X > 2 And X < WATERSIZE - 2 And Y > 2 And Y < WATERSIZE - 2 Then
Local D = ( CenterX - X )*( CenterX - X ) + ( CenterY - Y )*( CenterY - Y )
If D <= Radius*Radius Then
Disturbance# = Depth*( Radius - D )/Float( Radius )

If Disturbance# < -127 Then Disturbance# = -127 ElseIf Disturbance# > 127 Then Disturbance# = 127

If Not Obstacle( X, Y ) Then Buffer( X, Y, ReadBuffer ) = Disturbance#
EndIf
EndIf
Next
Next
End Function


Bankversion: BlitzBasic: [AUSKLAPPEN]
Const WATERSIZE = 256

Graphics WATERSIZE, WATERSIZE, 0, 2
SetBuffer BackBuffer()

Global Damping# = 0.02
Global ReadBuffer = CreateBank( WATERSIZE*WATERSIZE )
Global WriteBuffer = CreateBank( WATERSIZE*WATERSIZE )
Dim Obstacle( WATERSIZE, WATERSIZE )
Const PENSIZE = 2

Timer = CreateTimer( 60 )

Init()

While Not KeyHit( 1 )
Cls

T = MilliSecs()
ProcessWater()
SwapBuffers()
RenderWater()
Text 0, 0, MilliSecs() - T

If MouseDown( 1 ) Then SpillWater( MouseX(), MouseY(), 12, 10 )

If MouseDown( 2 ) Then
For X = MouseX() - PENSIZE To MouseX() + PENSIZE
For Y = MouseY() - PENSIZE To MouseY() + PENSIZE
If RectsOverlap( 0, 0, WATERSIZE, WATERSIZE, X, Y, 1, 1 ) Then Obstacle( X, Y ) = True
Next
Next
EndIf

Flip 0
WaitTimer Timer
Wend
End

Function ProcessWater()
For Y = 2 To WATERSIZE - 3
For X = 2 To WATERSIZE - 3
If Not Obstacle( X, Y ) Then
Local Value# = PeekByte( ReadBuffer, X + Y*WATERSIZE - 2 ) + PeekByte( ReadBuffer, X + Y*WATERSIZE + 2 )
Value# = Value# + PeekByte( ReadBuffer, X + ( Y - 2 )*WATERSIZE ) + PeekByte( ReadBuffer, X + ( Y + 2 )*WATERSIZE )
Value# = Value# + PeekByte( ReadBuffer, X + Y*WATERSIZE - 1 ) + PeekByte( ReadBuffer, X + Y*WATERSIZE + 1 )
Value# = Value# + PeekByte( ReadBuffer, X + ( Y - 1 )*WATERSIZE ) + PeekByte( ReadBuffer, X + ( Y + 1 )*WATERSIZE )
Value# = Value# + PeekByte( ReadBuffer, X + ( Y - 1 )*WATERSIZE - 1 ) + PeekByte( ReadBuffer, X + ( Y + 1 )*WATERSIZE - 1 )
Value# = Value# + PeekByte( ReadBuffer, X + ( Y - 1 )*WATERSIZE + 1 ) + PeekByte( ReadBuffer, X + ( Y + 1 )*WATERSIZE + 1 )
Value# = Value# - 1536

Value# = Value#/6.
Value# = Value# - PeekByte( WriteBuffer, X + Y*WATERSIZE ) + 128
Value# = Value# - Value#*Damping#

If Value# < -127 Then Value# = -127 ElseIf Value# > 127 Then Value# = 127

PokeByte WriteBuffer, X + Y*WATERSIZE, Value# + 128
Else
Curr = PeekByte( ReadBuffer, X + Y*WATERSIZE )
Prev = PeekByte( WriteBuffer, X + Y*WATERSIZE )

PokeByte ReadBuffer, X + Y*WATERSIZE, Prev
PokeByte WriteBuffer, X + Y*WATERSIZE, Curr
EndIf
Next
Next
End Function

Function RenderWater()
LockBuffer BackBuffer()

For X = 0 To WATERSIZE - 1
For Y = 0 To WATERSIZE - 1
If Not Obstacle( X, Y ) Then WritePixelFast X, Y, PeekByte( ReadBuffer, X + Y*WATERSIZE )*$010101
Next
Next

UnlockBuffer BackBuffer()
End Function

Function SwapBuffers()
Temp = ReadBuffer
ReadBuffer = WriteBuffer
WriteBuffer = Temp
End Function

Function Init()
For X = 0 To WATERSIZE - 1
For Y = 0 To WATERSIZE - 1
PokeByte ReadBuffer, X + Y*WATERSIZE, 128
PokeByte WriteBuffer, X + Y*WATERSIZE, 128
Next
Next
End Function

Function SpillWater( CenterX, CenterY, Radius, Depth )
For X = CenterX - Radius To CenterX + Radius
For Y = CenterY - Radius To CenterY + Radius
If X > 2 And X < WATERSIZE - 2 And Y > 2 And Y < WATERSIZE - 2 Then
Local D = ( CenterX - X )*( CenterX - X ) + ( CenterY - Y )*( CenterY - Y )
If D <= Radius*Radius Then
Disturbance# = Depth*( Radius - D )/Float( Radius )

If Disturbance# < -127 Then Disturbance# = -127 ElseIf Disturbance# > 127 Then Disturbance# = 127

If Not Obstacle( X, Y ) Then PokeByte ReadBuffer, X + Y*WATERSIZE, Disturbance# + 128
EndIf
EndIf
Next
Next
End Function


Die Bedienung ist relativ einfach - mit gedrückter linker Maustaste erzeugt man Wellen, mit der rechten Maustaste kann man Hindernisse setzen.
Die benötigte Rechen- und Renderzeit wird oben links angezeigt.

Eine 3D - Umsetzung wäre eigentlich kein Problem - man müsste die Werte der Wasserfläche einfach als Höhenwert und nicht als Farbe interpretieren.
Eine enstprechende Version in 3D schreibe ich vielleicht auch noch, bis anhin war ich einfach zu faul dazu Razz
Man is the best computer we can put aboard a spacecraft ... and the only one that can be mass produced with unskilled labor. -- Wernher von Braun
  • Zuletzt bearbeitet von Noobody am So, Apr 19, 2009 19:17, insgesamt einmal bearbeitet

coolo

BeitragMi, Feb 11, 2009 21:15
Antworten mit Zitat
Benutzer-Profile anzeigen
Wahnsinn! Ich bin imer mehr beeindruckt was du da alles vorstellst. Ich hoffe da kommt noch mehr.
(vllt. machst du mal ne vernünftige Schatten Engine für BB?)
http://programming-with-design.at/ <-- Der Preis ist heiß!
That's no bug, that's my project!
"Eigenzitate sind nur was für Deppen" -Eigenzitat

ozzi789

BeitragMi, Feb 11, 2009 21:21
Antworten mit Zitat
Benutzer-Profile anzeigen
Total geiler Effekt Smile !
Jedoch wären ein paar Code kommentare ganz nett, raff da fast nix ..
0x2B || ! 0x2B
C# | C++13 | Java 7 | PHP 5
 

n-Halbleiter

BeitragMi, Feb 11, 2009 21:44
Antworten mit Zitat
Benutzer-Profile anzeigen
Hey, das ist echt super!

Ich hab mich eben mal drangesetzt und versucht deinen Code zu verstehen... Ich kriegs nicht hin, zumindest nicht komplett. Wenn du irgendwann mal eine 3D-Version machen würdest, würde es sicher viele Leute freuen, da das gut Arbeit abnehmen kann. Bei den Kommentaren kann ich nur zustimmen, es wäre zumindest gut, um mal ein wenig mehr zu verstehen. Wink
mfg, Calvin
Maschine: Intel Core2 Duo E6750, 4GB DDR2-Ram, ATI Radeon HD4850, Win 7 x64 und Ubuntu 12.04 64-Bit
Ploing!
Blog

"Die Seele einer jeden Ordnung ist ein großer Papierkorb." - Kurt Tucholsky (09.01.1890 - 21.12.1935)

Eingeproggt

BeitragMi, Feb 11, 2009 21:45
Antworten mit Zitat
Benutzer-Profile anzeigen
Ich weiß es ist nicht einfach, aber so ganz Echtzeit is das nicht Sad

70ms pro Frame allein für ein 256² Wasser ist zwar zum Rumspielen ganz ok, aber für ein Spiel?

System:
P4 3.4GHz HT
ATI X700 SE mit 256MB
1GB RAM
Windows XP SP3

mfG, Christoph.
Gewinner des BCC 18, 33 und 65 sowie MiniBCC 9
 

n-Halbleiter

BeitragMi, Feb 11, 2009 21:52
Antworten mit Zitat
Benutzer-Profile anzeigen
Eingeproggt hat Folgendes geschrieben:
Ich weiß es ist nicht einfach, aber so ganz Echtzeit is das nicht Sad

70ms pro Frame allein für ein 256² Wasser ist zwar zum Rumspielen ganz ok, aber für ein Spiel?


Das stimmt, hatte ich nicht bedacht... Für ein Spiel wäre es dann sinnvoll, wenn man immer 2, 3 oder 4 pixel abarbeitet anstatt einen... Das wäre dann zumindest ein wenig schneller, wenn man nicht so eine unglaubliche Genauigkeit haben muss... Ansonsten lässt sich in einem Spiel evtl. noch das Wasser in verschiedene kleinere Bereiche unterteilen, die nur bei Bedarf (also wenn der Spieler gerade draufsieht) abgearbeitet werden... Ich denke, da lässt sich in Spielen noch etwas Performance rausholen, wenn man es ein wenig (*hust*) anpasst.
mfg, Calvin
Maschine: Intel Core2 Duo E6750, 4GB DDR2-Ram, ATI Radeon HD4850, Win 7 x64 und Ubuntu 12.04 64-Bit
Ploing!
Blog

"Die Seele einer jeden Ordnung ist ein großer Papierkorb." - Kurt Tucholsky (09.01.1890 - 21.12.1935)

Noobody

BeitragMi, Feb 11, 2009 22:03
Antworten mit Zitat
Benutzer-Profile anzeigen
Du hast aber den Debugger hoffentlich abgeschaltet? Sonst ist es kein Wunder, dass es so langsam läuft Razz
Andererseits ist es wirklich rechenaufwändig - ich habe hierzu ein paar Lösungsansätze ausprobiert.
Eine Möglichkeit wäre, das Wasser in einzelne Teilbereiche aufzuteilen und pro Frame ein anderes zu aktualisieren. Funktioniert relativ gut, jedoch bewegt sich das Wasser dann ein wenig langsamer. In 3D benötigt man ausserdem viel kleinere Auflösungen, weil ja die 3D - Wasseroberfläche nicht so detailliert sein muss wie das 2D - Bild (ich mach mal das ganze in 3D, damit es ersichtlich wird).
In meinem BCC - Beitrag habe ich ja auch dasselbe Wasser benutzt, dort habe ich einfach einen Pixel auf einen 3x3-Block gestreckt (und es lief noch einigermassen - zumindest auf meinem Laptop Razz ). Ausserdem wird der Rechenaufwand kleiner, wenn viele Hindernisse da sind - was ja in einem Spiel eher der Fall ist.

Alles in allem bleibt es aber rechenintensiv. Ich könnte mal probieren, das ganze in C zu schreiben und eine DLL draus zu machen, das dürfte noch einiges schneller sein.
Man is the best computer we can put aboard a spacecraft ... and the only one that can be mass produced with unskilled labor. -- Wernher von Braun

Eingeproggt

BeitragMi, Feb 11, 2009 22:07
Antworten mit Zitat
Benutzer-Profile anzeigen
Der Meister hat Folgendes geschrieben:
Du hast aber den Debugger hoffentlich abgeschaltet? Sonst ist es kein Wunder, dass es so langsam läuft


*hüstel*

Ohne Debugger hab ich ~15ms, schon viel besser Smile (Ich spreche von der Arrayversion)
Gewinner des BCC 18, 33 und 65 sowie MiniBCC 9

skey-z

BeitragMi, Feb 11, 2009 22:38
Antworten mit Zitat
Benutzer-Profile anzeigen
und selbst banks auf meinem Laptop bringen immerhin schnelle <30 ms bei gedrückter Maustaste und ca 20 Hindernissen
Awards:
Coffee's Monatswettbewerb Feb. 08: 1. Platz
BAC#57: 2. Platz
Twitter

Xaymar

ehemals "Cgamer"

BeitragMi, Feb 11, 2009 23:15
Antworten mit Zitat
Benutzer-Profile anzeigen
hmm das beispiel mit den Arrays lies eine einzige welle ca 50mal hin und her gehen, woei dieselbe welle im bank dinges nur 1 abgeprallt ist. bug?
Warbseite

Noobody

BeitragMi, Feb 11, 2009 23:23
Antworten mit Zitat
Benutzer-Profile anzeigen
Kein Bug, ein Feature!
In der Tat ist bei der Bank - Version die Globale 'Damping#' (=Dämpfung, innere Reibung des Wassers) auf 0.02, während es bei der Arrayversion auf 0.002 gesetzt ist.
Damit haben die Wellen dort eine geringere Dämpfung und gehen daher auch länger hin und her als bei der Bank - Version.
Scheint wohl noch ein kleiner Tippfehler zu sein, aber ist ja nicht wirklich schlimm. Diesen Faktor kann man übrigens beliebig verändern, um verschieden träge Flüssigkeiten zu simulieren.
Man is the best computer we can put aboard a spacecraft ... and the only one that can be mass produced with unskilled labor. -- Wernher von Braun

Noobody

BeitragDo, Feb 12, 2009 19:40
Antworten mit Zitat
Benutzer-Profile anzeigen
*Doppelpost*
So, ich hab das ganze mal in 3D umgesetzt.
Da ich auf externe Dateien verzichten wollte, habe ich flugs mal meine DiamondSquare - Funktion aus dem Codearchiv verwendet, um das Terrain während Laufzeit zu generieren.
Source ist im Moment nicht der sauberste, aber er funktioniert.
Das ganze funktioniert auf dem Prinzip, dass im Hintergrund eine viel grössere Wasserfläche berechnet wird, als schlussendlich dargestellt wird. Damit dauert die Berechnung zwar ein wenig länger, dafür sieht es viel besser aus (ist die berechnete Fläche gleich klein wie die dargestellte, sieht es... Nun ja.).

Da das Terrain dynamisch generiert wird, kann es vorkommen, dass die Karte fast komplett von Land bedeckt ist oder dass die Kamera im Berg steckt usw.
In solchen Fällen das Programm einfach kurz neustarten, dann kommt ein anderes Terrain heraus.


Der BlitzBasic: [AUSKLAPPEN]
Graphics3D 800, 600, 0, 2
SetBuffer BackBuffer()

Global Damping# = 0.0002, ReadBuffer
Const WATERSIZE = 256
Const TILESIZE = 64
Dim Buffer( WATERSIZE, WATERSIZE, 1 )
Dim Obstacle( WATERSIZE, WATERSIZE )
Dim HeightMap#( 0, 0 )
Const PENSIZE = 2

Global WaterMesh, WaterSurface

Cam = CreateCamera()
PositionEntity Cam, 0, 10, 0

Light = CreateLight( 2 )
PositionEntity Light, 0, 10, 0
LightRange Light, 10
LightColor Light, 255, 255, 255

InitTerrain()
InitWaterPlane()

Timer = CreateTimer( 60 )

MouseXSpeed()
MouseYSpeed()

While Not KeyHit( 1 )
Cls

TurnEntity Cam, MouseYSpeed(), -MouseXSpeed(), 0
MoveMouse 400, 300
MoveEntity Cam, ( KeyDown( 32 ) - KeyDown( 30 ) )*0.5, KeyDown( 57 )*0.1, ( KeyDown( 17 ) - KeyDown( 31 ) )*0.5

If MouseHit( 1 ) Then
CameraPick Cam, 400, 300

If PickedEntity() = WaterMesh Then
TFormPoint PickedX(), PickedY(), PickedZ(), 0, WaterMesh
SpillWater( ( TFormedX() + TILESIZE/2 )*WATERSIZE/TILESIZE, ( TFormedZ() + TILESIZE/2 )*WATERSIZE/TILESIZE, 5, 30 )
EndIf
EndIf

T = MilliSecs()
ProcessWater()
ReadBuffer = Not ReadBuffer
T = MilliSecs() - T

UpdateWaterPlane()

RenderWorld

Text 0, 0, T

Flip 0
WaitTimer Timer
Wend
End

Function ProcessWater()
For Y = 2 To WATERSIZE - 3
For X = 2 To WATERSIZE - 3
If Not Obstacle( X, Y ) Then
Local Value# = Buffer( X - 2, Y, ReadBuffer ) + Buffer( X + 2, Y, ReadBuffer )
Value# = Value# + Buffer( X - 1, Y, ReadBuffer ) + Buffer( X + 1, Y, ReadBuffer )
Value# = Value# + Buffer( X, Y - 2, ReadBuffer ) + Buffer( X, Y + 2, ReadBuffer )
Value# = Value# + Buffer( X, Y - 1, ReadBuffer ) + Buffer( X, Y + 1, ReadBuffer )
Value# = Value# + Buffer( X - 1, Y - 1, ReadBuffer ) + Buffer( X - 1, Y + 1, ReadBuffer )
Value# = Value# + Buffer( X + 1, Y - 1, ReadBuffer ) + Buffer( X + 1, Y + 1, ReadBuffer )

Value# = Value#/6.
Value# = Value# - Buffer( X, Y, Not ReadBuffer )
Value# = Value# - Value#*Damping#

If Value# < -127 Then Value# = -127 ElseIf Value# > 127 Then Value# = 127

Buffer( X, Y, Not ReadBuffer ) = Value#
Else
Curr = Buffer( X, Y, ReadBuffer )
Prev = Buffer( X, Y, Not ReadBuffer )

Buffer( X, Y, ReadBuffer ) = Prev
Buffer( X, Y, Not ReadBuffer ) = Curr
EndIf
Next
Next
End Function

Function RenderWater()
LockBuffer BackBuffer()

For X = 0 To WATERSIZE - 1
For Y = 0 To WATERSIZE - 1
RGB = ( Buffer( X, Y, ReadBuffer ) + 128 )*$010101

If Not Obstacle( X, Y ) Then WritePixelFast X, Y, RGB
Next
Next

UnlockBuffer BackBuffer()
End Function

Function UpdateWaterPlane()
For X = 0 To WATERSIZE - 1 Step WATERSIZE/TILESIZE
For Z = 0 To WATERSIZE - 1 Step WATERSIZE/TILESIZE
Index = ( X + Z*TILESIZE )/( WATERSIZE/TILESIZE )

VertexCoords WaterSurface, Index, VertexX( WaterSurface, Index ), Buffer( Z, X, ReadBuffer )/32., VertexZ( WaterSurface, Index )
VertexColor WaterSurface, Index, 0, 0, Buffer( Z, X, ReadBuffer ) + 128
Next
Next

UpdateNormals WaterMesh
End Function

Function SpillWater( CenterX, CenterY, Radius, Depth )
DebugLog CenterX + " " + CenterY
For X = CenterX - Radius To CenterX + Radius
For Y = CenterY - Radius To CenterY + Radius
If X > 2 And X < WATERSIZE - 2 And Y > 2 And Y < WATERSIZE - 2 Then
Local D = ( CenterX - X )*( CenterX - X ) + ( CenterY - Y )*( CenterY - Y )
If D <= Radius*Radius Then
Disturbance# = Depth*( Radius - D )/Float( Radius )

If Disturbance# < -127 Then Disturbance# = -127 ElseIf Disturbance# > 127 Then Disturbance# = 127

If Not Obstacle( X, Y ) Then Buffer( X, Y, ReadBuffer ) = Disturbance#
EndIf
EndIf
Next
Next
End Function

Function DiamondSquare( Size, S1#, S2#, S3#, S4# )
Dim HeightMap#( Size, Size )

HeightMap#( 0, 0 ) = S1#
HeightMap#( Size, 0 ) = S2#
HeightMap#( Size, Size ) = S3#
HeightMap#( 0, Size ) = S4#

Local StepSize = Size
While StepSize > 1
For X = 0 To Size - StepSize
For Y = 0 To Size - StepSize
HeightMap#( X + StepSize/2, Y ) = ( HeightMap#( X, Y ) + HeightMap#( X + StepSize, Y ) )/2
HeightMap#( X, Y + StepSize/2 ) = ( HeightMap#( X, Y ) + HeightMap#( X, Y + StepSize ) )/2
HeightMap#( X + StepSize/2, Y + StepSize ) = ( HeightMap#( X, Y + StepSize ) + HeightMap#( X + StepSize, Y + StepSize ) )/2
HeightMap#( X + StepSize, Y + StepSize/2 ) = ( HeightMap#( X + StepSize, Y ) + HeightMap#( X + StepSize, Y + StepSize ) )/2

HeightMap#( X + StepSize/2, Y + StepSize/2 ) = ( HeightMap#( X, Y ) + HeightMap#( X + StepSize, Y ) + HeightMap#( X, Y + StepSize ) + HeightMap#( X + StepSize, Y + StepSize ) )/4
HeightMap#( X + StepSize/2, Y + StepSize/2 ) = HeightMap#( X + StepSize/2, Y + StepSize/2 ) + Rnd( -1, 1 )*StepSize/Float( Size )*5

Y = Y + StepSize - 1
Next

X = X + StepSize - 1
Next

StepSize = StepSize/2
Wend
End Function

Function RenderHeightmap( Size )
Local Max#, Min# = 10000
For X = 0 To Size - 1
For Y = 0 To Size - 1
If HeightMap#( X, Y ) > Max# Then Max# = HeightMap#( X, Y )
If HeightMap#( X, Y ) < Min# Then Min# = HeightMap#( X, Y )
Next
Next

LockBuffer BackBuffer()
For X = 0 To Size - 1
For Y = 0 To Size - 1
Ratio = Floor( ( HeightMap#( X, Y ) - Min# )/( Max# - Min# )*255 )
WritePixelFast X, Y, $FF000000 + Ratio*$010101
Next
Next
UnlockBuffer BackBuffer()
End Function

Function CreateMeshPlane( XSize, ZSize )
Local Mesh = CreateMesh()
Local Surf = CreateSurface( Mesh )

For X# = -XSize/2. + 0.5 To XSize/2. - 0.5
For Z# = -ZSize/2. + 0.5 To ZSize/2. - 0.5
AddVertex Surf, X#, 0, Z#, ( X# + XSize/2. )/XSize, ( Z# + ZSize/2. )/ZSize
Next
Next

For X = 0 To XSize - 2
For Z = 0 To ZSize - 2
V1 = X*ZSize + Z + 1
V2 = ( X + 1 )*ZSize + Z + 1
V3 = ( X + 1 )*ZSize + Z
V4 = X*ZSize + Z

AddTriangle Surf, V1, V2, V3
AddTriangle Surf, V1, V3, V4
Next
Next

Return Mesh
End Function

Function InitTerrain()
SeedRnd MilliSecs()
DiamondSquare( TILESIZE, 5, 4, 3, 2 )

Terrain = CreateMeshPlane( TILESIZE, TILESIZE )
Surface = GetSurface( Terrain, 1 )
Texture = CreateTexture( TILESIZE, TILESIZE )
EntityTexture Terrain, Texture

Local Max# = -1000, Min# = 1000
For X = 0 To TILESIZE - 1
For Z = 0 To TILESIZE - 1
Index = X + Z*TILESIZE

If Heightmap( Z, X )*5 > Max# Then Max# = Heightmap( Z, X )*5 ElseIf Heightmap( Z, X )*5 < Min# Then Min# = HeightMap( Z, X )*5

VertexCoords Surface, Index, VertexX( Surface, Index ), HeightMap( Z, X )*5, VertexZ( Surface, Index )
Next
Next

UpdateNormals Terrain
TranslateEntity Terrain, 0, -( Max# - Min# )/2 - Min#, 0

For X = 0 To WATERSIZE - 1
For Z = 0 To WATERSIZE - 1
XCoord = X*TILESIZE/WATERSIZE
ZCoord = Z*TILESIZE/WATERSIZE

Index = XCoord + ZCoord*TILESIZE

If HeightMap( ZCoord, XCoord )*5 > Min# + ( Max# - Min# )/2 Then Obstacle( Z, X ) = True
Next
Next


RenderHeightmap( TILESIZE )
CopyRect 0, 0, TILESIZE, TILESIZE, 0, 0, BackBuffer(), TextureBuffer( Texture )
End Function

Function InitWaterPlane()
WaterMesh = CreateMeshPlane( TILESIZE, TILESIZE )
WaterSurface = GetSurface( WaterMesh, 1 )

EntityFX WaterMesh, 2
EntityPickMode WaterMesh, 2
End Function


Ich hab sogar einen Screenshot gemacht Razz
user posted image

Kamera mit WASD bewegen, mit Maus herumschauen und mit Mausklick Wasserwellen erzeugen.
  • Zuletzt bearbeitet von Noobody am So, Apr 19, 2009 19:17, insgesamt einmal bearbeitet

coolo

BeitragDo, Feb 12, 2009 19:48
Antworten mit Zitat
Benutzer-Profile anzeigen
Das schaut ja mal echt kuhl aus!
Das einzige, ist das das Wasser an den "Rändern" etwas arg zittert, aber ich glaube das kann man verbessern indem man die imaginäre Map vergrößert.
http://programming-with-design.at/ <-- Der Preis ist heiß!
That's no bug, that's my project!
"Eigenzitate sind nur was für Deppen" -Eigenzitat

ToeB

BeitragDo, Feb 12, 2009 21:06
Antworten mit Zitat
Benutzer-Profile anzeigen
Wäre villeicht schön in 2D wie auch in 3D wenn die wellen nicht unendlich das wasser bewegen würden sonder auch ausklingen könnten... Sonst siehts aber seeehr geil aus, nur wie kann ich von Schwarz weiß in Blau/schwart umschalten (also wie wasser) ?

mfg ToeB
Religiöse Kriege sind Streitigkeiten erwachsener Männer darum, wer den besten imaginären Freund hat.
Race-Project - Das Rennspiel der etwas anderen Art
SimpleUDP3.0 - Neuste Version der Netzwerk-Bibliothek
Vielen Dank an dieser Stelle nochmal an Pummelie, welcher mir einen Teil seines VServers für das Betreiben meines Masterservers zur verfügung stellt!

Noobody

BeitragDo, Feb 12, 2009 21:11
Antworten mit Zitat
Benutzer-Profile anzeigen
ToeB hat Folgendes geschrieben:
Wäre villeicht schön in 2D wie auch in 3D wenn die wellen nicht unendlich das wasser bewegen würden sonder auch ausklingen könnten

Dazu musst du nur die Globale 'Damping#' auf einen höheren Wert stellen.

ToeB hat Folgendes geschrieben:
Sonst siehts aber seeehr geil aus, nur wie kann ich von Schwarz weiß in Blau/schwart umschalten (also wie wasser) ?

Wie genau meinst du das?
Wenn du das Terrain blau-schwarz einfärben willst, dann musst du nur in RenderHeightmap die folgende Zeile Code: [AUSKLAPPEN]
WritePixelFast X, Y, $FF000000 + Ratio*$010101
abändern in Code: [AUSKLAPPEN]
WritePixelFast X, Y, $FF000000 + Ratio
Man is the best computer we can put aboard a spacecraft ... and the only one that can be mass produced with unskilled labor. -- Wernher von Braun

Noobody

BeitragMi, Apr 08, 2009 21:30
Antworten mit Zitat
Benutzer-Profile anzeigen
Kleine Information: Der Forenuser Barratator hat das ganze nochmal hübsch mit Skybox und Cubemapping umgesetzt.
Hier das Youtube Video. Sieht schon mal um einiges besser aus als meine Version in schlichtem Blau Razz
Man is the best computer we can put aboard a spacecraft ... and the only one that can be mass produced with unskilled labor. -- Wernher von Braun
 

barratator

BeitragFr, Apr 10, 2009 12:41
Antworten mit Zitat
Benutzer-Profile anzeigen
Kleine Erklärung zum Video:
Das Video war jetzt nicht wirklich in Realtime...Das ganze hat ca. 5 Minuten gedauert, weil ich jeden Frame mit SaveBuffer abgespeichert habe, um später die bestmögliche Qualität zu erreichen Wink

An dieser Stelle möchte ich Noobody auch nochmal für den Code danken und ihn motivieren, dass er es erweitern soll Wink Z.b. Flusstechnik vom Wasser, usw.


Gruß
Bastian

Neue Antwort erstellen


Übersicht BlitzBasic Codearchiv

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group