BSP Infos auslesen

Übersicht BlitzBasic FAQ und Tutorials

Neue Antwort erstellen

bruZard

Betreff: BSP Infos auslesen

BeitragFr, Feb 06, 2004 11:11
Antworten mit Zitat
Benutzer-Profile anzeigen
Wo's mein Player?

Wer mit Quake3 BSP Files arbeitet kennt das Problem: Blitz3D liest Geometrie, Texturen und Lightmap, alle Entity-Informationen gehen jedoch verloren. Ich will hier mal eine sehr einfache Möglichkeit zeigen wie man diese Informationen dennoch nutzen kann.

Am Anfang steht die Erkenntnis dass alle Entities als Klartext im *.bsp stehen und stets in geschweifte Klammern gefasst sind. So kann man mit einfachen Dateioperationen alles auslesen was man wissen möchte.
Wer sich nicht durch ein BSP File wühlen will um herauszubekommen welches Entity vom Mapeditor wie genannt wurde, der kann sich ganz einfach die *.map Datei in einem Texteditor ansehen, dort stehen die später kompilierten Informationen fein säuberlich im Klartext drin.
Eine wichtige Sache muss man sich noch einprägen bevor man daran geht die Informationen zu extrahieren und zu verwenden: Im Quake3 BSP Format sind die Z und Y Achse vertauscht, eine Zeile wie 36, 20, 16 bedeutet also X, Z, Y.

Um die Entities in Blitz3D zu sichern verwende ich ein Type. Dieses sieht für dieses Tutorial so aus:
Code: [AUSKLAPPEN]

; BSP Entities
Type tEntity
 Field orig#[3]
 Field name$
 Field rot#
End Type

orig# wird dazu verwendet um die Koordinaten eines Entities zu sichern (bspw. des Playerstarts), name$ wird später die Art des Entities beschreiben und rot# die Drehung des Entities im Level.
Es gibt noch wesentlich mehr Möglichkeiten ein Entity zu beschreiben, aber dies soll für's erste genügen. Wir wollen hier nur den Playerstart und seine Rotation auslesen, alle anderen Dinge können danach beliebig eingebaut werden.

Für das auslesen werden zwei Funktionen erstellt, zum einen die Funktion ParseBSP(bspfile$) und die Funktion NewEntity(stream). Erstere soll mit ReadLine() solange aus der Datei lesen bis sie auf eine öffnende, geschweifte Klammer trifft. Die andere Funktion wird dann die Entity-Informationen lesen.
Code: [AUSKLAPPEN]

Function ParseBSP(bspfile$)
  stream=Readfile(bspfile$)
  If stream
    While Not Eof(stream)
      in$=Trim(ReadLine(stream))
      If in$="{" Then NewEntity(stream)
    Wend
    CloseFile(stream)
  EndIf
End Function

Sobald eine Klammer gefunden wurde, wird NewEntity() aufgerufen, diese Funktion sucht dann nach einer schliessenden, geschweiften Klammer und sichert alle Daten die vorher gelesen werden.
Code: [AUSKLAPPEN]

Function NewEntity(stream)
  entity.tEntity=New tEntity
  While in$<>"}"
    in$=Trim(ReadLine(stream))
    If in$<>"}"
      in$=Replace(in$,Chr(34),"")  ; Anführungszeichen entfernen
     
      ; Hier kommen die Bedingungsblöcke in denen
      ; die verschiedenen Entity-Typen ausgelesen werden

      If Instr(in$,"origin")  ; Eine Positionsangabe
        space=Instr(in$," ")  ; Leerzeichen suchen

        temp_pos$=Trim(Right(in$,Len(in$)-space))  ; String teilen
        space=Instr(temp_pos$," ")

        entity\orig[1]=Float(Trim(Left(temp_pos$,space-1))) ; X

        rest$=Trim(Right(temp_pos$,Len(temp_pos$)-space))
        space=Instr(rest$," ")
        entity\orig[2]=Float(Trim(Left(rest$,space-1))) ; Z

        entity\orig[3]=Float(Trim(Right(rest$,Len(rest$)-space))) ; Y
      End If
    EndIf
  Wend
End Function

Das war auch schon der Code für die Koordinaten eines Entities, aber wir wissen noch nicht um was für ein Entity es sich handelt. Also erweitern wir NewEntity:
Code: [AUSKLAPPEN]

Function NewEntity(stream)
  entity.tEntity=New tEntity
  While in$<>"}"
    in$=Trim(ReadLine(stream))
    If in$<>"}"
      in$=Replace(in$,Chr(34),"")  ; Anführungszeichen entfernen
     
      ; Hier kommen die Bedingungsblöcke in denen
      ; die verschiedenen Entity-Typen ausgelesen werden

      If Instr(in$,"origin")  ; Eine Positionsangabe
        space=Instr(in$," ")  ; Leerzeichen suchen

        temp_pos$=Trim(Right(in$,Len(in$)-space))  ; String teilen
        space=Instr(temp_pos$," ")

        entity\orig[1]=Float(Trim(Left(temp_pos$,space-1))) ; X

        rest$=Trim(Right(temp_pos$,Len(temp_pos$)-space))
        space=Instr(rest$," ")
        entity\orig[2]=Float(Trim(Left(rest$,space-1))) ; Z

        entity\orig[3]=Float(Trim(Right(rest$,Len(rest$)-space))) ; Y
      End If

      ; Hier wird der Entity-Typ ausgelesen.
      ; Es kann sich hier auch um jedes andere mögliche
      ; Entity handeln
      If Instr(in$,"info_player_start") entity\name$="player_start"
    EndIf
  Wend
End Function

Da das dort oben schon recht simpel war, können wir nun auch einfach den Code einfügen der uns eine Rotation gibt.
Code: [AUSKLAPPEN]

Function NewEntity(stream)
  entity.tEntity=New tEntity
  While in$<>"}"
    in$=Trim(ReadLine(stream))
    If in$<>"}"
      in$=Replace(in$,Chr(34),"")  ; Anführungszeichen entfernen
     
      ; Hier kommen die Bedingungsblöcke in denen
      ; die verschiedenen Entity-Typen ausgelesen werden

      If Instr(in$,"origin")  ; Eine Positionsangabe
        space=Instr(in$," ")  ; Leerzeichen suchen

        temp_pos$=Trim(Right(in$,Len(in$)-space))  ; String teilen
        space=Instr(temp_pos$," ")

        entity\orig[1]=Float(Trim(Left(temp_pos$,space-1))) ; X

        rest$=Trim(Right(temp_pos$,Len(temp_pos$)-space))
        space=Instr(rest$," ")
        entity\orig[2]=Float(Trim(Left(rest$,space-1))) ; Z

        entity\orig[3]=Float(Trim(Right(rest$,Len(rest$)-space))) ; Y
      End If

      ; Hier wird der Entity-Typ ausgelesen.
      ; Es kann sich hier auch um jedes andere mögliche
      ; Entity handeln
      If Instr(in$,"info_player_start") entity\name$="player_start"

      ; Rotation auslesen
      If Instr(in$,"angle")
        If entity\name$="player_start"
          Replace(in$,Chr(34),"")
          space=Instr(in$," ")
          entity\rot=Int(Trim(Right(in$,Len(in$)-space)))
        End If
      EndIf

    EndIf
  Wend
End Function

Bei obigem Code zum auslesen der Rotation prüfen wir ob es sich bei dem Entity um den PlayerStart handelt. Das ist notwendig weil der PlayerStart nur um die Y Achse gedreht werden kann. Andere Entities können drei Rotationswerte besitzen, in diesem Fall müssen wir prüfen ob es sich bspw. um ein Model handelt und dann den Koordinatenteil an den Spaces teilen um die drei Werte einzeln zu bekommen. Wie das funktioniert haben wir beim auslesen der Koordinaten gesehen.


...und wieder einmal: Viel Spass beim erweitern Wink
PIV 2,4GHz - 1GB DDR 333 - ATI Radeon9600 - WinXP - DX9.0c - BMax 1.14 - B3D 1.91 - 1280x1024x32

User posted image
 

kolloffnikoff

BeitragMi, Sep 15, 2004 9:39
Antworten mit Zitat
Benutzer-Profile anzeigen
thx...der weg wie die strings verarbeitet werden hat mir sehr geholfen...stand da irgendwie voll auf der leitung

aber eins....die x,y,z koordinaten sind bei mir anderst wie hier beschrieben
X,Y,Z Quake
Z,-X,Y B3D

cya

Neue Antwort erstellen


Übersicht BlitzBasic FAQ und Tutorials

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group