336 lines
15 KiB
C++
336 lines
15 KiB
C++
/*
|
|
QGLView
|
|
Copyright (C) 2017 Ivan Pelipenko peri4ko@yandex.ru
|
|
|
|
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/>.
|
|
*/
|
|
|
|
#ifndef GLTYPES_H
|
|
#define GLTYPES_H
|
|
|
|
#if WIN32 || WIN64 || _WIN32 || _WIN64 || __WIN32__ || __WIN64__
|
|
# define WINDOWS
|
|
#endif
|
|
#if __QNX__ || __QNXNTO__
|
|
# define QNX
|
|
#endif
|
|
#ifdef __APPLE__
|
|
# define MAC
|
|
#endif
|
|
#ifndef WINDOWS
|
|
# ifndef QNX
|
|
# ifndef MAC
|
|
# define LINUX
|
|
# endif
|
|
# endif
|
|
#endif
|
|
#if __GNUC__
|
|
# define CC_GCC
|
|
#elif _MSC_VER
|
|
# define CC_VC
|
|
#endif
|
|
|
|
#define GL_GLEXT_PROTOTYPES
|
|
#ifdef WINDOWS
|
|
# include "GLee.h"
|
|
#else
|
|
# ifdef MAC
|
|
# include <OpenGL/gl.h>
|
|
# include <OpenGL/glu.h>
|
|
# include <GLUT/glut.h>
|
|
# else
|
|
# include <GL/gl.h>
|
|
# include <GL/glext.h>
|
|
# include <GL/glu.h>
|
|
# endif
|
|
#endif
|
|
#include <qgl.h>
|
|
#include <cmath>
|
|
#include <float.h>
|
|
//#include <limits>
|
|
#include <QMatrix4x4>
|
|
#include <QObject>
|
|
#include <QDebug>
|
|
#include <QDataStream>
|
|
#include <QColor>
|
|
#include <QVector2D>
|
|
#include <QVector3D>
|
|
#include <QImage>
|
|
#include <QMutex>
|
|
#include <QFile>
|
|
#include <QDir>
|
|
#include <QGLShaderProgram>
|
|
#ifndef QNX
|
|
# include <cmath>
|
|
# include <complex>
|
|
#else
|
|
# include <math.h>
|
|
# include <complex.h>
|
|
#endif
|
|
#include <iostream>
|
|
|
|
#ifdef WINDOWS
|
|
# define GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT 0x84FF
|
|
# define GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE
|
|
#endif
|
|
|
|
#ifdef CC_VC
|
|
# define M_PI 3.14159265358979323846
|
|
#endif
|
|
#define M_2PI 6.28318530717958647692
|
|
#define M_PI_3 1.04719755119659774615
|
|
|
|
#ifndef GL_RGBA16F
|
|
# define GL_RGBA16F GL_RGBA16F_ARB
|
|
#endif
|
|
|
|
using std::complex;
|
|
|
|
#ifndef PIP_VERSION
|
|
typedef long long llong;
|
|
typedef unsigned char uchar;
|
|
typedef unsigned short int ushort;
|
|
typedef unsigned int uint;
|
|
typedef unsigned long ulong;
|
|
typedef unsigned long long ullong;
|
|
typedef long double ldouble;
|
|
|
|
const double deg2rad = atan(1.) / 45.;
|
|
const double rad2deg = 45. / atan(1.);
|
|
|
|
# ifdef WINDOWS
|
|
inline int random() {return rand();}
|
|
# endif
|
|
#else
|
|
#define random randomi
|
|
#endif
|
|
|
|
#ifdef CC_VC
|
|
inline double round(const double & v) {return floor(v + 0.5);}
|
|
#endif
|
|
inline double randomu() {return double(random()) / RAND_MAX;}
|
|
|
|
inline const QSizeF operator *(const QSizeF & f, const QSizeF & s) {return QSizeF(f.width() * s.width(), f.height() * s.height());}
|
|
#ifndef PIP_VERSION
|
|
template<typename Type> inline void piSwap(Type & f, Type & s) {Type t = f; f = s; s = t;}
|
|
template<typename Type> inline Type piMin(const Type & f, const Type & s) {return (f > s) ? s : f;}
|
|
template<typename Type> inline Type piMin(const Type & f, const Type & s, const Type & t) {return (f < s && f < t) ? f : ((s < t) ? s : t);}
|
|
template<typename Type> inline Type piMax(const Type & f, const Type & s) {return (f < s) ? s : f;}
|
|
template<typename Type> inline Type piMax(const Type & f, const Type & s, const Type & t) {return (f > s && f > t) ? f : ((s > t) ? s : t);}
|
|
template<typename Type> inline Type piClamp(const Type & v, const Type & min, const Type & max) {return (v > max ? max : (v < min ? min : v));}
|
|
inline ushort letobe_s(ushort v) {return (v << 8) | (v >> 8);}
|
|
#endif
|
|
// return [-1, 1]
|
|
inline double urand(const double & scale = 1.) {return ((double)rand() / RAND_MAX - .5) * (scale + scale);}
|
|
// return [0, 1]
|
|
inline double uprand(const double & scale = 1.) {return ((double)rand() / RAND_MAX) * scale;}
|
|
QString readCharsUntilNull(QDataStream & s);
|
|
QString findFile(const QString & file, const QStringList & pathes);
|
|
inline QColor operator *(const QColor & c, double v) {return QColor(c.red() * v, c.green() * v, c.blue() * v, c.alpha() * v);}
|
|
inline QColor operator /(const QColor & c, double v) {return QColor(c.red() / v, c.green() / v, c.blue() / v, c.alpha() / v);}
|
|
|
|
inline void qglColor(const QColor & c) {glColor4f(c.redF(), c.greenF(), c.blueF(), c.alphaF());}
|
|
void qglMultMatrix(const QMatrix4x4 & m);
|
|
void glEnableDepth();
|
|
void glDisableDepth();
|
|
inline void glActiveTextureChannel(int channel) {glActiveTexture(GL_TEXTURE0 + channel); glClientActiveTexture(GL_TEXTURE0 + channel);}
|
|
inline void glResetAllTransforms() {glMatrixMode(GL_TEXTURE); glLoadIdentity(); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glMatrixMode(GL_MODELVIEW); glLoadIdentity();}
|
|
inline void glClearError() {int c = 100; while (glGetError() != GL_NO_ERROR && --c > 0) glGetError();}
|
|
inline void glClearAccumulation(const QColor & color = Qt::black) {glClearAccum(color.redF(), color.greenF(), color.blueF(), color.alphaF()); glClear(GL_ACCUM_BUFFER_BIT);}
|
|
void glClearFramebuffer(const QColor & color = Qt::black, bool depth = true);
|
|
inline void glReleaseTextures(int channels = 8) {for (int i = channels - 1; i >= 0; --i) {glActiveTextureChannel(i); glBindTexture(GL_TEXTURE_2D, 0); glBindTexture(GL_TEXTURE_CUBE_MAP, 0);}}
|
|
inline void glReleaseFramebuffer() {glBindFramebuffer(GL_FRAMEBUFFER, 0);}
|
|
inline void glDisableTextures(int channels = 8) {for (int i = channels - 1; i >= 0; --i) {glActiveTextureChannel(i); glDisable(GL_TEXTURE_2D); glDisable(GL_TEXTURE_CUBE_MAP);}}
|
|
inline void glReleaseShaders() {glUseProgram(0);}
|
|
inline void glSetCapEnabled(GLenum cap, bool on = true) {if (on) glEnable(cap); else glDisable(cap);}
|
|
inline void glSetLightEnabled(bool on) {if (on) glEnable(GL_LIGHTING); else glDisable(GL_LIGHTING);}
|
|
inline void glSetFogEnabled(bool on) {if (on) glEnable(GL_FOG); else glDisable(GL_FOG);}
|
|
inline void glSetPolygonMode(GLenum mode) {glPolygonMode(GL_FRONT_AND_BACK, mode);}
|
|
void glDrawQuad(QGLShaderProgram * prog = 0, QVector4D * corner_dirs = 0, GLfloat x = -1.f, GLfloat y = -1.f, GLfloat w = 2.f, GLfloat h = 2.f);
|
|
QMatrix4x4 getGLMatrix(GLenum matrix);
|
|
void setGLMatrix(QMatrix4x4 matrix);
|
|
inline void deleteGLTexture(GLuint & tex) {if (tex != 0) glDeleteTextures(1, &tex); tex = 0;}
|
|
inline void deleteGLFramebuffer(GLuint & fbo) {if (fbo != 0) glDeleteFramebuffers(1, &fbo); fbo = 0;}
|
|
inline void deleteGLRenderbuffer(GLuint & drbo) {if (drbo != 0) glDeleteRenderbuffers(1, &drbo); drbo = 0;}
|
|
inline void deleteGLBuffer(GLuint & bo) {if (bo != 0) glDeleteBuffers(1, &bo); bo = 0;}
|
|
inline void deleteGLVertexArray(GLuint & va) {if (va != 0) glDeleteVertexArrays(1, &va); va = 0;}
|
|
void createGLTexture(GLuint & tex, int width, int height, const GLenum & format = GL_RGBA8, const GLenum & target = GL_TEXTURE_2D);
|
|
void createGLTexture(GLuint & tex, const QImage & image, const GLenum & format = GL_RGBA8, const GLenum & target = GL_TEXTURE_2D);
|
|
inline void qglTranslate(const QVector3D & v) {glTranslated(v.x(), v.y(), v.z());}
|
|
inline void qglScale(const QVector3D & v) {glScaled(v.x(), v.y(), v.z());}
|
|
QMatrix4x4 glMatrixPerspective(double angle, double aspect, double near_, double far_);
|
|
QImage rotateQImageLeft(const QImage & im);
|
|
QImage rotateQImageRight(const QImage & im);
|
|
inline QImage rotateQImage180(const QImage & im) {return im.mirrored(true, true);}
|
|
//const double deg2rad = atan(1.) / 45.;
|
|
//const double rad2deg = 45. / atan(1.);
|
|
|
|
extern QGLWidget * currentQGLView;
|
|
extern QMutex globMutex;
|
|
|
|
struct Box3D {
|
|
GLfloat x;
|
|
GLfloat y;
|
|
GLfloat z;
|
|
GLfloat width;
|
|
GLfloat length;
|
|
GLfloat height;
|
|
GLfloat angle_z;
|
|
GLfloat angle_xy;
|
|
GLfloat angle_roll;
|
|
Box3D() {x = y = z = width = length = height = angle_z = angle_xy = angle_roll = 0.f;}
|
|
Box3D(const QVector3D & center, GLfloat hwid, GLfloat hlen, GLfloat hhei) {x = center.x() - hwid; y = center.y() - hlen; z = center.z() - hhei; width = 2 * hwid; length = 2 * hlen; height = 2 * hhei; angle_z = angle_xy = angle_roll = 0.f;}
|
|
QVector3D randomPoint() const {return QVector3D(uprand(length) + x, uprand(width) + y, uprand(height) + z);}
|
|
QVector3D pos() const {return QVector3D(x, y, z);}
|
|
QVector3D size() const {return QVector3D(length, width, height);}
|
|
QVector3D center() const {return QVector3D(length / 2. + x, width / 2. + y, height / 2. + z);}
|
|
QVector3D angles() const {return QVector3D(angle_xy, angle_roll, angle_z);}
|
|
void setPos(const QVector3D & p) {x = p.x(); y = p.y(); z = p.z();}
|
|
void setAngles(const QVector3D & a) {angle_xy = a.x(); angle_roll = a.y(); angle_z = a.z();}
|
|
void setSize(const QVector3D & s) {length = s.x(); width = s.y(); height = s.z();}
|
|
Box3D & moveTo(const QVector3D & v) {x = v.x(); y = v.y(); z = v.z(); return *this;}
|
|
Box3D & move(const QVector3D & v) {x += v.x(); y += v.y(); z += v.z(); return *this;}
|
|
Box3D movedTo(const QVector3D & v) const {Box3D t(*this); t.x = v.x(); t.y = v.y(); t.z = v.z(); return t;}
|
|
Box3D moved(const QVector3D & v) const {Box3D t(*this); t.x += v.x(); t.y += v.y(); t.z += v.z(); return t;}
|
|
};
|
|
|
|
inline QDebug operator <<(QDebug d, const Box3D & v) {d << "Box3D {center (" << v.x << "," << v.y << "," << v.z << "), size (" << v.length << "," << v.width << "," << v.height << ")}"; return d;}
|
|
|
|
struct Vector3d;
|
|
|
|
GLfloat dot(const Vector3d & v0, const Vector3d & v1);
|
|
|
|
struct Vector3d {
|
|
GLfloat x;
|
|
GLfloat y;
|
|
GLfloat z;
|
|
Vector3d(GLfloat x_ = 0., GLfloat y_ = 0., GLfloat z_ = 0.) {x = x_; y = y_; z = z_;}
|
|
Vector3d(const QVector3D & v) {x = v.x(); y = v.y(); z = v.z();}
|
|
Vector3d(const QString & str);
|
|
inline void clear() {x = y = z = 0.;}
|
|
inline GLfloat length() const {return sqrt(x*x + y*y + z*z);}
|
|
inline GLfloat lengthSquared() const {return x*x + y*y + z*z;}
|
|
Vector3d & normalize() {
|
|
GLfloat l = length();
|
|
if (l == 0.) return *this;
|
|
x /= l; y /= l; z /= l;
|
|
return *this;
|
|
};
|
|
Vector3d normalized() {return Vector3d(*this).normalize();}
|
|
Vector3d projectTo(Vector3d dir) {dir.normalize(); return dir * dot(dir, *this);}
|
|
Vector3d operator *(const GLfloat v) {return Vector3d(x*v, y*v, z*v);}
|
|
Vector3d operator /(const GLfloat v) {return Vector3d(x/v, y/v, z/v);}
|
|
Vector3d operator +(const GLfloat v) {return Vector3d(x+v, y+v, z+v);}
|
|
Vector3d operator -(const GLfloat v) {return Vector3d(x-v, y-v, z-v);}
|
|
Vector3d operator +(const Vector3d & v) {return Vector3d(x + v.x, y + v.y, z + v.z);}
|
|
Vector3d operator -(const Vector3d & v) {return Vector3d(x - v.x, y - v.y, z - v.z);}
|
|
Vector3d operator -() {return Vector3d(-x, -y, -z);}
|
|
Vector3d & operator *=(const GLfloat & v) {x *= v; y *= v; z *= v; return *this;}
|
|
Vector3d & operator /=(const GLfloat & v) {x /= v; y /= v; z /= v; return *this;}
|
|
Vector3d & operator +=(const GLfloat & v) {x += v; y += v; z += v; return *this;}
|
|
Vector3d & operator -=(const GLfloat & v) {x -= v; y -= v; z -= v; return *this;}
|
|
Vector3d & operator +=(const Vector3d & v) {x += v.x; y += v.y; z += v.z; return *this;}
|
|
Vector3d & operator -=(const Vector3d & v) {x -= v.x; y -= v.y; z -= v.z; return *this;}
|
|
bool operator ==(const Vector3d & v) {return x == v.x && y == v.y && z == v.z;}
|
|
QVector3D toQVector3D() const {return QVector3D(x, y, z);}
|
|
};
|
|
|
|
inline Vector3d operator *(const Vector3d & v0, const Vector3d & v1) {
|
|
return Vector3d(v0.y * v1.z - v1.y * v0.z, v1.x * v0.z - v0.x * v1.z, v0.x * v1.y - v1.x * v0.y);
|
|
}
|
|
inline GLfloat dot(const Vector3d & v0, const Vector3d & v1) {return v0.x*v1.x + v0.y*v1.y + v0.z*v1.z;}
|
|
|
|
struct Vector2d {
|
|
GLfloat x;
|
|
GLfloat y;
|
|
Vector2d(GLfloat x_ = 0., GLfloat y_ = 0.) {x = x_; y = y_;}
|
|
Vector2d(const Vector3d & v3) {x = v3.x; y = v3.y;}
|
|
Vector2d operator *(const GLfloat v) {return Vector2d(x*v, y*v);}
|
|
Vector2d operator /(const GLfloat v) {return Vector2d(x/v, y/v);}
|
|
Vector2d operator +(const GLfloat v) {return Vector2d(x+v, y+v);}
|
|
Vector2d operator -(const GLfloat v) {return Vector2d(x-v, y-v);}
|
|
Vector2d operator +(const Vector3d & v) {return Vector3d(x + v.x, y + v.y);}
|
|
Vector2d operator -(const Vector3d & v) {return Vector3d(x - v.x, y - v.y);}
|
|
Vector2d operator +(const Vector2d & v) {return Vector2d(x + v.x, y + v.y);}
|
|
Vector2d operator -(const Vector2d & v) {return Vector2d(x - v.x, y - v.y);}
|
|
Vector2d & operator *=(const GLfloat & v) {x *= v; y *= v; return *this;}
|
|
Vector2d & operator /=(const GLfloat & v) {x /= v; y /= v; return *this;}
|
|
Vector2d & operator +=(const GLfloat & v) {x += v; y += v; return *this;}
|
|
Vector2d & operator -=(const GLfloat & v) {x -= v; y -= v; return *this;}
|
|
Vector2d & operator +=(const Vector3d & v) {x += v.x; y += v.y;; return *this;}
|
|
Vector2d & operator -=(const Vector3d & v) {x -= v.x; y -= v.y;; return *this;}
|
|
};
|
|
|
|
struct Vector3i {
|
|
Vector3i(int p0_ = 0, int p1_ = 0, int p2_ = 0) {p0 = p0_; p1 = p1_; p2 = p2_;}
|
|
Vector3i(const QString & str);
|
|
Vector3i movedX(const int & o) {return Vector3i(p0 + o, p1, p2);}
|
|
Vector3i movedY(const int & o) {return Vector3i(p0, p1 + o, p2);}
|
|
Vector3i movedZ(const int & o) {return Vector3i(p0, p1, p2 + o);}
|
|
Vector3i moved(const int & x, const int & y, const int & z) {return Vector3i(p0 + x, p1 + y, p2 + z);}
|
|
int p0;
|
|
int p1;
|
|
int p2;
|
|
bool operator ==(const Vector3i & o) const {return p0 == o.p0 && p1 == o.p1 && p2 == o.p2;}
|
|
bool operator !=(const Vector3i & o) const {return p0 != o.p0 || p1 != o.p1 || p2 != o.p2;}
|
|
QVector3D toQVector3D() const {return QVector3D(p0, p1, p2);}
|
|
};
|
|
|
|
inline Vector3i operator +(const Vector3i & f, const Vector3i & s) {return Vector3i(f.p0 + s.p0, f.p1 + s.p1, f.p2 + s.p2);}
|
|
inline Vector3i operator -(const Vector3i & f, const Vector3i & s) {return Vector3i(f.p0 - s.p0, f.p1 - s.p1, f.p2 - s.p2);}
|
|
inline Vector3i operator /(const Vector3i & f, const int & s) {return Vector3i(f.p0 / s, f.p1 / s, f.p2 / s);}
|
|
inline uint qHash(const Vector3i & v) {return v.p0 + v.p1 * 1024 + v.p2 * 1024 * 1024;}
|
|
inline QDebug operator <<(QDebug d, const Vector3d& v) {d.nospace() << "{" << v.x << ", " << v.y << ", " << v.z << "}"; return d.space();}
|
|
inline QDebug operator <<(QDebug d, const Vector3i & v) {d.nospace() << "{" << v.p0 << ", " << v.p1 << ", " << v.p2 << "}"; return d.space();}
|
|
|
|
inline QDataStream & operator <<(QDataStream & s, const Vector3d & v) {s << v.x << v.y << v.z; return s;}
|
|
inline QDataStream & operator >>(QDataStream & s, Vector3d & v) {s >> v.x >> v.y >> v.z; return s;}
|
|
inline QDataStream & operator <<(QDataStream & s, const Vector3i & v) {s << v.p0 << v.p1 << v.p2; return s;}
|
|
inline QDataStream & operator >>(QDataStream & s, Vector3i & v) {s >> v.p0 >> v.p1 >> v.p2; return s;}
|
|
|
|
QColor colorFromString(const QString & str);
|
|
inline double cosABV(const QVector3D & v0, const QVector3D & v1) {
|
|
double l = v0.length() * v1.length();
|
|
if (l == 0.) return 0.;
|
|
return (QVector3D::dotProduct(v0, v1)) / l;
|
|
}
|
|
inline QVector3D projection(const QVector3D & v, const QVector3D & to) {return to.normalized() * v.length() * cosABV(v, to);}
|
|
QVector3D orthToVector(const QVector3D & v, const double & scale = 1.);
|
|
QVector3D rotateVector(const QVector3D & v, const QVector3D & a);
|
|
void setVectorLength(QVector3D & v, const double & l);
|
|
void lengthenVector(QVector3D & v, const double & l);
|
|
inline double squareLength(const QVector3D & from, const QVector3D & to) {return (to.x() - from.x())*(to.x() - from.x()) + (to.y() - from.y())*(to.y() - from.y()) + (to.z() - from.z())*(to.z() - from.z());}
|
|
inline QVector3D directionFromAngles(const QVector3D & a) {return rotateVector(QVector3D(1., 0., 0.), a);}
|
|
inline double frac(const double & x, const double & b) {return x - int(x / b) * b;}
|
|
|
|
class GLObjectBase;
|
|
class QGLView;
|
|
class Light;
|
|
class Camera;
|
|
|
|
class QGLViewBase
|
|
{
|
|
friend class GLObjectBase;
|
|
public:
|
|
QGLViewBase();
|
|
Camera & camera();
|
|
const Camera & camera() const;
|
|
void setCamera(const Camera & camera);
|
|
protected:
|
|
virtual void collectLights() = 0;
|
|
Camera * camera_;
|
|
};
|
|
|
|
#endif // GLTYPES_H
|