Frage

Ich habe eine Anwendung, die ein reales Rechteck über einem Bild/Foto definiert. In 2D ist es natürlich möglicherweise kein Rechteck, weil Sie es aus einem Winkel betrachten.

Das Problem besteht beispielsweise darin, dass auf dem Rechteck Gitterlinien gezeichnet werden müssen. Wenn es beispielsweise 3x5 groß ist, muss ich 2 Linien von Seite 1 zu Seite 3 und 4 Linien von Seite 2 zu Seite 4 zeichnen.

Im Moment teile ich jede Linie in äquidistante Teile auf, um den Anfangs- und Endpunkt aller Gitterlinien zu erhalten.Je größer der Winkel des Rechtecks ​​ist, desto „falscher“ werden diese Linien, da horizontale Linien, die weiter von Ihnen entfernt sind, näher beieinander liegen sollten.

Kennt jemand den Namen des Algorithmus, nach dem ich suchen sollte?

Ja, ich weiß, dass Sie dies in 3D tun können, für diese spezielle Anwendung bin ich jedoch auf 2D beschränkt.

War es hilfreich?

Lösung

Hier ist die Lösung.

Die Grundidee besteht darin, dass Sie die perspektivisch korrekte „Mitte“ Ihres Rechtecks ​​finden können, indem Sie die Ecken diagonal verbinden.Der Schnittpunkt der beiden resultierenden Linien ist Ihr perspektivisch korrekter Mittelpunkt.Von dort aus unterteilen Sie Ihr Rechteck in vier kleinere Rechtecke und wiederholen den Vorgang.Die Häufigkeit hängt davon ab, wie genau Sie es wünschen.Für eine nahezu perfekte Perspektive können Sie eine Unterteilung auf knapp unter die Größe eines Pixels vornehmen.

Dann wenden Sie in Ihren Unterrechtecken einfach Ihre standardmäßigen unkorrigierten „texturierten“ Dreiecke oder Rechtecke oder was auch immer an.

Sie können diesen Algorithmus ausführen, ohne sich die komplexe Mühe machen zu müssen, eine „echte“ 3D-Welt zu erstellen.Es ist auch gut für Sie Tun Sie haben eine echte 3D-Welt modelliert, aber Ihre Textdreiecke sind in der Hardware nicht perspektivisch korrigiert, oder Sie benötigen eine leistungsstarke Methode, um perspektivisch korrekte Ebenen ohne Tricks beim Rendern pro Pixel zu erhalten.

Andere Tipps

Bildbeschreibung Bild: Beispiel Bilinear & Perspective Transformations- (Anmerkung: Die Höhe des oberen und unteren horizontalen Gitterlinien ist tatsächlich die Hälfte der übrigen Linien der Höhe, auf beiden Zeichnungen)

========================================

Ich weiß, dass dies eine alte Frage, aber ich habe eine generische Lösung, damit ich es veröffentlichen entschieden Hopping es um die Zukunft Leser von Nutzen sein wird. Der Code kann einen beliebigen Balg Perspektivraster ohne die Notwendigkeit von wiederholten Berechnungen ziehen.

Ich fange tatsächlich mit einem ähnlichen Problem: ein 2D-Perspektive Gitter zu zeichnen und dann die unterstrichenen Bild verwandeln die Perspektive wiederherstellen

.

Ich begann hier zu lesen: http://www.imagemagick.org/Usage/distorts/#bilinear_forward

und dann hier (die Leptonica Library): http://www.leptonica.com/affine.html

waren ich diese gefunden:

  

Wenn man sich auf einem Objekt in einer Ebene aus einer beliebigen Richtung auf   eine endliche Distanz, eine zusätzliche „Keystone“ Verzerrung in der get   Bild. Dies ist eine projektive Transformation, die geraden Linien hält   nicht gerade, aber nicht die Winkel zwischen den Linien bewahren. diese Verwerfungen   kann nicht durch eine lineare affine Transformation, und in der Tat beschrieben werden   unterscheidet sich von x- und y-abhängigen Terme im Nenner.

Die Transformation ist nicht linear, wie viele Menschen bereits in diesem Thread hingewiesen. Es geht um ein lineares System von 8 Gleichungen (einmal) die Lösung der 8 erforderlichen Koeffizienten zu berechnen, und dann kann man sie so viele Punkte zu verwandeln, wie Sie wollen.

Um einschließlich aller Leptonica Bibliothek in meinem Projekt zu vermeiden, nahm ich einige Teile des Codes von ihm entfernte ich sämtliche Leptonica Datentypen und Makros, ich einige Speicherlecks festgelegt und ich konvertiert es in eine C ++ Klasse (meist für die Verkapselung Gründe), die nur eine Sache tut: Es bildet einen (Qt) QPointF Schwimmer (x, y) Koordinate auf die entsprechende Perspektive Koordinaten.

Wenn Sie den Code in einer anderen C ++ Bibliothek anpassen mögen, das einzige, was / Ersatz neu zu definieren, wird die QPointF Klasse koordinieren.

Ich hoffe, einige zukünftige Leser finden es nützlich wäre. Der Code unten ist in 3 Teile unterteilt:

A. Ein Beispiel dafür, wie die genImageProjective C ++ Klasse verwenden, um einen 2D-Perspektive Grid

ziehen

B. genImageProjective.h Datei

C. genImageProjective.cpp Datei

//============================================================
// C++ Code Example on how to use the 
//     genImageProjective class to draw a perspective 2D Grid
//============================================================

#include "genImageProjective.h"

// Input: 4 Perspective-Tranformed points:
//        perspPoints[0] = top-left
//        perspPoints[1] = top-right
//        perspPoints[2] = bottom-right
//        perspPoints[3] = bottom-left
void drawGrid(QPointF *perspPoints)
{
(...)
        // Setup a non-transformed area rectangle
        // I use a simple square rectangle here because in this case we are not interested in the source-rectangle,
        //  (we want to just draw a grid on the perspPoints[] area)
        //   but you can use any arbitrary rectangle to perform a real mapping to the perspPoints[] area
        QPointF topLeft = QPointF(0,0);
        QPointF topRight = QPointF(1000,0);
        QPointF bottomRight = QPointF(1000,1000);
        QPointF bottomLeft = QPointF(0,1000);
        float width = topRight.x() - topLeft.x();
        float height = bottomLeft.y() - topLeft.y();

        // Setup Projective trasform object
        genImageProjective imageProjective;
        imageProjective.sourceArea[0] = topLeft;
        imageProjective.sourceArea[1] = topRight;
        imageProjective.sourceArea[2] = bottomRight;
        imageProjective.sourceArea[3] = bottomLeft;
        imageProjective.destArea[0] = perspPoints[0];
        imageProjective.destArea[1] = perspPoints[1];
        imageProjective.destArea[2] = perspPoints[2];
        imageProjective.destArea[3] = perspPoints[3];
        // Compute projective transform coefficients
        if (imageProjective.computeCoeefficients() != 0)
            return; // This can actually fail if any 3 points of Source or Dest are colinear

        // Initialize Grid parameters (without transform)
        float gridFirstLine = 0.1f; // The normalized position of first Grid Line (0.0 to 1.0)
        float gridStep = 0.1f;      // The normalized Grd size (=distance between grid lines: 0.0 to 1.0)

        // Draw Horizonal Grid lines
        QPointF lineStart, lineEnd, tempPnt;
        for (float pos = gridFirstLine; pos <= 1.0f; pos += gridStep)
        {
            // Compute Grid Line Start
            tempPnt = QPointF(topLeft.x(), topLeft.y() + pos*width);
            imageProjective.mapSourceToDestPoint(tempPnt, lineStart);
            // Compute Grid Line End
            tempPnt = QPointF(topRight.x(), topLeft.y() + pos*width);
            imageProjective.mapSourceToDestPoint(tempPnt, lineEnd);

            // Draw Horizontal Line (use your prefered method to draw the line)
            (...)
        }
        // Draw Vertical Grid lines
        for (float pos = gridFirstLine; pos <= 1.0f; pos += gridStep)
        {
            // Compute Grid Line Start
            tempPnt = QPointF(topLeft.x() + pos*height, topLeft.y());
            imageProjective.mapSourceToDestPoint(tempPnt, lineStart);
            // Compute Grid Line End
            tempPnt = QPointF(topLeft.x() + pos*height, bottomLeft.y());
            imageProjective.mapSourceToDestPoint(tempPnt, lineEnd);

            // Draw Vertical Line (use your prefered method to draw the line)
            (...)
        }
(...)
}

==========================================



//========================================
//C++ Header File: genImageProjective.h
//========================================

#ifndef GENIMAGE_H
#define GENIMAGE_H

#include <QPointF>

// Class to transform an Image Point using Perspective transformation
class genImageProjective
{
public:
    genImageProjective();

    int computeCoeefficients(void);
    int mapSourceToDestPoint(QPointF& sourcePoint, QPointF& destPoint);

public:
    QPointF sourceArea[4]; // Source Image area limits (Rectangular)
    QPointF destArea[4];   // Destination Image area limits (Perspectivelly Transformed)

private:
    static int gaussjordan(float  **a, float  *b, int n);

    bool coefficientsComputed;
    float vc[8];           // Vector of Transform Coefficients
};

#endif // GENIMAGE_H
//========================================


//========================================
//C++ CPP File: genImageProjective.cpp
//========================================

#include <math.h>
#include "genImageProjective.h"

// ----------------------------------------------------
// class genImageProjective
// ----------------------------------------------------
genImageProjective::genImageProjective()
{
    sourceArea[0] = sourceArea[1] = sourceArea[2] = sourceArea[3] = QPointF(0,0);
    destArea[0] = destArea[1] = destArea[2] = destArea[3] = QPointF(0,0);
    coefficientsComputed = false;
}


// --------------------------------------------------------------
// Compute projective transform coeeeficients
// RetValue: 0: Success, !=0: Error
/*-------------------------------------------------------------*
 *                Projective coordinate transformation         *
 *-------------------------------------------------------------*/
/*!
 *  computeCoeefficients()
 *
 *      Input:  this->sourceArea[4]: (source 4 points; unprimed)
 *              this->destArea[4]:   (transformed 4 points; primed)
 *              this->vc  (computed vector of transform coefficients)
 *      Return: 0 if OK; <0 on error
 *
 *  We have a set of 8 equations, describing the projective
 *  transformation that takes 4 points (sourceArea) into 4 other
 *  points (destArea).  These equations are:
 *
 *          x1' = (c[0]*x1 + c[1]*y1 + c[2]) / (c[6]*x1 + c[7]*y1 + 1)
 *          y1' = (c[3]*x1 + c[4]*y1 + c[5]) / (c[6]*x1 + c[7]*y1 + 1)
 *          x2' = (c[0]*x2 + c[1]*y2 + c[2]) / (c[6]*x2 + c[7]*y2 + 1)
 *          y2' = (c[3]*x2 + c[4]*y2 + c[5]) / (c[6]*x2 + c[7]*y2 + 1)
 *          x3' = (c[0]*x3 + c[1]*y3 + c[2]) / (c[6]*x3 + c[7]*y3 + 1)
 *          y3' = (c[3]*x3 + c[4]*y3 + c[5]) / (c[6]*x3 + c[7]*y3 + 1)
 *          x4' = (c[0]*x4 + c[1]*y4 + c[2]) / (c[6]*x4 + c[7]*y4 + 1)
 *          y4' = (c[3]*x4 + c[4]*y4 + c[5]) / (c[6]*x4 + c[7]*y4 + 1)
 *
 *  Multiplying both sides of each eqn by the denominator, we get
 *
 *           AC = B
 *
 *  where B and C are column vectors
 *
 *         B = [ x1' y1' x2' y2' x3' y3' x4' y4' ]
 *         C = [ c[0] c[1] c[2] c[3] c[4] c[5] c[6] c[7] ]
 *
 *  and A is the 8x8 matrix
 *
 *             x1   y1     1     0   0    0   -x1*x1'  -y1*x1'
 *              0    0     0    x1   y1   1   -x1*y1'  -y1*y1'
 *             x2   y2     1     0   0    0   -x2*x2'  -y2*x2'
 *              0    0     0    x2   y2   1   -x2*y2'  -y2*y2'
 *             x3   y3     1     0   0    0   -x3*x3'  -y3*x3'
 *              0    0     0    x3   y3   1   -x3*y3'  -y3*y3'
 *             x4   y4     1     0   0    0   -x4*x4'  -y4*x4'
 *              0    0     0    x4   y4   1   -x4*y4'  -y4*y4'
 *
 *  These eight equations are solved here for the coefficients C.
 *
 *  These eight coefficients can then be used to find the mapping
 *  (x,y) --> (x',y'):
 *
 *           x' = (c[0]x + c[1]y + c[2]) / (c[6]x + c[7]y + 1)
 *           y' = (c[3]x + c[4]y + c[5]) / (c[6]x + c[7]y + 1)
 *
 */
int genImageProjective::computeCoeefficients(void)
{
    int retValue = 0;
    int     i;
    float  *a[8];  /* 8x8 matrix A  */
    float  *b = this->vc; /* rhs vector of primed coords X'; coeffs returned in vc[] */

    b[0] = destArea[0].x();
    b[1] = destArea[0].y();
    b[2] = destArea[1].x();
    b[3] = destArea[1].y();
    b[4] = destArea[2].x();
    b[5] = destArea[2].y();
    b[6] = destArea[3].x();
    b[7] = destArea[3].y();

    for (i = 0; i < 8; i++)
        a[i] = NULL;
    for (i = 0; i < 8; i++)
    {
        if ((a[i] = (float *)calloc(8, sizeof(float))) == NULL)
        {
            retValue = -100; // ERROR_INT("a[i] not made", procName, 1);
            goto Terminate;
        }
    }

    a[0][0] = sourceArea[0].x();
    a[0][1] = sourceArea[0].y();
    a[0][2] = 1.;
    a[0][6] = -sourceArea[0].x() * b[0];
    a[0][7] = -sourceArea[0].y() * b[0];
    a[1][3] = sourceArea[0].x();
    a[1][4] = sourceArea[0].y();
    a[1][5] = 1;
    a[1][6] = -sourceArea[0].x() * b[1];
    a[1][7] = -sourceArea[0].y() * b[1];
    a[2][0] = sourceArea[1].x();
    a[2][1] = sourceArea[1].y();
    a[2][2] = 1.;
    a[2][6] = -sourceArea[1].x() * b[2];
    a[2][7] = -sourceArea[1].y() * b[2];
    a[3][3] = sourceArea[1].x();
    a[3][4] = sourceArea[1].y();
    a[3][5] = 1;
    a[3][6] = -sourceArea[1].x() * b[3];
    a[3][7] = -sourceArea[1].y() * b[3];
    a[4][0] = sourceArea[2].x();
    a[4][1] = sourceArea[2].y();
    a[4][2] = 1.;
    a[4][6] = -sourceArea[2].x() * b[4];
    a[4][7] = -sourceArea[2].y() * b[4];
    a[5][3] = sourceArea[2].x();
    a[5][4] = sourceArea[2].y();
    a[5][5] = 1;
    a[5][6] = -sourceArea[2].x() * b[5];
    a[5][7] = -sourceArea[2].y() * b[5];
    a[6][0] = sourceArea[3].x();
    a[6][1] = sourceArea[3].y();
    a[6][2] = 1.;
    a[6][6] = -sourceArea[3].x() * b[6];
    a[6][7] = -sourceArea[3].y() * b[6];
    a[7][3] = sourceArea[3].x();
    a[7][4] = sourceArea[3].y();
    a[7][5] = 1;
    a[7][6] = -sourceArea[3].x() * b[7];
    a[7][7] = -sourceArea[3].y() * b[7];

    retValue = gaussjordan(a, b, 8);

Terminate:
    // Clean up
    for (i = 0; i < 8; i++)
    {
        if (a[i])
            free(a[i]);
    }

    this->coefficientsComputed = (retValue == 0);
    return retValue;
}


/*-------------------------------------------------------------*
 *               Gauss-jordan linear equation solver           *
 *-------------------------------------------------------------*/
/*
 *  gaussjordan()
 *
 *      Input:   a  (n x n matrix)
 *               b  (rhs column vector)
 *               n  (dimension)
 *      Return:  0 if ok, 1 on error
 *
 *      Note side effects:
 *            (1) the matrix a is transformed to its inverse
 *            (2) the vector b is transformed to the solution X to the
 *                linear equation AX = B
 *
 *      Adapted from "Numerical Recipes in C, Second Edition", 1992
 *      pp. 36-41 (gauss-jordan elimination)
 */
#define  SWAP(a,b)   {temp = (a); (a) = (b); (b) = temp;}
int genImageProjective::gaussjordan(float  **a, float  *b, int n)
{
    int retValue = 0;
    int i, icol=0, irow=0, j, k, l, ll;
    int *indexc = NULL, *indexr = NULL, *ipiv = NULL;
    float  big, dum, pivinv, temp;

    if (!a)
    {
        retValue = -1; // ERROR_INT("a not defined", procName, 1);
        goto Terminate;
    }
    if (!b)
    {
        retValue = -2; // ERROR_INT("b not defined", procName, 1);
        goto Terminate;
    }

    if ((indexc = (int *)calloc(n, sizeof(int))) == NULL)
    {
        retValue = -3; // ERROR_INT("indexc not made", procName, 1);
        goto Terminate;
    }
    if ((indexr = (int *)calloc(n, sizeof(int))) == NULL)
    {
        retValue = -4; // ERROR_INT("indexr not made", procName, 1);
        goto Terminate;
    }
    if ((ipiv = (int *)calloc(n, sizeof(int))) == NULL)
    {
        retValue = -5; // ERROR_INT("ipiv not made", procName, 1);
        goto Terminate;
    }

    for (i = 0; i < n; i++)
    {
        big = 0.0;
        for (j = 0; j < n; j++)
        {
            if (ipiv[j] != 1)
            {
                for (k = 0; k < n; k++)
                {
                    if (ipiv[k] == 0)
                    {
                        if (fabs(a[j][k]) >= big)
                        {
                            big = fabs(a[j][k]);
                            irow = j;
                            icol = k;
                        }
                    }
                    else if (ipiv[k] > 1)
                    {
                        retValue = -6; // ERROR_INT("singular matrix", procName, 1);
                        goto Terminate;
                    }
                }
            }
        }
        ++(ipiv[icol]);

        if (irow != icol)
        {
            for (l = 0; l < n; l++)
                SWAP(a[irow][l], a[icol][l]);
            SWAP(b[irow], b[icol]);
        }

        indexr[i] = irow;
        indexc[i] = icol;
        if (a[icol][icol] == 0.0)
        {
            retValue = -7; // ERROR_INT("singular matrix", procName, 1);
            goto Terminate;
        }
        pivinv = 1.0 / a[icol][icol];
        a[icol][icol] = 1.0;
        for (l = 0; l < n; l++)
            a[icol][l] *= pivinv;
        b[icol] *= pivinv;

        for (ll = 0; ll < n; ll++)
        {
            if (ll != icol)
            {
                dum = a[ll][icol];
                a[ll][icol] = 0.0;
                for (l = 0; l < n; l++)
                    a[ll][l] -= a[icol][l] * dum;
                b[ll] -= b[icol] * dum;
            }
        }
    }

    for (l = n - 1; l >= 0; l--)
    {
        if (indexr[l] != indexc[l])
        {
            for (k = 0; k < n; k++)
                SWAP(a[k][indexr[l]], a[k][indexc[l]]);
        }
    }

Terminate:
    if (indexr)
        free(indexr);
    if (indexc)
        free(indexc);
    if (ipiv)
        free(ipiv);
    return retValue;
}


// --------------------------------------------------------------
// Map a source point to destination using projective transform
// --------------------------------------------------------------
// Params:
//  sourcePoint: initial point
//  destPoint:   transformed point
// RetValue: 0: Success, !=0: Error
// --------------------------------------------------------------
//  Notes:
//   1. You must call once computeCoeefficients() to compute
//      the this->vc[] vector of 8 coefficients, before you call
//      mapSourceToDestPoint().
//   2. If there was an error or the 8 coefficients were not computed,
//      a -1 is returned and destPoint is just set to sourcePoint value.
// --------------------------------------------------------------
int genImageProjective::mapSourceToDestPoint(QPointF& sourcePoint, QPointF& destPoint)
{
    if (coefficientsComputed)
    {
        float factor = 1.0f / (vc[6] * sourcePoint.x() + vc[7] * sourcePoint.y() + 1.);
        destPoint.setX( factor * (vc[0] * sourcePoint.x() + vc[1] * sourcePoint.y() + vc[2]) );
        destPoint.setY( factor * (vc[3] * sourcePoint.x() + vc[4] * sourcePoint.y() + vc[5]) );
        return 0;
    }
    else // There was an error while computing coefficients
    {
        destPoint = sourcePoint; // just copy the source to destination...
        return -1;               // ...and return an error
    }
}
//========================================

Während mein Google-Fu hat es versäumt, jeden rock solid mathematische Lösung zu produzieren, vielleicht diese Zeichnung, die ich gefunden ein wenig helfen könnte.
http://studiochalkboard.evansville.edu/lp-diminish.html
Ich denke, es könnte eigentlich ziemlich schwierig sein, mit der richtigen Mathematik zu kommen auf eigener Faust, es ist wahrscheinlich eine Art von logarithmisch oder Summen Ausdruck. Hoffentlich wird die Zeichnung und Begriffe zu diesem Link könnte etwas mehr durchsuchbar für Sie.

Mit Bretons Unterteilungsverfahren (die Mongo-Extension-Methode verwandt ist), werden Sie genau beliebige Potenz von zwei Divisionen bekommen. Aufzuspalten in nicht-Power-of-zwei Divisionen, diese Methoden werden Sie unterteilen müssen, um Abstand Unterpixel, die rechenintensiv sein kann.

Aber ich glaube, Sie in der Lage sein können, eine Variation von

Die eleganteste und schnellste Lösung wäre, die Homografie Matrix zu finden, das Rechteck Foto Koordinaten abbildet Koordinaten.

Mit einer anständigen Matrix Bibliothek sollte es nicht eine schwierige Aufgabe sein, so lange wie Sie Ihre mathematischen kennen.

Stichwort: Collineation, Homografie, direkte lineare Transformation

Allerdings sollte der rekursiven Algorithmus oben arbeiten, aber wahrscheinlich, wenn Ihre Ressourcen begrenzt sind, projektive Geometrie ist der einzige Weg zu gehen.

Im speziellen Fall , wenn Sie Seiten schauen senkrecht zu 1 und 3, können Sie diese Seiten in gleiche Teile teilen. zeichnet dann eine diagonal, und ziehen Parallelen zu der Seite 1 durch jeden Schnittpunkt der Diagonalen und die Trennlinien gezogen früher.

Diese

eine geometrische Lösung, die ich durchdacht. Ich weiß nicht, ob der ‚Algorithmus‘ einen Namen hat.

Angenommen, Sie durch Division des ‚Rechteck‘ in n Stücke mit vertikalen Linien beginnen soll zuerst.

Das Ziel ist es, Punkte P1..Pn-1 in der oberen Zeile zu platzieren, die wir verwenden können Linien, die durch sie in die Punkte zu ziehen, wo die linke und die rechte Linie treffen oder parallel zu ihnen, wenn eine solche Stelle nicht existiert.

Wenn die obere und die untere Linie zueinander parallel sind nur thoose Punkte stellen die obere Linie zwischen den Ecken aufgeteilt in gleichen Abständen.

Else Ort n Punkte Q1..Qn auf der linken Linie, so dass theese und die linke obere Ecke ist gleich weit entfernt und i Qi ist näher an den oberen linken cornern als Qj. Um die Q-Punkte auf der oberen Zeile finden die Kreuzung S der Linie von Qn durch die obere rechte Ecke und die parallel zu der linken Linie durch den Schnittpunkt der oberen und unteren Zeile abzubilden. Nun verbinden S mit Q1..Qn-1. Der Schnittpunkt der neuen Linien mit der obersten Zeile sind die gewünschten P-Punkte.

Führen Sie diese analog für die horizontalen Linien.

eine Rotation um die y-Achse gegeben, insbesondere, wenn Rotationsflächen eben sind, ist die Perspektive, die durch vertikale Gradienten erzeugt. Diese kommen zunehmend näher in Sicht. Statt dessen Diagonalen mit vier Rechtecke zu definieren, die bestimmten Zweierpotenzen arbeiten können ... definieren zwei Rechtecke, links und rechts. Sie werden höher als breit, schließlich, wenn man die Oberfläche in schmalere vertikale Segmente zu unterteilen weiter. Dies kann Oberflächen aufnehmen, die nicht quadratisch sind. Wenn eine Drehung um die x-Achse ist, dann sind horizontale Gradienten benötigt.

Das Problem ist, dass es die Transformation von 3D auf 2D ist das bei Ihnen zu bekommen.

Hier 'sa Anleitung, wie man es fertig ist.

Was Sie tun müssen, ist vertreten es in 3D (Welt) und dann auf 2D-Projekt nach unten (Bildschirm).

Dies erfordert, dass Sie eine 4D-Transformations-Matrix zu verwenden, die den Vorsprung an einem 4D tut homogen bis zu einem 3D-homogenen Vektor, die Sie dann zu einem 2D-Screen-Space-Vektor konvertieren nach unten können.

Ich kann es nicht in Google finden entweder, aber ein gutes Computergrafik Bücher werden die Details haben.

Schlüsselwörter sind Projektionsmatrix, Projektions-Transformation, affine Transformation, homogener Vektor, Weltraum, Platz auf dem Bildschirm, perspektivische Transformation, 3D-Transformation

Und übrigens, dies dauert in der Regel ein paar Vorlesungen all das zu erklären. So viel Glück.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top