dırectx 10 pıckıng uygulaması
Transkript
dırectx 10 pıckıng uygulaması
KARADENĠZ TEKNĠK ÜNĠVERSĠTESĠ BĠLGĠSAYAR MÜHENDĠSLĠĞĠ BÖLÜMÜ BĠLGĠSAYAR GRAFĠKLERĠ LABORATUARI DIRECTX 10 PICKING UYGULAMASI 1.Giriş 3D cisimler ile kullanıcının etkileĢimine Bilgisayar Grafikleri uygulamalarında sıkça rastlanmaktadır. Örneğin günümüzdeki FPS (First Person Shooter) tarzı 3D oyunlarda, niĢan alınıp ateĢ edilen rakip oyuncunun vurulup vurulmadığına karar vermek için ona doğru bir ıĢın yollanır ve bu ıĢın ile rakip oyuncuyu temsil eden modeli oluĢturan üçgenler arasında kesiĢim testleri yapılır. Bu deneydeki benzeri uygulamada 3D ortamdaki cisimler mouse ile seçilmeye “picking” çalıĢılacaktır. 2. 3D Cisme Yollanacak Işının Üretilmesi ve Kesişim Testi Ekrandaki herhangi bir cismin seçilmesine, tıklanan noktadan 3D cismlere doğru ıĢın yollanarak baĢlanır. Ekranda tıklanan noktaya ait 2D koordinatlardan 3D ortamdaki cisimlerle kesiĢim testinde kullanılacak ıĢının üretilmesi için bir takım transformasyonlar gerekmektedir. Bilindiği gibi 3D ortamdaki herhangi bir noktanın ekran koordinatlarına dönüĢümü için sırasıyla World, View ve Projection matrisleri ile çarpılır. Dolayısıyla ekranda tıklanan 2D noktadan 3D ıĢını üretmek için matris çarpımlarının tersi yani ters matrisler ile iĢlemler yapmak gerekir. Çizim yapılacak pencerenin 800x600 çözünürlükte olduğu varsayıldığında bu pencerenin sol üst köĢesinin koordinatları (0,0) sağ alt köĢesinin de (799,599) olur. Bu koordinatlardan pencerenin merkezi (0,0) „dan sağa doğru +X, sola doğru –X; yukarı doğru +Y ve aĢağı doğru –Y olacak Ģekilde normalize edilmiĢ yani (-1,+1) arası değiĢen koordinatlara dönüĢüm yapan DirectX 10 kodu aĢağıdaki gibidir: D3DXVECTOR3 v; v.x = ( ( ( 2.0f * ptCursor.x ) / Width ) - 1 ) / pmatProj->_11; v.y = -( ( ( 2.0f * ptCursor.y ) / Height ) - 1 ) / pmatProj->_22; v.z = 1.0f; Burada ptCursor.x ekranda tıklanan noktanın (0,799) arası değiĢen x; ptCursor.y de (0,599) arası değiĢen y koordinatlarıdır. pmatProj de Projection matrisidir. ĠĢlemleri ters sırada yaptığımızdan Projection matrisi ile çarpmak yerine ona bölüyoruz. Yukarıdaki iĢlemler ıĢının üretilmesi için yeterli değildir. v vektörü ayrıca World ve View matrislerinin tersi ile de çarpılmalıdır: // Get the inverse view matrix const D3DXMATRIX matView = *g_Camera.GetViewMatrix(); const D3DXMATRIX matWorld = *g_Camera.GetWorldMatrix(); D3DXMATRIX mWorldView = matWorld * matView; D3DXMATRIX m; D3DXMatrixInverse( &m, NULL, &mWorldView ); // Transform the screen space vPickRayDir.x = v.x * m._11 + vPickRayDir.y = v.x * m._12 + vPickRayDir.z = v.x * m._13 + vPickRayOrig.x = m._41; vPickRayOrig.y = m._42; vPickRayOrig.z = m._43; pick ray into v.y * m._21 + v.y * m._22 + v.y * m._23 + 3D space v.z * m._31; v.z * m._32; v.z * m._33; Bu noktada 2D ekranda tıklanan noktaya 3D uzayda karĢılık gelen ıĢının baĢlangıç noktası vPickRayOrig ve doğrultusu vPickRayDir üretilmiĢtir. IĢın Ġzleme (Ray Tracing) yapılarak 3D ortamdaki cismin tam olarak hangi üçgenine tıklandığı belirlenmelidir. Bunun için 2 seçenek söz konusudur : 1. IĢın-Üçgen kesiĢim testi kodu yazmak, 2. DirectX‟in Intersect methodunu kullanmak. Web sayfasındaki kaynak kodda her iki seçenek de vardır. Intersect methodu kesiĢim testi sonucu kesiĢen üçgenlere olan uzaklık, üçgenlerin indisleri, (u,v) barisentrik koordinatlar gibi bilgiler döndürmektedir. Bu bilgilerden faydalanılarak hangi üçgene, hatta o üçgen üzerinde hangi koordinatlara tıklandığı hesaplanabilir. Yukarıdaki kod örnekleri kaynak koddaki Pick() methodundan alınmıĢtır. Pick() methodundaki if(GetCapture()) Ģartı sağlanıyorsa yani mouse ile ekranda bir noktaya tıklanmıĢ ve GetCapture() methodu ile ekran koordinatları alınmıĢsa yukarıdaki iĢlemler ile ıĢının baĢlangıç noktası vPickRayOrig ve doğrultusu vPickRayDir üretilebilir. Sonra if(g_bUseD3DXIntersect) Ģartı DirectX‟in Intersect methodunun kullanılıp kullanılmayacağına karar vermek içindir. Eğer o kullanılacaksa sonraki if(!g_bAllHits) Ģartı ile kesiĢen bütün üçgenler mi yoksa bunlardan en yakın olanına ait bilgiler mi alınacak ona karar verilir. if(g_bUseD3DXIntersect) Ģartı sağlanmıyorsa ıĢın-üçgen kesiĢim testi için gereken iĢlemler aĢağıdaki kod bloğunda verilmiĢtir: Burada dwNumFaces = g_Mesh.GetNumIndices(0)/3; ile g_Mesh isimli 3D modelin indisleri 3‟e bölünmüĢ ve üçgen sayısı olarak dwNumFaces „e atanmıĢtır. fBary1, fBary2 barisentrik koordinatları, fDist de üçgene olan t uzaklığını temsil etmektedir. for(DWORD i = 0; i < dwNumFaces; i++) ile bütün üçgenler için kesiĢim testleri yapılmaktadır. Döngüde öncelikle D3DXVECTOR3 v0 = pVertices[pIndices[3 * i + 0]].p; D3DXVECTOR3 v1 = pVertices[pIndices[3 * i + 1]].p; D3DXVECTOR3 v2 = pVertices[pIndices[3 * i + 2]].p; i değiĢkeni ile belirlenen üçgenin köĢe noktalarının koordinatları v0, v1 ve v2 „ye kopyalanmıĢtır. Sonra bizim yazdığımız IntersectTriangle methodu koĢularak kesiĢim varsa fBary1, fBary2 ve fDist değerleri hesaplanmıĢtır. Ayrıca g_bAllHits değiĢkeninin değerine bağlı olarak ya bütün üçgenler ya da en yakın üçgen için onun indisi ve fBary1, fBary2, fDist değerleri g_IntersectionArray[] dizisine eklenmiĢtir: DWORD dwNumFaces = (DWORD)g_Mesh.GetNumIndices(0)/3; FLOAT fBary1, fBary2; FLOAT fDist; for( DWORD i = 0; i < dwNumFaces; i++ ) { D3DXVECTOR3 v0 = pVertices[pIndices[3 * i + 0]].p; D3DXVECTOR3 v1 = pVertices[pIndices[3 * i + 1]].p; D3DXVECTOR3 v2 = pVertices[pIndices[3 * i + 2]].p; if( IntersectTriangle( vPickRayOrig, vPickRayDir, v0, v1, v2, &fDist, &fBary1, &fBary2 ) ) { if( g_bAllHits || g_nNumIntersections == 0 || fDist < g_IntersectionArray[0].fDist ) { if( !g_bAllHits ) g_nNumIntersections = 0; g_IntersectionArray[g_nNumIntersections].dwFace = i; g_IntersectionArray[g_nNumIntersections].fBary1 = fBary1; g_IntersectionArray[g_nNumIntersections].fBary2 = fBary2; g_IntersectionArray[g_nNumIntersections].fDist = fDist; g_nNumIntersections++; if( g_nNumIntersections == MAX_INTERSECTIONS ) break; } } } 3. Kesişen Üçgenlerin Çizilmesi KesiĢen üçgenlerin çizimi OnFrameRender() methodunda aĢağıdaki kod ile yapılır. Üçgenlerin köĢe noktaları g_pVB isimli vertex bufferda tutulmaktadır. KesiĢen üçgenlerin çizimi pd3dDevice->Draw( 3*g_nNumIntersections, 0 ) emri ile gerçekleĢtirildikten sonra g_pTechRenderSceneWireframe->GetPassByIndex(0)->Apply(0) ile modele ait diğer üçgenlerin çizim modu wireframe yapılmıĢtır. Böylece seçilen üçgen daha belirgin hale getirilmiĢtir. ġekil-1‟de programdan bir ekran görüntüsü verilmiĢtir. if( g_nNumIntersections > 0 ) { // Draw the picked triangle UINT Strides[1]; UINT Offsets[1]; Strides[0] = sizeof(D3DVERTEX); Offsets[0] = 0; pd3dDevice->IASetVertexBuffers(0, 1, &g_pVB, Strides, Offsets); pd3dDevice->IASetPrimitiveTopology( D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST ); pd3dDevice->Draw( 3*g_nNumIntersections, 0 ); // Set render mode to wireframe g_pTechRenderSceneWireframe->GetPassByIndex( 0 )->Apply( 0 ); } Şekil-1: DirectX 10 Picking Uygulaması 4. Deneye Hazırlık KesiĢim testinin döndürdüğü fDist uzaklık değerini kullanarak üçgen üzerindeki intersectionPoint_t koordinatını hesaplayınız. Ayrıca fBary1, fBary2 barisentrik koordinatları da kullanarak yine üçgen üzerindeki intersectionPoint_uv koordinatını hesaplayınız. Gerek intersectionPoint_t gerekse de intersectionPoint_uv üçgen üzerindeki koordinatlar olduğundan ikisi de aynı çıkmalıdır. Programda baĢlangıç değerleri (0,0,0) olarak setlenmiĢtir. 5. Deneyin Yapılışı IntersectTriangle() isimli IĢın-Üçgen kesiĢim testi methodunu “Alan Testi” yöntemini gerçekleyecek Ģekilde değiĢtiriniz. 6. Deney Raporu Deney Raporu, Rapor.docx adlı Ģablon belge ile hazırlanacak ve en geç sonraki hafta deney saatine kadar teslim edilecektir. Rapor, grup olarak hazırlanacaktır. Varsa Deneye Hazırlık veya Deneyin YapılıĢındaki eksikler tamamlanıp rapora eklenecek ve (USB bellekte getirilen) programlar ile birlikte teslim edilecektir.
Benzer belgeler
DirectX 10 Picking Uygulaması
kullanılmayacağına karar vermek içindir. Eğer o kullanılacaksa sonraki if(!g_bAllHits)
şartı ile kesişen bütün üçgenler mi yoksa bunlardan en yakın olanına ait bilgiler mi alınacak
ona karar verili...
Excel Fonksiyon Tablosunu İndir
Metin değeriyle belirtilen bir başvuru verir
Doğrusal bir eğilimin parametrelerini verir
Bir yatırımın dönem sayısını verir
Bir veri kümesinin kartil değerini verir
Bir dizinin ilk sütununa bakar v...