Pfeil eines Vektors in die richtige Richtung drehen, aber wie?



  • Vielleicht schreib ich nachher schnell was. Aber jetzt muss ich erstmal Late Knights schaun ;P



  • okay, vieln dank, ich wär dir echt sehr verbunden, weil von dieser arbeit ne menge abhängt und ich sowieso schon unter zeit druck stehe... Danke

    Gruß Tobi.



  • So, hab jetzt mal schnell was zusammengehackt. Der Code ist DirectX, aber das Prinzip sollte erkennbar sein.

    // init
    Vertex line[2]; // Die Linie aus 2 Vertices. line[0] ist Startpunkt
    
    line[1].x = 1;  // Beispielhaft ein Vektor mit Endpunkt (1,2,1)
    line[1].y = 2;
    line[1].z = 1;
    line[1].color = D3DCOLOR_XRGB(0, 255, 0);
    
    // Zylinder erzeugen (= Pfeilspitze)
    D3DXCreateCylinder(d3d9Device, 0.001, 0.1f, 0.5f, 10, 10, &mesh, NULL);
    
    // Der Render-Code:
    float zAngle, yAngle; // die 2 erwähnten Drehwinkel um die z bzw. y-Achse
    D3DXVECTOR3 yAxis(0, 1, 0), xAxis(1, 0, 0);
    
    D3DXVECTOR3 v, vProjOnXZplane;
    v.x = line[1].x;
    v.y = line[1].y;
    v.z = line[1].z;
    
    vProjOnXZplane.x = v.x;
    vProjOnXZplane.y = 0;
    vProjOnXZplane.z = v.z;
    
    D3DXVec3Normalize(&v, &v);
    D3DXVec3Normalize(&vProjOnXZplane, &vProjOnXZplane);
    
    zAngle = acos(D3DXVec3Dot(&yAxis, &v));
    yAngle = acos(D3DXVec3Dot(&xAxis, &vProjOnXZplane));
    if(v.z < 0)     // cos(alpha) = cos(-alpha). wenn yAngle z.B. 45° schauen wir
       yAngle*=-1;  // deshalb einfach, ob der Punkt vor oder hinter der xy-Ebene  liegt
    
    D3DXMATRIX transform, trans, rotX, rotY, rotZ, trans2;
    // trans und rotX kannst du ignorieren (DX spezifisch. Dient nur dazu den Zylinder so auszurichten, dass er im Ursprung steht und nach oben zeigt)
    D3DXMatrixTranslation(&trans, 0, 0, -0.25f); 
    D3DXMatrixRotationX(&rotX, D3DX_PI * 0.5f);  
    
    D3DXMatrixRotationZ(&rotZ, -zAngle);
    D3DXMatrixRotationY(&rotY, -yAngle);
    D3DXMatrixTranslation(&trans2, line[1].x, line[1].y, line[1].z);
    
    // Diese Zeile ist die ganze Quintessenz (trans und rotX wieder ignorieren!)
    // Du rotierst erst um Z, dann um Y und anschließend verschiebst du die Pfeilspitze an die Spitze des Vektors
    transform = trans * rotX * rotZ * rotY * trans2;
    
    // Zeichne Vektor
    D3DXMatrixIdentity(&world);
    d3d9Device->SetTransform(D3DTS_WORLD, &world);
    d3d9Device->DrawPrimitiveUP(D3DPT_LINELIST, 1, line, sizeof(Vertex));
    
    // Zeichne Pfeilspitze
    d3d9Device->SetTransform(D3DTS_WORLD, &transform);	
    mesh->DrawSubset(0);
    

    Hier nen kleiner Screenshot wie das ganze dann aussieht: http://www.infoboard.org/screenshots/pfeil.PNG



  • Jo danke, auch wenn ich nichts mit den DX funktionen anfang kann ist mir vorhin dank ich schon der fehler bei mir auf gefallen, denn ich wollts ja eigentlich so machen:

    Y
            ^   
            |  / <--- Vektor
            |./
           /|/.
      ------+------>X
           \|/
            | \
            |  \
                Winkel Alpha1 
    
            |  / <--- Vektor
            |./
           /|/.
      ------+------>X
           \|/
            | \
            |  \
            v   Winkel Alpha2
            Z
    

    wollte die beiden Winkel mit dem Anstieg ausrechnen also:

    Y2 - Y1
    m1 = ------- ==> m1 = tan( alpha ) ==> alpha1 = atan( m1 )
         X2 - X2
    
         Y2 - Y1
    m2 = ------- ==> m2 = tan( alpha ) ==> alpha2 = atan( m2 )
         X2 - X2
    

    was ich aber vergessen hatte war das Bogenmaß in Gradmaß umzurechnen

    Gradmaß = ( Bogenmaß * 180 )
              ------------------
                      PI
    

    also ich werds noch mal versuchen und hoffen das es jetzt klappt, danke euch erst mal allen.

    Gruß Tobi



  • hmm wieso nimmst du den acos? dachte man macht das mit tan?
    und wie arbeiten die funktionen hier?
    zAngle = acos(D3DXVec3Dot(&yAxis, &v));
    yAngle = acos(D3DXVec3Dot(&xAxis, &vProjOnXZplane));



  • Das Skalarprodukt heißt auf englisch Dot product.



  • hm ok und wie errechne ich das in opengl, hab ich da auch so funktionen mit den ich das machen kann?



  • T0bi schrieb:

    hm ok und wie errechne ich das in opengl, hab ich da auch so funktionen mit den ich das machen kann?

    Er hat dir den Wikipedialink doch gegeben. Ein Epsilon Eigeninitiative waere toll 🙄

    Das Skalarprodukt 2er Vektoren (a, b, c) und (x, y, z) ist ganz einafch a*x + b*y + c*z



  • gibts das auch für nen 13Klässler auf deutsch?
    wir hatten noch keine matrizen ect.

    Darf ich mal fragen, was das fuer eine Schule ist?



  • heißt das dann das die jeweils in der ebene liegende ache Null ist?



  • T0bi schrieb:

    heißt das dann das die jeweils in der ebene liegende ache Null ist?

    ???

    Hast du den Wiki Artikel überhaupt gelesen?
    Gleich die 1. Formel sagt alles:
    Das dot product dot(v,u) zweier Vektoren ist gleich die Länge der Vektoren multipliziert mit dem Kosinus des Zwischenwinkels von v und u:
    dot(v, u) = |v| * |u| * cos(v, u)

    Wenn v und u Einheitsvektoren sind, dann ist folglich der arccos vom Skalarprodukt (dot product) gleich dem Zwischenwinkel der Vektoren.

    Ernst gemeinter Rat: Wenn du was mit 3D-Programmierung machen willst, brauchst du einfach entsprechende Mathekenntnisse in LinAlg, Trigonometrie etc. Da du da noch große Lücken hast, solltest du erstmal da anfangen.



  • wie gesagt das bekomm ich erst im naechstem semester:

    aber etwas hab ich es glaube verstanden. ich muss 2mal das skalarprodukt errechnen

    einmal um den zylinder um die zAchse zu drehen

    y
    ^
    |   /<--- Vektor a
    |  /
    | /\
    |/a \<---------Windkel für glRotatef( a, 0.0f, 0.0f, 1.0f )
    +--------->x
    

    und einmal um den zylinder um die yAchse zu drehen

    x
    ^
    |   /<--- Vektor a
    |  /
    | /\
    |/b \<---------Windkel für glRotatef( b, 0.0f, 1.0f, 0.0f )
    +--------->z
    

    dabei ist beim winkel a, ist der eine vektor der den ich zeichnen lasse und der andere ist die xAchse( mit ( 1 / 0 / 0 ) ), oder?

    und beim winkel b, ist der eine vektor der den ich zeichnen lasse und der andere ist die zAchse( mit ( 0 / 0 / 1 ) ), oder?

    hab ich das jetzt einiger maßen richtig erkannt?



  • T0bi schrieb:

    aber etwas hab ich es glaube verstanden. ich muss 2mal das skalarprodukt errechnen

    einmal um den zylinder um die zAchse zu drehen
    und einmal um den zylinder um die yAchse zu drehen

    Ja

    T0bi schrieb:

    dabei ist beim winkel a, ist der eine vektor der den ich zeichnen lasse und der andere ist die xAchse( mit ( 1 / 0 / 0 ) ), oder?

    Ich habe v und die y-Achse genommen. Du kannst aber auch die x-Achse nehmen.

    und beim winkel b, ist der eine vektor der den ich zeichnen lasse und der andere ist die zAchse( mit ( 0 / 0 / 1 ) ), oder?

    Für den 2. Winkel habe ich (wie man im Code sieht) die x-Achse genommen. Allerdings kann man es auch mit der z-Achse machen.

    Wichtig ist halt einfach nur, dass du die 2 Winkel zur Orientierung errechnest. Das hier sollte eigentlich letzte Unklarheiten beseitigen: http://de.wikipedia.org/wiki/Kugelkoordinaten



  • okay danke erste mal, ich werds mal alles probieren und wenns net gehts frag ich noch mal 😉

    Gruß Tobi.



  • // ***** draw peak *****
        // ***** vector *****
        vec[ 0 ] = xPos2 - xPos1; // x
        vec[ 1 ] = yPos2 - yPos1; // y
        vec[ 2 ] = zPos2 - zPos1; // z
    
        // ***** xAxis *****
        vX[ 0 ] = 1.0f; // x
        vX[ 1 ] = 0.0f; // y
        vX[ 2 ] = 0.0f; // z
    
        // ***** zAxis *****
        vZ[ 0 ] = 0.0f; // x
        vZ[ 1 ] = 0.0f; // y
        vZ[ 2 ] = 1.0f; // z
    
        fa = (float)( ( ( vec[ 0 ] * vX[ 0 ] ) + ( vec[ 1 ] * vX[ 1 ] ) + ( vec[ 2 ] * vX[ 2 ] ) ) );
    
        fa /= ( sqrt( ( vec[ 0 ] * vec[ 0 ] ) + ( vec[ 1 ] * vec[ 1 ] ) + ( vec[ 2 ] * vec[ 2 ] ) ) *
                sqrt( ( vX[ 0 ] * vX[ 0 ] ) + ( vX[ 1 ] * vX[ 1 ] ) + ( vX[ 2 ] * vX[ 2 ] ) ) );
    
        fa = acos( fa );
        fa = ( fa * 180 ) / PI;
    
        fb = (float)( ( ( vec[ 0 ] * vZ[ 0 ] ) + ( vec[ 1 ] * vZ[ 1 ] ) + ( vec[ 2 ] * vZ[ 2 ] ) ) );
    
        fb /= ( sqrt( ( vec[ 0 ] * vec[ 0 ] ) + ( vec[ 1 ] * vec[ 1 ] ) + ( vec[ 2 ] * vec[ 2 ] ) ) *
                sqrt( ( vZ[ 0 ] * vZ[ 0 ] ) + ( vZ[ 1 ] * vZ[ 1 ] ) + ( vZ[ 2 ] * vZ[ 2 ] ) ) );
    
        fb = acos( fb );
        fb = ( fb * 180 ) / PI;
    
        glPushMatrix( );
    
            glRotatef( fb, 0.0f, 0.0f, 1.0f ); // rotate z
            glRotatef( fa, 0.0f, 1.0f, 0.0f ); // rotate y
            glTranslatef( -xPos2, -yPos2, zPos2 );
            gluCylinder( obj, ( froom * 0.04f ), 0, ( froom / 5 ), 30, 30 );
        glPopMatrix( );
    

    sooo? aber irgendwie ist die spitze jetzt immer wo anderes.



  • hallo?



  • Hi



  • Wenn du es verstehen möchtest, führt kein Weg an einem Matrizen/Vektor-Tutorial vorbei.
    Was nutzt dir fertiger Code, wenn du es danach immer noch nicht kapiert hast.
    http://cybersound.cy.funpic.de/tutorial-gfx-game/3d-mathematik.php
    Hier, das is recht gut geschrieben 🙂
    rya.



  • hm.. aber ich wollte doch nur wissen ob meine formel da richtig ist. ich habe mir noch mal zum verglich um einige Fälle durch zu spielen einekleine Konsolenanwendung gebastelt, mit der ich die Drehwinkel um beide Achsen ermitteln wollte.
    Hier das Miniprog:

    #include <iostream>
    #include <math.h>
        using namespace std;
    
    #define PI 3.1415926535897932384626433832795
    typedef struct DOT {
    
        float x;
        float y;
        float z;
    
    } Skalar;
    
    int main( int argc, char* argv[] ) {
    
        // ***** Rotation angels *****
        float fAngelOne = 0.0f;
        float fAngelTwo = 0.0f;
    
        // ***** Vectors *****
    
        Skalar sVector, sX, sZ;
        // ***** MyVector *****
        sVector.x = 1.0f;
        sVector.y = 0.0f;
        sVector.z = 0.0f;
    
        // ***** yAxis *****
        sX.x = 1.0f;
        sX.y = 0.0f;
        sX.z = 0.0f;
    
        // ***** xAxis *****
        sZ.x = 0.0f;
        sZ.y = 0.0f;
        sZ.z = 1.0f;
    
        // ***** Calculation *****
    
        // ***** for z rotation *****
        fAngelOne = ( ( sVector.x * sX.x ) + ( sVector.y * sX.y ) + ( sVector.z * sX.z ) ) /
                    ( ( sqrt( ( ( sVector.x * sVector.x ) + ( sVector.y * sVector.y ) + ( sVector.z * sVector.z ) ) ) *
                      ( sqrt( ( ( sX.x * sX.x ) + ( sX.y * sX.y ) + ( sX.z * sX.z ) ) ) ) ) );
    
        fAngelOne = acos( fAngelOne );
        fAngelOne = ( fAngelOne * 180.0f ) / PI;
    
        // ***** for y rotation *****
        fAngelTwo = ( ( sVector.x * sZ.x ) + ( sVector.y * sZ.y ) + ( sVector.z * sZ.z ) ) /
                    ( ( sqrt( ( ( sVector.x * sVector.x ) + ( sVector.y * sVector.y ) + ( sVector.z * sVector.z ) ) ) *
                      ( sqrt( ( ( sZ.x * sZ.x ) + ( sZ.y * sZ.y ) + ( sZ.z * sZ.z ) ) ) ) ) );
    
        fAngelTwo = acos( fAngelTwo );
        fAngelTwo = ( fAngelTwo * 180.0f ) / PI;
    
        cout << "\n 1. Angel :  " << fAngelOne << "   ( rotation angel for yAxis! )" << endl;
        cout << "\n 2. Angel :  " << fAngelTwo << "   ( rotation angel for zAxis! )" << endl;
        getchar( );
        return 0;
    }
    

    Diese Formel klappt eigentlich ganz gut solange x = Null ist, ist x aber != 0 dann wird die Pfeilspitze wieder krum. Beispiel
    1/1/0
    für zRotation wird der Winkel 90° und für die yRotation 45°. Das kann aber nicht stimmen. eigentlich müsste doch alles genau anders rum sein. wieso ist das aber nicht so?

    Oder muss ich noch den Vektor normalisieren?

    Gruß Tobi.



  • so gehts! wer einwende hat soll hier schrein...

    const double PI = 3.141592;
        GLUquadricObj *obj;
        typedef struct DOT {
    
            float x;
            float y;
            float z;
    
        } Skalar;
    
        Skalar sVector, sX, sZ;
    
        // ***** length of vector *****
        float fLength = 0.0f;
    
        // ***** Rotation angels *****
        float fAngelOne = 0.0f;
        float fAngelTwo = 0.0f;
    
        obj = gluNewQuadric( );
        gluQuadricNormals( obj, GL_SMOOTH );
        glLineWidth( 2.0f );
    
        glBegin( GL_LINES );
    
            // ***** start from O *****
            glVertex3f( -xPos1, -yPos1, zPos1 );
    
            // ***** to x/y/z *****
            glVertex3f( -xPos2, -yPos2, zPos2 );
        glEnd( );
    
        // ***** draw peak *****
        // ***** MyVector *****
        sVector.x = xPos2 - xPos1;
        sVector.y = yPos2 - yPos1;
        sVector.z = zPos2 - zPos1;
    
        // ***** xAxis *****
        if( yPos2 <= 0.0f ) {
    
            sX.x = -1.0f;
        }
        else {
    
            sX.x =  1.0f;
        }
        sX.y =  0.0f;
        sX.z =  0.0f;
    
        // ***** zAxis *****
        sZ.x = 0.0f;
        sZ.y = 0.0f;
        sZ.z = 1.0f;
    
        // ***** Calculation *****
    
        // ***** normal. vector *****
        fLength = sqrt( ( sVector.x * sVector.x ) + ( sVector.z * sVector.z ) + ( sVector.z * sVector.z ) );
    
        if( fLength != 0.0f ) {
    
            sVector.x /= fLength;
            sVector.y /= fLength;
            sVector.z /= fLength;
        }
        // ***** for z rotation *****
        fAngelOne = ( ( sVector.x * sX.x ) + ( sVector.y * sX.y ) + ( sVector.z * sX.z ) ) /
                    ( ( sqrt( ( ( sVector.x * sVector.x ) + ( sVector.y * sVector.y ) + ( sVector.z * sVector.z ) ) ) *
                      ( sqrt( ( ( sX.x * sX.x ) + ( sX.y * sX.y ) + ( sX.z * sX.z ) ) ) ) ) );
    
        fAngelOne = acos( fAngelOne );
        fAngelOne = ( fAngelOne * 180.0f ) / PI;
    
        // ***** for y rotation *****
        fAngelTwo = ( ( sVector.x * sZ.x ) + ( sVector.y * sZ.y ) + ( sVector.z * sZ.z ) ) /
                    ( ( sqrt( ( ( sVector.x * sVector.x ) + ( sVector.y * sVector.y ) + ( sVector.z * sVector.z ) ) ) *
                      ( sqrt( ( ( sZ.x * sZ.x ) + ( sZ.y * sZ.y ) + ( sZ.z * sZ.z ) ) ) ) ) );
    
        fAngelTwo = acos( fAngelTwo );
        fAngelTwo = ( fAngelTwo * 180.0f ) / PI;
    
        if( yPos2 > 0.0f ) {
    
            fAngelTwo *= -1;
        }
    
        glPushMatrix( );
            // ***** draw peak *****
            glTranslatef( -xPos2, -yPos2, zPos2 );
            glRotatef( fAngelOne, 0.0f, 0.0f, 1.0f ); // rotate z
            glRotatef( fAngelTwo, 0.0f, 1.0f, 0.0f ); // rotate y
    
            gluCylinder( obj, ( froom * 0.03f ), 0, ( froom / 10 ), 30, 30 );
        glPopMatrix( );
    

    dnake euch erst mal alle für eure hilfe und für die guzten tutorials.

    Gruß Tobi.


Anmelden zum Antworten