Qt goes to DirectX9 SDK-Tutorial Teil 1
-
- Beiträge: 99
- Registriert: 1. Dezember 2005 17:44
- Wohnort: Karlsruhe
Qt goes to DirectX9 SDK-Tutorial Teil 1
EDIT 28.05.2006
Vorbemerk:
Die ursprünglich im Qt-Programmieren Forum gestellte Frage ist nun Projektarbeit mit dem Ziel, das Microsoft SDK-Tutorial zur Programmierung von DirectX9 für Qt-Anwendung zu erarbeiten.
Das DirectX-SDK kann von dieser Seite herunter geladen werden:
http://www.microsoft.com/downloads/deta ... laylang=en
Der Workaround stellt keinerlei Ansprüche an irgend etwas. Es soll
ein Fingerzeig sein, wie man DirectX in seine Qt Anwendungen
einbauen könnte. Deiner Phantasie sind dabei keine Grenzen gesetzt.
Aus dem Grund geht der Code auch nur auf das wirklich notwendige
ein. Fehlerbehandlungen etc. oder sonstige Berücksichtigungen wurden
absichtlich weggelassen um das wesentliche nicht zu verschleiern.
Die SDK-Tutorials, von denen hier geschrieben wird, findet man in der
Help des SDK unter: DirectX Graphics/Programming Guide/Tutorials, Samples/Tools etc. DirectX ist der Übermantel für Graphics, Input, Musik u.v.a.m. Hier wird mit Graphics gearbeitet.
*Ärmelhochkremplundruff*
Q ... (have fun)
DIRECTX9 SDK-TUTORIAL
TEIL 1
Inhalt:
Titel: Creating a device
->Step1: Creating a Window
->Step2: Initializing DirectX
->Step3: Handling System Messages
->Step4: Rendering and Displaying a Scene
->Step5: Shutting down
Hi,
wie der Topic schon sagt: Ich vermenge gerade Qt mit DirectX. Macht zwar Plattformabhängig - aber was solls.
Mir macht QApplication momentan Sorgen. Konkret: Wohin mit der Render-Methode?
Windows-Like würde man sie in den App-Main-Loop schieben, konkret in den Teil, der nicht von Dispatchmessage abgegessen wird.
Wohin aber in winmain() zwischen
QApplication a(argc, argv);
// hier ist kein Main - Loop
return a.exec();
Momentan hooke ich einen Main-Loop noch vor return a.exec();
was aber m.M.n. nicht das Gelbe vom Ei sein kann.
Es muss irgendwie mit der QApplication-Klasse gehen - aber nur wie?
[/b]
Vorbemerk:
Die ursprünglich im Qt-Programmieren Forum gestellte Frage ist nun Projektarbeit mit dem Ziel, das Microsoft SDK-Tutorial zur Programmierung von DirectX9 für Qt-Anwendung zu erarbeiten.
Das DirectX-SDK kann von dieser Seite herunter geladen werden:
http://www.microsoft.com/downloads/deta ... laylang=en
Der Workaround stellt keinerlei Ansprüche an irgend etwas. Es soll
ein Fingerzeig sein, wie man DirectX in seine Qt Anwendungen
einbauen könnte. Deiner Phantasie sind dabei keine Grenzen gesetzt.
Aus dem Grund geht der Code auch nur auf das wirklich notwendige
ein. Fehlerbehandlungen etc. oder sonstige Berücksichtigungen wurden
absichtlich weggelassen um das wesentliche nicht zu verschleiern.
Die SDK-Tutorials, von denen hier geschrieben wird, findet man in der
Help des SDK unter: DirectX Graphics/Programming Guide/Tutorials, Samples/Tools etc. DirectX ist der Übermantel für Graphics, Input, Musik u.v.a.m. Hier wird mit Graphics gearbeitet.
*Ärmelhochkremplundruff*
Q ... (have fun)
DIRECTX9 SDK-TUTORIAL
TEIL 1
Inhalt:
Titel: Creating a device
->Step1: Creating a Window
->Step2: Initializing DirectX
->Step3: Handling System Messages
->Step4: Rendering and Displaying a Scene
->Step5: Shutting down
Hi,
wie der Topic schon sagt: Ich vermenge gerade Qt mit DirectX. Macht zwar Plattformabhängig - aber was solls.
Mir macht QApplication momentan Sorgen. Konkret: Wohin mit der Render-Methode?
Windows-Like würde man sie in den App-Main-Loop schieben, konkret in den Teil, der nicht von Dispatchmessage abgegessen wird.
Wohin aber in winmain() zwischen
QApplication a(argc, argv);
// hier ist kein Main - Loop
return a.exec();
Momentan hooke ich einen Main-Loop noch vor return a.exec();
was aber m.M.n. nicht das Gelbe vom Ei sein kann.
Es muss irgendwie mit der QApplication-Klasse gehen - aber nur wie?
[/b]
Zuletzt geändert von Querdenker am 30. Mai 2006 10:39, insgesamt 4-mal geändert.
e Grüssle au
Q...
Q...
-
- Beiträge: 99
- Registriert: 1. Dezember 2005 17:44
- Wohnort: Karlsruhe
hm also a lot of answers
Für das Tutorial 1 des Microsoft DirectX SDK habe ich es momentan so gemacht (es schreit nach Verbesserung!, nicht nachCode-Verkomplizierung), so das der Qt-Progger einen Einstieg findet
Es prallen klar zwei Welten zusammen, die von M$ und der Rest der Welt. Ein Qt-Like-Progger hat aber auch seine Standpunkte und die gilt es unter einen Hut zu bringen. Es geht - aber nicht ganz, und genau hier liegt ein Schönheitsfehler.
Zunächst mein MainFile: dx.cpp mit der Mainroutine:
Auf eine Prüfung auf OS habe ich verzichtet - es ist nur zur Übung. Nicht schön ist:
Die globale Variable auf die Klasse DirectX9.
Natürlich der offengelegte Windows Message Callback, weil genau
darin wirkungsvoll die Render-Methode aufgerufen werden kann.
Mit QWidgets funktioniert das über die QPaintEvent() eben nicht. Deshalb
verwaltet die Klasse ein eigenes Windows-Like-Fenster nur für DirectX Ausgaben (vielleicht noch nicht einmal ein Fehler).
directX9.h
und die Implementierung (wie gesagt ein Beispiel aus dem Tutorial der DirectX-SDK von M$)
Das funkt mit MinGW ganz gut.
In die Projektfile muss folgender Satz:
win32:LIBS += C:/MinGW/lib/libd3d9.a
Viel schöner, wenn man eine Vollintegration hin bekäme. Vielleicht kommt ja noch eine Idee [/code]
Für das Tutorial 1 des Microsoft DirectX SDK habe ich es momentan so gemacht (es schreit nach Verbesserung!, nicht nachCode-Verkomplizierung), so das der Qt-Progger einen Einstieg findet
Es prallen klar zwei Welten zusammen, die von M$ und der Rest der Welt. Ein Qt-Like-Progger hat aber auch seine Standpunkte und die gilt es unter einen Hut zu bringen. Es geht - aber nicht ganz, und genau hier liegt ein Schönheitsfehler.
Zunächst mein MainFile: dx.cpp mit der Mainroutine:
Code: Alles auswählen
#include <QApplication>
#include <windows.h>
#include "directX9.h"
DirectX9 *directX9;
LRESULT WINAPI MsgProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam ){
switch( msg ){
case WM_PAINT:
directX9->Render(hWnd);
ValidateRect( hWnd, NULL );
return 0;
}
return DefWindowProc( hWnd, msg, wParam, lParam );
}
int main(int argc, char* argv[]){
QApplication app(argc, argv);
directX9 = new DirectX9((WNDPROC)MsgProc);
return app.exec();
}
Die globale Variable auf die Klasse DirectX9.
Natürlich der offengelegte Windows Message Callback, weil genau
darin wirkungsvoll die Render-Methode aufgerufen werden kann.
Mit QWidgets funktioniert das über die QPaintEvent() eben nicht. Deshalb
verwaltet die Klasse ein eigenes Windows-Like-Fenster nur für DirectX Ausgaben (vielleicht noch nicht einmal ein Fehler).
directX9.h
Code: Alles auswählen
#ifndef M_DIRECTX9
#define M_DIRECTX9
#include <windows.h>
#include <d3d9.h>
#include <d3d9types.h>
#include <QObject>
struct CUSTOMVERTEX{
FLOAT x, y, z, rhw;
DWORD color;
};
#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZRHW|D3DFVF_DIFFUSE)
class DirectX9 : public QObject{
Q_OBJECT
public:
DirectX9(WNDPROC);
~DirectX9();
void Render(HWND);
IDirect3D9 *GetDx9Interface() { return IDirectX; };
IDirect3DDevice9 *GetDxDevice() { return IDevice; };
bool IsDxInit;
HWND hwnd;
private:
HMODULE hInst;
IDirect3D9 *IDirectX;
IDirect3DDevice9 *IDevice;
};
#endif
Code: Alles auswählen
#include "directX9.h"
DirectX9::DirectX9(WNDPROC wndProc){
IDirectX = NULL;
IDevice = NULL;
hwnd = 0;
IsDxInit = false;
hInst = GetModuleHandle(NULL);
if(wndProc != NULL){
IDirectX = Direct3DCreate9(D3D_SDK_VERSION);
if(IDirectX == NULL) return;
D3DPRESENT_PARAMETERS d3dpp;
ZeroMemory( &d3dpp, sizeof(d3dpp) );
d3dpp.Windowed = TRUE;
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;
WNDCLASSEXA wc = { sizeof(WNDCLASSEXA), CS_CLASSDC, wndProc, 0L, 0L,
hInst, NULL, NULL, NULL, NULL,"DirectX9-Win", NULL };
RegisterClassExA( &wc );
hwnd = CreateWindowA( "DirectX9-Win", "DX_BASE",
WS_OVERLAPPEDWINDOW | WS_VISIBLE, 100, 100, 300, 300,
GetDesktopWindow(), NULL, hInst, NULL );
if(hwnd != 0){
HRESULT res = IDirectX->CreateDevice(D3DADAPTER_DEFAULT,
D3DDEVTYPE_HAL, hwnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING,
&d3dpp, &IDevice);
if(res != D3D_OK){
IDirectX->Release();
return;
}
}else return;
IsDxInit=true;
}
};
DirectX9::~DirectX9(){
if(IDevice !=0) IDevice->Release();
if(IDirectX !=0) IDirectX->Release();
if(hwnd !=0) DestroyWindow(hwnd);
};
void DirectX9::Render(HWND hwndCaller){
if(hwndCaller != hwnd) return;
if(IDevice == NULL) return;
//Zeichnen ...
CUSTOMVERTEX vertices[] = {
{ 150.0f, 50.0f, 0.5f, 1.0f, 0xffff0000, }, // x, y, z, rhw, color
{ 250.0f, 250.0f, 0.5f, 1.0f, 0xff00ff00, },
{ 50.0f, 250.0f, 0.5f, 1.0f, 0xff00ffff, }, };
IDirect3DVertexBuffer9 *IVBuffer;
if( FAILED(IDevice->CreateVertexBuffer( 3*sizeof(CUSTOMVERTEX),
0, D3DFVF_CUSTOMVERTEX,
D3DPOOL_DEFAULT, &IVBuffer, NULL ) ) ){
return;
}
VOID* pVertices;
if( FAILED( IVBuffer->Lock( 0, sizeof(vertices), (void**)&pVertices, 0 ) ) )
return;
memcpy( pVertices, vertices, sizeof(vertices) );
IVBuffer->Unlock();
IDevice->Clear( 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0,0,255), 1.0f, 0 );
IDevice->BeginScene();
IDevice->SetStreamSource( 0, IVBuffer, 0, sizeof(CUSTOMVERTEX) );
IDevice->SetFVF( D3DFVF_CUSTOMVERTEX );
IDevice->DrawPrimitive( D3DPT_TRIANGLELIST, 0, 1 );
IDevice->EndScene();
IDevice->Present( NULL, NULL, NULL, NULL );
};
In die Projektfile muss folgender Satz:
win32:LIBS += C:/MinGW/lib/libd3d9.a
Viel schöner, wenn man eine Vollintegration hin bekäme. Vielleicht kommt ja noch eine Idee [/code]
- Dateianhänge
-
- direct.jpg (20.76 KiB) 12935 mal betrachtet
e Grüssle au
Q...
Q...
-
- Beiträge: 99
- Registriert: 1. Dezember 2005 17:44
- Wohnort: Karlsruhe
Done
nach einigem hin und her habe ich doch ein QWidget überreden können und nun ist die Sache voll gekapselt:
Entscheidend dabei ist das paintEvent(), dass die Klasse reimplementiert, aber: Der Background wird immer wieder übertüncht. Das ändert sich, wenn man die Attributes des Widget setzt:
setAttribute(Qt::WA_OpaquePaintEvent,true);
Damit erklärt man dem Widget: Den Background übernimmt ab sofort der User und damit: DirectX!
*schweißabtupf*
Und so ist's geworden:
Die dx.cpp
Die QDirectX9 Klasse. QDirectX9.h
Die QDirectX9.cpp
have fun
Entscheidend dabei ist das paintEvent(), dass die Klasse reimplementiert, aber: Der Background wird immer wieder übertüncht. Das ändert sich, wenn man die Attributes des Widget setzt:
setAttribute(Qt::WA_OpaquePaintEvent,true);
Damit erklärt man dem Widget: Den Background übernimmt ab sofort der User und damit: DirectX!
*schweißabtupf*
Und so ist's geworden:
Die dx.cpp
Code: Alles auswählen
#include <QApplication>
#include "QDirectX9.h"
QDirectX9 *directX9;
int main(int argc, char* argv[]){
QApplication app(argc, argv);
directX9 = new QDirectX9();
directX9->Initialize();
directX9->show();
return app.exec();
}
Code: Alles auswählen
#ifndef M_WDIRECTX9
#define M_WDIRECTX9
#include <d3d9.h>
#include <d3d9types.h>
#include <QWidget>
class QPaintEvent;
struct CUSTOMVERTEX{
FLOAT x, y, z, rhw;
DWORD color;
};
#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZRHW|D3DFVF_DIFFUSE)
class QDirectX9 : public QWidget{
Q_OBJECT
public:
~QDirectX9();
bool Initialize();
void Render();
IDirect3D9 *GetDx9Interface() { return IDirectX; };
IDirect3DDevice9 *GetDxDevice() { return IDevice; };
bool IsDxInit;
private:
IDirect3D9 *IDirectX;
IDirect3DDevice9 *IDevice;
void paintEvent(QPaintEvent*);
};
#endif
Code: Alles auswählen
#include "QDirectX9.h"
#include <QPaintEvent>
void QDirectX9::paintEvent(QPaintEvent *event){
Render();
};
bool QDirectX9::Initialize(){
IDirectX = NULL;
IDevice = NULL;
IsDxInit = false;
IDirectX = Direct3DCreate9(D3D_SDK_VERSION);
if(IDirectX == NULL) return false;
D3DPRESENT_PARAMETERS d3dpp;
ZeroMemory( &d3dpp, sizeof(d3dpp) );
d3dpp.Windowed = TRUE;
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;
HRESULT res = IDirectX->CreateDevice(D3DADAPTER_DEFAULT,
D3DDEVTYPE_HAL, winId(), D3DCREATE_SOFTWARE_VERTEXPROCESSING,
&d3dpp, &IDevice);
if(res != D3D_OK){
IDirectX->Release();
return false;
}
IsDxInit = true;
setAttribute(Qt::WA_OpaquePaintEvent,true);
return true;
};
QDirectX9::~QDirectX9(){
if(IDevice !=0) IDevice->Release();
if(IDirectX !=0) IDirectX->Release();
};
void QDirectX9::Render(){
if(IDevice == NULL) return;
//Zeichnen ...
CUSTOMVERTEX vertices[] = {
{ 150.0f, 50.0f, 0.5f, 1.0f, 0xffff0000, }, // x, y, z, rhw, color
{ 250.0f, 250.0f, 0.5f, 1.0f, 0xff00ff00, },
{ 50.0f, 250.0f, 0.5f, 1.0f, 0xff00ffff, }, };
IDirect3DVertexBuffer9 *IVBuffer;
if( FAILED(IDevice->CreateVertexBuffer( 3*sizeof(CUSTOMVERTEX),
0, D3DFVF_CUSTOMVERTEX,
D3DPOOL_DEFAULT, &IVBuffer, NULL ) ) ){
return;
}
VOID* pVertices;
if( FAILED( IVBuffer->Lock( 0, sizeof(vertices), (void**)&pVertices, 0 ) ) )
return;
memcpy( pVertices, vertices, sizeof(vertices) );
IVBuffer->Unlock();
IDevice->Clear( 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0,0,0), 1.0f, 0 );
IDevice->BeginScene();
IDevice->SetStreamSource( 0, IVBuffer, 0, sizeof(CUSTOMVERTEX) );
IDevice->SetFVF( D3DFVF_CUSTOMVERTEX );
IDevice->DrawPrimitive( D3DPT_TRIANGLELIST , 0, 1 );
IDevice->EndScene();
IDevice->Present( NULL, NULL, NULL, NULL );
};
e Grüssle au
Q...
Q...
-
- Beiträge: 99
- Registriert: 1. Dezember 2005 17:44
- Wohnort: Karlsruhe
Die SDK-Tuts
Hi Alle,
wenn gewünscht, so werden noch ein paar Tuts des DirectX-SDK's durchgezogen und möglichst einfach gehalten dargestellt.
Ich muss es eh durcharbeiten *seufz*
wenn gewünscht, so werden noch ein paar Tuts des DirectX-SDK's durchgezogen und möglichst einfach gehalten dargestellt.
Ich muss es eh durcharbeiten *seufz*
e Grüssle au
Q...
Q...
-
- Beiträge: 99
- Registriert: 1. Dezember 2005 17:44
- Wohnort: Karlsruhe
->Step1: Creating a Window
Zusammenfassung:
->Step1: Creating a Window
In Qt null Problem: Wir erstellen eine Klasse die unsere DirectX-Funktionalität kapselt
UND DIE ERBT GANZ EINFACH VON QWIDGET!
->Step2: Initializing DirectX
Zur Erzeugung des DirectXDevice wird die winId des Widgets benötigt.
Die Initialisierung wurde in eine eigene Methode: Initialize() implementiert. Der Beispielcode von MS in der SDK kann 1:1 übernommen werden.
Für Qt wichtig: Includieren der Headerfiles: d3d9.h und d3d9types.h.
Für den Zugriff auf externe Biblotheken muss die Projektdatei um diesen Satz erweitert werden:
win32:LIBS Pfad_Compiler/lib/libd3d9.a
das gilt für den MinGW. Für andere Compiler die entsprechende LibFile eintragen.[/b]
->Step3: Handling System Messages
Windows-like wäre ideal, wenn die Render()Methode, das ist der eigentliche Motor, der die Szenarios in Gange hält, im App-Main-Loop unterbracht wäre. Der Main-Loop wird aber von QApplication gekapselt.
Alternativ bietet MS die Möglichkeit, die Render()-Methode aus dem Event-Callback des unter winId genannten Windows aufzurufen. DirectX ruft WM_Paint auf, wenn die Szenarios refreshed werden müssen. Hier ist ein Ansatz. Wir reimplementieren: paintEvent und fügen da die Render()-Methode ein.
So dann, die QDirectX9.h
Implementiert in der QDirectX9.cpp:
Wenn im Bildschrim die untere linke Ecke gezeichnet wird, wird DirectX eine WM_Paint Message posten, aber auch andere Events, die ein Neuzeichnen erfordern bewirken den Aufruf der Render()-Methode - aber:
Unser Widget wird sich nicht von Render() bändigen lassen, weil es eine eigene Backgroundrole spielt. Das bewirkt, dass die Ausgabe von Render() durch das Widget übertüncht werden. Man merkt das, wenn man das Window zieht, dass kurz die Figur gezeichnet wird und aber sofort wieder im Windows-grau verschwindet. Man muss dem Widget es abgewöhnen, die Hintergrund Rolle abzuspielen. Deshalb wurde in der Initialize()-Methode:
Die Anweisung: setAttribute(Qt::WA_OpaquePaintEvent,true); aufgenommen, die genau das bewirkt, dass das Widget das Zeichnen des Hintergrunds uns überlässt! Auch hier wurde der Code aus der SDK fast 1:1 übernommen. winId() ist hWnd unseres DirectX-Windows.
->Step4: Rendering and Displaying a Scene
Das ist ein Kunstgriff auf Tutorial Teil2 -> Vectors, wird in Teil 2 des Tuts behandelt.
->Step5: Shutting down
War ein schwerer Fall für den Destruktor! Klar ist: DirectX ist eine ActiveX-Komponente und Teile darin sind COM-Klassen. Es ist Vertrag, dass wenn man eine COM-Class aufruft, sie auch wieder löschen muss. Jede Class, jede Komponente beginnt mit:
QueryInterface()
Addref()
Release()
Ein Aufruf einer Class bedeutet, dass der Instanzzähler in Addref um 1 erhöht wird. Die Class wird solange im Speicher gehalten, bis der Zähler auf 0 gesetzt wird und das allein bewirkt die Methode: Release().
Für Qt bedeutet das, dass Qt der Client ist, der anfordert. Also wird Addref() gesetzt, was die Class selbst tut. Was Qt und wir tun müssen ist:
Wenn wir die Class nicht mehr brauchen einfach Release() aufzurufen. COM terminiert das selbst aus dem Speicher.
Somit ist der Destruktor also:
Ich glaube, das dies keiner weiteren Erklärung mehr bedarf Die restlichen Aufräumarbeiten kann man getrost Qt überlassen. Für DirectX sind wir aber, immer daran denken!, selbst voll verantwortlich.
->Step1: Creating a Window
In Qt null Problem: Wir erstellen eine Klasse die unsere DirectX-Funktionalität kapselt
UND DIE ERBT GANZ EINFACH VON QWIDGET!
Code: Alles auswählen
#ifndef M_DIRECTX9
#define M_DIRECTX9
#include <QWidget>
class QDirectX9 : public QWidget {
Q_OBJECT
};
#endif
Zur Erzeugung des DirectXDevice wird die winId des Widgets benötigt.
Die Initialisierung wurde in eine eigene Methode: Initialize() implementiert. Der Beispielcode von MS in der SDK kann 1:1 übernommen werden.
Für Qt wichtig: Includieren der Headerfiles: d3d9.h und d3d9types.h.
Für den Zugriff auf externe Biblotheken muss die Projektdatei um diesen Satz erweitert werden:
win32:LIBS Pfad_Compiler/lib/libd3d9.a
das gilt für den MinGW. Für andere Compiler die entsprechende LibFile eintragen.[/b]
->Step3: Handling System Messages
Windows-like wäre ideal, wenn die Render()Methode, das ist der eigentliche Motor, der die Szenarios in Gange hält, im App-Main-Loop unterbracht wäre. Der Main-Loop wird aber von QApplication gekapselt.
Alternativ bietet MS die Möglichkeit, die Render()-Methode aus dem Event-Callback des unter winId genannten Windows aufzurufen. DirectX ruft WM_Paint auf, wenn die Szenarios refreshed werden müssen. Hier ist ein Ansatz. Wir reimplementieren: paintEvent und fügen da die Render()-Methode ein.
So dann, die QDirectX9.h
Code: Alles auswählen
#ifndef M_DIRECTX9
#define M_DIRECTX9
#include <d3d9.h>
#include <d3d9types.h>
#include <QWidget>
class QPaintEvent; //vorwärtsdeklaration von QPaintEvent
class QDirectX9 : public QWidget{
Q_OBJECT
public:
Render();
private:
void paintEvent(QPaintEvent*); //<-Deklaration
};
#endif
Code: Alles auswählen
#include "QDirectX9.h"
#include <QPaintEvent>
void QDirectX9::paintEvent(QPaintEvent *event){
Render();
};
Unser Widget wird sich nicht von Render() bändigen lassen, weil es eine eigene Backgroundrole spielt. Das bewirkt, dass die Ausgabe von Render() durch das Widget übertüncht werden. Man merkt das, wenn man das Window zieht, dass kurz die Figur gezeichnet wird und aber sofort wieder im Windows-grau verschwindet. Man muss dem Widget es abgewöhnen, die Hintergrund Rolle abzuspielen. Deshalb wurde in der Initialize()-Methode:
Code: Alles auswählen
bool QDirectX9::Initialize(){
IDirectX = Direct3DCreate9(D3D_SDK_VERSION);
if(IDirectX == NULL) return false;
D3DPRESENT_PARAMETERS d3dpp;
ZeroMemory( &d3dpp, sizeof(d3dpp) );
d3dpp.Windowed = TRUE;
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;
HRESULT res = IDirectX->CreateDevice(D3DADAPTER_DEFAULT,
D3DDEVTYPE_HAL, winId(), D3DCREATE_SOFTWARE_VERTEXPROCESSING,
&d3dpp, &IDevice);
if(res != D3D_OK){
IDirectX->Release();
return false;
}
IsDxInit = true;
setGeometry(10,10,200,200);
setAttribute(Qt::WA_OpaquePaintEvent,true);
return true;
};
->Step4: Rendering and Displaying a Scene
Das ist ein Kunstgriff auf Tutorial Teil2 -> Vectors, wird in Teil 2 des Tuts behandelt.
->Step5: Shutting down
War ein schwerer Fall für den Destruktor! Klar ist: DirectX ist eine ActiveX-Komponente und Teile darin sind COM-Klassen. Es ist Vertrag, dass wenn man eine COM-Class aufruft, sie auch wieder löschen muss. Jede Class, jede Komponente beginnt mit:
QueryInterface()
Addref()
Release()
Ein Aufruf einer Class bedeutet, dass der Instanzzähler in Addref um 1 erhöht wird. Die Class wird solange im Speicher gehalten, bis der Zähler auf 0 gesetzt wird und das allein bewirkt die Methode: Release().
Für Qt bedeutet das, dass Qt der Client ist, der anfordert. Also wird Addref() gesetzt, was die Class selbst tut. Was Qt und wir tun müssen ist:
Wenn wir die Class nicht mehr brauchen einfach Release() aufzurufen. COM terminiert das selbst aus dem Speicher.
Somit ist der Destruktor also:
Code: Alles auswählen
QDirectX9::~QDirectX9(){
if(IDevice !=0) IDevice->Release();
if(IDirectX !=0) IDirectX->Release();
};
e Grüssle au
Q...
Q...
Hier ist mein Code aber es wird nur schwarzer bildschirm angezeigt ich versteh net wieso obwohl ich den backbuffer weiß anzeige mit rgb 255,255,255. ich hoffe ihr könnt helfen ich mach schon ganzen abend an den kack rum
es wird nurn schwarzer bildschirm angezeigt... hoffe ihr könnt helfen bitte...
Code: Alles auswählen
// also erstmal QDirectX9.h
#ifndef QDIRECTX9_H
#define QDIRECTX9_H
#include <QtGui/QWidget>
#include <d3d9.h>
#include <d3d9types.h>
class QPaintEvent;
struct CUSTOMVERTEX{
FLOAT x, y, z, rhw;
DWORD color;
};
#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZRHW|D3DFVF_DIFFUSE)
class QDirectX9 : public QWidget
{
Q_OBJECT
public:
~QDirectX9();
bool Init();
void Render();
IDirect3D9 *GetDXInterface () {return D3D;}
IDirect3DDevice9 *GetDXDevice () {return Device;}
private:
void paintEvent(QPaintEvent *event);
IDirect3D9 *D3D;
IDirect3DDevice9 *Device;
bool IsDXInit;
};
#endif
dann QDirectX9.cpp
#include "QDirectX9.h"
#include <QtGui/QPaintEvent>
void QDirectX9::paintEvent(QPaintEvent *event)
{
Render();
}
bool QDirectX9::Init()
{
D3D = NULL;
Device = NULL;
IsDXInit = false;
D3D = Direct3DCreate9(D3D_SDK_VERSION);
if (D3D == NULL)
return false;
D3DPRESENT_PARAMETERS pp;
ZeroMemory(&pp, sizeof(pp));
pp.Windowed = true;
pp.SwapEffect = D3DSWAPEFFECT_DISCARD;
pp.BackBufferFormat = D3DFMT_UNKNOWN;
pp.hDeviceWindow = winId();
pp.BackBufferCount = 1;
pp.BackBufferWidth = 640;
pp.BackBufferHeight = 480;
HRESULT res = D3D->CreateDevice(D3DADAPTER_DEFAULT,
D3DDEVTYPE_HAL, winId(), D3DCREATE_SOFTWARE_VERTEXPROCESSING,
&pp, &Device);
if (res != D3D_OK)
{
D3D->Release();
return false;
}
IsDXInit = true;
setGeometry(200,200,640,480);
setAttribute(Qt::WA_OpaquePaintEvent, true);
return true;
}
QDirectX9::~QDirectX9()
{
if(Device !=0) Device->Release();
if(D3D !=0) D3D->Release();
};
void QDirectX9::Render()
{
if(Device == NULL) return;
Device->Clear( 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(255,255,255), 1.0f, 0 );
Device->Present( NULL, NULL, NULL, NULL );
}
//dann main.cpp
#include "QDirectX9.h"
#include <QtGui/QApplication>
QDirectX9 *DirectX;
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
DirectX = new QDirectX9;
DirectX->Init();
DirectX->show();
return app.exec();
}
Hip Hop is Life !
-
- Beiträge: 7
- Registriert: 31. März 2010 01:04
Das habe ich mit den Sourcebeispielen von euch beiden.es wird nurn schwarzer bildschirm angezeigt... hoffe ihr könnt helfen bitte...
Ich habe aber folgendes gefunden:
Schaue dir dort mal den 2. Eintrag an:
wenn du dann mal dein Fenster auf Maximum vergroesserst, dann sieht man doch wirklich das Dreieck; ansonsten nicht.
http://www.qtforum.org/article/18392/qt ... #post71016
btw: wenn du eine andere Farbe als weiss verwendest, z. B. blau und dann die Groesse des Fensters staendig aenderst, wirst du sehen, dass das blau fuer einen Bruchteil zu sehen ist. Noch schoener sieht man das, wenn man win Parent-Widget mitgibt.
Das ganze muss also am DirectX und Qt liegen.
-
- Beiträge: 7
- Registriert: 31. März 2010 01:04
-
- Beiträge: 7
- Registriert: 31. März 2010 01:04
Da ich das Problem mit dem Schwarz auch hatte
Hier die Loesung:
muss vor oder nach dem setAttribute eingefuegt werden und alles funzt
Den Painteventkommentar unterhalb des 2. Kommentars bitte ebenso
beachten.
Hier die Loesung:
Code: Alles auswählen
setAttribute(Qt::WA_PaintOnScreen, true)
Den Painteventkommentar unterhalb des 2. Kommentars bitte ebenso
beachten.
Guten Tag,
danke für den Thread, deine erste Lösung ohne erben von QWidget funktioniert auch recht gut, da deine zweite Variante aber natürlich schöner ist würde ich auch diese gern zum Laufen bekommen, habe aber das von euch beschriebene Problem des schwarzen Bildschirms. Wenn man das Fenster größer/kleiner zeiht zeigt sich das Dreieck auch kurz, ist dann aber wieder weg. Das einfügen von
versucht, da sollte es doch hin?
LG
danke für den Thread, deine erste Lösung ohne erben von QWidget funktioniert auch recht gut, da deine zweite Variante aber natürlich schöner ist würde ich auch diese gern zum Laufen bekommen, habe aber das von euch beschriebene Problem des schwarzen Bildschirms. Wenn man das Fenster größer/kleiner zeiht zeigt sich das Dreieck auch kurz, ist dann aber wieder weg. Das einfügen von
hat da leider nichts dran geändert, habe es sowohl vor als auch nachCode: Alles auswählen
setAttribute(Qt::WA_PaintOnScreen, true)
Code: Alles auswählen
setAttribute(Qt::WA_OpaquePaintEvent,true);
LG
-
- Beiträge: 7
- Registriert: 31. März 2010 01:04
Bei mir schaut das ganze wie folgt im Konstruktor aus:
Roadrunner
Code: Alles auswählen
QDirectX9::QDirectX9( QWidget* pParent)
: QWidget( pParent)
{
//dcmimage = img;
setAttribute(Qt::WA_OpaquePaintEvent, true);
setAttribute(Qt::WA_NoSystemBackground, true);
setAttribute(Qt::WA_PaintOnScreen, true);
Init();
}