BlitzBasic-Community-Tutorial/ Einführung in Blitz3D

Nachfolgend werden die wichtigsten Unterschiede von B3D im gegensatz zu B2D erläutert.

Graphics3d, RenderWorld

Bearbeiten

Bei BlitzBasic stand am Anfang immer Graphics und in einer Mainloop immer Cls und Flip. Bei Blitz3d kommen noch UpdateWorld und RenderWorld hinzu, das Cls kann weggelassen werden. Der 3d-Modus wird durch Graphics3d initialisiert. Seine anderen Parameter sind wie schon von Graphics bekannt.

 Graphics3D 800,600,16,2
 SetBuffer BackBuffer()
 Repeat
  
  ;Animationen updaten
  UpdateWorld
  
  ;Szene rendern
  RenderWorld
  
  Flip
 Until KeyHit(1)
 End

Updateworld aktuallisiert Kollisionen und Animationen, die einem Blitz vollständig berechnet, Renderworld zeichnet die gesamte 3dSzene. Man zeichnet nicht mehr manuell einzelne Bilder, sondern RenderWorld zeichnet alle vorher definierten Entities.

Entities?!

Bearbeiten

Eine der größten Neuheiten von Blitz3d gegenüber BlitzBasic ist das Entitysystem. Entity ist ein englisches Wort für Ding, Dasein, Gebilde, Einheit, Objekt. Die gesamte 3dWelt besteht aus Entities. Egal ob Boden, Figur oder Sonne, jedes Objekt ist eine Entity. Entites haben alle dieselben Grundeigenschaften, wie Position, Drehung, Größe und Bezugssystem.

Anders als in BlitzBasic, wo man Bilder immer wieder von neuem Zeichnen muss, bleiben einmal erstellte 3d-Objekte solange bestehen, bis man sie löscht. Das ist nach BlitzBasic vielleicht etwas gewöhnungsbedürftig, aber schlussendlich doch recht logisch: Man baut einmal eine Welt und manipuliert sie dann, anstatt sie jedes Frame von vorne aufzubauen.

Wie auch im Film braucht man für eine ordentliche Szene nicht nur eine Szene, sondern vor allen Dingen eine Kamera. Ohne Kamera kein Film. Ohne Kamera auch kein PC-Spiel. Kameras sind Entities, die angeben, wo und wie man auf die Welt schaut. Erstellt werden sie mit CreateCamera() vor der Hauptschleife. Der Befehl liefert das Handle der Kamera zurück. Das ist eine Zahl, mit der man wieder auf das Entity zugreifen kann. Man behandelt die Kamera dann wie alle anderen Entities. Zur Entitybehandlung kommen wir gleich.

 Graphics3d 800,600,16,2
 SetBuffer Backbuffer()
 camera = CreateCamera()
 Repeat
  Cls 
  ;Aktuallisieren
  UpdateWorld
  Renderworld
  Flip
 Until KeyHit(1)
 End

Nichts zu sehen? Tja, was auch?

Würfel, Kugeln, Zylinder, Kegel

Bearbeiten

In BlitzBasic kann man zum Testen von 2d-Dingen Grundformen mit Oval und Rect Grundformen zeichnen (in Blitz3D kann man das natürlich auch, man muss die Befehle aber nach RenderWorld und vor Flip setzen). Auch in Blitz3d gibt es solche Grundformen, beziehungsweise natürlich -körper: die aus Mathe und vielen 3d-Programmen bekannten Grundfiguren Würfel, Kugeln, Zylinder und Kegel. Man nennt sie Primitves. Und die brauchen wir jetzt, damit wir etwas zum Anschauen und Testen haben.

Würfel werden mit CreateCube() erstellt. Kugeln mit CreateSphere(), Zylinder mit CreateCylinder(), Kegel mit CreateCone().

Mehr von den Entitäten

Bearbeiten

Jippy, endlich kann es losgehen! Zeit für unsere erste Szene. Es werden ein paar Primitives erstellt und vor der Kamera angeordnet.

Graphics3D 800,600,32,2
SetBuffer BackBuffer()

camera = CreateCamera()

cube = CreateCube()
PositionEntity cube,-2,0,5

sphere = CreateSphere()
PositionEntity sphere,0,2,5

cylinder = CreateCylinder()
PositionEntity cylinder,1,5,0,3

cone = CreateCone()
PositionEntity cone,0,-2,5

Repeat
 Cls
 RenderWorld
 Flip
Until KeyHit(1)
End

Zum positionieren der Entities nutzt man PositionEntity. Der erste Parameter gibt das zu positionierende Entity an, die drei Zahlen danach geben die X-, Y- und Z-Koordinaten an.

X,Y und Z

Bearbeiten
 

Koordinaten werden in 3d nicht ganz so angegeben wie in 2d. Der auffälligste Unterschied ist wohl, dass es nicht mehr nur X und Y, sondern auch noch einen dritten Bestandteil, Z, gibt. Z steht für die Tiefe.

Der Urprung der Welt liegt an 0,0,0. Objekte werden normalerweise am Ursprung erstellt und zeigen entlang der Z-Achse. So auch die Kamera. 0,0,0 ist bei einer unbewegten Kamera immer genau der Mittelpunkt des Bildschirms auf der Kameralinse.

Schauen wir uns einmal das letzte Beispiel an. Der Würfel/Cube wird mit PositionEntity an -2,0,5 positioniert. -2 als X-Wert bedeutet, dass der Würfel zwei Einheiten links von der Bildschirmmitte liegt. Ist er positiv, so liegt das Objekt weiter rechts. Der Z-Wert von 5 verschiebt das Objekt nach hinten. Wenn man ihn weiter erhöht, wird das Objekt nach hinten verschoben, also kleiner und bewegt sich auf den Fluchtpunkt zu.

Mit dem Y-Wert verhält es sich genau wie in Mathe: Je größer der Wert, desto weiter oben der Punkt. Also nicht mehr wie im 2d-Modus umgekehrt.

Natürlich bietet Blitz3D weit mehr als nur den Umgang mit Entities. Man kann z.B. eine Lichtquelle erstellen und diese frei im Raum positionieren. Dies erreicht man mit dem Befehl CreateLight(). CreateLight() erzeugt eine Lichtquelle, die fast genauso wie alle anderen Entities behandelt wird: Man kann sie genau wie alle anderen Entities drehen, verschieben und positionieren.

light = CreateLight(1)

Was sucht denn die 1 da? Fragt sich jetzt der ein oder andere. Dem Befehl CreateLight() kann eine Zahl von 1-3 zugewiesen werden.

Createlight(1) ;gerichtetes Licht
Createlight(2) ;Punkt-Licht
Createlight(3) ;Spot-Licht

Damit kann man jetzt mal ne Runde rumspielen!

Einfach, wie vorher beschrieben, ein Entity hinzaubern und dann mal kucken was die Lichter machen. Dazu noch ein Quelltext

Graphics3D 640,480

camera = CreateCamera() 
MoveEntity camera,0,0,-3 

dings = CreateCube() 

licht = CreateLight(1) ;Verändere den Wert in den Klammern (1,2 oder 3?)
MoveEntity licht,5,0,0 
PointEntity licht,dings ;Wir richten unser "gerichtetes Licht" auf den Würfel

While Not KeyDown(1) 
RenderWorld:Flip 
Wend 
End


Zusätze zum Licht


Mit unserem "Licht=Createlight(x)" können wir noch ne Menge anstellen! Zum Beispiel: Zusätzliche Befehle nutzen um Reichweite und Scherze zu modifizieren.

Zur Reichweite

LightRange licht,reichweite#

heißt das gute Stück und damit können wir unserem licht eine neue Reichweite zuweisen. Normalerweise hat jedes Licht, welches mit CreateLight() erstellt wurde, eine Reichweite von 1000.0 Hier sollte wieder jeder den Befehl in den Code einfügen und damit ein wenig rumspielen. Werte ändern und kucken was passiert!

LightColor licht,rot,grün,blau

Macht genau dass, was sich jetzt die meisten denken. Es ändert einfach die Farbe des Lichts.

Und was macht

LightConeAngles licht,innerer-winkel,äußerer-winkel

???? Es verändert den Winkel des Lichtkegels eines Spotlights.

Dass heißt: Wir brauchen ein Spotlight! Also:

Graphics3D 1024,768,32,1

camera=CreateCamera()

SetBuffer BackBuffer()

dingns = CreateCube()

licht=CreateLight(3) ;unser "Spot Light"
LightConeAngles licht,10,10  ;dem weisen wir mal ein paar Winkel zu

PositionEntity dingns,0,0,10

Repeat

Cls

;Hier werden die Pfeiltasten abgefragt
If KeyDown(208) pitch=pitch+1 ;oben
If KeyDown(200) pitch=pitch-1 ;unten
If KeyDown(203) yaw=yaw+1     ;links
If KeyDown(205) yaw=yaw-1     ;rechts

RotateEntity dings,pitch,yaw,0 ;Ein neuer Befehl, welcher unseren Würfel dreht

UpdateWorld
RenderWorld

Flip

Until KeyHit(1)

End

Hier ist der Befehl RotateEntity dinges,Pitch,Yaw,Roll. Dieser dreht, selbstverständlich, ein Objekt in unserer kleinen 3D Welt.

  • Pitch ist die Drehung auf der X-Achse des Objekts
  • Yaw ist die Drehung auf der Y-Achse des Objekts
  • und, natürlich, ist der letzte Wert Roll die Drehung auf der Z-Achse des Objekts

Hierbei ist zu beachten. Wenn ich mit Pitch den Würfel Dingens auf seiner eigenen X-Achse drehe, drehen sich die anderen Achsen von Dingens! Dadurch ist Y und Z Woanders. Hier gilt erneut! Rumspielen. Und sich vielleicht mal eine Zeichnung zum Verständnis malen.

Noch mehr zum Licht

Wir sind jetzt also fähig einen klobigen Würfel in die Welt zu setzen. Diesen mit einigen Lichttypen zu beschmeißen und ihn zu drehen. Nicht schlecht! Aber... Es gibt noch viel mehr!

Also, zur Sache.

EntityFX dingens,Zahl

Ist der neue, mächtige Befehl, den es zu meistern gilt! Er gibt einem Objekt einen Effekt. Welchen, entscheidet die Zahl!

  • 0 - nichts(default)
  • 1 - volle Helligkeit, oder strahlend
  • 2 - Vertex-Beleuchtung ;Also, jedes Polygon bekommt einen Farbwert
  • 4 - Flat Shading ;Also, jeder Pixel eines Polygons bekommt einen Farbwert, jedoch hat jedes Polygon trotzdem nur eine Beleuchtungsstufe
  • 8 - Nebeleffekt deaktivieren ;wird erst nötig, wenn wir wissen, was denn ein Nebeleffekt ist
  • 16 - Backface Culling deaktivieren ;Backface Culling ist eine Technology, bei der alle nicht sichtbaren Polygone entfernt werden
  • 32 - Vertex-Alpha aktivieren ;ein großes Thema, welches ich an dieser Stelle mal auslasse

Die Effekte können sogar kombiniert werden. Dazu rechnen wir die Zahlen der gewünschten Effekte zusammen (Also, z.B. 1+2=3) und schreiben dass Ergebnis rein.

EntityFX dingens,3

Mal wieder gilt, in den Code einfügen und damit rumspielen. 8,16 und 32 kann dabei ausgelassen werden. Damit beschäftigen wir uns noch früh genug.

Wir werten mal ein wenig zusammen aus:

Wenn unser Würfel den Effekt 1 hat, strahlt dieser. Dass bedeutet, wir sehen unser Licht nicht mehr, da dingens ja schon hell ist. Also ist die 1 in unserem Licht-Tutorial unnötig.

Bei Effekt 2 kommt eine sehr beknackte Lichtberechnung raus. Vertex-Licht kennt vielleicht der ein oder andere noch von alten Games. Dort gab es, zumeist, den Umschalter Vertex nutzen ja/nein. Damit will ich sagen, diese Art der Lichtberechnung ist sehr alt. Pre 2000.

Bei Effekt 4 hat jede Seite des Würfels ein Lichtwert? Leider ja.

Alle anderen Effekte brauchen wir nicht. Und was passiert bei dem kombinierten Effekt 2+4? Richtig, sieht auch schäbig aus. Wir nutzen erstmal Effekt 2.

LightMesh

LightMesh mesh,rot,grün,blau,[reichweite,licht_x,licht_y,licht_z]

Ein neuer Befehl! Dieser produziert ein "fake" Licht auf jedem Objekt. Voraussetzung dafür ist der Befehl EntityFX dings,2. Wenn wir jetzt unser Spotlight licht wegnehmen, neben unseren Würfel einen Würfel packen und den 1. mit Lightmesh behandeln, dann... Hier mal die aktualisierte Edition unseres Codes:

Graphics3D 1024,768,32,1

camera=CreateCamera()

SetBuffer BackBuffer()

blub=CreateCube()
dings=CreateCube()
EntityTexture dings,tex
EntityFX blub,2
EntityFX dings,2 ;Den Effekt müssen wir vor LightMesh einbauen
LightMesh dings,200,200,0 ;Wie machen dings mal gelblich

PositionEntity dings,5,0,10 ;wir richten beide, nebeneinander auf der x Achse an
PositionEntity blub,-5,0,10

Repeat ;und hier beginnt wieder die bekannte Hauptschleife

Cls
If KeyDown(208) pitch=pitch+1
If KeyDown(200) pitch=pitch-1
If KeyDown(203) yaw=yaw+1
If KeyDown(205) yaw=yaw-1
RotateEntity blub,pitch,yaw,0 ,Mit dem Unterschied, dass blub sich dreht.

UpdateWorld
RenderWorld

Flip

Until KeyHit(1)

End

Klappt nicht so ganz, ne? LightMesh setzt auch keine echte Lichtquelle ein. Sondern belichtet exakt ein Objekt mit den Werten.

AmbientLight

Übersetzt: Umgebungs Licht. Und genau darum handelt es sich auch! Dieser Befehl setzt eine Art "Sonne" ein. Ums genau zu nehmen, kann damit die Welt, unabhängig von allen anderen Lampen, erhellt werden.

Setzen wir dies in unseren Code mal ein.

AmbientLight rot,grün,blau

Diese Zeile kommt vor die Hauptschleife. Alle anderen Lichtquellen, sowie LightMesh kommt weg.

Tatsache ist, dieses Umgebungslicht war schon immer da. Per BB3D Standard Einstellung gibt es immer ein Umgebungslicht mit den Werten 127,127,127. Hintergrund dieser Standard Einstellung ist, dass junge Entwickler überhaupt was sehen.

Dadurch können wir also auch die Welt schwärzen und alles blau färben.

Kreation einer logischen Lichtquelle

Ich habe es mir mal erlaubt, unsere Lichtquelle in einen Würfel zu packen und sie auf den anderen Würfel zu richten. Dadurch entsteht eine halbwegs logische Lichtquelle.

Jedoch ist dabei noch vieles hinzuzufügen.

  1. Der Würfel muss leuchten
  2. Der Würfel muss mehr nach Glas aussehen.

das Leuchten erreichen wir mit LightMesh (siehe oben).

Da greife ich mal dem Thema Textur vor und lade mit den Befehl tex=LoadTexture("grau.png") ein 258*258 großes Bild, welches einfach nur grau ist. Dieses lege ich mit dem Befehl EntityTexture würfel,tex auf meinen Würfel. Dadurch ist dieser komplett grau. Dank LightMesh sieht er was aus wie ein Leuchtender Würfel. Und jetzt mach ich daraus ne Kugel und... es entsteht eine halbwegs logische Lichtquelle.

Texturen

Bearbeiten

LoadTexture

Ist der erste und wichtigste Befehl. Denn, wenn wir keine Textur laden, können wir diese auch auf kein Objekt malen, ne?

Es funktioniert folgender Weise:

texture=LoadTexture(Pfad$,[Zahl])

Ich mache es meistens so:

Den Code in einen Ordner speichern und alle Daten, welche ich laden möchte, dort reinpacken.

;Dadurch ändert sich Pfad einfach in Dateiname
textur=Loadtexture("Dateiname.png",[Zahl])

Die Textur ist so etwas Ähnliches wie ein Bild in der 2D Umgebung. Wir müssen es erstmal irgendwo zeichnen.

Der Unterschied ist, bei einer Textur, muss diese auf ein Objekt mit mindestens 1 Polygon gezeichnet werden. Sozusagen, nicht auf die Kamera und auch nicht auf das Licht.

Dafür gibt es diesen Befehl:

EntityTexture dings,textur

Aus dem Abschnitt Licht haben wir noch einen Code:

Graphics3D 1024,768,32,1

camera=CreateCamera()

SetBuffer BackBuffer()

blub=CreateCube()
dings=CreateCube()
tex=LoadTexture("brick-01.png") ;wir laden die Textur
EntityTexture dings,tex ;Wir packen sie auf unseren Würfel "dings"
EntityFX dings,2
EntityFX blub,2

PositionEntity dings,5,0,10
PositionEntity blub,-5,0,10

AmbientLight 255,255,255 ;Für gute Sichtverhältnisse sorgt ein Umgebungslicht

Repeat ,Die bekannte Schleife

Cls

If KeyDown(208) pitch=pitch+1
If KeyDown(200) pitch=pitch-1
If KeyDown(203) yaw=yaw+1
If KeyDown(205) yaw=yaw-1

RotateEntity blub,pitch,yaw,0

UpdateWorld
RenderWorld

Flip

Until KeyHit(1)

End
Bei LoadTexture gibt es ja noch die [Zahl]!

Dazu eine Übersicht:

  • 1 - Farbe (Standard)
  • 2 - Mit Alpha-Information
  • 4 - Mit 0,0,0 Maske ;also, alle Bereiche einer Textur, welche den Farbwert 0,0,0 schneidet BB3D weg
  • 8 - Mipmapping ;bei größeren Entfernungen zum Objekt wird die Textur in einer geringeren Qualität dargestellt
  • 16 - Klemme U ;dazu kommen wir noch
  • 32 - Klemme V ;dazu kommen wir noch ;)
  • 64 - Reflections Textur ;Umgebung-mapping, für den shiny, metall-look
  • 128 - in meiner Version von BB3D nicht benutzt ;als definition cubic-enviroment-mapping für einen effizenteren shiny, metall-look
  • 256 - Speichere die Textur in den vRAM ;speichert die Textur zur schnelleren Berechnung in der Arbeitsspeicher der Grafikkarte
  • 512 - Erzwingt die Nutzung einer hochauflösenden Textur in einer 16 bit Grafikeinstellung

Wir sehen schon, LoadTexture ist ein äußerst mächtiger Befehl. Aber, was zum Teufel bedeutet bitte "Alpha"?


Alpha

Ein Bild kann eine zusätzliche Information, neben seinen normalen Farben speichern. Die Alpha Information. Diese beinhaltet, welche Bereiche des Bildes wie stark ausgeblendet werden. dadurch wird ein Farbverlauf von Farbe r,g,b zu farblos möglich.

Dieses muss mit einem Bildbearbeitungsprogramm geschehen, welches besser als MS Paint ist.

BB3D kann diese Information lesen. Durch den Befehl LoadTexture("textur.bmp",2) Wird die Alhpa-Information verarbeitet.


Multi-Textur

Wir haben bis jetzt eine Textur geladen und diese auf unseren Würfel gepackt. Jetzt Soll noch eine Textur darüber.

Dazu gibt es mehrere Möglichkeiten:

  1. LoadTexture("tex1.bmp",2) ;Also, mit Alpha Info
  2. LoadTexture("tex1.bmp",4) ;Also, alles was ganz schwarz ist, bitte weglassen
tex1=LoadTexture("block-01.png") ;Hier laden wir sogar 4 Texturen
tex2=LoadTexture("block-02.png",2)
tex3=LoadTexture("block-03.png",4)
tex4=LoadTexture("block-04.png",4)

EntityTexture dings,tex1 ;Hier zeichnen wir nacheinander tex1 und tex2 auf den Würfel dings
EntityTexture dings,tex2 ;Zuerst tex1, da diese voll Farbig ist, danach tex2, da diese Alpha Informationen enthält

Dadurch wird tex2 und tex1 zusammengemischt. Da aus tex2 einiges aus geschnitten wird, ist in den farblosen Bereichen tex1 zu sehen. In allen anderen Bereichen, werden die Texturen gemischt. Dies kann man jetzt mit sehr vielen Texturen machen.

Und genau dass ist MultiTexturing. Einfach, mehr als eine Textur auf einem 3D Objekt.

Und, wenn BB3D weiß, wie dies geschehen soll, kann das Ergebnis richtig gut aussehen!

An dieser Stelle möchte ich erneut darauf hinweisen, dass ein jeder Leser jetzt mit den vielen neuen befehlen arbeiten sollte.


Terrain

Wir können also kleine 3D Objekte Erstellen und diese mit einer Textur bemalen. Wir wissen, dass BB3D Alpha Informationen verarbeiten kann, wenn wir diese unseresn Bildern mit auf den Weg gegeben haben.

Doch, was ist unsere 3D Welt ohne ein Terrain?

Wie erstellen wir ein Terrain? und was ist dass schon wieder?

Das Terrain ist der Untere Boden unserer Welt. Auf der steht alles. Also, wollen wir mal ein Terrain selbst erstellen:

terrain=CreateTerrain([größe])

Dadurch erstellen wir ein Terrain. Es erstreckt sich Standard mäßig von 0,0,0 (Der Ursprung des KoordinatenSystems) zu größe,größe,1. Das bedeutet, wir bekommen eine Fläche, welche den Boden darstellt.

Mal wieder ein kleiner Code zum kucken. Wichtig! Schmiert bitte irgendeine Textur auf das Terrain!

Graphics3D 1024,768,32,1
SetBuffer BackBuffer() 

camera=CreateCamera() 
PositionEntity camera,0,1,0 

lichtt=CreateLight() 
MoveEntity licht,0,50,0
RotateEntity licht,90,0,0 

; Create terrain 
terrain=CreateTerrain(128) 

; Texture terrain 
grass_tex=LoadTexture( "grass.bmp" ) 
EntityTexture terrain,grass_tex 

While Not KeyDown( 1 ) 

If KeyDown( 205 )=True Then TurnEntity camera,0,-1,0 
If KeyDown( 203 )=True Then TurnEntity camera,0,1,0 
If KeyDown( 208 )=True Then MoveEntity camera,0,0,-0.5 
If KeyDown( 200 )=True Then MoveEntity camera,0,0,0.5 

RenderWorld 

Text 0,0,"Benutze die Pfeiltasten um über das Terrain zu fliegen." 

Flip 

Wend 

End 

Ihr seht, wir haben jetzt eine gewissen Fläche Spielplatz. Jedoch, ohne jegliche Höhe oder Tiefe! Wenn wir ein Terrain mit CreateTerrain erstellen ist dieses automatisch Flach.

Dieses Terrain kann man leider nur sehr schwer mit BB3D bearbeiten. Es ist zwar möglich, jedoch viel zu Umständlich für uns.

Der einfache Weg ist ein Terrain zu laden! Nur, wo bekommen wir dass den her?

Wir müssen erneut ein Bild malen. Nur, dieses Bild muss aus Farbverläufen zwischen schwarz und weiß bestehen und groß sein. Die Größe des Bildes entscheidet darüber, wie groß unser Terrain wird. Je weißer das Bild, desto höher wird der entsprechende Punkt auf der Z-Achse. je schwarzer der Punkt, desto tiefer liegt er auf der Z-Achse.

Nach diesen Kriterien müssen wir jetzt also ein Bild zusammen pfriemeln.

Wenn du jetzt gerade keine Lust hast ein Bild zu malen. dann schau doch mal in deinen BB3D Ordner unter Samples nach. Dort gibt es einige hervorragende Bilder.

Diese Laden wir mit

terrain=LoadTerrain("terrain.bmp")

Dieser Befehl liest die Datei "terrain.bmp", verarbeitet diese zu einem Terrain und erstellt es am Ursprung.

Diesen kann man einfach mit CreateTerrain ersetzten und erneut rumfliegen.

"Das Terrain ist noch immer flach." Mag man jetzt schreien. Stimmt jedoch nicht ganz. BB3D hat uns ein fast flaches Terrain hingezaubert. Denn, BB3D macht es manchmal viel zu groß.

Wenn wir diesem entgehen wollen, brauchen wir

ScaleEntity terrain,x,y,z

Dieser Befehl verändert die größe eines Objekts.

Wir versuchen es also und setzen ScaleEntity terrain,2,2,2 ein. Der Wert 2,2,2 sagt aus, dass das Objekt terrain in jede Richtung doppelt so groß ist. Entsprechend kannst du jetzt die Werte einstellen, sodass dein Terrain gut aussieht.

Wenn dein Terrain zu hoch ist, oder zu kantig, solltest du versuchen, ein wesentlich geschmeidigeres Bild zu malen. Es muss ein guter Farbverlauf von schwarz zu weiß vorhanden sein.

(psst. Dazu, sollten man vielleicht auch noch ne Menge Licht in die Szene bringen.)

Mal ein kleiner Quellcode, wie es jetzt bei mir im guten blah.bb aussieht:

Graphics3D 1024,768,32,1
SetBuffer BackBuffer() 

camera=CreateCamera() 
PositionEntity camera,0,100,0 

light=CreateLight() 
MoveEntity light,0,0,50
RotateEntity light,22.5,0,0

; Create terrain 
terrain=LoadTerrain("hmap_1024.bmp")
ScaleEntity terrain,1,20,1 ;der Faktor 20 auf der y-Achse, damit die Berge auch Berge sind
EntityFX terrain,1 ;Da die kleine Leuchte von oben nix bringt

; Texture terrain 
grass_tex=LoadTexture( "brick-01.png" ) 
EntityTexture terrain,grass_tex 

While Not KeyDown( 1 ) 

If KeyDown( 205 ) TurnEntity camera,0,-1,0 
If KeyDown( 203 ) TurnEntity camera,0,1,0 
If KeyDown( 208 ) MoveEntity camera,0,0,-1 
If KeyDown( 200 ) MoveEntity camera,0,0,1 
If KeyDown(44) MoveEntity camera,0,-1,0 ;Y um nach unter zu fliegen
If KeyDown(30) MoveEntity camera,0,1,0 ;a um nach oben zu fliegen

RenderWorld 

Text 0,0,"Benutze die Pfeiltasten und A/Y zum Bewegen."

Flip 

Wend 

End 

Wenn du jetzt diesen Code hast und durch das Terrain fliegt fällt dir auf, dass sich das Terrain beim vorbeifliegen verändert. Dies ist hängt damit zusammen, dass BB3D ein Terrain automatisch mit einer sehr geringen Polygonen Zahl darstellt. Es verändert, da mehr Polygone hinzugefügt werden, je näher die Kamera ist.

Wir können allerdings auch mit dem Befehl

TerrainDetail terrain,detail_level,vertex_morph

Unser Terrain besser darstellen.

Also, fügen wir, nach dem Laden des Terrain und vor der Haupt-Schleife, diesen Befehl ein. Eine typische Detailstufe ist 2000. Es wird korrekt angezeigt ohne Endlos Resourcen zu nutzen.

Der Zusatz vertex_morph kann nur wahr oder falsch sein. Er sagt einfach aus, ob den Morph genutzt wird. Ich empfehle dies Anzuschalten. Vertex Morph ist einfach eine verbesserte Methode der Verformung eines Polygon-Objekts.

Dadurch haben wir jetzt ein Terrain, welches, zumindest hoffe ich das, relativ groß und bergig ist. Jedoch, wird es wohl nicht super gut aussehen wegen der Textur.

Terrain und Textur

Ein äußerst großes Thema, welches wir hier betreten.

Wenn wir eine Textur laden und diese einfach mit EntityTexture auf unser Terrain malen, wird die Textur von BB3D so oft wiederholt, bis es über das gesamte Terrain verteilt wird.

Beispielsweise:

Unser Terrain ist 640,640 groß. Die Textur ist 80,80 groß. Also, wird die Textur 640:80=8 mal auf das Terrain gepackt.

Mein Terrain, ist tatsächlich 1024 groß und die Textur ist 256. Also wird meine Textur 4 mal auf das Terrain gemalt. Da Terrain aber zusätzlich noch nach oben geht, wird die Textur in der Praxis wesentlich öfter auf das Terrain gemalt.

Wie können wir etwas tun?

Wir können die Textur an die Größe des Terrains anpassen.

ScaleTexture textur,TerrainSize(terrain),TerrainSize(terrain)

Zwei neue Befehle: ScaleTexture vergrößert eine Textur um die Faktoren. TerrainSize(terrain) gibt die Größe unseres Terrains aus. Dadurch wird die Textur auf unser Terrain angepasst, solange dieses auf der x und z Achse gleichgroß ist.

Ansonsten könnten da wilde Experimente entstehen.

Zum vollständigen Code:

Graphics3D 1024,768,32,1
SetBuffer BackBuffer()

camera=CreateCamera() 
PositionEntity camera,0,100,0 

light=CreateLight() 
MoveEntity light,0,0,50
RotateEntity light,22.5,0,0

; Create terrain 
terrain=LoadTerrain("hmap_1024.bmp")
ScaleEntity terrain,1,20,1
EntityFX terrain,1
TerrainDetail terrain,4000,True

; Texture terrain 
grass_tex=LoadTexture( "lmap_256.bmp" ) 
EntityTexture terrain,grass_tex 
ScaleTexture grass_tex,TerrainSize(terrain),TerrainSize(terrain)

While Not KeyDown( 1 ) 

If KeyDown( 205 ) TurnEntity camera,0,-1,0 
If KeyDown( 203 ) TurnEntity camera,0,1,0 
If KeyDown( 208 ) MoveEntity camera,0,0,-1 
If KeyDown( 200 ) MoveEntity camera,0,0,1 
If KeyDown(44) MoveEntity camera,0,-1,0
If KeyDown(30) MoveEntity camera,0,1,0

RenderWorld 

Text 0,0,"Benutze die Pfeiltasten und A/Y zum Bewegen."

Flip 

Wend 

End 

"Aus der Entfernung kann es sich sehen lassen, doch wenn ich nah ran fliege, bäh!" Wir haben jetzt die Grafik von Outcast erreicht! Juhu!

Jetzt, kann man einerseits eine Textur mal die einfach so passt, wobei dass sehr schwer zu berechnen ist, wie groß die Textur sein muss. Oder, wir tricksen ein wenig rum.

Der Befehl EntityTexture ist sehr mächtig

EntityTexture terrain,texture,0,0

Was sollen jetzt die beiden Nullen da? Ganz einfach. Die erste Null steht für den Frame innerhalb der Textur. Da es nur 1 Frame gibt, bleibt dass bei einer null, damit BB dies ignoriert. Die zweite null ist eine Index Zahl. Dadurch wird dem Terrain die Textur zugewiesen und bekommet die Identifikationsnummer 0. Dadurch wird sie direkt ansprechbar.

Das ganze machen wir jetzt mit einer 2. Textu

EntityTexture terrain,texture2,0,1

Jetzt haben wir dem Terrain 2 Texturen zugewiesen. Nummer 0 und 1.

Jetzt füge man dies in den Code ein. Also, direkt nach dem Laden der 1. Textur, laden wir eine 2. Diese werden dann beide mit EntityTexture terrain,textur,0,x dem Terrain zugewiesen und von BB rauf gemalt.

Die Frage ist nun, warum sieht dass ganze denn jetzt besser aus? 1. Weil BB3D gut ist. 2. Weil die beiden Texturen gemischt werden, denn 1.

Natürlich kommt es darauf an welche Texturen du da jetzt rauf gemalt hast. Einmal Holz und Steine macht sich ein wenig komisch auf einem Terrain. Grüne und braune Fabren in der 1. Textur, welche über das gesamte Terrain gezogen wird, und ein grauer Unterton kann sich schonwieder sehen lassen.

Soviel zum Terrain

LoadMesh

Bearbeiten
Hier fehlen noch Inhalte! Bitte ergänzen!