使用QPainter画一个3D正方体

本文实例为大家分享了QPainter画一个3D正的具体代码,供大家参考,具体内容如下

My3DBox .h

#include <Eigen/Geometry>

using namespace Eigen;

#define SQUARE_LENGTH 200//是一个边长200的正方体

#define CAMERA_DISTANCE 300//视点距离

class My3DBox : public QWidget

{

Q_OBJECT

public:

explicit My3DBox(QWidget *parent = 0);

protected:

QPoint m_mousePos;

Vector3d m_vector[8];//正方形8个点坐标

void mouseMoveEvent(QMouseEvent *);

void paintEvent(QPaintEvent *);

void drawPlane(const QPoint *points,QPainter &painter);

Matrix3d getMartix();

QPoint ToPoint(Vector3d vector);

void drawUp(QPoint *points,QPainter &painter);//正方体面的绘制

void drawDown(QPoint *points,QPainter &painter);

void drawLeft(QPoint *points,QPainter &painter);

void drawRight(QPoint *points,QPainter &painter);

};

My3DBox .cpp

#include "widget.h"

#define PI 3.1415926

My3DBox::My3DBox(QWidget *parent) :

QWidget(parent),m_mousePos(0,0)

{

setMouseTracking(true);//在任何情况下启用mouseMoveEvent

setGeometry(400,200,500,500);

m_vector[0] << -100,100,100;//设置正方体顶点初始位置

m_vector[1] << 100,100,100;

m_vector[2] << -100,-100,100;

m_vector[3] << 100,-100,100;

m_vector[4] << -100,100,-100;

m_vector[5] << 100,100,-100;

m_vector[6] << -100,-100,-100;

m_vector[7] << 100,-100,-100;

}

void My3DBox::mouseMoveEvent(QMouseEvent *e)//此处把坐标原点从左上角变换至屏幕中心

{

if(e->pos().x() < 0)

m_mousePos.setX(-width()/2);

else if(e->pos().x() > width())

m_mousePos.setX(width()/2);

else

m_mousePos.setX(e->pos().x() - width()/2);

if(e->pos().y() < 0)

m_mousePos.setY(height()/2);

else if(e->pos().y() > height())

m_mousePos.setY(-height()/2);

else

m_mousePos.setY(-e->pos().y() + height()/2);

update();

}

void My3DBox::paintEvent(QPaintEvent *)

{

QPainter painter(this);

painter.setRenderHint(QPainter::Antialiasing);

painter.setRenderHint(QPainter::SmoothPixmapTransform);

painter.setPen(Qt::NoPen);

painter.fillRect(rect(),QColor(3,22,52));

Vector3d vector[8];

Matrix3d matrix = getMartix();//获取变换矩阵

QPoint points[8];//正面0123 左面4062 右面1537 上面4501 下面 2367(以观察者的方向为主)

for(int i = 0;i < 8;++i)//计算变换后坐标

{

vector[i] = matrix*m_vector[i];

points[i] = ToPoint(vector[i]);

points[i].setX(points[i].x()+width()/2);//将坐标系原点变换至左上角

points[i].setY(-points[i].y()+height()/2);

}

//一共要画5个面,最后画正面

if(qAbs(m_mousePos.x()) > qAbs(m_mousePos.y()))

{

if(m_mousePos.x() > 0)

{

if(m_mousePos.y() > 0)

drawDown(points,painter);

else

drawUp(points,painter);

drawLeft(points,painter);

}

else

{

if(m_mousePos.y() > 0)

drawDown(points,painter);

else

drawUp(points,painter);

drawRight(points,painter);

}

}

else

{

if(m_mousePos.y() > 0)

{

if(m_mousePos.x() > 0)

drawLeft(points,painter);

else

drawRight(points,painter);

drawDown(points,painter);

}

else

{

if(m_mousePos.x() > 0)

drawLeft(points,painter);

else

drawRight(points,painter);

drawUp(points,painter);

}

}

//画正面

QPoint point[4] =

{

points[0],

points[1],

points[3],

points[2]

};

drawPlane(point,painter);

}

void My3DBox::drawPlane(const QPoint *points,QPainter &painter)

{

QLinearGradient linearGradient(points[1],points[3]);//设置渐变色

linearGradient.setColorAt(0.0,QColor(150,150,250));

linearGradient.setColorAt(1.0,QColor(170,170,255));

painter.setBrush(QBrush(linearGradient));

painter.drawConvexPolygon(points,4);

}

Matrix3d My3DBox::getMartix()

{

double unit_x = 0;//同方向单位向量的x和y

double unit_y = 0;

double z = 0;

if(m_mousePos.x() != 0 || m_mousePos.y() != 0)

{

unit_x = m_mousePos.x()/qSqrt(m_mousePos.x()*m_mousePos.x() + m_mousePos.y()*m_mousePos.y());

unit_y = m_mousePos.y()/qSqrt(m_mousePos.x()*m_mousePos.x() + m_mousePos.y()*m_mousePos.y());

z = qSqrt(m_mousePos.x()*m_mousePos.x() + m_mousePos.y()*m_mousePos.y())/qSqrt(width()*width()/4 + height()*height()/4);

}

Matrix3d M_Z;

if(unit_x == 0 && unit_y == 0)

M_Z << 1,0,0,

0,1,0,

0,0,1;

else

M_Z << unit_y,-unit_x,0,

unit_x,unit_y,0,

0,0,1;

Matrix3d M_X;

if(z == 0)

M_X << 1,0,0,

0,1,0,

0,0,1;

else

M_X << 1,0,0,

0,cos(z*PI/2.6),sin(z*PI/2.6),

0,-sin(z*PI/2.6),cos(z*PI/2.6);//为什么PI/2大于90度?因为没画背面所以必须小于90度(偷懒)

return M_Z.inverse()*M_X*M_Z;

}

QPoint My3DBox::ToPoint(Vector3d vector)//将3d坐标投影至平面上

{

QPoint point;

point.setX(CAMERA_DISTANCE*vector[0]/(CAMERA_DISTANCE-vector[2]));

point.setY(CAMERA_DISTANCE*vector[1]/(CAMERA_DISTANCE-vector[2]));

return point;

}

void My3DBox::drawUp(QPoint *points,QPainter &painter)

{

QPoint point[4] =

{

points[4],

points[5],

points[1],

points[0]

};

drawPlane(point,painter);

}

void My3DBox::drawDown(QPoint *points,QPainter &painter)

{

QPoint point[4] =

{

points[2],

points[3],

points[7],

points[6]

};

drawPlane(point,painter);

}

void My3DBox::drawLeft(QPoint *points,QPainter &painter)

{

QPoint point[4] =

{

points[4],

points[0],

points[2],

points[6]

};

drawPlane(point,painter);

}

void My3DBox::drawRight(QPoint *points,QPainter &painter)

{

QPoint point[4] =

{

points[1],

points[5],

points[7],

points[3]

};

drawPlane(point,painter);

}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。

以上是 使用QPainter画一个3D正方体 的全部内容, 来源链接: utcz.com/p/245492.html

回到顶部