/* GLObjectBase & Light 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 . */ #ifndef GLOBJECT_H #define GLOBJECT_H #include "glframebuffer.h" #include "glmaterial.h" #include "glvbo.h" class Camera; class QGLView; class GLObjectBase { friend class QGLView; friend class GLRendererBase; friend QDataStream & operator<<(QDataStream & s, const GLObjectBase * p); friend QDataStream & operator>>(QDataStream & s, GLObjectBase *& p); friend GLObjectBase * loadFromQGLFile(const QString & filepath); public: enum Type { glMesh, glLight, glCamera, glParticlesSystem }; enum Pass { Solid, Transparent, Reflection, User }; enum GeomPrimitives { Triangles = GL_TRIANGLES, Quads = GL_QUADS }; enum RenderMode { View = 0, Point = GL_POINT, Line = GL_LINE, Fill = GL_FILL }; explicit GLObjectBase(); virtual ~GLObjectBase(); virtual GLObjectBase * clone(bool withChildren = true); QString name() const { return name_; } void setName(const QString & name) { name_ = name; } // virtual GLuint hList() {return list;} virtual void init(); virtual void draw(QOpenGLShaderProgram * prog, bool simplest = false); virtual void update() {} bool isInit() const { return is_init; } bool isTexturesLoaded() const { return is_tex_loaded; } Type type() const { return type_; } RenderMode renderMode() const { return render_mode; } void setRenderMode(RenderMode mode) { render_mode = mode; } float lineWidth() const { return line_width; } void setLineWidth(const float & width) { line_width = width; } GLObjectBase * parent() { return parent_; } void setParent(GLObjectBase * o) { parent_ = o; } bool hasParent() const { return parent_ != nullptr; } bool hasChildren() const { return children_.size() != 0; } void setView(QGLView * v); void addChild(GLObjectBase * o); void removeChild(GLObjectBase * o); void removeChild(int index); void clearChildren(bool deleteAll = false); int childCount() const { return children_.size(); } GLObjectBase * child(int index); GLObjectBase * child(const QString & name); const GLObjectBase * child(int index) const; const GLObjectBase * child(const QString & name) const; QList children(bool all_ = false); bool isVisible() const { return visible_; } bool isHidden() const { return !visible_; } void setVisible(bool v) { visible_ = v; } void setHidden(bool v) { visible_ = !v; } void show() { visible_ = true; } void hide() { visible_ = false; } bool isReceiveShadows() const { return rec_shadow; } bool isCastShadows() const { return cast_shadow; } void setReceiveShadows(bool on) { rec_shadow = on; } void setCastShadows(bool on) { cast_shadow = on; } void move(const QVector3D & dv) { pos_ += dv; buildTransform(); } void moveTo(const QVector3D & dv) { pos_ = dv; buildTransform(); } void move(GLfloat dx, GLfloat dy, GLfloat dz = 0.) { move(QVector3D(dx, dy, dz)); buildTransform(); } void moveTo(GLfloat dx, GLfloat dy, GLfloat dz = 0.) { moveTo(QVector3D(dx, dy, dz)); buildTransform(); } void moveX(GLfloat o) { pos_.setX(pos_.x() + o); buildTransform(); } void moveY(GLfloat o) { pos_.setY(pos_.y() + o); buildTransform(); } void moveZ(GLfloat o) { pos_.setZ(pos_.z() + o); buildTransform(); } void setPosX(GLfloat o) { pos_.setX(o); buildTransform(); } void setPosY(GLfloat o) { pos_.setY(o); buildTransform(); } void setPosZ(GLfloat o) { pos_.setZ(o); buildTransform(); } void setPos(GLfloat x, GLfloat y, GLfloat z) { pos_ = QVector3D(x, y, z); buildTransform(); } void setPos(const QVector3D & p) { pos_ = p; buildTransform(); } void resetPos() { pos_ = QVector3D(0., 0., 0.); buildTransform(); } QVector3D pos() const { return pos_; } float posX() const { return pos_.x(); } float posY() const { return pos_.y(); } float posZ() const { return pos_.z(); } QVector3D worldPos() const { return (itransform_ * QVector4D(0, 0, 0, 1.)).toVector3D(); } QMatrix4x4 worldTransform() const { return itransform_; } QVector3D rotation() const { return angles_; } float rotationX() const { return angles_.x(); } float rotationY() const { return angles_.y(); } float rotationZ() const { return angles_.z(); } void rotateX(GLfloat a); void rotateY(GLfloat a); void rotateZ(GLfloat a); void setRotationX(GLfloat a); void setRotationY(GLfloat a); void setRotationZ(GLfloat a); void setRotation(const QVector3D & a); void resetRotation(); QVector3D scale() { return scale_; } float scaleX() { return scale_.x(); } float scaleY() { return scale_.y(); } float scaleZ() { return scale_.z(); } void scale(const QVector3D & sv) { raw_matrix = false; scale_ *= sv; buildTransform(); } void scale(GLfloat sx, GLfloat sy, GLfloat sz) { raw_matrix = false; scale(QVector3D(sx, sy, sz)); buildTransform(); } void scale(GLfloat sx, GLfloat sy) { raw_matrix = false; scale(QVector3D(sx, sy, sy)); buildTransform(); } void scale(GLfloat sx) { raw_matrix = false; scale(QVector3D(sx, sx, sx)); buildTransform(); } void scaleX(GLfloat a) { raw_matrix = false; scale_.setX(scale_.x() + a); buildTransform(); } void scaleY(GLfloat a) { raw_matrix = false; scale_.setY(scale_.y() + a); buildTransform(); } void scaleZ(GLfloat a) { raw_matrix = false; scale_.setZ(scale_.z() + a); buildTransform(); } void setScale(const QVector3D & a) { raw_matrix = false; scale_ = a; buildTransform(); } void setScale(GLfloat a) { raw_matrix = false; scale_ = QVector3D(a, a, a); buildTransform(); } void setScaleX(GLfloat a) { raw_matrix = false; scale_.setX(a); buildTransform(); } void setScaleY(GLfloat a) { raw_matrix = false; scale_.setY(a); buildTransform(); } void setScaleZ(GLfloat a) { raw_matrix = false; scale_.setZ(a); buildTransform(); } void resetScale() { raw_matrix = false; scale_ = QVector3D(1., 1., 1.); buildTransform(); } QMatrix4x4 transform() { return mat_; } void setTransform(const QMatrix4x4 & t); bool isRawMatrix() { return raw_matrix; } bool isAcceptLight() const { return accept_light; } void setAcceptLight(bool yes) { accept_light = yes; } bool isAcceptFog() const { return accept_fog; } void setAcceptFog(bool yes) { accept_fog = yes; } bool isSelected() const { return selected_; } void setSelected(bool yes) { selected_ = yes; } void select(); void deselect() { selected_ = false; } bool isSelectable() const { return select_; } void setSelectable(bool yes) { select_ = yes; } /* bool isWriteDepth() const {return write_depth_;} void setWriteDepth(bool yes) {write_depth_ = yes;}*/ QColor color() const { return material_.color_diffuse; } void setColor(const QColor & c) { material_.color_diffuse = c; checkPass(); } GLenum srcAlpha() const { return blend_src; } GLenum destAlpha() const { return blend_dest; } void setSrcAlpha(GLenum mode) { blend_src = mode; } void setDestAlpha(GLenum mode) { blend_dest = mode; } void setMaterial(const Material & m, bool with_children = false); Material & material() { return material_; } const Box3D & boundingBox(bool withChildren = true) const { return bound; } GLVBO & VBO() { return vbo; } void calculateBoundingBox(); void setProperty(const QString & pn, const QVariant & v); QVariant property(const QString & pn, bool * exists = 0) const; bool hasProperty(const QString & pn) const; void removeProperty(const QString & pn); QVector3D pos_h; QVector points, puvws; QVector faces, uvws, norms; QVector normals; // QVector d_vertices, d_normals, d_uvs; protected: void addChildren(QList & list, GLObjectBase * where); void loadTextures(bool with_children = false); // void deleteTextures() {foreach (GLuint i, textures) currentQGLView->deleteTexture(i); textures.clear();} void buildTransform(); void initInternal(); void render(int * id = nullptr, QMap * ids = nullptr, int sh_id_loc = 0); void checkPass(); virtual void localTransform(QMatrix4x4 & m); QMatrix4x4 worldMatrix(QMatrix4x4 parent) const; int pass_; // Pass bool is_init, is_tex_loaded, accept_light, accept_fog, /*write_depth_,*/ visible_, cast_shadow, rec_shadow, select_, selected_, raw_matrix; bool is_root; float line_width; Type type_; GeomPrimitives geom_prim; RenderMode render_mode; Material material_; Box3D bound; QVector3D pos_, angles_, scale_; QList children_; QList textures; QMatrix4x4 itransform_, mat_; // QColor color_; QString name_; GLenum blend_src, blend_dest; GLObjectBase * parent_; QGLViewBase * view_; GLVBO vbo; QVariantMap meta; }; inline bool operator<(const GLObjectBase & f, const GLObjectBase & s) { return f.pos_h.z() < s.pos_h.z(); } class Light: public GLObjectBase { friend class QGLView; friend class GLRendererBase; public: enum Type { Omni, Directional, Cone }; Light(); Light(const QVector3D & p, const QColor & c = Qt::white, float i = 1.); virtual GLObjectBase * clone(bool withChildren = true); virtual void init() { shadow_map.resize(512, 512); is_init = true; } virtual void draw(QOpenGLShaderProgram * prog, bool simplest = false); QVector3D direction, dir0, dir1; float angle_start; float angle_end; float intensity; float decay_const; float decay_linear; float decay_quadratic; float decay_start; float decay_end; Type light_type; GLFramebuffer shadow_map; QMatrix4x4 shadow_matrix; protected: }; template inline T globject_cast(GLObjectBase * object) { return reinterpret_cast(object); } template inline T globject_cast(const GLObjectBase * object) { return reinterpret_cast(object); } QDataStream & operator<<(QDataStream & s, const GLObjectBase * p); QDataStream & operator>>(QDataStream & s, GLObjectBase *& p); #endif // GLOBJECT_H