/* QGLView Copyright (C) 2019 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 . */ #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 #include //#ifndef WINDOWS //# ifdef MAC //# include //# include //# include //# else //# include //# include //# include //# endif //#endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifndef QNX # include # include #else # include # include #endif #include //#ifdef WINDOWS //# define GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT 0x84FF //# define GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE //#endif #ifndef M_PI # define M_PI 3.14159265358979323846 #endif #ifndef M_2PI # define M_2PI 6.28318530717958647692 #endif #ifndef M_PI_3 # define M_PI_3 1.04719755119659774615 #endif #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 float deg2rad = atanf(1.f) / 45.f; const float rad2deg = 45.f / atanf(1.f); # ifdef WINDOWS inline int random() {return rand();} # endif #else #define random randomi #endif #ifdef CC_VC inline float round(const float & v) {return floor(v + 0.5);} #endif inline float randomu() {return float(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 inline void piSwap(Type & f, Type & s) {Type t = f; f = s; s = t;} template inline Type piMin(const Type & f, const Type & s) {return (f > s) ? s : f;} template inline Type piMin(const Type & f, const Type & s, const Type & t) {return (f < s && f < t) ? f : ((s < t) ? s : t);} template inline Type piMax(const Type & f, const Type & s) {return (f < s) ? s : f;} template inline Type piMax(const Type & f, const Type & s, const Type & t) {return (f > s && f > t) ? f : ((s > t) ? s : t);} template 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);} inline uint letobe_i(const uint & v) {return (v >> 24) | ((v >> 8) & 0xFF00) | ((v << 8) & 0xFF0000) | ((v << 24) & 0xFF000000);} #endif // return [-1, 1] inline float urand(const float & scale = 1.) {return ((float)rand() / RAND_MAX - .5f) * (scale + scale);} // return [0, 1] inline float uprand(const float & scale = 1.) {return ((float)rand() / RAND_MAX) * scale;} QString readCharsUntilNull(QDataStream & s); QString findFile(const QString & file, const QStringList & pathes); inline QColor operator *(const QColor & c, float v) {return QColor(piClamp(c.red() * v, 0, 255), piClamp(c.green() * v, 0, 255), piClamp(c.blue() * v, 0, 255), piClamp(c.alpha() * v, 0, 255));} inline QColor operator /(const QColor & c, float v) {return QColor(piClamp(c.red() / v, 0, 255), piClamp(c.green() / v, 0, 255), piClamp(c.blue() / v, 0, 255), piClamp(c.alpha() / v, 0, 255));} inline void qglColor(const QColor & c) {glColor4f(c.redF(), c.greenF(), c.blueF(), c.alphaF());} inline void glClearError() {int c = 100; while (glGetError() != GL_NO_ERROR && --c > 0) glGetError();} inline void glSetCapEnabled(GLenum cap, bool on = true) {if (on) glEnable(cap); else glDisable(cap);} inline void glSetPolygonMode(GLenum mode) {glPolygonMode(GL_FRONT_AND_BACK, mode);} inline void deleteGLTexture(QOpenGLExtraFunctions * f, GLuint & tex) {if (tex != 0) f->glDeleteTextures(1, &tex); tex = 0;} void glEnableDepth(); void glDisableDepth(); void glClearFramebuffer(const QColor & color = Qt::black, bool depth = true); void glDrawQuad(QOpenGLShaderProgram * prog = nullptr, QVector4D * corner_dirs = nullptr, GLfloat x = -1.f, GLfloat y = -1.f, GLfloat w = 2.f, GLfloat h = 2.f); void createGLTexture(QOpenGLExtraFunctions * f, GLuint & tex, int width, int height, const GLenum & format = GL_RGBA, const GLenum & target = GL_TEXTURE_2D); void createGLTexture(QOpenGLExtraFunctions * f, GLuint & tex, const QImage & image, const GLenum & format = GL_RGBA, const GLenum & target = GL_TEXTURE_2D); QMatrix4x4 glMatrixPerspective(float angle, float aspect, float near_, float far_); QImage rotateQImageLeft(const QImage & im); QImage rotateQImageRight(const QImage & im); inline QImage rotateQImage180(const QImage & im) {return im.mirrored(true, true);} class QGLView; class ObjectBase; class Light; class Camera; class Texture; class CubeTexture; class Map; class Material; class TextureManager; class Texture2DArray; class Mesh; class Scene; class RendererBase; class Renderer; class RendererMaterial; class RendererService; class RendererSelection; 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;} Box3D(const QVector & points); bool isEmpty() const {return (qAbs(width) < 1E-6f) && (qAbs(length) < 1E-6f) && (qAbs(height) < 1E-6f);} 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.f + x, width / 2.f + y, height / 2.f + z);} QVector3D angles() const {return QVector3D(angle_xy, angle_roll, angle_z);} QVector corners() const; 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;} Box3D & operator |=(const Box3D & o); }; inline QDebug operator <<(QDebug d, const Box3D & v) {d << "Box3D {start (" << v.x << "," << v.y << "," << v.z << "), size (" << v.length << "," << v.width << "," << v.height << ")}"; return d;} #pragma pack(push, 1) struct Vector2i { Vector2i(int p0_ = 0, int p1_ = 0) {p0 = p0_; p1 = p1_;} Vector2i(const QString & str); Vector2i movedX(const int & o) {return Vector2i(p0 + o, p1);} Vector2i movedY(const int & o) {return Vector2i(p0, p1 + o);} Vector2i moved(const int & x, const int & y) {return Vector2i(p0 + x, p1 + y);} GLint p0; GLint p1; bool operator ==(const Vector2i & o) const {return p0 == o.p0 && p1 == o.p1;} bool operator !=(const Vector2i & o) const {return p0 != o.p0 || p1 != o.p1;} void operator +=(int v) {p0 += v; p1 += v;} QVector2D toQVector2D() const {return QVector2D(p0, p1);} }; #pragma pack(pop) inline Vector2i operator +(const Vector2i & f, const Vector2i & s) {return Vector2i(f.p0 + s.p0, f.p1 + s.p1);} inline Vector2i operator -(const Vector2i & f, const Vector2i & s) {return Vector2i(f.p0 - s.p0, f.p1 - s.p1);} inline Vector2i operator /(const Vector2i & f, const int & s) {return Vector2i(f.p0 / s, f.p1 / s);} inline uint qHash(const Vector2i & v) {return v.p0 ^ ((v.p1 << 8) | (v.p1 >> 24));} inline QDebug operator <<(QDebug d, const Vector2i & v) {d.nospace() << "{" << v.p0 << ", " << v.p1 << "}"; return d.space();} inline QDataStream & operator <<(QDataStream & s, const Vector2i & v) {s << v.p0 << v.p1; return s;} inline QDataStream & operator >>(QDataStream & s, Vector2i & v) {s >> v.p0 >> v.p1; return s;} #pragma pack(push, 1) 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);} GLint p0; GLint p1; GLint 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;} void operator +=(int v) {p0 += v; p1 += v; p2 += v;} QVector3D toQVector3D() const {return QVector3D(p0, p1, p2);} }; #pragma pack(pop) 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 << 8) | (v.p1 >> 24)) ^ ((v.p2 << 16) | (v.p2 >> 16));} 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 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;} QVector3D vectorFromString(const QString & str); QColor colorFromString(const QString & str); inline QVector4D QColor2QVector(const QColor & c) {return QVector4D(c.redF(), c.greenF(), c.blueF(), c.alphaF());} inline float cosABV(const QVector3D & v0, const QVector3D & v1) { float l = v0.length() * v1.length(); if (l == 0.f) 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 float & scale = 1.); QVector3D rotateVector(const QVector3D & v, const QVector3D & a); void setVectorLength(QVector3D & v, const float & l); void lengthenVector(QVector3D & v, const float & l); inline float 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 float frac(const float & x, const float & b) {return x - int(x / b) * b;} #endif // GLTYPES_H