Files
qad/libs/qglview/gltypes.h
2022-12-14 14:14:33 +03:00

602 lines
17 KiB
C++

/*
QGLView
Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser 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
#include <QObject>
#ifndef WINDOWS
# ifdef MAC
# include <GLUT/glut.h>
# include <OpenGL/gl.h>
# include <OpenGL/glu.h>
# else
# include <GL/gl.h>
# include <GL/glext.h>
# include <GL/glu.h>
# endif
#endif
#include <QColor>
#include <QDataStream>
#include <QDebug>
#include <QDir>
#include <QFile>
#include <QImage>
#include <QMatrix4x4>
#include <QMutex>
#include <QOpenGLFunctions>
#include <QOpenGLShader>
#include <QOpenGLShaderProgram>
#include <QOpenGLWidget>
#include <QVector2D>
#include <QVector3D>
#include <cmath>
#include <float.h>
#ifndef QNX
# include <cmath>
# include <complex>
#else
# include <complex.h>
# include <math.h>
#endif
#include <iostream>
#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<typename T>
inline void piSwap(T & f, T & s) {
T 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 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<int>(c.red() * v, 0, 255),
piClamp<int>(c.green() * v, 0, 255),
piClamp<int>(c.blue() * v, 0, 255),
piClamp<int>(c.alpha() * v, 0, 255));
}
inline QColor operator/(const QColor & c, float v) {
return QColor(piClamp<int>(c.red() / v, 0, 255),
piClamp<int>(c.green() / v, 0, 255),
piClamp<int>(c.blue() / v, 0, 255),
piClamp<int>(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<QVector3D> & 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<QVector3D> 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