這一篇,是把上一篇的文章改成一個class
header file
#include <QString>
#include <QFont>
#include <QVector3D>
#include <QVector>
class Mesh{
public:
QVector<QVector3D> points;
QVector<QVector3D> normals;
QVector<int> lengths;
QVector<unsigned int> types;
};
class Text3D
{
public:
Text3D(QString text, QFont font, qreal size = 0.5f);
Mesh getEdge(){return edge;}
Mesh getEdge3D(){return edge3D;}
Mesh get2D(){return front;}
Mesh get3D(){return all;}
private:
void extrude(QPointF prePoint, QPointF point, qreal z);
Mesh face(QList<QPolygonF> polygons, qreal z);
void merge(Mesh mesh);
Mesh edge;
Mesh edge3D;
Mesh front;
Mesh all;
};
source file
#include <QPainterPath>
#include <GL/glu.h>
#ifndef CALLBACK
#define CALLBACK
#endif
Text3D::Text3D(QString text, QFont font, qreal size)
{
size = size*0.5;
QPainterPath path;
path.addText(QPointF(0, 0), font, text);
QRectF rect = path.boundingRect();
QPointF center = rect.center();
// move to center;
QList<QPolygonF> polygons;
foreach(QPolygonF path, path.toSubpathPolygons()){
QPolygonF polygon;
foreach(QPointF point, path){
polygon << point - center;
}
polygons << polygon;
}
// edge
foreach(QPolygonF polygon, polygons){
foreach(QPointF point, polygon){
edge.points << QVector3D(point);
edge.normals << QVector3D(0,0,1);
}
edge.lengths << polygon.count();
edge.types << GL_LINE_LOOP;
}
// 3d edge
foreach(QPolygonF polygon, polygons){
QPointF startPoint,prePoint;
foreach(QPointF point, polygon){
if(startPoint.isNull()){
startPoint = point;
}else{
extrude(prePoint, point, size);
}
prePoint = point;
}
extrude(prePoint, startPoint, size);
edge3D.lengths << polygon.count()*6;
edge3D.types << GL_TRIANGLES;
}
//front
front = face(polygons, size);
//back
QList<QPolygonF> invertPolygons;
foreach(QPolygonF path, polygons){
QPolygonF polygon;
for(int i = path.count()-1; i>=0; i--){
polygon << path.at(i);
}
invertPolygons << polygon;
}
Mesh back = face(invertPolygons, -size);
merge(front);
merge(back);
merge(edge3D);
}
void Text3D::extrude(QPointF prePoint, QPointF point, qreal z)
{
qreal x1 = prePoint.rx();
qreal y1 = prePoint.ry();
qreal x2 = point.rx();
qreal y2 = point.ry();
edge3D.points << QVector3D(x1, y1, +z);
edge3D.points << QVector3D(x2, y2, +z);
edge3D.points << QVector3D(x1, y1, -z);
edge3D.points << QVector3D(x2, y2, -z);
edge3D.points << QVector3D(x1, y1, -z);
edge3D.points << QVector3D(x2, y2, +z);
QVector3D n = QVector3D::normal
(QVector3D(x2 - x1, y2 - y1, 0.0f), QVector3D(0.0f, 0.0f, -0.1f));
edge3D.normals << n;
edge3D.normals << n;
edge3D.normals << n;
edge3D.normals << n;
edge3D.normals << n;
edge3D.normals << n;
}
QVector<QVector3D> tessPoints;
QVector<QVector3D> tessNormals;
QVector<int> tessLengths;
QVector<unsigned int> tessTypes;
int counter;
void CALLBACK tessBeginCB(GLenum which)
{
tessTypes << which;
counter=0;
}
void CALLBACK tessEndCB()
{
tessLengths << counter;
}
void CALLBACK tessVertexCB(const GLvoid *data)
{
const GLdouble *ptr = (const GLdouble*)data;
tessPoints << QVector3D(ptr[0], ptr[1], ptr[2]);
tessNormals << QVector3D(0,0,1);
counter++;
}
#include <QDebug>
void CALLBACK errorCB(GLenum errorCode){
const GLubyte *estring;
estring = gluErrorString(errorCode);
qDebug()<<estring;
}
Mesh Text3D::face(QList<QPolygonF> polygons, qreal z)
{
tessPoints.clear();
tessNormals.clear();
tessLengths.clear();
tessTypes.clear();
GLUtesselator *tess = gluNewTess();
gluTessCallback(tess, GLU_TESS_BEGIN, (void (__stdcall *)())tessBeginCB);
gluTessCallback(tess, GLU_TESS_END, (void (__stdcall *)())tessEndCB);
gluTessCallback(tess, GLU_TESS_VERTEX, (void (__stdcall *)())tessVertexCB);
gluTessCallback(tess, GLU_TESS_ERROR, (void (__stdcall *)())errorCB);
gluTessBeginPolygon(tess, NULL);
foreach(QPolygonF polygon, polygons){
GLdouble (*quad)[3] = new GLdouble[polygon.count()][3];
for(int i=0; i<polygon.count(); i++){
QPointF point = polygon.at(i);
quad[i][0] = point.rx();
quad[i][1] = point.ry();
quad[i][2] = z;
}
gluTessBeginContour(tess);
for(int i=0; i<polygon.count(); i++){
gluTessVertex(tess, quad[i], quad[i]);
}
gluTessEndContour(tess);
}
gluTessEndPolygon(tess);
gluDeleteTess(tess);
Mesh mesh;
mesh.points = tessPoints;
mesh.normals = tessNormals;
mesh.lengths = tessLengths;
mesh.types = tessTypes;
return mesh;
}
void Text3D::merge(Mesh mesh)
{
all.points << mesh.points;
all.normals << mesh.normals;
all.lengths << mesh.lengths;
all.types << mesh.types;
}
沒有留言:
張貼留言