Licht/Normals

Übersicht BlitzBasic Blitz3D

Neue Antwort erstellen

 

Nox

Betreff: Licht/Normals

BeitragDi, Jul 18, 2006 11:38
Antworten mit Zitat
Benutzer-Profile anzeigen
Tag zusammen.

Habe folgendes Problem: Ich baue mir mein Levelmesh selbst zusammen und richte danach auch die Normalen neu aus (UpdateNormals()). Doch einige Triangles werden absolut falsch beleuchtet. Muss ich bei der Reihenfolge der Vertices eines Triangles denn noch was beachten? (außer natürlich, dass sie im Uhrzeigersinn angeordnet sein müssen)
Für eine Veranschaulichung hier klicken. Ein Punktlicht ist an die Kamera angehängt.
 

Dreamora

BeitragDi, Jul 18, 2006 11:58
Antworten mit Zitat
Benutzer-Profile anzeigen
Das sieht für mich aus, als ob du die Wand aus einzelnen Quads gemacht hast.

In diesem Falle wären die Vertexnormalen auch nur für 1 Quad aufgestellt und nicht für die gesamte Wand, weswegen es so falsch aussieht.

Um das zu beheben, musst du dafür sorgen, das Vertices, die in 2 Quads vorkommen auch in beiden Quads (also den zugehörigen Triangles) genutzt werden und nicht für jedes Quad neue Vertices erzeugt werden.
Dann sollte das auch mit UpdateNormals klappen Smile
Ihr findet die aktuellen Projekte unter Gayasoft und könnt mich unter @gayasoft auf Twitter erreichen.
 

Nox

BeitragDi, Jul 18, 2006 12:08
Antworten mit Zitat
Benutzer-Profile anzeigen
Das ist sch... Wink Hast es aber richtig erkannt, die Wand besteht aus einzelnen Quads, diese jeweils aus 4 Vertices und 2 Triangles. Nur dachte ich mir: Die Normalen der ganzen Triangles - bspw. der hinteren Wand - zeigen eh alle in die selbe Richtung, was ja für's Belichten ausschlaggebend ist. Deshalb auch mein Gedanke, dass sie dann auch korrekt belichtet werden müssten.
Wenn's keinen Weg um deine genannte Methode drumherum gibt, wird das ne ziemlich mühselige Arbeit. Smile

Edit: Und nochwas: Wieso wird die Wand ganz "hinten" beleuchtet, doch der Vorsprung ganz rechts garnicht? Das ist mir irgendwie ganz unlogisch, denn die Normalen zeigen in dieselbe Richtung.
 

Dreamora

BeitragDi, Jul 18, 2006 12:33
Antworten mit Zitat
Benutzer-Profile anzeigen
Da bin ich überfragt.
Eigentlich sollten die normalen stimmen, auch bei einzelteilen, da hast du recht.

Kannst dir ja sonst mal "Debugobjekte" überall ankleben und dir die Daten ausgeben lassen ... vielleicht läuft auch sonstwas schief.

Alternativ gibts auch die Möglichkeit, dass du die Normalen angibst. Da du ja scheinbar nur die 3 Axenrichtungen zulässt, sind das 6 möglichkeiten für die vertexnormalen, du könntest die also bei der Generierung ganz einfach selbst mit rein schreiben. Weisst ja in welche richtung die Wand schaut.
*nur für den Fall das UpdateNormals sich nicht mit dem Konstrukt vertragen würde*

Alternativ wäre vielleicht ein Code der das Problem zeigt nicht schlecht, für den Fall das da was bogus wäre. (wie meshFX auf double sided geschaltet und so dinge)
Ihr findet die aktuellen Projekte unter Gayasoft und könnt mich unter @gayasoft auf Twitter erreichen.

Markus2

BeitragDi, Jul 18, 2006 12:36
Antworten mit Zitat
Benutzer-Profile anzeigen
Bei Ecken solltest du die Vertices nicht doppelt benutzen .
Also wie in deinem Level Decke,Wand links und Wand hinten etc. trennen
weil die Normalen ja je Punkt gelten .
 

Nox

BeitragDi, Jul 18, 2006 12:55
Antworten mit Zitat
Benutzer-Profile anzeigen
Dreamora hat Folgendes geschrieben:
Alternativ gibts auch die Möglichkeit, dass du die Normalen angibst.

Das müsste ich dann mal ausprobieren, jepp. Falls es daran liegen sollte, kann man UpdateNormals() also getrost in die Tonne kloppen.. Wink

Zitat:
Alternativ wäre vielleicht ein Code der das Problem zeigt nicht schlecht, für den Fall das da was bogus wäre. (wie meshFX auf double sided geschaltet und so dinge)

Kann ich gerne hier pasten. Was genau ist gewünscht? Vorab kann ich jedoch schonmal sagen, dass ich kein MeshFX oder sonstiges genutzt habe. Erstelle lediglich die einzelnen Vertices und verbinde sie zu jeweils zwei Dreiecken, das war's.

Markus2 hat Folgendes geschrieben:
Bei Ecken solltest du die Vertices nicht doppelt benutzen .
Also wie in deinem Level Decke,Wand links und Wand hinten etc. trennen
weil die Normalen ja je Punkt gelten.

Wenn ich dich jetzt richtig verstanden habe, dann lautet die Antwort "Mach ich nich". Wink Jedes Quad hat seine eigenen 4 Vertices. Ob's nun ein Quad an der Decke, an der Wand oder am Boden ist. Die Dreiecke werden immer mit den 4 Vertices des jeweiligen Quads verbunden. Es werden also keine "benachbarten" Vertices genutzt (ist vielleicht unschön gelöst, reicht mir aber eigentlich völlig aus, sprich für den Stil, den ich mit dem Spiel verfolge).
Vielleicht macht's das Bild hier ein bisschen klarer (jedes Quad ist einzeln, deutlich durch versch. Farben)
user posted image

Was mich ja total daran wundert ist, dass die ganze Wand nach demselben Prinzip aufgebaut wird. Und sofern die Textur übereinstimmt, wird das alles auch in ein Surface gepresst, d.h. völlig identische Quads..aber falsche Beleuchtung.
 

Dreamora

BeitragDi, Jul 18, 2006 22:11
Antworten mit Zitat
Benutzer-Profile anzeigen
Naja das UpdateNormals nicht die hellste Funktion ist, ist bekannt.

Fredborg musste für Gile[s] eine eigene Funktion schreiben, weil die von Blitz zuviele Dinge einfach "vergisst" beim erzeugen der Normalen ...
Ihr findet die aktuellen Projekte unter Gayasoft und könnt mich unter @gayasoft auf Twitter erreichen.
 

BIG BUG

BeitragDi, Jul 18, 2006 23:02
Antworten mit Zitat
Benutzer-Profile anzeigen
UpdateNormals ist nur für runde Objekte geeignet. Für eckige Sachen kannste folgende Funktion benutzen(geht noch ein bisschen einfacher, da man auch direkt das Kreuzprodukt von v1-2 und v1-3 bilden könnte):
Code: [AUSKLAPPEN]

Function UpdateNormalsFlat(mesh)

  Local surface, mesh_surface, faktor#
  Local v1, v2, v3
  Local ax#, ay#, az#
  Local lx#, ly#, lz#
  Local nx#, ny#, nz#

  For mesh_surface = 0 To CountSurfaces(mesh)

     surface=GetSurface(mesh,mesh_surface)

     For triangle = 0 To CountTriangles(surface)-1

        v1 = TriangleVertex(surface, triangle, 0)
        v2 = TriangleVertex(surface, triangle, 1)
        v3 = TriangleVertex(surface, triangle, 2)

        ;Achse durch v1 als Vektor     
        lx# = -((VertexX#(surface,v3) + VertexX#(surface,v2))/2-VertexX#(surface,v1))
        ly# = -((VertexY#(surface,v3) + VertexY#(surface,v2))/2-VertexY#(surface,v1))
        lz# = -((VertexZ#(surface,v3) + VertexZ#(surface,v2))/2-VertexZ#(surface,v1))

        ;Kante von v2 zu v3 als Vektor
        ax# = VertexX#(surface,v2) - VertexX#(surface,v3)
        ay# = VertexY#(surface,v2) - VertexY#(surface,v3)
        az# = VertexZ#(surface,v2) - VertexZ#(surface,v3)

        ;Kreuzprodukt beider Vektoren
       nx# = (ly# * az#)-(lz# * ay#)
       ny# = (lz# * ax#)-(lx# * az#)
       nz# = (lx# * ay#)-(ly# * ax#)
   
       ;Ergebnisvektor auf Laenge 1 bringen
       faktor# = Sqr((nx# * nx#)+(ny# * ny#)+(nz# * nz#))   
       nx# = nx# / faktor#
       ny# = ny# / faktor#
       nz# = nz# / faktor#

        VertexNormal surface, v1, nx#, ny#, nz#

     Next
  Next

End Function
B3D-Exporter für Cinema4D!(V1.4)
MD2-Exporter für Cinema4D!(final)

Markus2

BeitragMi, Jul 19, 2006 0:01
Antworten mit Zitat
Benutzer-Profile anzeigen
@Nox
Jup das hört sich gut an ,
da die Normalen ja berechnet sind ,laß sie dir mal mit einer 3D Linien
Funk. am besten anzeigen .
Wenn deine Entitys nicht gedreht wurden geht das relativ einfach .
ansonsten einfach erstmal versuchen die Eckpunkte anzeigen zu lassen
an der richtigen Stelle .
 

Nox

BeitragMi, Jul 19, 2006 10:19
Antworten mit Zitat
Benutzer-Profile anzeigen
@BIG BUG:
Erstmal vielen Dank für den Codeschnippsel. Allerdings habe ich - wie du sagtest - direkt das Kreuzprodukt angewandt. Nun aber die Frage: Ist es wirklich notwendig, das Kreuzprodukt von v0*v1 und v0*v2 anzuwenden, oder reicht nicht schon ein v0*v1? Mein Gedanke dabei ist, dass die ganzen Triangles immer gleich ausgerichtet sind. D.h. die Normale zwischen v0 und v1 ist auch die Normale von v2 - rechnerisch...mein ich. Wink

Ich zeig einfach mal, wie ich's probiert habe zu lösen (klappt natürlich nicht Smile ):
Code: [AUSKLAPPEN]

Function UpdateNormalsFlat( mesh% )
   Local srfMesh%
   Local srfnum%, trinum%
   Local v0%, v1%, v2%
   Local nx#, ny#, nz#, norm#
   Local v0x#, v0y#, v0z#, v1x#, v1y#, v1z#
   
   For srfnum% = 1 To CountSurfaces( mesh% )
      srfMesh% = GetSurface( mesh%, srfnum% )

      For trinum% = 0 To CountTriangles( srfMesh% ) - 1
         v0% = TriangleVertex( srfMesh%, trinum%, 0 )
         v1% = TriangleVertex( srfMesh%, trinum%, 1 )
         v2% = TriangleVertex( srfMesh%, trinum%, 2 )

         v0x# = VertexX( srfMesh%, v0% ) ; Nur zur besseren Lesbarkeit..
         v0y# = VertexY( srfMesh%, v0% )
         v0z# = VertexZ( srfMesh%, v0% )
         v1x# = VertexX( srfMesh%, v1% )
         v1y# = VertexY( srfMesh%, v1% )
         v1z# = VertexZ( srfMesh%, v1% )
      
         nx# = v0y# * v1z# - v0z# * v1y#   ; Kreuzprodukt zwischen v0 und v1.
         ny# = v0x# * v1z# - v0z# * v1x#
         nz# = v0x# * v1y# - v0y# * v1x#
      
         ; Normalisierungsfaktor bestimmen.
         norm# = Sqr( nx# * nx# + ny# * ny# + nz# * nz# )
         nx# = nx# / norm#   ; ...und normalisieren.
         ny# = ny# / norm#
         nz# = nz# / norm#
      
         ; Normale auf alle Vertices anwenden.
         VertexNormal( srfMesh%, v0%, nx#, ny#, nz# )
         VertexNormal( srfMesh%, v1%, nx#, ny#, nz# )
         VertexNormal( srfMesh%, v2%, nx#, ny#, nz# )
   
      Next
   Next

End Function
 

Dreamora

BeitragMi, Jul 19, 2006 10:23
Antworten mit Zitat
Benutzer-Profile anzeigen
Es gibt keine normale zwischen v0 und v1
Was du machen musst ist:

(v0-v1) X (v0-v2) (oder sonstwie, da das immer aufs gleiche raus kommt da kommutativ)
Damit erhälst du die Normale des Triangles, was ja bei etwas flachem auch den VertexNormalen entspricht.
Das entspricht auch dem was BigBug schrieb.

Das Kreuzprodukt der Vertexpositionen macht dabei keinen Sinn, da diese rein garnichts mit dem Triangle zu tun haben, da keiner der beiden Vektoren überhaupt in der Triangle Ebene zu liegen braucht (und normalerweise auch nicht wird)
Ihr findet die aktuellen Projekte unter Gayasoft und könnt mich unter @gayasoft auf Twitter erreichen.
 

Nox

BeitragMi, Jul 19, 2006 10:49
Antworten mit Zitat
Benutzer-Profile anzeigen
Dreamora hat Folgendes geschrieben:
Das Kreuzprodukt der Vertexpositionen macht dabei keinen Sinn, da diese rein garnichts mit dem Triangle zu tun haben, da keiner der beiden Vektoren überhaupt in der Triangle Ebene zu liegen braucht (und normalerweise auch nicht wird)

Okay das leuchtet mir ein, danke.
Gesagt, getan: Die Normalen sind korrekt ausgerichtet, allerdings nicht von allen Triangles. Wie im o.g. Code zu sehen, iteriere ich durch sämtliche Triangles aller Surfaces. Doch komischerweise wird immer nur ein Triangle eines Quads berücksichtigt. Ob das nun an meiner Rechnung liegt oder an der Iteration, kann ich mir nicht beantworten.

Zuerst ein Bildchen:
user posted image
Sehr gut zu sehen auf dem Bild ist der Effekt an den Decken- und Wandquads.

Ich nehme mir mal die Freiheit, einfach nochmal die Funktion zu pasten. Vielleicht findet ihr meinen Fehler..
Code: [AUSKLAPPEN]

Function UpdateNormalsFlat( mesh% )
   Local srfMesh%
   Local srfnum%, trinum%
   Local v0%, v1%, v2%
   Local nx#, ny#, nz#, norm#
   Local v0x#, v0y#, v0z#, v1x#, v1y#, v1z#
   Local v01x#, v01y#, v01z#, v02x#, v02y#, v02z#
   
   For srfnum% = 1 To CountSurfaces( mesh% )
      srfMesh% = GetSurface( mesh%, srfnum% )

      For trinum% = 0 To CountTriangles( srfMesh% ) - 1
         v0% = TriangleVertex( srfMesh%, trinum%, 0 )
         v1% = TriangleVertex( srfMesh%, trinum%, 1 )
         v2% = TriangleVertex( srfMesh%, trinum%, 2 )

         v0x# = VertexX( srfMesh%, v0% ) ; Nur zur besseren Lesbarkeit..
         v0y# = VertexY( srfMesh%, v0% )
         v0z# = VertexZ( srfMesh%, v0% )
         v1x# = VertexX( srfMesh%, v1% )
         v1y# = VertexY( srfMesh%, v1% )
         v1z# = VertexZ( srfMesh%, v1% )
      
         v01x# = v0x# - v1x#
         v01y# = v0y# - v1y#
         v01z# = v0z# - v1z#
         v02x# = v0x# - v2x#
         v02y# = v0y# - v2y#
         v02z# = v0z# - v2z#

         ; Kreuzprodukt zwischen (v0 - v1) und (v0 - v2).
         nx# = v01y# * v02z# - v01z# * v02y#
         ny# = v01x# * v02z# - v01z# * v02x#
         nz# = v01x# * v02y# - v01y# * v02x#
      
         ; Normalisierungsfaktor bestimmen.
         norm# = Sqr( nx# * nx# + ny# * ny# + nz# * nz# )
         nx# = nx# / norm#   ; ...und normalisieren.
         ny# = ny# / norm#
         nz# = nz# / norm#
      
         ; Normale auf alle Vertices anwenden.
         VertexNormal( srfMesh%, v0%, nx#, ny#, nz# )
         VertexNormal( srfMesh%, v1%, nx#, ny#, nz# )
         VertexNormal( srfMesh%, v2%, nx#, ny#, nz# )

      Next
   Next

End Function
 

Dreamora

BeitragMi, Jul 19, 2006 11:36
Antworten mit Zitat
Benutzer-Profile anzeigen
Das ist einer der Fälle bei dem ich weiss warum BM >>>> B3D
BM würde dir jetzt nämlich sagen: V2x/y/z existieren nicht Wink

Sprich dort kommt immer 0 womit die gesamte Rechnung schief kommt, weswegen die Triangles so komisch aussehen.
Ihr findet die aktuellen Projekte unter Gayasoft und könnt mich unter @gayasoft auf Twitter erreichen.
  • Zuletzt bearbeitet von Dreamora am Mi, Jul 19, 2006 12:23, insgesamt einmal bearbeitet
 

Nox

BeitragMi, Jul 19, 2006 12:04
Antworten mit Zitat
Benutzer-Profile anzeigen
Verdammte §$%&=("&. Ich geb dir ja sowas von Recht. Ne Art Option Explicit wäre verdammt angebracht. Wink Danke für die Aufmerksamkeit hehe. Mal schauen, ob's denn jetzt mal klappt..
 

Dreamora

BeitragMi, Jul 19, 2006 12:26
Antworten mit Zitat
Benutzer-Profile anzeigen
Nö ... wird jetzt aber gleichmässig falsch sein Wink
NY ist noch falsch. Dort müsste das negative des jetzigen stehen (also v1z*v2x - v1x*v2z ).

Dann müsste es eigentlich stimmen Smile
Ihr findet die aktuellen Projekte unter Gayasoft und könnt mich unter @gayasoft auf Twitter erreichen.
 

Nox

BeitragMi, Jul 19, 2006 12:30
Antworten mit Zitat
Benutzer-Profile anzeigen
Laughing
Jap, das ist mir auch aufgefallen, als ich sah, dass zwar alle Wände korrekt beleuchtet werden, aber Boden und Decke nicht, da die Normalen immer genau in die entgegengesetzte Richtung zeigten. =)
Vielen Dank euch für die Hilfe, hat mir super weitergeholfen - und schließlich klappt jetzt auch alles. Merci. =)

Neue Antwort erstellen


Übersicht BlitzBasic Blitz3D

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group