All pastes #948740 Raw Edit

Mine

public cpp v1 · immutable
·published 2008-03-19 12:18 UTC
rendered paste body
//-----------------------------------------------------------------------------// File: Pick.cpp//// Desc: Example code showing how to do picking in D3D.//// Copyright (c) Microsoft Corporation. All rights reserved.//-----------------------------------------------------------------------------#define STRICT#include <Windows.h>#include <commctrl.h>#include <math.h>#include <stdio.h>#include <D3DX9.h>#include "DXUtil.h"#include "D3DEnumeration.h"#include "D3DSettings.h"#include "D3DApp.h"#include "D3DFont.h"#include "D3DFile.h"#include "D3DUtil.h"#include "Resource.h"struct D3DVERTEX{    D3DXVECTOR3 p;    D3DXVECTOR3 n;    FLOAT       tu, tv;    static const DWORD FVF;};const DWORD D3DVERTEX::FVF = D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_TEX1;struct INTERSECTION{    DWORD dwFace;                 // mesh face that was intersected    FLOAT fBary1, fBary2;         // barycentric coords of intersection    FLOAT fDist;                  // distance from ray origin to intersection    FLOAT tu, tv;                 // texture coords of intersection};// For simplicity's sake, we limit the number of simultaneously intersected // triangles to 16#define MAX_INTERSECTIONS 16//-----------------------------------------------------------------------------// Name: class CMyD3DApplication// Desc: Application class. The base class (CD3DApplication) provides the //       generic functionality needed in all Direct3D samples. CMyD3DApplication //       adds functionality specific to this sample program.//-----------------------------------------------------------------------------class CMyD3DApplication : public CD3DApplication{    CD3DFont*   m_pFont;                      // Font for drawing text    CD3DFont*   m_pFontSmall;                 // Font for drawing text    CD3DMesh*   m_pObject;                    // Object to render    DWORD       m_dwNumIntersections;         // Number of faces intersected    INTERSECTION m_IntersectionArray[MAX_INTERSECTIONS]; // Intersection info    LPDIRECT3DVERTEXBUFFER9 m_pVB;            // VB for picked triangles    BOOL        m_bShowHelp;                  // Whether to show help    BOOL        m_bUseD3DX;                   // Whether to use D3DXIntersect    BOOL        m_bClosestOnly;               // Whether to just get the closest intersection    // Internal member functions    HRESULT Pick();    BOOL    IntersectTriangle( const D3DXVECTOR3& orig, const D3DXVECTOR3& dir,                               D3DXVECTOR3& v0, D3DXVECTOR3& v1, D3DXVECTOR3& v2,                               FLOAT* t, FLOAT* u, FLOAT* v );    HRESULT ConfirmDevice( D3DCAPS9*, DWORD, D3DFORMAT, D3DFORMAT );protected:    HRESULT OneTimeSceneInit();    HRESULT InitDeviceObjects();    HRESULT RestoreDeviceObjects();    HRESULT InvalidateDeviceObjects();    HRESULT DeleteDeviceObjects();    HRESULT Render();    HRESULT FrameMove();    HRESULT FinalCleanup();public:    LRESULT MsgProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam );    CMyD3DApplication();};//-----------------------------------------------------------------------------// Name: WinMain()// Desc: Entry point to the program. Initializes everything, and goes into a//       message-processing loop. Idle time is used to render the scene.//-----------------------------------------------------------------------------INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR, INT ){    CMyD3DApplication d3dApp;    InitCommonControls();    if( FAILED( d3dApp.Create( hInst ) ) )        return 0;    return d3dApp.Run();}//-----------------------------------------------------------------------------// Name: CMyD3DApplication()// Desc: Application constructor. Sets attributes for the app.//-----------------------------------------------------------------------------CMyD3DApplication::CMyD3DApplication(){    m_strWindowTitle    = _T("Pick: D3D Picking Sample");    m_d3dEnumeration.AppUsesDepthBuffer   = TRUE;    m_bShowCursorWhenFullscreen = TRUE;    m_pFont         = new CD3DFont( _T("Arial"), 12, D3DFONT_BOLD );    m_pFontSmall    = new CD3DFont( _T("Arial"), 9, D3DFONT_BOLD );    m_pObject       = new CD3DMesh();    m_dwNumIntersections = 0;    m_pVB           = NULL;    m_bShowHelp     = FALSE;    m_bUseD3DX      = TRUE;    m_bClosestOnly  = FALSE;}//-----------------------------------------------------------------------------// Name: OneTimeSceneInit()// Desc: Called during initial app startup, this function performs all the//       permanent initialization.//-----------------------------------------------------------------------------HRESULT CMyD3DApplication::OneTimeSceneInit(){    return S_OK;}//-----------------------------------------------------------------------------// Name: Pick()// Desc: Checks if mouse point hits geometry//       the scene.//-----------------------------------------------------------------------------HRESULT CMyD3DApplication::Pick(){    HRESULT hr;    D3DXVECTOR3 vPickRayDir;    D3DXVECTOR3 vPickRayOrig;    m_dwNumIntersections = 0L;    // Get the pick ray from the mouse position    if( GetCapture() )    {        D3DXMATRIXA16 matProj;        m_pd3dDevice->GetTransform( D3DTS_PROJECTION, &matProj );        POINT ptCursor;        GetCursorPos( &ptCursor );        ScreenToClient( m_hWnd, &ptCursor );        // Compute the vector of the pick ray in screen space        D3DXVECTOR3 v;        v.x =  ( ( ( 2.0f * ptCursor.x ) / m_d3dsdBackBuffer.Width  ) - 1 ) / matProj._11;        v.y = -( ( ( 2.0f * ptCursor.y ) / m_d3dsdBackBuffer.Height ) - 1 ) / matProj._22;        v.z =  1.0f;        // Get the inverse view matrix        D3DXMATRIXA16 matView, m;        m_pd3dDevice->GetTransform( D3DTS_VIEW, &matView );        D3DXMatrixInverse( &m, NULL, &matView );        // Transform the screen space pick ray into 3D space        vPickRayDir.x  = v.x*m._11 + v.y*m._21 + v.z*m._31;        vPickRayDir.y  = v.x*m._12 + v.y*m._22 + v.z*m._32;        vPickRayDir.z  = v.x*m._13 + v.y*m._23 + v.z*m._33;        vPickRayOrig.x = m._41;        vPickRayOrig.y = m._42;        vPickRayOrig.z = m._43;    }    // Get the picked triangle    if( GetCapture() )    {        LPD3DXBASEMESH          pMesh = m_pObject->GetLocalMesh();        LPDIRECT3DVERTEXBUFFER9 pVB;        LPDIRECT3DINDEXBUFFER9  pIB;        pMesh->GetVertexBuffer( &pVB );        pMesh->GetIndexBuffer( &pIB );        WORD*      pIndices;        D3DVERTEX*    pVertices;        pIB->Lock( 0, 0, (void**)&pIndices, 0 );        pVB->Lock( 0, 0, (void**)&pVertices, 0 );        if( m_bUseD3DX )        {            // When calling D3DXIntersect, one can get just the closest intersection and not            // need to work with a D3DXBUFFER.  Or, to get all intersections between the ray and             // the mesh, one can use a D3DXBUFFER to receive all intersections.  We show both            // methods.            if( m_bClosestOnly )            {                // Collect only the closest intersection                BOOL bHit;                DWORD dwFace;                FLOAT fBary1, fBary2, fDist;                D3DXIntersect(pMesh, &vPickRayOrig, &vPickRayDir, &bHit, &dwFace, &fBary1, &fBary2, &fDist,                     NULL, NULL);                if( bHit )                {                    m_dwNumIntersections = 1;                    m_IntersectionArray[0].dwFace = dwFace;                    m_IntersectionArray[0].fBary1 = fBary1;                    m_IntersectionArray[0].fBary2 = fBary2;                    m_IntersectionArray[0].fDist = fDist;                }                else                {                    m_dwNumIntersections = 0;                }            }            else             {                // Collect all intersections                BOOL bHit;                LPD3DXBUFFER pBuffer = NULL;                D3DXINTERSECTINFO* pIntersectInfoArray;                if( FAILED( hr = D3DXIntersect(pMesh, &vPickRayOrig, &vPickRayDir, &bHit, NULL, NULL, NULL, NULL,                     &pBuffer, &m_dwNumIntersections) ) )                {                    return hr;                }                if( m_dwNumIntersections > 0 )                {                    pIntersectInfoArray = (D3DXINTERSECTINFO*)pBuffer->GetBufferPointer();                    if( m_dwNumIntersections > MAX_INTERSECTIONS )                        m_dwNumIntersections = MAX_INTERSECTIONS;                    for( DWORD iIntersection = 0; iIntersection < m_dwNumIntersections; iIntersection++ )                    {                        m_IntersectionArray[iIntersection].dwFace = pIntersectInfoArray[iIntersection].FaceIndex;                        m_IntersectionArray[iIntersection].fBary1 = pIntersectInfoArray[iIntersection].U;                        m_IntersectionArray[iIntersection].fBary2 = pIntersectInfoArray[iIntersection].V;                        m_IntersectionArray[iIntersection].fDist = pIntersectInfoArray[iIntersection].Dist;                    }                }                SAFE_RELEASE( pBuffer );            }        }        else        {            // Not using D3DX            DWORD dwNumFaces = m_pObject->GetLocalMesh()->GetNumFaces();            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;                // Check if the pick ray passes through this point                if( IntersectTriangle( vPickRayOrig, vPickRayDir, v0, v1, v2,                                       &fDist, &fBary1, &fBary2 ) )                {                    if( !m_bClosestOnly || m_dwNumIntersections == 0 || fDist < m_IntersectionArray[0].fDist )                    {                        if( m_bClosestOnly )                            m_dwNumIntersections = 0;                        m_IntersectionArray[m_dwNumIntersections].dwFace = i;                        m_IntersectionArray[m_dwNumIntersections].fBary1 = fBary1;                        m_IntersectionArray[m_dwNumIntersections].fBary2 = fBary2;                        m_IntersectionArray[m_dwNumIntersections].fDist = fDist;                        m_dwNumIntersections++;                        if( m_dwNumIntersections == MAX_INTERSECTIONS )                            break;                    }                }            }        }        // Now, for each intersection, add a triangle to m_pVB and compute texture coordinates        if( m_dwNumIntersections > 0 )        {            D3DVERTEX* v;            D3DVERTEX* vThisTri;            WORD* iThisTri;            D3DVERTEX  v1, v2, v3;            INTERSECTION* pIntersection;            m_pVB->Lock( 0, 0, (void**)&v, 0 );            for( DWORD iIntersection = 0; iIntersection < m_dwNumIntersections; iIntersection++ )            {                pIntersection = &m_IntersectionArray[iIntersection];                vThisTri = &v[iIntersection * 3];                iThisTri = &pIndices[3*pIntersection->dwFace];                // get vertices hit                vThisTri[0] = pVertices[iThisTri[0]];                vThisTri[1] = pVertices[iThisTri[1]];                vThisTri[2] = pVertices[iThisTri[2]];                // If all you want is the vertices hit, then you are done.  In this sample, we                // want to show how to infer texture coordinates as well, using the BaryCentric                // coordinates supplied by D3DXIntersect                FLOAT dtu1 = vThisTri[1].tu - vThisTri[0].tu;                FLOAT dtu2 = vThisTri[2].tu - vThisTri[0].tu;                FLOAT dtv1 = vThisTri[1].tv - vThisTri[0].tv;                FLOAT dtv2 = vThisTri[2].tv - vThisTri[0].tv;                pIntersection->tu = vThisTri[0].tu + pIntersection->fBary1 * dtu1 + pIntersection->fBary2 * dtu2;                pIntersection->tv = vThisTri[0].tv + pIntersection->fBary1 * dtv1 + pIntersection->fBary2 * dtv2;            }            m_pVB->Unlock();        }        pVB->Unlock();        pIB->Unlock();        pVB->Release();        pIB->Release();    }    return S_OK;}//-----------------------------------------------------------------------------// Name: FrameMove()// Desc: Called once per frame, the call is the entry point for animating//       the scene.//-----------------------------------------------------------------------------HRESULT CMyD3DApplication::FrameMove(){    // Rotate the camera about the y-axis    D3DXVECTOR3 vFromPt   = D3DXVECTOR3( 0.0f, 0.0f, 0.0f );    D3DXVECTOR3 vLookatPt = D3DXVECTOR3( 0.0f, 0.0f, 0.0f );    D3DXVECTOR3 vUpVec    = D3DXVECTOR3( 0.0f, 1.0f, 0.0f );    vFromPt.x = -cosf(m_fTime/3.0f) * 4.0f;    vFromPt.y = 1.0f;    vFromPt.z =  sinf(m_fTime/3.0f) * 4.0f;    D3DXMATRIXA16 matView;    D3DXMatrixLookAtLH( &matView, &vFromPt, &vLookatPt, &vUpVec );    m_pd3dDevice->SetTransform( D3DTS_VIEW, &matView );    return S_OK;}//-----------------------------------------------------------------------------// Name: Render()// Desc: Called once per frame, the call is the entry point for 3d//       rendering. This function sets up render states, clears the//       viewport, and renders the scene.//-----------------------------------------------------------------------------HRESULT CMyD3DApplication::Render(){    // Set up the cursor    POINT ptCursor;    GetCursorPos( &ptCursor );    ScreenToClient( m_hWnd, &ptCursor );    m_pd3dDevice->SetCursorPosition( ptCursor.x, ptCursor.y, 0L );    // Check for picked triangles    Pick();    // Clear the viewport    m_pd3dDevice->Clear( 0L, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER,                         0x000000ff, 1.0f, 0L );    // Begin the scene    if( SUCCEEDED( m_pd3dDevice->BeginScene() ) )    {        // Set render mode to lit, solid triangles        m_pd3dDevice->SetRenderState( D3DRS_FILLMODE, D3DFILL_SOLID );        m_pd3dDevice->SetRenderState( D3DRS_LIGHTING, TRUE );        // If a triangle is picked, draw it        if( m_dwNumIntersections > 0 )        {            // Draw the picked triangle            m_pd3dDevice->SetFVF( D3DVERTEX::FVF );            m_pd3dDevice->SetStreamSource( 0, m_pVB, 0, sizeof(D3DVERTEX) );            m_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLELIST, 0, m_dwNumIntersections );            // Set render mode to unlit, wireframe triangles            m_pd3dDevice->SetRenderState( D3DRS_FILLMODE, D3DFILL_WIREFRAME );            m_pd3dDevice->SetRenderState( D3DRS_LIGHTING, FALSE );        }        // Render the mesh        m_pObject->Render( m_pd3dDevice );        // Output statistics        m_pFont->DrawText( 2,  0, D3DCOLOR_ARGB(255,255,255,0), m_strFrameStats );        m_pFont->DrawText( 2, 20, D3DCOLOR_ARGB(255,255,255,0), m_strDeviceStats );        // Output help        FLOAT yText = 40.0f;        if( m_bShowHelp )        {            m_pFontSmall->DrawText( 2, yText, D3DCOLOR_ARGB(255,255,255,255), _T("F1: Toggle Help") );            yText += 20.0f;            m_pFontSmall->DrawText( 2, yText, D3DCOLOR_ARGB(255,255,255,255), _T("F2: Change Device") );            yText += 20.0f;            m_pFontSmall->DrawText( 2, yText, D3DCOLOR_ARGB(255,255,255,255), _T("F3: Toggle D3DX Usage") );            yText += 20.0f;            m_pFontSmall->DrawText( 2, yText, D3DCOLOR_ARGB(255,255,255,255), _T("F4: Toggle All Hits") );            yText += 20.0f;        }        else        {            m_pFontSmall->DrawText( 2, yText, D3DCOLOR_ARGB(255,255,255,255), _T("Press F1 for Help") );            yText += 20.0f;        }        // Output info        m_pFontSmall->DrawText( 2, yText, D3DCOLOR_ARGB(255,255,255,255), m_bUseD3DX ? _T("Using D3DX") : _T("Not Using D3DX") );        yText += 20.0f;        m_pFontSmall->DrawText( 2, yText, D3DCOLOR_ARGB(255,255,255,255), m_bClosestOnly ? _T("Showing First Hit") : _T("Showing All Hits") );        yText += 20.0f;        CHAR strBuffer[90];        if( m_dwNumIntersections > 0 )        {            for( DWORD iIntersection = 0; iIntersection < m_dwNumIntersections; iIntersection++ )            {                INTERSECTION* pIntersection = &m_IntersectionArray[iIntersection];                sprintf( strBuffer, _T("Face=%d, tu=%3.02f, tv=%3.02f"), pIntersection->dwFace, pIntersection->tu, pIntersection->tv );                m_pFontSmall->DrawText( 2, yText, D3DCOLOR_ARGB(255,0,255,255), strBuffer );                yText += 20;            }        }        else        {            sprintf( strBuffer, _T("Use mouse to pick a polygon") );            m_pFontSmall->DrawText( 2, yText, D3DCOLOR_ARGB(255,0,255,255), strBuffer );        }                // End the scene.        m_pd3dDevice->EndScene();    }    return S_OK;}//-----------------------------------------------------------------------------// Name: InitDeviceObjects()// Desc: Initialize scene objects.//-----------------------------------------------------------------------------HRESULT CMyD3DApplication::InitDeviceObjects(){    // Restore the font    m_pFont->InitDeviceObjects( m_pd3dDevice );    m_pFontSmall->InitDeviceObjects( m_pd3dDevice );    if( FAILED( m_pObject->Create( m_pd3dDevice, _T("Tiger.x") ) ) )        return D3DAPPERR_MEDIANOTFOUND;    m_pObject->SetFVF( m_pd3dDevice, D3DVERTEX::FVF );    // Create the vertex buffer    DWORD dwNumVertices = MAX_INTERSECTIONS * 3;    if( FAILED( m_pd3dDevice->CreateVertexBuffer( dwNumVertices*sizeof(D3DVERTEX),                                                  D3DUSAGE_WRITEONLY, D3DVERTEX::FVF,                                                  D3DPOOL_MANAGED, &m_pVB, NULL ) ) )    {        return E_FAIL;    }    return S_OK;}//-----------------------------------------------------------------------------// Name: RestoreDeviceObjects()// Desc: Initialize scene objects.//-----------------------------------------------------------------------------HRESULT CMyD3DApplication::RestoreDeviceObjects(){    m_pFont->RestoreDeviceObjects();    m_pFontSmall->RestoreDeviceObjects();    // Restore device-memory objects for the mesh    m_pObject->RestoreDeviceObjects( m_pd3dDevice );    // Set up the textures    m_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );    m_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE );    m_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLOROP,   D3DTOP_MODULATE );    m_pd3dDevice->SetSamplerState( 0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR );    m_pd3dDevice->SetSamplerState( 0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR );    // Set miscellaneous render states    m_pd3dDevice->SetRenderState( D3DRS_DITHERENABLE,   FALSE );    m_pd3dDevice->SetRenderState( D3DRS_SPECULARENABLE, FALSE );    m_pd3dDevice->SetRenderState( D3DRS_ZENABLE,        TRUE );    m_pd3dDevice->SetRenderState( D3DRS_AMBIENT,        0x00444444 );    // Set the world matrix    D3DXMATRIXA16 matIdentity;    D3DXMatrixIdentity( &matIdentity );    m_pd3dDevice->SetTransform( D3DTS_WORLD,  &matIdentity );    // Set the projection matrix    D3DXMATRIXA16 matProj;    FLOAT fAspect = ((FLOAT)m_d3dsdBackBuffer.Width) / m_d3dsdBackBuffer.Height;    D3DXMatrixPerspectiveFovLH( &matProj, D3DX_PI/4, fAspect, 1.0f, 100.0f );    m_pd3dDevice->SetTransform( D3DTS_PROJECTION, &matProj );    // Setup a material    D3DMATERIAL9 mtrl;    D3DUtil_InitMaterial( mtrl, 1.0f, 1.0f, 1.0f, 1.0f );    m_pd3dDevice->SetMaterial( &mtrl );    // Set up lighting states    D3DLIGHT9 light;    D3DUtil_InitLight( light, D3DLIGHT_DIRECTIONAL, 0.1f, -1.0f, 0.1f );    m_pd3dDevice->SetLight( 0, &light );    m_pd3dDevice->LightEnable( 0, TRUE );    m_pd3dDevice->SetRenderState( D3DRS_LIGHTING, TRUE );    return S_OK;}//-----------------------------------------------------------------------------// Name: InvalidateDeviceObjects()// Desc://-----------------------------------------------------------------------------HRESULT CMyD3DApplication::InvalidateDeviceObjects(){    m_pFont->InvalidateDeviceObjects();    m_pFontSmall->InvalidateDeviceObjects();    m_pObject->InvalidateDeviceObjects();    return S_OK;}//-----------------------------------------------------------------------------// Name: DeleteDeviceObjects()// Desc: Called when the app is exiting, or the device is being changed,//       this function deletes any device dependent objects.//-----------------------------------------------------------------------------HRESULT CMyD3DApplication::DeleteDeviceObjects(){    m_pFont->DeleteDeviceObjects();    m_pFontSmall->DeleteDeviceObjects();    m_pObject->Destroy();    SAFE_RELEASE( m_pVB );    return S_OK;}//-----------------------------------------------------------------------------// Name: FinalCleanup()// Desc: Called before the app exits, this function gives the app the chance//       to cleanup after itself.//-----------------------------------------------------------------------------HRESULT CMyD3DApplication::FinalCleanup(){    SAFE_DELETE( m_pFont );    SAFE_DELETE( m_pFontSmall );    SAFE_DELETE( m_pObject );    return S_OK;}//-----------------------------------------------------------------------------// Name: ConfirmDevice()// Desc: Called during device initialization, this code checks the device//       for some minimum set of capabilities//-----------------------------------------------------------------------------HRESULT CMyD3DApplication::ConfirmDevice( D3DCAPS9* pCaps, DWORD dwBehavior,                                          D3DFORMAT adapterFormat, D3DFORMAT backBufferFormat ){    if( dwBehavior & D3DCREATE_PUREDEVICE )        return E_FAIL; // GetTransform doesn't work on PUREDEVICE    // If this is a TnL device, make sure it supports directional lights    if( (dwBehavior & D3DCREATE_HARDWARE_VERTEXPROCESSING ) ||        (dwBehavior & D3DCREATE_MIXED_VERTEXPROCESSING ) )    {        if( !(pCaps->VertexProcessingCaps & D3DVTXPCAPS_DIRECTIONALLIGHTS ) )            return E_FAIL;    }    return S_OK;}//-----------------------------------------------------------------------------// Name: MsgProc()// Desc: Overrrides the main WndProc, so the sample can do custom message//       handling (e.g. processing mouse, keyboard, or menu commands).//-----------------------------------------------------------------------------LRESULT CMyD3DApplication::MsgProc( HWND hWnd, UINT msg, WPARAM wParam,                                    LPARAM lParam ){    switch( msg )    {        case WM_LBUTTONDOWN:            // User pressed left mouse button            SetCapture( hWnd );            break;        case WM_LBUTTONUP:            // The user released the left mouse button            ReleaseCapture();            break;        case WM_COMMAND:            if( LOWORD(wParam) == IDM_HELP )                m_bShowHelp = !m_bShowHelp;            if( LOWORD(wParam) == IDM_TOGGLED3DX )                m_bUseD3DX = !m_bUseD3DX;            else if( LOWORD(wParam) == IDM_TOGGLEALLHITS )                m_bClosestOnly = !m_bClosestOnly;            break;    }    return CD3DApplication::MsgProc( hWnd, msg, wParam, lParam );}//-----------------------------------------------------------------------------// Name: IntersectTriangle()// Desc: Given a ray origin (orig) and direction (dir), and three vertices of//       of a triangle, this function returns TRUE and the interpolated texture//       coordinates if the ray intersects the triangle//-----------------------------------------------------------------------------BOOL CMyD3DApplication::IntersectTriangle( const D3DXVECTOR3& orig,                                       const D3DXVECTOR3& dir, D3DXVECTOR3& v0,                                       D3DXVECTOR3& v1, D3DXVECTOR3& v2,                                       FLOAT* t, FLOAT* u, FLOAT* v ){    // Find vectors for two edges sharing vert0    D3DXVECTOR3 edge1 = v1 - v0;    D3DXVECTOR3 edge2 = v2 - v0;    // Begin calculating determinant - also used to calculate U parameter    D3DXVECTOR3 pvec;    D3DXVec3Cross( &pvec, &dir, &edge2 );    // If determinant is near zero, ray lies in plane of triangle    FLOAT det = D3DXVec3Dot( &edge1, &pvec );    D3DXVECTOR3 tvec;    if( det > 0 )    {        tvec = orig - v0;    }    else    {        tvec = v0 - orig;        det = -det;    }    if( det < 0.0001f )        return FALSE;    // Calculate U parameter and test bounds    *u = D3DXVec3Dot( &tvec, &pvec );    if( *u < 0.0f || *u > det )        return FALSE;    // Prepare to test V parameter    D3DXVECTOR3 qvec;    D3DXVec3Cross( &qvec, &tvec, &edge1 );    // Calculate V parameter and test bounds    *v = D3DXVec3Dot( &dir, &qvec );    if( *v < 0.0f || *u + *v > det )        return FALSE;    // Calculate t, scale parameters, ray intersects triangle    *t = D3DXVec3Dot( &edge2, &qvec );    FLOAT fInvDet = 1.0f / det;    *t *= fInvDet;    *u *= fInvDet;    *v *= fInvDet;    return TRUE;}