Fenster in Weltkoordinaten umwandeln



  • @Headhunter: Vorschlag, poste dein Code noch hier her und verschieb das Teil mal in die FAQ, oder isses das nich wert?



  • da braucht er nicht den ganzen code posten, dass sample ist beim sdk dabei und zwar hier:

    (SDK root)\Samples\Multimedia\Direct3D\Pick
    🙂



  • Öh, wieso redet hier jeder von der DXSDK ?

    Das ganze in OpenGL also bitte keine DX8 Funktionen posten



  • 🙄
    hab ich garnicht mitgekriegt, wiedermal zu faul alles zu lesen...
    naja, aber für die faq kanns ja nicht schaden...



  • Ich habs auch so verstanden als hätte er 'nen anderen Source (für OpenGL tausglich). Ausserdem wäre ein Sprachen und Api unabhängiger Ansatz nicht sowieso wertvoller, zumindest für die FAQ?

    Bye, TGGC

    [ Dieser Beitrag wurde am 21.07.2002 um 20:09 Uhr von TGGC editiert. ]



  • Hi !

    Ich hab wirklich ne vollkommen Apiunabhängige
    klasse dafür (eigene Matrix, Vektoren, BBox ... Klasse,
    kein Zugriff auf D3D benötigt)

    Leider habe ich im moment damit ein kleines Problem :
    Es wird immer das Falsche ausgewählt, bzw es werden
    Objekte ausgewählt die eigentlich gar nicht in der BBox
    sind...
    Ich bin völlig ratlos, versuche aber das Problem zu beheben.
    Dann kann ich den Source hier gerne posten 🙂



  • Wenn das noch lange dauert ist der Thread weg, und wir haben wieder nix für die FAQ 😞

    Also fix!

    Bye, TGGC



  • Hi !

    Ok, ok, ich hab mal geguckt was der Fehler sein kann...
    Leider bin ich _absolut_ ratlos wo das Problem ist...

    Folgende Probleme :

    D3DXMATRIX matrix;
    GetRenderState (D3DRS_WORLD/D3DRS_VIEW/D3DRS_PROJECTION, &matrix);

    Klappt NICHT !! Jedes mal bekomme ich D3DERR_INVALIDCALL zurück.
    Der Fehler tritt aber nur in meiner Rayklasse auf, die auf meine
    D3D Klassezugreift.

    Ich kann mal gucken, ich hab glaubich noch ein älteres
    Sample dazu, allerdings ohne meine eigene Matrixklasse...



  • Original erstellt von Headhunter:
    **Hi !

    Ok, ok, ich hab mal geguckt was der Fehler sein kann...
    Leider bin ich _absolut_ ratlos wo das Problem ist...

    Folgende Probleme :

    D3DXMATRIX matrix;
    GetRenderState (D3DRS_WORLD/D3DRS_VIEW/D3DRS_PROJECTION, &matrix);

    Klappt NICHT !! Jedes mal bekomme ich D3DERR_INVALIDCALL zurück.
    Der Fehler tritt aber nur in meiner Rayklasse auf, die auf meine
    D3D Klassezugreift.

    Ich kann mal gucken, ich hab glaubich noch ein älteres
    Sample dazu, allerdings ohne meine eigene Matrixklasse...**

    Merk dir doch einfach die Matrizen, wenn du sie setzt?! Bei Gelegenheit schau ich auch nochmal in die SDK Doku dazu...

    Bye, TGGC



  • Hi !

    Hier ist der Code meiner Rayclass, mit zusätzlichen Comments...
    Bei Fragen könnt ihr hier posten / mir mailen
    Der Code stammt wie gesagt aus meiner alten Engine,
    OHNE meine Matrixklasse, d.h. ich greife auf ein
    paar D3DX Funktionen zu, sollte aber kein Problem sein
    die durch andere zu ersetzen...

    Ich hoffe das Forum kann so lange Posts darstellen 🙂

    (Hehe, wenn ich euch ärgen will würd ich jetzt Syntaxcoloring
    ausscalten *gg*)

    ---------------------------------------------------------------------------
    //smartbbox.h
    class CSmartBBox
    {
        CSmartVector min, max;
    };
    ---------------------------------------------------------------------------
    //smartplane.h
    class CSmartPlane
    {
    public :
        CSmartVector    n;
        float           d;
    };
    ---------------------------------------------------------------------------
    #include "smartplane.h"
    #include "smartbbox.h"
    #include "smartvector.h"
    #include "smartinput.h"
    #include "smartd3d.h"
    //smartray.h
    class CSmartRay
    {
    public :
    
        //hiermit wird die Rayklasse m.h. der Mauskoordinaten erstellt.
        //d.h. man hat dann einen Strahl den man für Intersection tests verwenden
        //kann ("auf etwas in der 3D scene klicken")
        void FillFromMouse ();
    
        //naja, checkt ob der Ray ein triangle trifft,
        //v MUSS ein array der größe 3 sein (CSmartVector* v = new CSmartVector[3];)
        //in "t" kommt die Entfernung m_start->Punkt auf dem Triangle wo der Ray "reintraf"
        BOOL IntersectTriangle (CSmartVector* v,float& t) const;    
    
        //hiermit kann man testen ob der Ray eine Boundingbox schneidet.
        //wenn ja wird TRUE returned, in "in" kommt die Distanz m_start->Intersection point,
        //in "out" kommt die Distanz von m_start->Punkt wo der Ray AUS der Box kommt
        BOOL IntersectBoundingBox (CSmartBBox&b, float& in, float& out) const;  
    
        //intersection von dem Ray und ner Ebene, ist nüztlich für Collision detection
        BOOL IntersectPlane (const CSmartPlane& p) const;   
    
        //das hier ist der Startpunkt des Rays in Weltkoordinaten
        //CSmartVector ist ne Vektorklasse (*echt* ??)
        CSmartVector            m_start;
        //das ist die Richtung in die der Ray "zeigt". Dieser Vektor
        //ist normalisiert
        CSmartVector            m_dir;
    };
    ---------------------------------------------------------------------------
    //smartray.cpp
    BOOL CSmartRay::FillFromMouse ()
    {
        //in rx und ry kommt die Auflösung bzw die Größe des Fensters
        //GetResolution ermittelt die Werte indem es einfach die 
        //breite und höhe des Backbuffer returned
        int rx,ry;
        g_smartD3D.GetResolution (rx,ry);
        //nun holen wir uns die Projection matrix von D3D
        //in meiner neuen Engine gibts hier einen Fehler : D3DERR_INVALIDCALL,
        //hier klappt es aber einwandfrei
        D3DXMATRIX matProj;
        g_smartD3D.GetD3DDevice()->GetTransform (D3DTS_PROJECTION, &matProj);
    
        //nun wandeln wir die Mausposition (von DirectInput in diesem Fall)
        //in einen 3D Punkt um
        CSmartVector v;
        v.x =  (((2.0f * g_smartInput.m_x) / rx) - 1.0f) / matProj._11;
        v.y = -(((2.0f * g_smartInput.m_y) / ry) - 1.0f) / matProj._22;
        v.z =  1.0f;
    
        //hier holen wir uns die Viewmatrix und invertieren sie
        D3DXMATRIX matView, m;
        g_smartD3D.GetD3DDevice()->GetTransform (D3DTS_VIEW, &matView);
        D3DXMatrixInverse (&m, NULL, &matView);
    
        //jetzt wird die Raydirection m.h. der invertierten Viewmatrix 
        //ermittelt.
        m_dir.x  = v.x*m._11 + v.y*m._21 + v.z*m._31;
        m_dir.y  = v.x*m._12 + v.y*m._22 + v.z*m._32;
        m_dir.z  = v.x*m._13 + v.y*m._23 + v.z*m._33;
        //und die Startposition gesetzt
        m_start.x = m._41;
        m_start.y = m._42;
        m_start.z = m._43;
        m_dir.Normalize ();
    }
    ---------------------------------------------------------------------------
    BOOL CSmartRay::IntersectBBox (CSmartBBox&b, float& enter, float& leave)
    {
        //der Algorithmus den ich hier verwende heißt "Kay and Kayjia "slab" method"
        //komischer Name :-)
        //ich hab hier keine Comments zu der Funktion, da ich durch die Mathe 
        //nicht ganz durchblicke...
    
        float tnear = -99999.0f;
        float tfar =   99999.0f;
        for (int i=0; i<3; i++)
        {
            //ich habe bei meinen Vektoren den operator [] überladen
            //Bsp :
            //CSmartVector v;
            //v[0] = 2; // v.x = 3;
            //v[1] = 3; // v.y = 2;
            //v[2] = 0; // v.z = 0;
            float origin = m_start[i];
            float direction = m_dir[i];
            float mmin = b.min[i];
            float mmax = b.max[i];
    
            if (direction)
            {
                direction = 1.0f / direction;
                float t1 = (mmin - origin) * direction;
                float t2 = (mmax - origin) * direction;
    
                if (t1 > t2)
                {
                    if (t2 > tnear) tnear = t2;
                    if (t1 < tfar) tfar = t1;
                }
                else
                {
                    if (t1 > tnear) tnear = t1;
                    if (t2 < tfar) tfar = t2;
                }
    
                //keine intersection
                if (tnear > tfar || tfar < 0.0f)
                    return FALSE;
            }
            else
            {
                //wieder keine Intersection
                if (rigin < mmin || origin > mmax)
                    return FALSE;
            }
        }
    
        //Werte speichern
        enter = tnear;
        leave = tfar;
    
        //ray hits box
        return TRUE;
    }
    ---------------------------------------------------------------------------
    BOOL CSmartRay::IntersectTriangle (CSmartVector* vv,float& t)
    {
        //diese Methode wurde von Möller entwickelt (k.a. wie der mit
        //Vornamen heißt, er ist auf jeden Fall der größte Theoretiker
        //was Mathematik usw bei Games angeht, Einfach mal was googlen...
        //der Code stammt btw aus dem DX8 SDK, wo er super implementiert wurde !
    
        //keinen NULLPointer annehmen !
        assert (vv != NULL);
    
        float u,v;
        //die Eckvectoren des Triangles finden
        CSmartVector edge1 = vv[1]- vv[0];
        CSmartVector edge2 = vv[2]- vv[0];
    
        //determinant berechnen, wird auch für U (texturkoordinate) verwendet
        CSmartVector pvec;
        pvec=CrossProduct(m_dir, edge2);
        //wenn der determinant fast 0 ist, ist der Ray paralell zum Triangle (=> keine Intersection)
        float det = DotProduct(edge1, pvec);
        if (det < 0.0001f)
            return FALSE;
    
        //distanz von vv[0] zu m_start berechnen
        CSmartVector tvec = m_start - vv[0];
    
        //berechnen U, und check ob der Ray überhaupt treffen kann
        u = DotProduct(tvec,pvec);
        if (u < 0.0f || u > det)
            return FALSE;
    
        //gleich berechnen wir V (texturkoordinate)
        CSmartVector qvec;
        qvec=CrossProduct(tvec, edge1);
    
        //so ähnlich wie ein paar Zeilen oben :-)
        v = DotProduct(m_dir, qvec);
        if (v < 0.0f || u + v > det)
            return FALSE;
    
        //distanz berechnen
        t = DotProduct(edge2, qvec);
        float fInvDet = 1.0f / det;
        t *= fInvDet;
    
        //juhu ! intersection
        return TRUE;
    }
    ---------------------------------------------------------------------------
    BOOL CSmartRay::IntersectPlane (const CSmartPlane& p) const
    {
        //diesmal ziemlich kurz, he ?
        float dista = m_start.Length ();
        float distb = (m_start + m_dir).GetLength();
        if ((dista > 0.0f)&&(distb < 0.0f)) return TRUE;
        if ((dista < 0.0f)&&(distb > 0.0f)) return TRUE;
        return FALSE;
    }
    ---------------------------------------------------------------------------
    

Anmelden zum Antworten