在Qt中使用DirectX

在Qt中使用DirectX
  本文大部分内容转自七星重剑的 在Qt窗口里用D3D画转动的三角形一文,加上点滴个人研究笔记。
  先上个自己的运行结果图吧:
  在Qt中使用DirectX_第1张图片

  现在的问题是只有“脏”了才画,也就是才去调用如下的method;不是三角形没动,是动了但是没画出来,我们看不见。
1  void  QD3DWidget::paintEvent(QPaintEvent  * )
2  {
3       if  (updatesEnabled())
4      {
5          d3dDraw();
6      }
7  }


  用个timer去解决这个问题?

  这老外的帖子对我帮助很大,不搞下面的两条整个QD3DWidget都看不到:

    Using Direct3D 9 with Qt - flicker problem

   According to the Qt docs, if you want to use GDI or Direct3D on Windows with Qt, you need to:

  1) Override QWidget::paintEngine to return NULL
  2) Call QWidget::setAttribute(Qt::WA_PaintOnScreen, true) 

  完整代码:
D3D相关代码
  1 #pragma once
  2 
  3 #include <d3d9.h>
  4 #include <d3dx9.h>
  5 #include <mmsystem.h>
  6 
  7 #pragma comment(lib, "d3d9.lib")
  8 #pragma comment(lib, "d3dx9.lib")
  9 #pragma comment(lib, "winmm.lib")
 10 
 11 LPDIRECT3D9 g_pD3D;
 12 LPDIRECT3DDEVICE9 g_pDevice;
 13 LPDIRECT3DVERTEXBUFFER9 g_pVB;
 14 
 15 //const DWORD D3DFVF_CUSTOMVERTEX = (D3DFVF_XYZ | D3DFVF_DIFFUSE); 
 16 #define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ | D3DFVF_DIFFUSE)
 17 
 18 struct CUSTOMVERTEX
 19 {
 20     float x;
 21     float y;
 22     float z;
 23     DWORD color;
 24 };
 25 
 26 // 此代码模块中包含的函数的前向声明:
 27 ATOM                MyRegisterClass(HINSTANCE hInstance);
 28 BOOL                InitInstance(HINSTANCE, int);
 29 LRESULT CALLBACK    WndProc(HWND, UINT, WPARAM, LPARAM);
 30 INT_PTR CALLBACK    About(HWND, UINT, WPARAM, LPARAM);
 31 
 32 LRESULT InitD3D(HWND hWnd)
 33 {
 34     if (NULL == (g_pD3D = Direct3DCreate9(D3D_SDK_VERSION)))
 35     {
 36         return E_FAIL;
 37     }
 38 
 39     D3DPRESENT_PARAMETERS d3dpp;
 40 
 41     ZeroMemory(&d3dpp, sizeof (D3DPRESENT_PARAMETERS));
 42 
 43     d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
 44     d3dpp.Windowed = true;
 45     d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;
 46     d3dpp.EnableAutoDepthStencil = TRUE;
 47     d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
 48 
 49     if (FAILED(g_pD3D->CreateDevice(D3DADAPTER_DEFAULT,                      // 图形适配器索引。
 50         D3DDEVTYPE_HAL,                          // 设备类型。    
 51         hWnd,                                  // 渲染主窗口。
 52         D3DCREATE_HARDWARE_VERTEXPROCESSING,  // 顶点处理类型。
 53         &d3dpp,                                  // D3DPRESENT_PARAMETERS。    
 54         &g_pDevice)))                          // g_pDevice,D3D设备指针。    
 55     {
 56         return E_FAIL;
 57     }
 58 
 59     g_pDevice->SetRenderState(D3DRS_LIGHTING, FALSE);
 60     g_pDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
 61     g_pDevice->SetRenderState(D3DRS_ZENABLE, TRUE);
 62     return D3D_OK;
 63 }
 64 
 65 LRESULT InitVB()
 66 {
 67     CUSTOMVERTEX vertices[3=
 68     {
 69         { -1.0f,-1.0f0.0f0xffff0000},
 70         {  1.0f,-1.0f0.0f0xff0000ff},
 71         {  0.0f1.0f0.0f0xffffffff}
 72     };
 73 
 74 
 75 
 76     if (FAILED(g_pDevice->CreateVertexBuffer(3 * sizeof (CUSTOMVERTEX),  // 要创建的缓冲区大小(自定义定点结构体大小 * 数目)。
 77         0,                            // D3DUSAGE_*。
 78         D3DFVF_CUSTOMVERTEX,        // 自定义顶点标志。    
 79         D3DPOOL_DEFAULT,            // 资源类型。
 80         &g_pVB,                        // g_pVB,顶点缓冲指针。
 81         NULL)))
 82     {
 83         return E_FAIL;
 84     }
 85 
 86     void* pVertices;
 87 
 88     if (FAILED(g_pVB->Lock(0sizeof (vertices), (void**)&pVertices, 0)))
 89     {
 90         return E_FAIL;
 91     }
 92 
 93     memcpy(pVertices, vertices, sizeof (vertices));
 94 
 95     g_pVB->Unlock();
 96 
 97     return D3D_OK;
 98 }
 99 
100 void Render()
101 {
102     D3DXMATRIX matWorld;
103     D3DXMATRIX matProj;
104     D3DXMATRIX matView;
105 
106     UINT iTime = timeGetTime() % 1000;
107     FLOAT fAngle = iTime * ( 2.0f * D3DX_PI ) / 1000.0f;
108     D3DXMatrixRotationY( &matWorld, fAngle );
109 
110     g_pDevice->SetTransform( D3DTS_WORLD, &matWorld );
111 
112     // Create and set the view matrix
113     D3DXMatrixLookAtLH(&matView,                                
114         &D3DXVECTOR3(0.0f0.0f-2.0f),       
115         &D3DXVECTOR3(0.0f0.0f0.0f),          
116         &D3DXVECTOR3(0.0f1.0f0.0f));
117 
118     g_pDevice->SetTransform(D3DTS_VIEW, &matView);
119 
120     // Create and set the projection matrix
121     D3DXMatrixPerspectiveFovLH(&matProj, D3DX_PI/4.0f1.33333f1.0f1000.0f);
122 
123     g_pDevice->SetTransform(D3DTS_PROJECTION, &matProj);
124 
125     g_pDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(00255), 1.0f0);
126 
127     g_pDevice->BeginScene();
128 
129     g_pDevice->SetStreamSource(0, g_pVB, 0sizeof (CUSTOMVERTEX));
130     g_pDevice->SetFVF(D3DFVF_CUSTOMVERTEX);
131     g_pDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, 01);
132 
133     g_pDevice->EndScene();
134 
135     g_pDevice->Present(NULL, NULL, NULL, NULL);
136 }
137 
138 void Cleanup()
139 {
140     if (g_pVB != NULL)
141     {
142         g_pVB->Release();
143     }
144 
145     if (g_pDevice != NULL)
146     {
147         g_pDevice->Release();
148     }
149 
150     if (g_pD3D != NULL)
151     {
152         g_pD3D->Release();
153     }
154 }

 1  //  QD3DWidget.h
 2 
 3  #pragma once
 4 
 5  #include  < Qt / qwidget.h >
 6 
 7  class  QD3DWidget :  public  QWidget
 8  {
 9      Q_OBJECT
10 
11  public :
12      QD3DWidget(QWidget *  parent  =   0 );
13      ~ QD3DWidget();
14 
15     QPaintEngine *  paintEngine()  const ;
16 
17  protected :
18       virtual   void  initializeD3D();
19       virtual   void  paintD3D();
20 
21       void  paintEvent(QPaintEvent  * );
22 
23       virtual   void  d3dInit();
24       virtual   void  d3dDraw();
25 
26       bool  initialized()  const  { return  m_bInit;}
27 
28       void  MsgBox();
29  private :
30       bool  m_bInit;
31  };

 1  //  QD3DWidget.cpp
 2 
 3  #include  " QtD3DWidget.h "
 4  #include  " D3D.h "
 5  #include  < qtimer.h >
 6 
 7  void  QD3DWidget::MsgBox()
 8  {
 9      QMessageBox mb( this );
10 
11      mb.exec();
12  }
13 
14  QD3DWidget::QD3DWidget(QWidget *  parent  /*  = 0  */ ) : QWidget(parent), m_bInit( false )
15  {
16      resize(QSize( 400 300 ));
17      setAttribute(Qt::WA_PaintOnScreen,  true );
18      
19      QTimer  *timer = new QTimer(this );
20      connect(timer, SIGNAL(timeout()),  this , SLOT(update()));
21      timer ->start(20 );
22  }
23 
24  QD3DWidget:: ~ QD3DWidget()
25  {
26     
27  }
28 
29  void  QD3DWidget::initializeD3D()
30  {
31      InitD3D(winId());
32      InitVB();
33 
34      m_bInit  =   true ;
35  }
36 
37  void  QD3DWidget::paintD3D()
38  {
39      Render();
40  }
41 
42  void  QD3DWidget::paintEvent(QPaintEvent  * )
43  {
44       if  (updatesEnabled())
45      {
46          d3dDraw();
47      }
48  }
49 
50  void  QD3DWidget::d3dInit()
51  {
52      initializeD3D();
53  }
54 
55  void  QD3DWidget::d3dDraw()
56  {
57       if  ( ! initialized())
58      {
59          d3dInit();
60      }
61 
62      paintD3D();
63  }
64 
65  QPaintEngine *  QD3DWidget::paintEngine()  const
66  {
67       return  NULL;
68  }

   红字部分是根据原作者的文章自己研究后加上去的,现在的代码已经可以实现窗体中三角型的转动,关键就是利用定时器每隔20ms强制窗体重绘(update()),因为不太熟悉Qt,搞了半天才知道是update这个函数。

   用如下测试代码就可以得到开头的结果画面:
 1  #include  " stdafx.h "
 2  #include  " QtD3DWidget.h "
 3  #include  < qapplication.h >
 4 
 5  int  _tmain( int  argc,  char *  argv[])
 6  {
 7      QApplication app(argc, argv);
 8 
 9      QD3DWidget *  d3dWidget  =   new  QD3DWidget();
10 
11      d3dWidget -> show();
12 
13       return  app.exec();
14  }
  

你可能感兴趣的:(在Qt中使用DirectX)