Files |  Tutorials |  Articles |  Links |  Home |  Team |  Forum |  Wiki |  Impressum

Aktuelle Zeit: Mo Jul 14, 2025 02:33

Foren-Übersicht » Programmierung » Allgemein
Unbeantwortete Themen | Aktive Themen



Ein neues Thema erstellen Auf das Thema antworten  [ 5 Beiträge ] 
Autor Nachricht
 Betreff des Beitrags: Problem mit Matrizen
BeitragVerfasst: Di Okt 26, 2010 13:57 
Offline
DGL Member
Benutzeravatar

Registriert: Fr Dez 11, 2009 08:02
Beiträge: 532
Programmiersprache: pascal (Delphi 7)
Ich versuch gerade, nen kleinen raytracer zu schreiben. Wollte grad Dreiecke implementieren, funktioniet aber nicht ganz so, wie ich mir das vorstell.

Im Konstruktor berechne ich eine Matrix, die das Dreieck auf das Dreieck A = (-1, 0, 0) B = (1, 0, 0) C = (0, 0, 1) abbildet. Da wird vermutlich der Fehler liegen, ich find ihn bloß nicht.
Bei der Schnittpunkt berechnung multiplizier ich den Strahl mit der Matrix (origin mit der homogenen, direction mit der affinen). Damit muss ich nur noch prüfen, ob der Schnittpunkt (mit der Ebene, auf der das Dreieck liegt) im Dreieck liegt, was recht einfach sein sollte, weils nur ein ganz bestimmtes Dreieck ist (das ich mir extra so ausgesucht hab) Den Rest machen die Matrizen... oder jedenfalls hab ich mir das so vorgestellt.

Nur: die Translation wird bei Origin großzügig ignoriert. Da Origin normalerweise im Punkt (0, 0, 0) lieg, liegts auch nach der Transformation noch in diesem Punkt. Hab mir zuerst gedacht, Vector3d.Transform macht halt keine Translation, und deswegen Vector4d.Transform benutzt, und die W Koordinate auf 1.0 gesetzt. Ich kann aber nach wie vor nix erkennen. Und das Problem mit der Translation bleibt auch.

Code:
 public class Triangle : Intersectable
    {       
        public Vertex A;
        public Vertex B;
        public Vertex C;
        public Matrix4d Transformations;
        public Matrix4d Affine;       

        public override double Intersect(Ray ray)
        {
            ray.Origin = Vector4d.Transform(new Vector4d(ray.Origin, 1.0d), Transformations).Xyz; //Translation wird ignoriert!?!
            ray.Direction = Vector3d.Transform(ray.Direction, Affine); //Skalierung wird berücksichtigt, daher ist Rückskalierung nicht nötig
            if (ray.Direction.Y == 0.0d)
            {
                return -1.0d;
            }
            double distance = -ray.Origin.Y / ray.Direction.Y; //liegt auf XZ Ebene
            Vector3d Pos = ray.Origin + ray.Direction * distance;
            double absPosX = Pos.X < 0.0d ? -Pos.X : Pos.X;
            if (absPosX + Pos.Z > 1.0d || Pos.Z < 0.0d)
            {
                return -1.0d; //nicht getroffen
            }
            return distance;
        }

        public override Vertex Evaluate(Vector3d position, Ray ray)
        {
            Vector3d pos = Vector3d.Transform(position, Transformations);
            double ab = (pos.X + 1.0d) * 0.5d;           
            double aPart = ab - pos.Z * 0.5;
            double bPart = (1.0d - ab) - pos.Z * 0.5d;
            float a = (float)aPart;
            float b = (float)bPart;
            float c = (float)pos.Z;
            return Vertex.Create(position, A.Normal * aPart + B.Normal * bPart + C.Normal * pos.Z, A.Diffuse * a + B.Diffuse * b + C.Diffuse * c, A.Specular * a + B.Specular * b + C.Specular * c);
        }   

       
        public Triangle(Vertex _A, Vertex _B, Vertex _C)
        {
            A = _A;
            B = _B;
            C = _C;
            Vector3d AB = (_B.Pos - _A.Pos) * 0.5d;
            Vector3d Pos = (_A.Pos + _B.Pos) * 0.5d;
            Vector3d Height = _C.Pos - Pos;
            Vector3d N = Vector3d.Normalize(Vector3d.Cross(AB, Height));
            Transformations = new Matrix4d(AB.X, AB.Y, AB.Z, Pos.X, N.X, N.Y, N.Z, Pos.Y, Height.X, Height.Y, Height.Z, Pos.Z, 0.0d, 0.0d, 0.0d, 1.0d);
            Affine = Transformations;
            Affine.Row0.W = 0.0d;
            Affine.Row1.W = 0.0d;
            Affine.Row2.W = 0.0d;
            Affine.Row3.W = 1.0d;
            Affine.Row3.Z = 0.0d;
            Affine.Row3.Y = 0.0d;
            Affine.Row3.X = 0.0d;
            Transformations = Matrix4d.Invert(Transformations);
            Affine = Matrix4d.Invert(Affine);                             
              //Transformationen berechnen, die das Dreieck A = (-1, 0, 0) B = (1, 0, 0) C = (0, 0, 1) auf das Angegebene Dreieck abbilden, und diese dann umkehren.
        }
    }


Die Vectoren und Matrizen kommen von OpenTK


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: Problem mit Matrizen
BeitragVerfasst: Di Okt 26, 2010 14:46 
Offline
DGL Member
Benutzeravatar

Registriert: Do Dez 29, 2005 12:28
Beiträge: 2249
Wohnort: Düsseldorf
Programmiersprache: C++, C#, Java
Um eine Richtung zu transformieren brauchst du die 3x3 große NormalMatrix. Dabei handelt es sich um den Rotationsanteil der Transformationsmatrix, also den 3x3-Teil links oben. Die NormalMatrix muss zudem invertiert und transponiert werden.

Sofern du ausschließlich Rotation und Translation in deiner Transformationsmatrix hast ist die NormalMatrix orthonormal, d.h. die Operationen "invertieren" und "transponieren" heben sich gegenseitig auf. Aus deinem Kommentar "Skalierung wird berücksichtigt" schließe ich aber, dass du eine Skalierung in der Matrix hast, weshalb die Matrix nicht mehr orthonormal ist.

Des weiteren ist die Transformation mit der NormalMatrix nicht Längen erhaltend, d.h. eine Richtung muss ggf. erneut normalisiert werden.

_________________
Yeah! :mrgreen:


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: Problem mit Matrizen
BeitragVerfasst: Di Okt 26, 2010 15:01 
Offline
DGL Member
Benutzeravatar

Registriert: Fr Dez 11, 2009 08:02
Beiträge: 532
Programmiersprache: pascal (Delphi 7)
Zitat:
Um eine Richtung zu transformieren brauchst du die 3x3 große NormalMatrix.
Nur Matrix3d gibts nicht ==> ich benutz halt Matrix4d und setz den Rest auf Identity

Zitat:
Des weiteren ist die Transformation mit der NormalMatrix nicht Längen erhaltend, d.h. eine Richtung muss ggf. erneut normalisiert werden.
Also, das war eigentlich Absicht, dass die Richting nicht normalisiert wird. Der Sinn davon ist, dass distance richtig bleibt, trotz Transformation. Und die (hier vereinfachte) Schnittpunktberechnung zwischen Gerade und Ebene funktioniert unabhängig von der Länge des Richtungsvektors. Sollte eigentlich.

Zitat:
Die NormalMatrix muss zudem invertiert und transponiert werden.
Habs jetzt nach dem Invertieren noch transponiert, sieht anders aus, aber nicht so, wies aussehen soll. Außerdem ist da (zumindest unter anderem) bezüglich Origin irgendwo ein Fehler, und Origin sieht diese Matrix nie.


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: Problem mit Matrizen
BeitragVerfasst: Di Okt 26, 2010 15:16 
Offline
DGL Member
Benutzeravatar

Registriert: Do Dez 29, 2005 12:28
Beiträge: 2249
Wohnort: Düsseldorf
Programmiersprache: C++, C#, Java
Zitat:
Der Sinn davon ist, dass distance richtig bleibt, trotz Transformation.

Die Länge des Vektors ändert sich. D.h. wenn du die Länge behalten willst musst du dir vorher die Länge merken und den Vektor nach der Transformation wieder auf die richtige Länge setzen.

Wenn es hier um eine Kante/Strecke geht, also ein Strahl mit Anfang und Ende ist es ggf. einfacher beide Endpunkte zu transformieren. Dann kannst du dir den ganzen Kram mit der NormalMatrix sparen.

Zitat:
Nur Matrix3d gibts nicht ==> ich benutz halt Matrix4d und setz den Rest auf Identity

Klar, geht auch.

Zitat:
Habs jetzt nach dem Invertieren noch transponiert, sieht anders aus, aber nicht so, wies aussehen soll.

Da du die Transformationsmatrix invertierst musst du die Normalmatrix auch von der invertierten Transformationsmatrix berechnen. Spricht zweimal invertieren (=keinmal) und einmal transponieren.

Zitat:
new Matrix4d(AB.X, AB.Y, AB.Z, Pos.X, N.X, N.Y, N.Z, Pos.Y, Height.X, Height.Y, Height.Z, Pos.Z, 0.0d, 0.0d, 0.0d, 1.0d);

Versuch mal:
Code:
new Matrix4d(AB.X, AB.Y, AB.Z, 0.0d, N.X, N.Y, N.Z, 0.0d, Height.X, Height.Y, Height.Z, 0.0d, Pos.X, Pos.Y, Pos.Z, 1.0d);

_________________
Yeah! :mrgreen:


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: Problem mit Matrizen
BeitragVerfasst: Di Okt 26, 2010 16:08 
Offline
DGL Member
Benutzeravatar

Registriert: Fr Dez 11, 2009 08:02
Beiträge: 532
Programmiersprache: pascal (Delphi 7)
Zitat:
new Matrix4d(AB.X, AB.Y, AB.Z, 0.0d, N.X, N.Y, N.Z, 0.0d, Height.X, Height.Y, Height.Z, 0.0d, Pos.X, Pos.Y, Pos.Z, 1.0d);
Ja, so gehts. Thx

Zitat:
Die Länge des Vektors ändert sich. D.h. wenn du die Länge behalten willst musst du dir vorher die Länge merken und den Vektor nach der Transformation wieder auf die richtige Länge setzen.
Schnittpunkt = Origin + Direction * Distance. Normalerweise hat Direction Länge 1, daher die Bezeichnung Distance. Nur wegen den den Transformationen hats halt nicht mehr die Länge 1. Aber deswegen soll idealerweise trotzdem die richtige Distance berechnet werden, deswegen nicht Normalize.


Nach oben
 Profil  
Mit Zitat antworten  
Beiträge der letzten Zeit anzeigen:  Sortiere nach  
Ein neues Thema erstellen Auf das Thema antworten  [ 5 Beiträge ] 
Foren-Übersicht » Programmierung » Allgemein


Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 8 Gäste


Du darfst keine neuen Themen in diesem Forum erstellen.
Du darfst keine Antworten zu Themen in diesem Forum erstellen.
Du darfst deine Beiträge in diesem Forum nicht ändern.
Du darfst deine Beiträge in diesem Forum nicht löschen.
Du darfst keine Dateianhänge in diesem Forum erstellen.

Suche nach:
Gehe zu:  
  Powered by phpBB® Forum Software © phpBB Group
Deutsche Übersetzung durch phpBB.de
[ Time : 0.008s | 14 Queries | GZIP : On ]