Proog

Mit der 3D Library "OpenB3D" von angros47 (siehe hier, externer Link) ist die 3D Programmierung sehr einfach. Die Library unterstützt Windows und Linux.

 

3D-Programmierung in 10 Schritten

10 einfache Beispielprogramme zeigen, wie man schnell und einfach eigene Programme von einer Box bis hin zu einer 3D Welt erstellen kann.

Beispiele zum Download: (Link)

 

Beginn - Programmgerüst für ein 3D-Programm

 

{codecitation}

#include "openb3d.bi"

'see MultiKey example
#include "fbgfx.bi"
#if __FB_LANG__ = "fb"
Using FB '' Scan code constants are stored in the FB namespace in lang FB
#endif

screen 18, 32, , &h02
Graphics3d 640,480,32,1,1

..
[initialization]
..

Do
  ..
   [mainloop]
  ..
  renderworld
  flip
   Sleep 10
Loop Until MultiKey(SC_Escape)

{/codecitation}

 

Erläuterung zum Programmgerüst

 

Einbinden der 3D-Bibliothek

{codecitation}
#include "openb3d.bi"
{/codecitation}

Die Zeile sorgt dafür, dass Befehle für die 3D-Programmierung zur Verfügung stehen. Zum Compilieren des Programms wird die Datei "openb3d.bi" benötigt. Damit das fertig compilierte Programm ausgeführt werden kann, wird unter Windows die Datei "openb3d.dll" benötigt. Für Linux wird die entsprechende Datei aus dem Linux-Paket benötigt.

 

Einbinden der Tastatur-Konstanten für den MultiKey Befehl

{codecitation}

'see MultiKey example
#include "fbgfx.bi"
#if __FB_LANG__ = "fb"
Using FB '' Scan code constants are stored in the FB namespace in lang FB
#endif

{/codecitation}

Die Zeilen sind aus der FreeBASIC Dokumentation entnommen. Sie binden die Tastaturkonstanten für den MultiKey Befehl ein ("SC_Escape" zum Beispiel).

 

Grafik und 3D Modus einschalten

Mit folgenden Programmzeilen wird die Bildschirmauflösung auf 640*480 gesetzt:

{codecitation}
screen 18, 32, , &h02
Graphics3d 640,480,32,1,1
{/codecitation}

Der Wert "GFX_FULLSCREEN" aktiviert den Vollbild-Modus, wenn man die Programmzeile "screen" ändert.

{codecitation}
screen 18, 32, , &h02 Or GFX_FULLSCREEN
{/codecitation}

 

Bildauflösung ändern

Anstatt 640*480 lassen sich auch höhere Auflösungen auswählen.

Beispiel für 800*600 Auflösung

{codecitation}
Screen 19, 32, , &h02 Or GFX_FULLSCREEN
Graphics3d 800,600,32,1,1
{/codecitation}

Beispiel für 1024*768 Auflösung

{codecitation}
Screen 20, 32, , &h02 Or GFX_FULLSCREEN
Graphics3d 1024,768,32,1,1
{/codecitation}

 

Programm Initialisierung

An der Stelle [initialization] stehen Befehle, die einmalig zum Programmbeginn ausgeführt werden.

 

3D Programmschleife

Anweisungen, die fortlaufend ausgeführt werden sollen, stehen im Bereich [mainloop].

 

 

Beispiel 1 - 3D Version von "Hello World"

Das erste Programm zeigt, wie man einen einfachen Würfel erzeugt, den man per Tastatur drehen kann.

Screenshot

Cube01.bas

 

Programmcode Cube1.bas

Initialisierungsteil [initialization]

{codecitation}

var cube=createcube()
moveentity cube,0,0,5
var cam=createcamera()

{/codecitation}

 

Programmschleife [mainloop]

{codecitation}

  If MultiKey(SC_s) Then turnentity cube,1,0,0,0
  If MultiKey(SC_w) Then turnentity cube,-1,0,0,0
  If MultiKey(SC_d) Then turnentity cube,0,-1,0,0
  If MultiKey(SC_a) Then turnentity cube,0,1,0,0
  If MultiKey(SC_e) Then turnentity cube,0,0,-1,0
  If MultiKey(SC_q) Then turnentity cube,0,0,1,0

{/codecitation}

 

Einen Würfel erzeugen

Die Programmzeile "var cube=CreateCube()" erzeugt einen Würfel an der Position 0,0,0 sowie die Variable cube, die einen Zeiger auf den Würfel erhält. Mit der Zeigervariable "cube" kann man den Würfel manipulieren.

 

Eine Kamera erzeugen

Die Programmzeile "var cam=CreateCamera()" erzeugt eine Kamera an der Position 0,0,0 und weist den Zeiger auf die Kamera an die neu erzeugte Variable "cam" zu.

 

Ein 3D-Objekt bewegen

Mit der Programmzeile "MoveEntity cube,0,0,5"  wird der Würfel "cube" um 5 Positionen in Z-Richtung verschoben, also von der Kamera weg.

 

Ein 3D-Objekt drehen und kippen

Mit dem Befehl "TurnEntity" kann man ein 3D-Objekt drehen und kippen. Das Programmbeispiel dreht und kippt den Würfel in drei Achsen. Mit der Esc-Taste beendet man das Programm.

 

 

Beispiel 2 - Ein Objekt im Raum bewegen

Das zweite Beispiel zeigt, wie man den Würfel aus dem letzten Beispiel per Tastatur in drei Raumachsen verschoben werden kann.

Screenshot

Cube02.bas

 

Ein 3D-Objekt im Raum bewegen

Der Befeht "MoveEntity" wird eingesetzt, um den Würfel in alle drei Raumachsen zu verschieben (Tasten rtz / fgh).

 

Tastenbelegung anpassen

Benutzer mit englischem Tastenlayout sollten im Quelltext die Tasten "y" und "z" tauschen (MultiKey(SC_y) <> MultiKey(SC_z)).

 

 

Beispiel 3 - Unterschiedliche Körper und Farben

Das dritte Beispiel zeigt, wie man verschiedene Grundelemente erzeugt und wie man Farben nutzt.

 

Screenshot

Cube03.bas

{codecitation}
var cylinder=CreateCylinder(16)
var cube=CreateCube()
var cone=CreateCone(4)
{/codecitation}

Mit dem Parameter bei CreateCylinder() und CreateCone() stellt man ein, wie viele Dreiecke für die Rundung eingesetzt werden. Mehr Elemente erzeugen eine glattere Fläche, belegen aber mehr Speicher und Rechenzeit.

{codecitation}
EntityColor cylinder,100,50,50
EntityColor cube,0,100,50
EntityColor cone,0,50,100
{/codecitation}

Mit dem Befehl EntityColor kann man Grundkörper einfärben. Nach einem Zeiger auf den Grundkörper werden die drei Farbwerte für Rot, Grün und Blau angegeben.

 

 

Beispiel 4 - Untergrund erzeugen

Wir erzeugen mit "CreateTerrain" einen Untergrund, überziehen ihn mit einer Textur (Schachbrettmuster) und legen unterschiedliche Höhen fest.

Screenshot

Cube04.bas

Mit "CreateTerrain(Größe)" erzeugt man einen Untergrund mit einer >Größe von 32*32 Stützpunkten. Die Größe von Untergründen muß als Zweierpotenz angegeben werden (2, 4, 8, 16, 32, 64, 128, 256, 512, 1024).

{codecitation}
var terrain = CreateTerrain(32)
{/codecitation}

Damit das Terrain ein Aussehen erhält, wird ihm eine Textur zugewiesen. Eine Textur, die als Bitmap-Datei vorliegt, kann man mit dem Befehl LoadTexture laden. Alternativ kann man eine Textur aus einer Grafik erzeugen. Der nächste Programmteil zeigt, wie man eine Textur als Grafik berechnet.

1. Schritt: Grafik erzeugen

{codecitation}
'create image of terrain
'(RGB swap red and blue when converting to texture)
var terimg=imagecreate(32,32,32)
  Line terimg,(0,0)-(31,31),RGB(255,100,0),BF
  Line terimg,(0,0)-(15,15),RGB(100,255,0),BF
  Line terimg,(16,16)-(31,31),RGB(100,255,0),BF
{/codecitation}

2. Schritt: Grafik in Textur umwandeln

{codecitation}
'create texture from image
var tertex=CreateTexture(32,32,1,1)
BufferToTex tertex,terimg+32,1
{/codecitation}

Anschließend weisen wir dem Untergrund die neue Textur zu.

{codecitation}
EntityTexture terrain,tertex
{/codecitation}

Auch dem Untergrund kann man eine Farbe zuweisen.

{codecitation}
EntityColor terrain,20,100,40
{/codecitation}

Der Befehl ModifyTerrain() dient zur Einstellung der Geländehöhe an unterschiedlichen Positionen. Ein Terrain wird mittels PositionEntity in der simulierten Welt platziert.

{codecitation}
for x As Integer = 0 To 31
   for z As Integer = 0 To 31
    ModifyTerrain(terrain,x,z,0.05*Sin(x/2)*Sin(z/2))
   next z
next x

PositionEntity terrain,-15,-5,30
{/codecitation}

Mit AmbientLight(R,G,B) stellen wir das Umgebungslicht ein. Die Helligkeitswerte lassen sich für Rot, Grün und Blau einzeln definieren.

 

Beispiel 5 - Kamera steuern, Objekte animieren und Texturen beschriften

Im Beispiel 5 steuern wir die Kamera mit der Tastatur und beschriften die Textur des Würfels mit einem Text.

 

Screenshot

Cube05.bas

 

Das folgende Beispiel erzeugt eine Grafik mit einem Text. Die Grafik wird anschließend in eine Textur umgewandelt und dem Würfel übergezogen.

{codecitation}
var tex1=CreateTexture(128,128,1,1)
var img = imagecreate(128,128,32)
Line img,(0,0)-(127,127),RGB(0,200,100),BF
draw string img, (64-4*12,10)," ** CUBE ** "
BufferToTex tex1,img+32,1
EntityTexture cube,tex1
{/codecitation}

 

Die Animation bewegt den Kegel und den Zylinder in einer langsamen sinusförmigen Bewegung. Bei dem Würfel ändert sich die Transparenz.

{codecitation}
'animation
EntityAlpha cube, 0.3+0.7*(1.0+Cos(Timer))/2
moveentity cylinder,0,Cos(Timer)/100,0
moveentity cone,0,0,Cos(Timer)/33
{/codecitation}

Für die Steuerung der Kamera lassen sich die Befehle TurnEntity und TranslateEntity einsetzen.

{codecitation}
If Multikey(SC_RIGHT) Then turnentity cam,0,-1,0,0
If Multikey(SC_LEFT)  Then turnentity cam,0,1,0,0
If Multikey(SC_DOWN)  Then TranslateEntity cam,0,0,-.1,0
If Multikey(SC_UP)    Then TranslateEntity cam,0,0, .1,0
If Multikey(SC_y) Then TranslateEntity cam,0,-.1,0,0
If Multikey(SC_x) Then TranslateEntity cam,0,.1,0,0
If Multikey(SC_c) Then TranslateEntity cam,-.1,0,0
If Multikey(SC_v) Then TranslateEntity cam,.1,0,0
{/codecitation}

 

 

 

 

Beispiel 6 - Ein Feld von Objekten erzeugen

 

Screenshot

Cube06.bas

 

Das folgende Beispiel erzeugt ein Feld von 20*20 Würfeln, die leicht aufsteigend angeordnet sind. Durch Ändern der Konstanten MaxBlocks kann man die Größe des Feldes verändern.

Das Array block(x,y) enthält Zeiger auf jeden Würfel des Feldes.

{codecitation}
Dim As Any Ptr block(100,100)
Const maxblocks=20
For x As Integer=0 To maxblocks
   For y As Integer=0 To maxblocks
     block(x,y)=createcube()
     moveentity block(x,y),x*3,-3+x*.1+y*.5,11+y*3
     EntityColor block(x,y),50,50+4*x,50+4*y
     EntityTexture block(x,y),cubetex
     EntityAlpha block(x,y), 0.5
   Next y
Next x
{/codecitation}

 

 

 

 

Beispiel 7 - Weitere Objekte und eine Fläche erzeugen

Eine blaue Fläche wird mittels CreatePlane()  zur Simulation von Wasser eingesetzt. Eine Kugel und ein Sprite werden als weitere Objekte erzeugt.

 

Screenshot

Cube07.bas

 

 

 

 

Beispiel 8 - Over Head Display, Schuss und Treffererkennung

Mittels Sprite wird ein Overhead Display (OHD) erzeugt, das in fester Position zur Kamera verankert ist. Der Ball wird mittels LoadTexture mit einer Bitmap überzogen. Mit der Leertaste kann man einen kleinen Ball schießen, der ab der Kameraposition startet und in Blickrichtung fliegt. Die Befehle ShowEntity und HideEntity sorgen dafür, dass der kleine Ball nur während des Fluges sichtbar ist. Trifft man mit dem Schuss auf den großen Ball, so hüpft dieser einen Meter höher.

Für die Kollisionserkennung wird der kleine Ball zwischen zwei Frames in 20 kleinen Schritten weiterbewegt und der Abstand zwischen dem kleinen und dem großen Ball ausgemessen.

 

Screenshot

Cube08.bas

 

 

 

 

Beispiel 9 - Wasser, Bäume und ein hellblauer Himmel

Mit dem Befehl "LoadTexture" erzeugen wir Wasser, das sehr gut aussieht. Der Befehl "PositionEntity" sorgt für eine gleichmäßige Bewegung der Wellen. Der Himmel erhält mit dem Befehl "CameraClsColor cam,128,192,255" seine schöne blaue Färbung.

Die Bäume bestehen aus zwei einzelnen Körpern, die mit einem gemeinsamen Bezugspunkt (CreatePivot()) verbunden sind. Eine Animation zeigt, dass es ausreicht, den Bezugspunkt zu bewegen, damit sich der ganze Baum bewegt.

Die Kamera folgt der Höhe des Untergrunds, die fortlaufend mit der Funktion "TerrainY" ermittelt wird.

 

Screenshot

Cube09.bas

 

 

 

 

Beispiel 10 - Eine Insel mit Straßennetz

Der Untergrund ist in der Mitte der Insel flach und am Rand stärker hügelig. Würfel sind mit Straßentextur überzogen und bilden ein Straßennetz.

 

Screenshot

Cube10.bas

Das Straßennetz ist als Stringarray definiert und kann leicht verändert werden.

{codecitation}
Dim Shared As String*16 streetgrid(15)=>{_
  "................",_
  "................",_
  "..f----z........",_
  "..i....i........",_
  "..i....i........",_
  "..i....i........",_
  "..i....i........",_
  "..i....i........",_
  "..l----x-----z..",_
  ".......i.....i..",_
  ".......i..f--j..",_
  ".......i..l--z..",_
  ".......i.....i..",_
  ".......l-----j..",_
  "................",_
  "................" }
{/codecitation}

 

Und wie geht es weiter?

Schau Dir den Artikel über TileCity an.TileCity ist die Fortsetzung der "cube"-Programme.

(Link)