/* GLObjectBase & Light 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 GLOBJECT_H #define GLOBJECT_H #include "glvbo.h" #include "glframebuffer.h" #include "glmaterial.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}; 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() {calculateBoundingBox(); vbo.init(); vbo.rebuffer(); /*material_.reflection.create();*/ /*qDebug() << "init" << vbo.buffer_;*/ is_init = true;} virtual void draw(QGLShaderProgram * 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;} double lineWidth() const {return line_width;} void setLineWidth(const double & width) {line_width = width;} GLObjectBase * parent() {return parent_;} void setParent(GLObjectBase * o) {parent_ = o;} bool hasParent() const {return parent_ != 0;} bool hasChildren() const {return children_.size() != 0;} void setView(QGLView * v); void addChild(GLObjectBase * o) {if (o == this) return; if (o->parent_ != 0) o->parent_->children_.removeAll(o); children_ << o; o->parent_ = this; o->buildTransform(); if (view_ != 0) view_->collectLights();} void removeChild(GLObjectBase * o) {if (o == this) return; children_.removeAll(o); o->parent_ = 0; o->buildTransform(); if (view_ != 0) view_->collectLights();} void removeChild(int index) {children_[index]->parent_ = 0; children_[index]->buildTransform(); children_.removeAt(index); if (view_ != 0) view_->collectLights();} void clearChildren(bool deleteAll = false); int childCount() const {return children_.size();} GLObjectBase * child(int index) {if (index < 0 || index >= children_.size()) return 0; return children_[index];} GLObjectBase * child(const QString & name) {foreach (GLObjectBase * i, children_) if (i->name_ == name) return i; return 0;} const GLObjectBase * child(int index) const {if (index < 0 || index >= children_.size()) return 0; return children_[index];} const GLObjectBase * child(const QString & name) const {foreach (GLObjectBase * i, children_) if (i->name_ == name) return i; return 0;} 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(GLdouble dx, GLdouble dy, GLdouble dz = 0.) {move(QVector3D(dx, dy, dz)); buildTransform();} void moveTo(GLdouble dx, GLdouble dy, GLdouble dz = 0.) {moveTo(QVector3D(dx, dy, dz)); buildTransform();} void moveX(GLdouble o) {pos_.setX(pos_.x() + o); buildTransform();} void moveY(GLdouble o) {pos_.setY(pos_.y() + o); buildTransform();} void moveZ(GLdouble o) {pos_.setZ(pos_.z() + o); buildTransform();} void setPosX(GLdouble o) {pos_.setX(o); buildTransform();} void setPosY(GLdouble o) {pos_.setY(o); buildTransform();} void setPosZ(GLdouble o) {pos_.setZ(o); buildTransform();} void setPos(GLdouble x, GLdouble y, GLdouble 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_;} double posX() const {return pos_.x();} double posY() const {return pos_.y();} double 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_;} double rotationX() const {return angles_.x();} double rotationY() const {return angles_.y();} double rotationZ() const {return angles_.z();} void rotateX(GLdouble a) {raw_matrix = false; angles_.setX(angles_.x() + a); buildTransform();} void rotateY(GLdouble a) {raw_matrix = false; angles_.setY(angles_.y() + a); buildTransform();} void rotateZ(GLdouble a) {raw_matrix = false; angles_.setZ(angles_.z() + a); while (angles_.z() < -360.) angles_.setZ(angles_.z() + 360.); while (angles_.z() > 360.) angles_.setZ(angles_.z() - 360.); buildTransform();} void setRotationX(GLdouble a) {raw_matrix = false; angles_.setX(a); buildTransform();} void setRotationY(GLdouble a) {raw_matrix = false; angles_.setY(a); buildTransform();} void setRotationZ(GLdouble a) {raw_matrix = false; angles_.setZ(a); while (angles_.z() < -360.) angles_.setZ(angles_.z() + 360.); while (angles_.z() > 360.) angles_.setZ(angles_.z() - 360.); buildTransform();} void setRotation(const QVector3D & a) {raw_matrix = false; angles_= a; buildTransform();} void resetRotation() {raw_matrix = false; angles_ = QVector3D(0., 0., 0.); buildTransform();} QVector3D scale() {return scale_;} double scaleX() {return scale_.x();} double scaleY() {return scale_.y();} double scaleZ() {return scale_.z();} void scale(const QVector3D & sv) {raw_matrix = false; scale_ *= sv; buildTransform();} void scale(GLdouble sx, GLdouble sy, GLdouble sz) {raw_matrix = false; scale(QVector3D(sx, sy, sz)); buildTransform();} void scale(GLdouble sx, GLdouble sy) {raw_matrix = false; scale(QVector3D(sx, sy, sy)); buildTransform();} void scale(GLdouble sx) {raw_matrix = false; scale(QVector3D(sx, sx, sx)); buildTransform();} void scaleX(GLdouble a) {raw_matrix = false; scale_.setX(scale_.x() + a); buildTransform();} void scaleY(GLdouble a) {raw_matrix = false; scale_.setY(scale_.y() + a); buildTransform();} void scaleZ(GLdouble a) {raw_matrix = false; scale_.setZ(scale_.z() + a); buildTransform();} void setScale(const QVector3D & a) {raw_matrix = false; scale_ = a; buildTransform();} void setScale(GLdouble a) {raw_matrix = false; scale_ = QVector3D(a, a, a); buildTransform();} void setScaleX(GLdouble a) {raw_matrix = false; scale_.setX(a); buildTransform();} void setScaleY(GLdouble a) {raw_matrix = false; scale_.setY(a); buildTransform();} void setScaleZ(GLdouble 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 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_ = m; if (with_children) foreach (GLObjectBase * i, children_) i->setMaterial(m, true); checkPass(); is_tex_loaded = false;} Material & material() {/*is_tex_loaded = false;*/ return material_;} const Box3D & boundingBox(bool withChildren = true) const {return bound;} GLVBO & VBO() {return vbo;} 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) {material_.loadTextures((GLTextureManagerBase * )currentGLTextureManager); if (with_children) foreach (GLObjectBase * i, children_) i->loadTextures(); is_tex_loaded = true; checkPass();} void deleteTextures() {foreach (GLuint i, textures) currentQGLView->deleteTexture(i); textures.clear();} void calculateBoundingBox(); void buildTransform(); void initInternal() {init(); loadTextures(); foreach (GLObjectBase * i, children_) i->initInternal();} void render(int * id = 0, QMap * ids = 0, 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; double 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; }; 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, GLdouble i = 1.); virtual GLObjectBase * clone(bool withChildren = true); virtual void init() {shadow_map.resize(512, 512); is_init = true;} virtual void draw(QGLShaderProgram * prog, bool simplest = false); QVector3D direction, dir0, dir1; GLdouble angle_start; GLdouble angle_end; GLdouble intensity; GLdouble decay_const; GLdouble decay_linear; GLdouble decay_quadratic; GLdouble decay_start; GLdouble 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