/* 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 . */ #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 # 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 #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 #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 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 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); 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());} 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);} inline void glClearFramebuffer(const QColor & color = Qt::black, bool depth = true) {glClearColor(color.redF(), color.greenF(), color.blueF(), color.alphaF()); if (depth) glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); else glClear(GL_COLOR_BUFFER_BIT);} 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(GLfloat x = -1.f, GLfloat y = -1.f, GLfloat w = 2.f, GLfloat h = 2.f); QMatrix4x4 getGLMatrix(GLenum 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;} 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());} bool loadShaders(QGLShaderProgram * prog, const QString & name, const QString & dir = QString()); 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 QMatrix4x4 globCameraMatrix; extern QMutex globMutex; class GLTexture { public: GLTexture(int _width, int _height, const GLenum & _format = GL_RGBA8, const GLenum & _target = GL_TEXTURE_2D) {wid = _width; hei = _height; format_ = _format; target_ = _target; id_ = 0;} bool create() {destroy(); createGLTexture(id_, wid, hei, format_, target_); return id_ > 0;} void destroy() {if (id_ > 0) glDeleteTextures(1, &id_); id_ = 0;} void bind() {if (id_ > 0) glBindTexture(target_, id_);} void release() {glBindTexture(target_, 0);} int width() const {return wid;} int height() const {return hei;} GLenum format() const {return format_;} GLenum target() const {return target_;} GLuint id() const {return id_;} private: int wid, hei; GLenum format_, target_; GLuint id_; }; class GLCubeTexture { public: GLCubeTexture(int _size, const GLenum & _format = GL_RGBA8) {size = _size; format_ = _format; id_ = 0; changed_ = false; pathes.resize(6);} bool create(); void destroy() {if (id_ > 0) glDeleteTextures(1, &id_); id_ = 0;} void bind() {if (changed_) {changed_ = false; create();} if (id_ > 0) glBindTexture(GL_TEXTURE_CUBE_MAP, id_);} void release() {glBindTexture(GL_TEXTURE_CUBE_MAP, 0);} void resize(int _size) {size = _size; changed_ = true;} void loadFromDirectory(const QString & dir); void loadFront(const QString & path) {bind(); pathes[0] = path; createGLTexture(id_, rotateQImageLeft(QImage(path)).scaled(size, size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation), format_, GL_TEXTURE_CUBE_MAP_POSITIVE_X);} void loadBack(const QString & path) {bind(); pathes[1] = path; createGLTexture(id_, rotateQImageRight(QImage(path)).scaled(size, size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation), format_, GL_TEXTURE_CUBE_MAP_NEGATIVE_X);} void loadLeft(const QString & path) {bind(); pathes[2] = path; createGLTexture(id_, QImage(path).scaled(size, size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation), format_, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y);} void loadRight(const QString & path) {bind(); pathes[3] = path; createGLTexture(id_, rotateQImage180(QImage(path)).scaled(size, size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation), format_, GL_TEXTURE_CUBE_MAP_POSITIVE_Y);} void loadTop(const QString & path) {bind(); pathes[4] = path; createGLTexture(id_, rotateQImageLeft(QImage(path)).scaled(size, size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation), format_, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z);} void loadBottom(const QString & path) {bind(); pathes[5] = path; createGLTexture(id_, rotateQImageLeft(QImage(path)).scaled(size, size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation), format_, GL_TEXTURE_CUBE_MAP_POSITIVE_Z);} void load(); bool isEmpty() const {foreach (const QString & i, pathes) if (!i.isEmpty()) return false; return true;} GLenum format() const {return format_;} void setFormat(GLenum f) {format_ = f; changed_ = true;} GLuint id() const {return id_;} const QString & path(int side) const {return pathes[side];} void setPath(int side, const QString & p) {pathes[side] = p;} void loadPathesFromDirectory(const QString & dir); private: bool changed_; int size; GLenum format_; GLuint id_; QVector pathes; }; class GLTextureManager; class GLTextureManagerBase { public: static GLuint loadTexture(const QString & path, bool ownership = true); static GLuint loadTexture(const QImage & image, bool ownership = true); int textureID(const QString & path) {return tex_ids[path];} protected: QMap tex_ids; }; extern GLTextureManager * currentGLTextureManager; class Camera { friend class QGLView; friend class GLParticlesSystem; public: Camera() {fov_ = 60.; angle_xy = angle_z = angle_roll = 0.; angle_limit_lower_xy = 180.; angle_limit_upper_xy = 360.; depth_start = 0.1; depth_end = 1000.; mirror_x = mirror_y = false;} void setPos(const QVector3D & p) {pos_ = p; anglesFromPoints();} /*void setPosX(const double & o) {QVector3D dv = aim_ - pos_; pos_.setX(o); aim_ = pos_ + dv;} void setPosY(const double & o) {QVector3D dv = aim_ - pos_; pos_.setY(o); aim_ = pos_ + dv;} void setPosZ(const double & o) {QVector3D dv = aim_ - pos_; pos_.setZ(o); aim_ = pos_ + dv;}*/ void setAim(const QVector3D & p) {aim_ = p; anglesFromPoints();} void move(const QVector3D & p) {pos_ += p; aim_ += p;} void move(const double & x, const double & y = 0., const double & z = 0.) {pos_ += QVector3D(x, y, z); aim_ += QVector3D(x, y, z);} void moveForward(const double & x, bool withZ = true); void moveBackward(const double & x, bool withZ = true) {moveForward(-x, withZ);} void moveLeft(const double & x, bool withZ = true); void moveRight(const double & x, bool withZ = true) {moveLeft(-x, withZ);} void moveUp(const double & x, bool onlyZ = false); void moveDown(const double & x, bool onlyZ = false) {moveUp(-x, onlyZ);} void rotateZ(const double & a); void rotateXY(const double & a); void rotateRoll(const double & a) {angle_roll += a;} void orbitZ(const double & a); void orbitXY(const double & a); void panZ(const double & a); void panXY(const double & a); void setFOV(const double & f) {fov_ = f;} void setAngles(const QVector3D & a) {angle_xy = a.x(); angle_roll = a.y(); angle_z = a.z();} void setAngleZ(const double & a); void setAngleXY(const double & a); void setAngleRoll(const double & a) {angle_roll = a;} void setAngleLowerLimitXY(const double & a) {angle_limit_lower_xy = a;} void setAngleUpperLimitXY(const double & a) {angle_limit_upper_xy = a;} void setAngleLimitsXY(const double & lower, const double & upper) {angle_limit_lower_xy = lower; angle_limit_upper_xy = upper;} void setDepthStart(const double & d) {depth_start = d;} void setDepthEnd(const double & d) {depth_end = d;} void setMirrorX(bool yes) {mirror_x = yes;} void setMirrorY(bool yes) {mirror_y = yes;} void flyCloser(const double & s); void flyFarer(const double & s); void flyToDistance(const double & d); QVector3D pos() const {return pos_;} QVector3D aim() const {return aim_;} QVector3D angles() const {return QVector3D(angle_xy, angle_roll, angle_z);} QVector3D direction() const {return (aim_ - pos_).normalized();} QVector3D directionXY() const {QVector3D tv = aim_ - pos_; return QVector3D(tv.x(), tv.y(), 0.).normalized();} double FOV() const {return fov_;} double distance() const {return (pos_ - aim_).length();} double angleZ() const {return angle_z;} double angleXY() const {return angle_xy;} double angleRoll() const {return angle_roll;} double angleLowerLimitXY() const {return angle_limit_lower_xy;} double angleUpperLimitXY() const {return angle_limit_upper_xy;} double depthStart() const {return depth_start;} double depthEnd() const {return depth_end;} bool isMirrorX() const {return mirror_x;} bool isMirrorY() const {return mirror_y;} void anglesFromPoints(); void apply(const GLdouble & aspect = 1.); void assign(const Camera & c) {pos_ = c.pos_; aim_ = c.aim_; fov_ = c.fov_; angle_z = c.angle_z; angle_xy = c.angle_xy; angle_roll = c.angle_roll; angle_limit_lower_xy = c.angle_limit_lower_xy; angle_limit_upper_xy = c.angle_limit_upper_xy;} QVector3D pointFromViewport(int x_, int y_, double z_); private: QVector3D pos_; QVector3D aim_; GLdouble fov_; GLdouble depth_start; GLdouble depth_end; GLdouble angle_z; GLdouble angle_xy; GLdouble angle_roll; GLdouble angle_limit_lower_xy; GLdouble angle_limit_upper_xy; GLdouble modelview[16], projection[16]; GLint viewport[4]; bool mirror_x; bool mirror_y; }; extern Camera * currentCamera; struct Map { Map() {bitmap_id = 0; bitmap_amount = 1.f; animation_frame_rate = -1.f;} QString bitmap_path; GLuint bitmap_id; QPointF bitmap_offset; float bitmap_amount; QString animation; float animation_frame_rate; }; struct Material { enum LightModel {Phong = 0, CookTorrance = 1, Minnaert = 2, Strauss = 3, OrenNayar = 4}; Material(); void apply(); void loadTextures(GLTextureManagerBase * tm = 0); QColor color_diffuse; QColor color_specular; QColor color_self_illumination; LightModel light_model; bool glass; float shine; float shine_strength; float transparency; float reflectivity; float iof; float dispersion; float bump_scale; float relief_scale; Map diffuse; Map bump; Map relief; Map diffuse_2; Map diffuse_3; Map diffuse_4; GLCubeTexture reflection; }; 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 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 Map & m) {s << m.bitmap_path << m.bitmap_amount << m.animation << m.animation_frame_rate; return s;} inline QDataStream & operator <<(QDataStream & s, const 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, const Material & m) {s << m.color_diffuse << m.shine << m.shine_strength << m.color_specular << m.transparency << m.diffuse << m.bump; return s;} inline QDataStream & operator >>(QDataStream & s, Map & m) {s >> m.bitmap_path >> m.bitmap_amount >> m.animation >> m.animation_frame_rate; return s;} inline QDataStream & operator >>(QDataStream & s, Vector3d & v) {s >> v.x >> v.y >> v.z; return s;} inline QDataStream & operator >>(QDataStream & s, Vector3i & v) {s >> v.p0 >> v.p1 >> v.p2; return s;} inline QDataStream & operator >>(QDataStream & s, Material & m) {s >> m.color_diffuse >> m.shine >> m.shine_strength >> m.color_specular >> m.transparency >> m.diffuse >> m.bump; 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 QGLViewBase { friend class GLObjectBase; public: QGLViewBase() {} Camera & camera() {return camera_;} void setCamera(const Camera & camera) {camera_ = camera;} protected: virtual void collectLights() = 0; Camera camera_; }; class GLRendererBase: public QObject { friend class QGLView; Q_OBJECT public: GLRendererBase(QGLView * view_): view(*view_) {} virtual void renderScene() = 0; protected: struct RenderingParameters { int pass; int light_pass; bool light; bool fog; bool textures; bool prev_light; bool prev_fog; Material::LightModel prev_light_model; GLuint prev_tex[32]; void * shaders; QGLShaderProgram * cur_shader; }; virtual void setupLight(const Light & l, int inpass_index, int gl_index); virtual void setupAmbientLight(const QColor & a, bool first_pass); virtual void setupShadersLights(int lights_count); virtual void setupTextures(GLObjectBase & object, GLRendererBase::RenderingParameters & rp, bool first_object = false); virtual void setupShadersTextures(GLObjectBase & object, GLRendererBase::RenderingParameters & rp) {} virtual void reloadShaders() {} virtual void init(int width, int height) {} virtual void resize(int width, int height) {} void setupLights(int pass, int lights_per_pass); inline void applyFilteringParameters(); void renderObjects(int pass, int light_pass, void * shaders = 0, bool textures = true, bool light = true, bool fog = true); void renderSingleObject(GLObjectBase & o, RenderingParameters & rp); QGLView & view; }; #endif // GLTYPES_H