/* QGLView Copyright (C) 2020 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);} #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));} //extern __GLWidget__ * currentQGLView; 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 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 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(QOpenGLShaderProgram * 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;} //# define QGLCI if (!QOpenGLContext::currentContext()) return; QOpenGLFunctions gf(QOpenGLContext::currentContext()); //# define QGLC gf. //inline void glActiveTextureChannel(int channel) {QGLCI gf.glActiveTexture(GL_TEXTURE0 + channel);} //inline void glDisableTextures(int channels = 8) {QGLCI for (int i = channels - 1; i >= 0; --i) {glActiveTextureChannel(i); glDisable(GL_TEXTURE_2D); glDisable(GL_TEXTURE_CUBE_MAP);}} //inline void glReleaseTextures(int channels = 8) {QGLCI for (int i = channels - 1; i >= 0; --i) {glActiveTextureChannel(i); glBindTexture(GL_TEXTURE_2D, 0); glBindTexture(GL_TEXTURE_CUBE_MAP, 0);}} //inline void glReleaseFramebuffer() {QGLCI gf.glBindFramebuffer(GL_FRAMEBUFFER, 0);} //inline void glReleaseShaders() {QGLCI gf.glUseProgram(0);} //inline void deleteGLFramebuffer(GLuint & fbo) {QGLCI if (fbo != 0) gf.glDeleteFramebuffers(1, &fbo); fbo = 0;} //inline void deleteGLRenderbuffer(GLuint & drbo) {QGLCI if (drbo != 0) gf.glDeleteRenderbuffers(1, &drbo); drbo = 0;} //inline void deleteGLBuffer(GLuint & bo) {QGLCI if (bo != 0) gf.glDeleteBuffers(1, &bo); bo = 0;} //inline void deleteGLVertexArray(GLuint & va) {QGLCI if (va != 0) gf.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) {glTranslatef(v.x(), v.y(), v.z());} inline void qglScale(const QVector3D & v) {glScalef(v.x(), v.y(), v.z());} 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);} //const double deg2rad = atan(1.) / 45.; //const double rad2deg = 45. / atan(1.); 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;} 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 sqrtf(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.f) 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 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;} class GLObjectBase; class QGLView; class Light; class Camera; class GLTextureManagerBase; class QGLViewBase { friend class GLObjectBase; public: QGLViewBase(); virtual ~QGLViewBase(); Camera * camera(); const Camera * camera() const; void setCamera(Camera * camera); GLTextureManagerBase * textureManager(); protected: virtual void collectLights() = 0; Camera * camera_; GLTextureManagerBase * textures_manager; }; #endif // GLTYPES_H