Seite 2 von 2

Einfarbige Sprites...

Verfasst: 22.08.2005 13:22
von Nalfein
Wenn ich bei TransformSprite3D (zusätzlich zu einer normale Verformung in X- und Y-Richtung noch z-Werte angebe, kann ich NICHT mehr erkennen, ob diese korrekt berücksichtigt werden, da dann alle Sprites einfarbig sind! (meistens die dunkelste Farbe der Textur...)

Ich wollte eine einfache 3D-Engine machen und TransformSprite3D für die Texturen beutzen. Funktioniert soweit. Die Z-Sortierung funktioniert nicht so ganz (ich weise jedem Sprite eine Tiefe zu, die dem Durchschnitt der Tiefen der 4 Eckpunkte entspricht. Danach wird absteigend sortiert (so daß die Sprites mit niedriger Tiefe weiter hinten kommen und später angezeigt werden und somit andere überschreiben).

Funktioniert leidlich. Im Detail wollte ich die Z-Werte benutzen. Funktioniert nicht ! (s.o.)

Weiß einer woran DAS schon wieder liegen kann?

Mir ist auch aufgefallen, daß wenn ich EINMAL einen Sprite MIT z-Werten versuche anzuzeigen, alle denselben Fehler aufweisen, auch wenn ich die Angabe von z-Werten an-aus-schaltbar gemacht habe und wieder aus stelle. Aber ohne Neustart des Programms zeigt er sie nicht mehr richtig an...

Verfasst: 22.08.2005 14:43
von unix
Ich hatte auch das Problem mit den Z Werten ich wollte das ein Sprite mit weniger Z das andere Überdekt.
Nur leider habe ich herausgefunden das des nicht klappt.
Also Sortierte ich ebenfalls die Sprites in einer Linket List nach den Z Wert

Ich bin dafür das dieser Befehl von irgendjemanden nochmal überarbeitet werden sollte

Danke

überarbeiten!

Verfasst: 22.08.2005 14:55
von Nalfein
Der Befehl tut anscheinend etwas. Nur funktioniert es bei dem einen bei dem andern anscheinend nicht. Meine Grafikkarte ist nich SO alt (G-Force 4 MX oder so...) und sollte schon z-buffer unterstützung kennen (falls das nicht eh in purebasic selbst irgendwo verwaltet wird).

Ich hab's grad auch nochmal ausprobiert. Zusätzlich zu den Koordinaten der 4 Eckpunkte laß ich ihn sauber den Z-Unterschied und die Z-werte ausrechnen.
Die Z-werte einfach wie im beispiel der hilfe [,z] anzugeben führt zu einem irgendwie psychodelischen Bild. Textur ist total verzogen.

Die Z-Unterschiede der 4 Punkte zueinander zu übergeben bewirkt, daß die Textur bei gleichen Werten sich zwischen den Punkten bewegt bis alles verwaschen aussieht....

Falls dieser Befehl generell benutzbar ist (bzw. sein soll), müßte man kontrollieren, warum er es bei dem einen tut und bei dem anderen nicht!

Ein Beispiel mehr könnte (generell) der Anleitung bzw. Hilfe-Funktion nicht schaden! Ein "dieser Befehl ist nur für fortschrittliche Programmierer" (mit einem zwischen den Zeilen gelesenen "probieren Sie selbst aus! - Wenn nicht läuft, nicht unser Fehler!") sollte in keiner Anleitung stehen.... (gefunden bei Blending Mode aus Sprite3D-Library...)

Verfasst: 22.08.2005 20:59
von Batze
Ich kann ja mal die Unfertige Version meiner Batzengine posten. Da ist z-Sortierung drin.

Code: Alles auswählen

; 3D-Engine
; IncludeFile "batzengine.pb"
; in die Hauptdatei schreiben und diese Datei in den selben Ordner legen.
;————————————————————————————————————————————————————————————————————————
; Befehlsreferenz:
; ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
; So weit bin ich noch nicht ;)
;

;- Konstanten
; Hier können sie Einstellungen vornehmen:
#Drehgenauigkeit = 3600  ; Werte von 360 - 9000 sind zu empfehlen    (3600 = Standard) 
#Pi              = 3.14159256 ; Es wäre unklug diesen Wert zu ändern (Pi = 3.1415956)
distanz          = 500   ; Distanz zum Objekt: 0-400000              (500 = Standard) 

;- Init
If InitSprite3D() = 0
  ; Hier können sie eine Fehlermeldung eintragen
  End
EndIf
Sprite3DQuality(1)                 ; Qualität des Spriterendering
Dim sinus.f  (#Drehgenauigkeit)    ; Sinuswerte für Drehungen
Dim cosinus.f(#Drehgenauigkeit)    ; Cosinuswerte für Drehung
For i=1 To #Drehgenauigkeit        ; Schleife zum Füllen
  sinus  (i) = Sin(i / #Drehgenauigkeit * 2 * #Pi) ; Sinuswert
  cosinus(i) = Cos(i / #Drehgenauigkeit * 2 * #Pi) ; Cosinuswert
Next

;###########################################################################################

Structure Object3D       ; Struktur für einfache 3D-Objekte
  Mem_P.l                ; Speicheraddresse an der sich die Punktdaten   befinden
  Mem_F.l                ; Speicheraddresse an der sich die Flächendaten befinden
  Faces.w                ; Anzahl der Vierecke des Objektes
  Points.w               ; Anzahl der Punkte des Objektes
  x.f                    ; x-Position des Objektes
  y.f                    ; y-Position des Objektes
  z.f                    ; z-Position des Objektes
  Rx.l                   ; Rotation in x-Richtung 
  Ry.l                   ; Rotation in y-Richtung
  Rz.l                   ; Rotation in z-Richtung
EndStructure
NewList Obj.Object3D()   ; Objektliste

Procedure P_(Nr)  ; Gibt die Memoryaddresse eines Punktes aus 
  ProcedureReturn Obj()\Mem_P + Nr*12 ; F+F+F = 12
EndProcedure
Procedure F_(Nr)  ; Gibt die Memoryaddresse eines Viereckes aus 
  ProcedureReturn Obj()\Mem_F + Nr*12 ; W+W+W+W+L = 12
EndProcedure

Procedure RotateObject(Mem, Wx.l, Wy.l, Wz.l) ; 3DObjekt drehen
  Protected temp.f, x.f, y.f, z.f             ; interne Variablen
  ChangeCurrentElement(Obj(), Mem)            ; Objekt auswählen
  Obj()\Rx + Wx                               ; Drehung in der Struktur speichern
  Obj()\Ry + Wy
  Obj()\Rz + Wz
  If Obj()\Rx > #Drehgenauigkeit : Obj()\Rx - #Drehgenauigkeit : EndIf ; Bei einem ...
  If Obj()\Ry > #Drehgenauigkeit : Obj()\Ry - #Drehgenauigkeit : EndIf ; Überlauf einen Kreis ...
  If Obj()\Rz > #Drehgenauigkeit : Obj()\Rz - #Drehgenauigkeit : EndIf ; abziehen.
  
  For i=0 To Obj()\Points-1               ; Jeden Punkt durchgehen
    x    = PeekF(P_(i))                   ; X-Koordinate des Punktes 
    y    = PeekF(P_(i)+4)                 ; Y-Koordinate des Punktes
    z    = PeekF(P_(i)+8)                 ; Z-Koordinate des Punktes
    ; X-Rotation:
    temp = y*cosinus(Wx) - z*sinus(Wx)
    z    = z*cosinus(Wx) + y*sinus(Wx)
    y    = temp
    ; Y-Rotation:
    temp = z*cosinus(Wy) - x*sinus(Wy)
    x    = x*cosinus(Wy) + z*sinus(Wy)
    z    = temp
    ; Z-Rotation:
    temp = x*cosinus(Wz) - y*sinus(Wz)
    y    = y*cosinus(Wz) + x*sinus(Wz)
    x    = temp
    
    PokeF(P_(i),    x)    ; Werte wieder in die Struktur schreiben
    PokeF(P_(i)+4,  y)
    PokeF(P_(i)+8,  z)
  Next
   
  ProcedureReturn @Obj   ; Addresse wird zurückgegeben
EndProcedure

Procedure CreateObject(x, y, z) ; 3DObjekt erstellen
  
  AddElement( Obj() ) ; Objekt zur Liste hinzufügen
  Obj()\Faces  = 0     ; Werte auf 0 setzen
  Obj()\Points = 0
  Obj()\Mem_P  = 0
  Obj()\Mem_F  = 0
  Obj()\x      = x     ; Werte mit definierbarem Inhalt
  Obj()\y      = y
  Obj()\z      = z
  Obj()\Rx     = 0
  Obj()\Ry     = 0
  Obj()\Rz     = 0
   
  ProcedureReturn @Obj() ; Adresse zurückgeben
EndProcedure

Procedure ObjectID(Nr)       ; Objekt-ID ausgeben
  If Nr = -1                 ; Wenn #PB_Any ->
    ProcedureReturn @Obj()   ; Aktuelle ID
  EndIf
                             ; Ansonsten ->
  SelectElement(Obj(), Nr)   ; Element auswählen ... 
  ProcedureReturn @Obj       ; und Addresse zurückgeben
EndProcedure

;******** Edit Objects *************************************************************************

Procedure StartEditing(Mem, Anzahl.l) ; Startet die Bearbeitung
  ChangeCurrentElement(Obj(), Mem)                          ; Objkekt zur Bearbeitung auswählen
  Obj()\Mem_P = ReAllocateMemory( Obj()\Mem_P, Anzahl*12*4) ; Speicher verändern (oder Erstellen)
  Obj()\Mem_F = ReAllocateMemory( Obj()\Mem_F, Anzahl*12  ) ;    "        "
  ProcedureReturn @Obj()
EndProcedure

Procedure AddPoint(Nr.w, x.f, y.f, z.f)    ; Punkt hinzufügen
  If Nr = -1                               ; #PB_Any als Nr ->
    Nr = Obj()\Points                      ; Am Ende einfügen
    Obj()\Points + 1                       ; Ein Punkt mehr ist vorhanden
  EndIf
  PokeF(P_(Nr),    x)                      ; X-Position angeben
  PokeF(P_(Nr)+4,  y)                      ; Y-Position angeben
  PokeF(P_(Nr)+8,  z)                      ; Z-Position angeben
  ProcedureReturn Nr                       ; Position zurückgeben
EndProcedure
  
Procedure AddFace(Nr.w, e1.w, e2.w, e3.w, e4.w, textur.l) ; Viereck hinzufügen
  If Nr = -1                  ; #PB_Any als NR ->
    Nr = Obj()\Faces          ; Am Ende einfügen
    Obj()\Faces + 1           ; Ein Viereck mehr ist vorhanden
  EndIf
  PokeW(F_(Nr),    e1)        ; Ecke 1    2-----3
  PokeW(F_(Nr)+2,  e2)        ; Ecke 2    |     |
  PokeW(F_(Nr)+4,  e3)        ; Ecke 3    |     |
  PokeW(F_(Nr)+6,  e4)        ; Ecke 4    1-----4
  PokeL(F_(Nr)+8,  textur)    ; Textur = Sprite3D
  ProcedureReturn Nr          ; Position zurückgeben
EndProcedure
  
Procedure StopEditing()               ; Stopt die Bearbeitung
  Obj()\Mem_P = ReAllocateMemory( Obj()\Mem_P, Obj()\Points * 12) ; Speicher auf verbrauchte ...
  Obj()\Mem_F = ReAllocateMemory( Obj()\Mem_F, Obj()\Faces  * 12) ; Größe reduzieren.
  ProcedureReturn @Obj()              ; Objekt zurückgeben
EndProcedure

;***********************************************************************************************

;**************** Rendering ********************************************************************

Procedure GetTexture(Nr.w)          ; TexturNr ermitteln
  ProcedureReturn PeekL(F_(Nr)+8)   ; Liest die SpriteNummer aus
EndProcedure

Procedure ScreenX(Nr.w)             ; X-Wert auf dem Screen
  Shared distanz                    ; Variable aus dem Hauptbereich
  ProcedureReturn PeekF(P_(Nr))   * distanz / (PeekF(P_(Nr)+8) - distanz)
EndProcedure

Procedure ScreenY(Nr.w)             ; Y-Wert auf dem Screen
  Shared distanz                    ; Variable aus dem Hauptbereich
  ProcedureReturn PeekF(P_(Nr)+4) * distanz / (PeekF(P_(Nr)+8) - distanz)
EndProcedure

Procedure ZPos(Nr.w)                ; Z-Position eines Punkts für Sprite 3D
  Shared distanz                    ; Variable aus dem Hauptbereich
  ProcedureReturn PeekF(P_(Nr)) - distanz
EndProcedure

Procedure Render3D() ; Objekte Rendern
  Shared distanz     ; Variable aus dem Hauptbereich  
  Start3D()
    
  ForEach Obj()
    For i=0 To Obj()\Faces -1
      e1 = PeekW(F_(i)  )
      e2 = PeekW(F_(i)+2)
      e3 = PeekW(F_(i)+4)
      e4 = PeekW(F_(i)+6)
      TransformSprite3D(GetTexture(i), ScreenX(e1), ScreenY(e1), ZPos(e1), ScreenX(e2), ScreenY(e2), ZPos(e2), ScreenX(e3), ScreenY(e3), ZPos(e3), ScreenX(e4), ScreenY(e4), ZPos(e4))
      DisplaySprite3D  (GetTexture(i), 500, 400, 255)
    Next
  Next
    
  Stop3D()
   
  ProcedureReturn 1
EndProcedure

Naja, drehen geht noch nicht richtig aber sonst funktionierts