This repository has been archived on 2020-09-07. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
libs/qglview/gltypes.cpp

452 lines
12 KiB
C++

/*
QGLView
Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "gltypes.h"
#include "qglview.h"
QGLWidget * currentQGLView;
Camera * currentCamera;
QMatrix4x4 globCameraMatrix;
QMutex globMutex;
QString readCharsUntilNull(QDataStream & s) {
QString str;
char ch;
s.readRawData(&ch, 1);
while (ch != '\0') {
str += ch;
s.readRawData(&ch, 1);
}
return str;
}
QString findFile(const QString & file, const QStringList & pathes) {
QFileInfo fi(QString(file).replace("\\", "/"));
//qDebug() << "search" << file << "in" << pathes;
if (fi.exists()) return fi.absoluteFilePath();
QString fn = fi.fileName();
if (fn.contains("/")) fn = fn.mid(fn.lastIndexOf("/"));
foreach (QString p, pathes) {
QFileInfoList fil = QDir(p).entryInfoList(QStringList(fn), QDir::Files | QDir::NoDotAndDotDot);
//qDebug() << "findFile" << fn << "in" << p << "->" << fil.size();
if (!fil.isEmpty())
return fil[0].absoluteFilePath();
}
return QString();
}
void glDrawQuad(GLfloat x, GLfloat y, GLfloat w, GLfloat h) {
glResetAllTransforms();
glSetPolygonMode(GL_FILL);
glBegin(GL_QUADS);
glColor3f(1.f, 1.f, 1.f);
glTexCoord2f(0.f, 0.f); glVertex2f(x, y);
glTexCoord2f(1.f, 0.f); glVertex2f(x + w, y);
glTexCoord2f(1.f, 1.f); glVertex2f(x + w, y + h);
glTexCoord2f(0.f, 1.f); glVertex2f(x, y + h);
glEnd();
}
QMatrix4x4 getGLMatrix(GLenum matrix) {
GLfloat gm[16];
glGetFloatv(matrix, gm);
qreal qm[16];
for (int i = 0; i < 16; ++i)
qm[i] = gm[i];
return QMatrix4x4(qm).transposed();
}
void setGLMatrix(QMatrix4x4 matrix) {
GLfloat gm[16];
qreal qm[16];
matrix.transposed().copyDataTo(qm);
for (int i = 0; i < 16; ++i)
gm[i] = qm[i];
glLoadMatrixf(gm);
}
void qglMultMatrix(const QMatrix4x4 & m) {
GLdouble gm[16];
qreal qm[16];
m.transposed().copyDataTo(qm);
for (int i = 0; i < 16; ++i)
gm[i] = qm[i];
glMultMatrixd(gm);
}
void createGLTexture(GLuint & tex, int width, int height, const GLenum & format, const GLenum & target) {
glClearError();
if (tex == 0) {
glGenTextures(1, &tex);
glBindTexture(target, tex);
}
//glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
if (format == GL_DEPTH_COMPONENT || format == GL_DEPTH_COMPONENT16 || format == GL_DEPTH_COMPONENT24 || format == GL_DEPTH_COMPONENT32)
glTexImage2D(target, 0, format, width, height, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, 0);
else {
int t = GL_UNSIGNED_BYTE;
if (format == GL_RGB32F || format == GL_RGB16F)
t = GL_FLOAT;
glTexImage2D(target, 0, format, width, height, 0, GL_RGBA, t, 0);
}
//qDebug() << QString::number(glGetError(), 16);
}
void createGLTexture(GLuint & tex, const QImage & image, const GLenum & format, const GLenum & target) {
if (tex == 0) {
glGenTextures(1, &tex);
glBindTexture(target, tex);
}
QImage im = QGLWidget::convertToGLFormat(image);
//const QImage & cim(im);
//glClearError();
//glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
if (target == GL_TEXTURE_1D || target == GL_TEXTURE_2D || target == GL_TEXTURE_3D) {
glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(target, GL_TEXTURE_WRAP_R, GL_REPEAT);
glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(target, GL_GENERATE_MIPMAP_SGIS, GL_TRUE);
}
glTexImage2D(target, 0, format, im.width(), im.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, im.bits());
//qDebug() << tex << im.width() << im.height() << im.bits() << glGetError();
}
QMatrix4x4 glMatrixPerspective(double angle, double aspect, double near_, double far_) {
QMatrix4x4 ret;
double t = 1. / (tan(angle * deg2rad / 2.));
ret(0, 0) = t / aspect;
ret(1, 1) = t;
ret(2, 2) = far_ / (far_ - near_) - 1.;
ret(2, 3) = 2. * far_ * near_ / (far_ - near_);
ret(3, 2) = -1;
ret(3, 3) = 0.;
return ret;
}
QImage rotateQImageLeft(const QImage & im) {
QImage ri(im.height(), im.width(), im.format());
QPainter p(&ri);
p.rotate(90);
p.drawImage(0, -im.height(), im);
p.end();
return ri;
}
QImage rotateQImageRight(const QImage & im) {
QImage ri(im.height(), im.width(), im.format());
QPainter p(&ri);
p.rotate(-90);
p.drawImage(-im.width(), 0, im);
p.end();
return ri;
}
void Camera::anglesFromPoints() {
QVector3D dv = aim_ - pos_, tv;
tv = QVector3D(dv.x(), dv.y(), 0.);
angle_z = atan2(tv.x(), tv.y()) * rad2deg;
angle_xy = piClamp<GLdouble>(atan2(tv.length(), dv.z()) * rad2deg + 180., angle_limit_lower_xy, angle_limit_upper_xy);
}
void Camera::apply(const GLdouble & aspect) {
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
if (aspect <= 1.)
glScaled(aspect, aspect, 1.);
QMatrix4x4 pm;// = glMatrixPerspective(fov_, aspect, depth_start, depth_end);
pm.perspective(fov_, aspect, depth_start, depth_end);
//qDebug() << pm << glMatrixPerspective(fov_, aspect, depth_start, depth_end);;
setGLMatrix(pm);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslated(0., 0., -distance());
glRotated(angle_xy, 1., 0., 0.);
glRotated(angle_roll, 0., -1., 0.);
glRotated(angle_z, 0., 0., 1.);
//glTranslated(pos_.x(), pos_.y(), pos_.z());
//if (mirror_y) glScalef(1,-1,-1);
//if (mirror_x) glScalef(-1,1,-1);
//glScalef(-1,-1,1);
glTranslated(-aim_.x(), -aim_.y(), -aim_.z());
glGetIntegerv(GL_VIEWPORT, viewport);
glGetDoublev(GL_PROJECTION_MATRIX, projection);
glGetDoublev(GL_MODELVIEW_MATRIX, modelview);
//qDebug() << "viewport" << viewport[0] << viewport[1] << viewport[2] << viewport[3];
}
void Camera::panZ(const double & a) {
QVector3D dv = aim_ - pos_;
double tl = QVector2D(dv.x(), dv.y()).length();
angle_z += a;
dv = QVector3D(sin(angle_z * deg2rad) * tl, cos(angle_z * deg2rad) * tl, dv.z());
aim_ = pos_ + dv;
}
void Camera::panXY(const double & a) {
QVector3D dv = aim_ - pos_;
double tl = dv.length(), tc;
angle_xy += a;
angle_xy = piClamp<GLdouble>(angle_xy, angle_limit_lower_xy, angle_limit_upper_xy);
tc = -sin(angle_xy * deg2rad);
dv = QVector3D(sin(angle_z * deg2rad) * tl * tc, cos(angle_z * deg2rad) * tl * tc, -cos(angle_xy * deg2rad) * tl);
aim_ = pos_ + dv;
}
void Camera::rotateZ(const double & a) {
QVector3D dv = aim_ - pos_;
double tl = QVector2D(dv.x(), dv.y()).length();
angle_z += a;
dv = QVector3D(sin(angle_z * deg2rad) * tl, cos(angle_z * deg2rad) * tl, dv.z());
aim_ = pos_ + dv;
}
void Camera::rotateXY(const double & a) {
QVector3D dv = aim_ - pos_;
double tl = dv.length(), tc;
angle_xy += a;
angle_xy = piClamp<GLdouble>(angle_xy, angle_limit_lower_xy, angle_limit_upper_xy);
tc = -sin(angle_xy * deg2rad);
dv = QVector3D(sin(angle_z * deg2rad) * tl * tc, cos(angle_z * deg2rad) * tl * tc, -cos(angle_xy * deg2rad) * tl);
aim_ = pos_ + dv;
}
void Camera::orbitZ(const double & a) {
QVector3D dv = aim_ - pos_;
double tl = QVector2D(dv.x(), dv.y()).length();
angle_z += a;
dv = QVector3D(sin(angle_z * deg2rad) * tl, cos(angle_z * deg2rad) * tl, dv.z());
pos_ = aim_ - dv;
}
void Camera::orbitXY(const double & a) {
QVector3D dv = aim_ - pos_;
double tl = dv.length(), tc;
angle_xy += a;
angle_xy = piClamp<GLdouble>(angle_xy, angle_limit_lower_xy, angle_limit_upper_xy);
tc = -sin(angle_xy * deg2rad);
dv = QVector3D(sin(angle_z * deg2rad) * tl * tc, cos(angle_z * deg2rad) * tl * tc, -cos(angle_xy * deg2rad) * tl);
pos_ = aim_ - dv;
}
void Camera::setAngleZ(const double & a) {
QVector3D dv = aim_ - pos_;
double tl = QVector2D(dv.x(), dv.y()).length();
angle_z = a;
dv = QVector3D(sin(angle_z * deg2rad) * tl, cos(angle_z * deg2rad) * tl, dv.z());
aim_ = pos_ + dv;
}
void Camera::setAngleXY(const double & a) {
QVector3D dv = aim_ - pos_;
double tl = dv.length(), tc;
angle_xy = a;
tc = -sin(angle_xy * deg2rad);
dv = QVector3D(sin(angle_z * deg2rad) * tl * tc, cos(angle_z * deg2rad) * tl * tc, -cos(angle_xy * deg2rad) * tl);
//pos_ = aim_ - dv;
aim_ = pos_ + dv;
//anglesFromPoints();
}
void Camera::moveForward(const double & x, bool withZ) {
QVector3D dv;// = aim_ - pos_;
double tc = -sin(angle_xy * deg2rad);
dv = QVector3D(sin(angle_z * deg2rad) * tc, cos(angle_z * deg2rad) * tc, 0.);
if (withZ) dv.setZ(-cos(angle_xy * deg2rad));
dv.normalize();
dv *= x;
pos_ += dv;
aim_ += dv;
}
void Camera::moveLeft(const double & x, bool withZ) {
QVector3D dv;// = aim_ - pos_;
double tc = -sin(angle_xy * deg2rad);
dv = QVector3D(sin(angle_z * deg2rad - M_PI_2) * tc, cos(angle_z * deg2rad - M_PI_2) * tc, 0.);
if (withZ) dv.setZ(-sin(angle_roll * deg2rad));
dv.normalize();
dv *= x;
pos_ += dv;
aim_ += dv;
}
void Camera::moveUp(const double & x, bool onlyZ) {
QVector3D dv;
if (onlyZ)
dv = QVector3D(0., 0., x);
else {
double tc = cos(angle_xy * deg2rad);
dv = QVector3D(sin(angle_z * deg2rad) * tc, cos(angle_z * deg2rad) * tc, -sin(angle_xy * deg2rad));
dv.normalize();
dv *= x;
}
pos_ += dv;
aim_ += dv;
}
void Camera::flyCloser(const double & s) {
QVector3D dv = aim_ - pos_;
double tl = dv.length() / (1. + s), tc = -sin(angle_xy * deg2rad);
dv = QVector3D(sin(angle_z * deg2rad) * tl * tc, cos(angle_z * deg2rad) * tl * tc, -cos(angle_xy * deg2rad) * tl);
pos_ = aim_ - dv;
}
void Camera::flyFarer(const double & s) {
QVector3D dv = aim_ - pos_;
double tl = dv.length() * (1. + s), tc = -sin(angle_xy * deg2rad);
dv = QVector3D(sin(angle_z * deg2rad) * tl * tc, cos(angle_z * deg2rad) * tl * tc, -cos(angle_xy * deg2rad) * tl);
pos_ = aim_ - dv;
}
void Camera::flyToDistance(const double & d) {
QVector3D dv = aim_ - pos_;
double tc = -sin(angle_xy * deg2rad);
dv = QVector3D(sin(angle_z * deg2rad) * d * tc, cos(angle_z * deg2rad) * d * tc, -cos(angle_xy * deg2rad) * d);
pos_ = aim_ - dv;
}
QVector3D Camera::pointFromViewport(int x_, int y_, double z_) {
GLsizei mx = x_, my = viewport[3] - y_, mz = z_;
GLdouble x,y,z;
gluUnProject(mx, my, mz, modelview, projection, viewport, &x, &y, &z);
return QVector3D(x,y,z);
}
QColor colorFromString(const QString & str) {
QString s = str.trimmed();
int i = s.indexOf("\t");
double r, g, b;
r = s.left(i).toFloat(); s = s.right(s.length() - i - 1); i = s.indexOf("\t");
g = s.left(i).toFloat(); s = s.right(s.length() - i - 1);
b = s.toFloat();
return QColor(r * 255., g * 255., b * 255.);
}
QVector3D orthToVector(const QVector3D & v, const double & scale) {
if (v.isNull()) return QVector3D();
QVector3D rv, fn, sn;
if (v.x() != 0) rv.setZ(1.);
else if (v.y() != 0) rv.setX(1.);
else rv.setY(1.);
fn = QVector3D::crossProduct(v, rv).normalized();
sn = QVector3D::crossProduct(v, fn).normalized();
return fn * urand(scale) + sn * urand(scale);
}
QVector3D rotateVector(const QVector3D & v, const QVector3D & a) {
QMatrix4x4 m;
m.rotate(a.z(), 0., 0., 1.);
m.rotate(a.y(), 0., 1., 0.);
m.rotate(a.x(), 1., 0., 0.);
return m * v;
}
void setVectorLength(QVector3D & v, const double & l) {
double vl = v.length();
if (vl == 0.) return;
double c = l / vl;
v *= c;
}
void lengthenVector(QVector3D & v, const double & l) {
double vl = v.length();
if (l == 0. || vl == 0.) return;
double c = 1. + l / vl;
v *= c;
}
Vector3d::Vector3d(const QString & str) {
QString s = str.trimmed();
int i = s.indexOf("\t");
x = s.left(i).toFloat(); s = s.right(s.length() - i - 1); i = s.indexOf("\t");
y = s.left(i).toFloat(); s = s.right(s.length() - i - 1);
z = s.toFloat();
}
Vector3i::Vector3i(const QString & str) {
QString s = str.trimmed();
int i = s.indexOf("\t");
p0 = s.left(i).toInt(); s = s.right(s.length() - i - 1); i = s.indexOf("\t");
p1 = s.left(i).toInt(); s = s.right(s.length() - i - 1);
p2 = s.toInt();
}
void glEnableDepth() {
glEnable(GL_DEPTH_TEST);
//glDepthFunc(GL_GREATER);
glDepthFunc(GL_LESS);
glDepthMask(GL_TRUE);
}
void glDisableDepth() {
glDisable(GL_DEPTH_TEST);
glDepthMask(GL_FALSE);
}
void glClearFramebuffer(const QColor & color, bool depth) {
glClearColor(color.redF(), color.greenF(), color.blueF(), color.alphaF());
glClearDepth(1.);
if (depth)
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
else
glClear(GL_COLOR_BUFFER_BIT);
}