QT调用D3D绘制旋转三角形

 

我的环境是win7+Qt5.1

之前在网上找了一些例子, 怎么调试都不出来. 原来是窗口属性的问题.

解决方法:

网上的例子: setAttribute(Qt::WA_PaintOnScreen, true);

Note: This flag is only supported on X11 and it disables double buffering.

看文档发现这个属性只能用于X11环境.

修改为:

setWindowFlags(Qt::WindowStaysOnTopHint | Qt::FramelessWindowHint);
setAttribute(Qt::WA_TranslucentBackground, true);

 

具体代码如下:

D3DWidget.h

#ifndef QD3DWIDGET_H
#define QD3DWIDGET_H

#include <QWidget>
#include <d3d9.h>
#include <d3dx9.h>

extern LPDIRECT3D9 g_pD3D;
extern LPDIRECT3DDEVICE9 g_pDevice;
extern LPDIRECT3DVERTEXBUFFER9 g_pVertexBuffer;
extern LPDIRECT3DINDEXBUFFER9 g_pIndexBuffer;
HRESULT Init3D(HWND hWnd);

struct CUSTOMVERTEX
{
	float x,y,z;
	DWORD color;
};

#define D3DFVF_CUSTOMVERTEXT (D3DFVF_XYZ|D3DFVF_DIFFUSE)

class QD3DWidget : public QWidget
{
	Q_OBJECT

public:
	QD3DWidget(QWidget *parent = NULL);
	~QD3DWidget();

	//reimplement paintEngine 
	QPaintEngine *paintEngine()const;

protected:
	void paintEvent(QPaintEvent *ev);

	virtual void initialize3D();
	virtual void paintD3D();
	virtual bool initGemetry();

	virtual void d3dInit();
	virtual void d3dDraw();
	virtual void render();

public:
	bool initialized()const{
		return fInit;
	}

public slots:
	void rotateTriangle();

private:
	void setupMatrices();

private:
	bool fInit;
	int fRotateY;
};

#endif // QD3DWIDGET_H


 

D3DWidget.cpp

#include "QD3DWidget.h"
#include "D3D9.h"
#include <QTimer>
#include <QMessageBox>

LPDIRECT3D9 g_pD3D = NULL;
LPDIRECT3DDEVICE9 g_pDevice = NULL;
LPDIRECT3DVERTEXBUFFER9 g_pVertexBuffer = NULL;
LPDIRECT3DINDEXBUFFER9 g_pIndexBuffeer = NULL;

HRESULT Init3D(HWND hWnd)
{
	//create d3d object 
	if(NULL ==(g_pD3D = Direct3DCreate9(D3D_SDK_VERSION)))
		return E_FAIL;

	//set up the structure used to create the D3DDevice 
	D3DPRESENT_PARAMETERS d3dpp;
	ZeroMemory(&d3dpp , sizeof(d3dpp));
	d3dpp.Windowed = TRUE;
	d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
	d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;
	d3dpp.EnableAutoDepthStencil = TRUE;
	d3dpp.AutoDepthStencilFormat = D3DFMT_D16;//

	//create the d3ddevice 
	if(FAILED(g_pD3D->CreateDevice(D3DADAPTER_DEFAULT,D3DDEVTYPE_REF,hWnd,D3DCREATE_SOFTWARE_VERTEXPROCESSING,&d3dpp,&g_pDevice)))
		return E_FAIL;

	//turn off culling , so we can see the front and back of the triangle 
	g_pDevice->SetRenderState(D3DRS_CULLMODE,D3DCULL_NONE);

	//turn off d3d lighting , since we are prodving our own vertex colors 
	g_pDevice->SetRenderState(D3DRS_LIGHTING,FALSE);
	g_pDevice->SetRenderState(D3DRS_ANTIALIASEDLINEENABLE,TRUE);
	g_pDevice->SetRenderState(D3DRS_ZENABLE,D3DZB_TRUE);

	return S_OK;
}

QD3DWidget::QD3DWidget(QWidget *parent)
	: QWidget(parent)
	, fInit(false)
	, fRotateY(0)
{
	setFixedSize(400,400);
	setWindowFlags(Qt::WindowStaysOnTopHint | Qt::FramelessWindowHint);
	setAttribute(Qt::WA_TranslucentBackground, true);
}

QD3DWidget::~QD3DWidget()
{
	g_pIndexBuffeer->Release();
	g_pVertexBuffer->Release();
	g_pDevice->Release();
	g_pD3D->Release();
}

QPaintEngine * QD3DWidget::paintEngine()const
{
	return NULL;
}

void QD3DWidget::initialize3D()
{
	Init3D((HWND)winId());
	initGemetry();
	fInit = true;
}

void QD3DWidget::paintD3D()
{
	render();
}

void QD3DWidget::paintEvent(QPaintEvent *ev)
{
	if(updatesEnabled()){
		d3dDraw();
	}
}

void QD3DWidget::d3dInit()
{
	initialize3D();
}

void QD3DWidget::d3dDraw()
{
	if(!initialized()){
		d3dInit();
	}
	paintD3D();
}

void QD3DWidget::render()
{
	g_pDevice->Clear(0,NULL,D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER,D3DCOLOR_XRGB(255,0,255),1.0f,0);

	g_pDevice->BeginScene();

	setupMatrices();

	//set fvf 
	g_pDevice->SetFVF(D3DFVF_CUSTOMVERTEXT);

	//bind vertex buffer data to device source data 
	g_pDevice->SetStreamSource(0,g_pVertexBuffer,0,sizeof(CUSTOMVERTEX));

	//draw 
	//g_pDevice->DrawPrimitive(D3DPT_TRIANGLELIST,0,1);
	g_pDevice->SetIndices(g_pIndexBuffeer);
	g_pDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST,0,0,4,0,4);
	g_pDevice->EndScene();
	g_pDevice->Present(NULL,NULL,NULL,NULL);
}

bool QD3DWidget::initGemetry()
{
	// 平面三角形原形
	//CUSTOMVERTEX vertices[] = {
	//    {
	//        -1.0f,-1.0f,0.0f,D3DCOLOR_XRGB(255,0,0)//red 
	//    },
	//    {
	//        0.0f,1.0f,0.0f,D3DCOLOR_XRGB(0,255,0)//green
	//    },
	//    {
	//        1.0f,-1.0f,0.0f,D3DCOLOR_XRGB(0,0,255)//blue
	//    }
	//};

	// 立体三角形原形
	CUSTOMVERTEX vertices[] = {
		{0.0f,1.0f,0.0f,D3DCOLOR_XRGB(0,255,0)},
		{-1.0f,-1.0f,-0.577f,D3DCOLOR_XRGB(255,0,0)},
		{1.0f,-1.0f,-0.577f,D3DCOLOR_XRGB(0,255,255)},
		{0.0f,-1.0f,1.155f,D3DCOLOR_XRGB(0,0,255)}
	};
	WORD indices[] ={0,2,1,0,3,2,0,1,3,1,2,3};

	//create vertex buffer 
	if(FAILED(g_pDevice->CreateVertexBuffer(sizeof(vertices),0,D3DFVF_CUSTOMVERTEXT,D3DPOOL_DEFAULT,&g_pVertexBuffer,NULL)))
		return false;

	//store the vertex data into buffer 
	void *pVertices;
	g_pVertexBuffer->Lock(0,sizeof(vertices),(void**)&pVertices,0);
	memcpy(pVertices,vertices,sizeof(vertices));
	g_pVertexBuffer->Unlock();

	//create index buffer 
	g_pDevice->CreateIndexBuffer(sizeof(indices),0,D3DFMT_INDEX16,D3DPOOL_DEFAULT,&g_pIndexBuffeer,NULL);

	//store the index data 
	void *pIndices;
	g_pIndexBuffeer->Lock(0,sizeof(indices),(void**)&pIndices,0);
	memcpy(pIndices,indices,sizeof(indices));
	g_pIndexBuffeer->Unlock();

	return true;
}


void QD3DWidget::setupMatrices()
{
	float angle = fRotateY *D3DX_PI/180;
	D3DXMATRIX matWorld;
	D3DXMatrixRotationY(&matWorld,angle);
	//set the world matrix 
	g_pDevice->SetTransform(D3DTS_WORLD,&matWorld);

	D3DXVECTOR3 eye(0.0f,3.0f,-5.0f);
	D3DXVECTOR3 lookat(0.0f,0.0f,0.0f);
	D3DXVECTOR3 up(0.0f,1.0f,0.0f);
	D3DXMATRIX matView;
	//calculate the view matrix 
	D3DXMatrixLookAtLH(&matView,&eye,&lookat,&up);
	g_pDevice->SetTransform(D3DTS_VIEW,&matView);

	//perspective matrix 
	D3DXMATRIXA16 matProj;
	D3DXMatrixPerspectiveFovLH(&matProj,D3DX_PI/4,1.0f,1.0f,100.0f);
	g_pDevice->SetTransform(D3DTS_PROJECTION,&matProj);
}

void QD3DWidget::rotateTriangle()
{
	fRotateY+=2;
	if(fRotateY>360)
		fRotateY=0;

	update();
}


 

QTestWidget.h

#ifndef QTESTWIDGET_H
#define QTESTWIDGET_H

#include <QWidget>
#include <QtCore>
#include "qd3dwidget.h"

class QTestWidget : public QWidget
{
	Q_OBJECT

public:
	QTestWidget(QWidget *parent=NULL);
	~QTestWidget();

	public slots:
		void startRotate();
		void endRotate();

private:
	QD3DWidget * fD3DWidget;

	QTimer fTimer;

};

#endif // QTESTWIDGET_H


 

QTestWidget.cpp

#include "QTestWidget.h"
#include <QPushButton>
#include <QGridLayout>

QTestWidget::QTestWidget(QWidget *parent)
	: QWidget(parent)
	,fTimer(this)
{
	fD3DWidget = new QD3DWidget(this);

	QGridLayout *layout = new QGridLayout(this);
	layout->addWidget(fD3DWidget,0,0,1,2);

	QPushButton *rotateBt = new QPushButton("start rotate");
	QPushButton *endBt = new QPushButton("end rotate");
	layout->addWidget(rotateBt,1,0);
	layout->addWidget(endBt,1,1);

	connect(rotateBt,SIGNAL(clicked()),this,SLOT(startRotate()));
	connect(endBt,SIGNAL(clicked()),this,SLOT(endRotate()));

	connect(&fTimer,SIGNAL(timeout()),fD3DWidget,SLOT(rotateTriangle()));

	layout->setContentsMargins(0,0,0,0);
	layout->setSpacing(0);
}

QTestWidget::~QTestWidget()
{

}

void QTestWidget::startRotate()
{
	fTimer.start(10);
}

void QTestWidget::endRotate()
{
	fTimer.stop();
}


 

main.cpp

#include "testqq.h"
#include <QtWidgets/QApplication>
#include "QTestWidget.h"


int main(int argc, char *argv[])
{
	QApplication a(argc, argv);

	QTestWidget w;
	w.show();

	return a.exec();
}


 

 Link的时候, 添加这几个库:

d3d9.lib
d3dx9.lib
winmm.lib

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
### 回答1: Qt是一个开发桌面和移动应用程序的跨平台C++框架,它提供了丰富的图形绘制和交互功能。 要实现可鼠标旋转三角形,我们可以使用Qt的绘图类和鼠标事件类。 首先, 在Qt创建一个继承自QOpenGLWidget的自定义小部件类。在其重写paintGL()函数来绘制一个三角形(使用OpenGL的绘制函数)。 在鼠标事件,我们需要重写鼠标按下、鼠标移动和鼠标松开事件。当鼠标按下时,我们需要存储鼠标坐标。当鼠标移动时,我们需要计算鼠标移动的偏移量,并利用偏移量来旋转三角形。当鼠标松开时,我们需要清除存储的鼠标坐标。 具体的步骤如下: 1. 创建一个自定义的QOpenGLWidget类,重写paintGL()函数用于绘制三角形。 2. 在类的构造函数设置鼠标追踪功能,以便能够捕获鼠标移动事件。 3. 在类添加成员变量用于存储鼠标按下时的坐标(例如lastPos)。 4. 重写鼠标按下事件,并将当前鼠标坐标保存到lastPos。 5. 重写鼠标移动事件,并计算当前鼠标位置与lastPos之间的偏移量(例如delta)。 6. 在paintGL()函数获取delta,并使用OpenGL的旋转函数来旋转三角形。 7. 重写鼠标松开事件,并清除lastPos的值。 通过以上步骤,我们可以在Qt实现一个可鼠标旋转三角形。当鼠标按下并移动时,三角形会根据鼠标的移动方向进行旋转。 ### 回答2: 要实现用Qt来实现可鼠标旋转三角形,我们可以按照以下步骤进行: 1. 创建一个Qt应用程序窗口。 2. 在窗口,创建一个QOpenGLWidget作为绘图区域,并将其设置为全屏。 3. 在QOpenGLWidget,重写initializeGL()、resizeGL()和paintGL()函数。 4. 在initializeGL()函数,进行OpenGL的初始化工作,包括设置清屏颜色、启用深度测试等。 5. 在resizeGL()函数,根据窗口的大小重新设置OpenGL的视口。 6. 在paintGL()函数,进行具体的绘图操作。首先,使用OpenGL的函数来清屏。然后,使用glRotatef()函数来进行三角形旋转操作。 7. 在QOpenGLWidget,重写mouseMoveEvent()函数,获取鼠标的移动事件。根据鼠标的移动距离,更新三角形旋转角度,并通过update()函数刷新窗口。 8. 在主窗口,创建一个QHBoxLayout,并将QOpenGLWidget添加到其。将该布局设置为窗口的主布局。 9. 运行程序,通过鼠标移动来旋转三角形。 以上是使用Qt来实现可鼠标旋转三角形的大致思路。具体的实现,可能还需要对三角形的顶点坐标进行计算、设置OpenGL的投影矩阵等等。实现方法可以根据具体需求进行调整和优化。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值