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ı

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...

Detaylı

Excel Fonksiyon Tablosunu İndir

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...

Detaylı