356 lines
11 KiB
C++
356 lines
11 KiB
C++
/*
|
|
QGL ObjectBase & 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 <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#ifndef GLOBJECT_H
|
|
#define GLOBJECT_H
|
|
|
|
#include "glframebuffer.h"
|
|
#include "glmaterial.h"
|
|
#include "gltransform.h"
|
|
#include "gltypes.h"
|
|
|
|
|
|
class QGLENGINE_CORE_EXPORT ObjectBase {
|
|
friend class Scene;
|
|
friend class RendererSelection;
|
|
friend QGLENGINE_CORE_EXPORT QDataStream & operator<<(QDataStream & s, const ObjectBase * p);
|
|
friend QGLENGINE_CORE_EXPORT QDataStream & operator>>(QDataStream & s, ObjectBase *& p);
|
|
friend QGLENGINE_CORE_EXPORT QDataStream & operator<<(QDataStream & s, const Scene * p);
|
|
friend QGLENGINE_CORE_EXPORT QDataStream & operator>>(QDataStream & s, Scene *& p);
|
|
|
|
public:
|
|
enum Type {
|
|
glMesh,
|
|
glLight,
|
|
glCamera,
|
|
glParticlesSystem
|
|
};
|
|
|
|
explicit ObjectBase(Mesh * geom = nullptr, Material * mat = nullptr);
|
|
virtual ~ObjectBase();
|
|
|
|
virtual ObjectBase * clone(bool withChildren = true);
|
|
void destroy();
|
|
|
|
QString name() const { return name_; }
|
|
void setName(const QString & name) { name_ = name; }
|
|
virtual void init();
|
|
virtual void update() {}
|
|
bool isInit() const { return is_init; }
|
|
Type type() const { return type_; }
|
|
RenderPass pass() const;
|
|
uint id() const { return id_; }
|
|
|
|
float lineWidth() const { return line_width; }
|
|
void setLineWidth(const float & width) { line_width = width; }
|
|
|
|
ObjectBase * parent() { return parent_; }
|
|
void setParent(ObjectBase * o) { parent_ = o; }
|
|
bool hasParent() const { return parent_ != nullptr; }
|
|
bool hasChildren() const { return !children_.isEmpty(); }
|
|
void setScene(Scene * v);
|
|
|
|
void addChild(ObjectBase * o);
|
|
void removeChild(ObjectBase * o);
|
|
void removeChild(int index);
|
|
void clearChildren(bool deleteAll = false);
|
|
int childCount() const { return children_.size(); }
|
|
ObjectBase * child(int index);
|
|
ObjectBase * child(const QString & name);
|
|
const ObjectBase * child(int index) const;
|
|
const ObjectBase * child(const QString & name) const;
|
|
ObjectBaseList children(bool all_ = false);
|
|
|
|
bool isVisible(bool check_parents = false) const;
|
|
bool isHidden(bool check_parents = false) const { return !isVisible(check_parents); }
|
|
void setVisible(bool v);
|
|
void setHidden(bool v) { setVisible(!v); }
|
|
void show() { setVisible(true); }
|
|
void hide() { setVisible(false); }
|
|
|
|
bool isReceiveShadows() const { return currentPreset().receive_shadow; }
|
|
bool isCastShadows() const { return currentPreset().cast_shadow; }
|
|
void setReceiveShadows(bool on);
|
|
void setCastShadows(bool on);
|
|
|
|
void move(const QVector3D & dv);
|
|
void moveTo(const QVector3D & dv);
|
|
void move(GLfloat dx, GLfloat dy, GLfloat dz = 0.);
|
|
void moveTo(GLfloat dx, GLfloat dy, GLfloat dz = 0.);
|
|
void moveX(GLfloat o);
|
|
void moveY(GLfloat o);
|
|
void moveZ(GLfloat o);
|
|
void setPosX(GLfloat o);
|
|
void setPosY(GLfloat o);
|
|
void setPosZ(GLfloat o);
|
|
void setPos(GLfloat x, GLfloat y, GLfloat z);
|
|
void setPos(const QVector3D & p);
|
|
void resetPos();
|
|
|
|
QVector3D pos() const { return trans.translation(); }
|
|
float posX() const { return trans.translation().x(); }
|
|
float posY() const { return trans.translation().y(); }
|
|
float posZ() const { return trans.translation().z(); }
|
|
QVector3D worldPos() const { return (itransform_ * QVector4D(0, 0, 0, 1.)).toVector3D(); }
|
|
QMatrix4x4 worldTransform() const { return itransform_; }
|
|
|
|
QVector3D rotation() const { return trans.rotation(); }
|
|
float rotationX() const { return rotation().x(); }
|
|
float rotationY() const { return rotation().y(); }
|
|
float rotationZ() const { return rotation().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 trans.scale3D(); }
|
|
float scaleX() { return trans.scale3D().x(); }
|
|
float scaleY() { return trans.scale3D().y(); }
|
|
float scaleZ() { return trans.scale3D().z(); }
|
|
void scale(const QVector3D & sv);
|
|
void scale(GLfloat sx, GLfloat sy, GLfloat sz);
|
|
void scale(GLfloat sx, GLfloat sy);
|
|
void scale(GLfloat sx);
|
|
void scaleX(GLfloat a);
|
|
void scaleY(GLfloat a);
|
|
void scaleZ(GLfloat a);
|
|
void setScale(const QVector3D & a);
|
|
void setScale(GLfloat a);
|
|
void setScaleX(GLfloat a);
|
|
void setScaleY(GLfloat a);
|
|
void setScaleZ(GLfloat a);
|
|
void resetScale();
|
|
|
|
Transform transform() { return trans; }
|
|
void setTransform(const Transform & t);
|
|
void setMatrix(const QMatrix4x4 & t);
|
|
QMatrix4x4 matrix() const;
|
|
|
|
bool isRawMatrix() { return raw_matrix; }
|
|
QVector3D inParentSpace(const QVector3D & v) const;
|
|
void transferTransformToChildren(bool only_scale = false);
|
|
void cleanTree();
|
|
|
|
Transform textureTransform() { return trans_texture; }
|
|
void setTextureTransform(const Transform & t);
|
|
void setTextureMatrix(const QMatrix4x4 & t);
|
|
QMatrix4x4 textureMatrix() const;
|
|
QGenericMatrix<3, 2, float> textureGLMatrix() const;
|
|
|
|
bool isAcceptLight() const { return currentPreset().accept_light; }
|
|
void setAcceptLight(bool yes);
|
|
|
|
bool isAcceptFog() const { return currentPreset().accept_fog; }
|
|
void setAcceptFog(bool yes);
|
|
|
|
bool isSelected(bool check_parents = false) const;
|
|
void setSelected(bool yes);
|
|
void select() { setSelected(true); }
|
|
void deselect() { setSelected(false); }
|
|
ObjectBase * selectedParent() const;
|
|
void setAimSelected(bool yes) { selected_aim = yes; }
|
|
bool isAimSelected() const { return selected_aim; }
|
|
|
|
bool isSelectable() const { return select_; }
|
|
void setSelectable(bool yes) { select_ = yes; }
|
|
|
|
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(Material * m, bool with_children = false);
|
|
Material * material() { return currentPreset().material; }
|
|
|
|
void setColor(QColor c, bool with_children = false);
|
|
QColor color() { return color_; }
|
|
|
|
const Box3D & boundingBox() const { return bound; }
|
|
void setMesh(Mesh * v);
|
|
Mesh * mesh() { return mesh_; }
|
|
|
|
void calculateBoundingBox();
|
|
void updateTransform();
|
|
|
|
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);
|
|
|
|
void setPreset(int preset);
|
|
|
|
QVector3D pos_h;
|
|
|
|
protected:
|
|
struct Preset {
|
|
bool visible = true;
|
|
bool accept_light = true;
|
|
bool accept_fog = true;
|
|
bool cast_shadow = true;
|
|
bool receive_shadow = true;
|
|
Material * material = nullptr;
|
|
};
|
|
friend QGLENGINE_CORE_EXPORT QDataStream & operator<<(QDataStream & s, const ObjectBase::Preset & p);
|
|
friend QGLENGINE_CORE_EXPORT QDataStream & operator>>(QDataStream & s, ObjectBase::Preset & p);
|
|
|
|
virtual void transformChanged() {}
|
|
void addChildren(ObjectBaseList & list, ObjectBase * where);
|
|
void buildTransform(bool force = false);
|
|
void initInternal();
|
|
void setSceneTreeChanged();
|
|
void setObjectsChanged();
|
|
void localTransform(QMatrix4x4 & m);
|
|
QMatrix4x4 worldMatrix(QMatrix4x4 parent) const;
|
|
const Preset & currentPreset() const { return presets[cur_preset]; }
|
|
Preset & currentPreset() { return presets[cur_preset]; }
|
|
|
|
int prev_pass = rpSolid; // Pass
|
|
int cur_preset = 0;
|
|
bool is_init = false, select_ = true, selected_ = false, raw_matrix = false;
|
|
bool is_root = false, selected_aim = false;
|
|
float line_width = -1.f;
|
|
QVector<Preset> presets;
|
|
QColor color_ = Qt::white;
|
|
uint id_ = 0;
|
|
Type type_ = glMesh;
|
|
Box3D bound;
|
|
Transform trans, trans_texture;
|
|
ObjectBaseList children_;
|
|
QMatrix4x4 itransform_, mat_;
|
|
QString name_;
|
|
GLenum blend_src, blend_dest;
|
|
ObjectBase * parent_ = nullptr;
|
|
Scene * scene_ = nullptr;
|
|
Mesh * mesh_ = nullptr;
|
|
QVariantMap meta;
|
|
};
|
|
|
|
inline bool operator<(const ObjectBase & f, const ObjectBase & s) {
|
|
return f.pos_h.z() < s.pos_h.z();
|
|
}
|
|
|
|
|
|
class QGLENGINE_CORE_EXPORT AimedObject: public ObjectBase {
|
|
friend class QGLView;
|
|
friend class GLRendererBase;
|
|
friend class Light;
|
|
friend class Camera;
|
|
|
|
public:
|
|
AimedObject();
|
|
~AimedObject() {}
|
|
QVector3D aim() const { return pos() + (direction() * aim_dist); }
|
|
QVector3D worldAim() const;
|
|
void setAim(const QVector3D & p);
|
|
QVector3D direction() const;
|
|
QVector3D worldDirection() const { return (itransform_ * QVector4D(QVector3D(0, 0, -1), 0.)).toVector3D().normalized(); }
|
|
void setDirection(const QVector3D & d);
|
|
void setDirection(double x, double y, double z) { setDirection(QVector3D(x, y, z)); }
|
|
|
|
double distance() const { return aim_dist; }
|
|
void setDistance(double d) { aim_dist = d; }
|
|
void flyCloser(double s);
|
|
void flyFarer(double s);
|
|
void flyToDistance(double d);
|
|
|
|
void moveForward(const float & x, bool withZ = true);
|
|
void moveBackward(const float & x, bool withZ = true) { moveForward(-x, withZ); }
|
|
void moveLeft(const float & x, bool withZ = true);
|
|
void moveRight(const float & x, bool withZ = true) { moveLeft(-x, withZ); }
|
|
void moveUp(const float & x, bool onlyZ = false);
|
|
void moveDown(const float & x, bool onlyZ = false) { moveUp(-x, onlyZ); }
|
|
|
|
void rotateRoll(const float & a) { rotateY(a); }
|
|
void orbitZ(const float & a);
|
|
void orbitXY(const float & a);
|
|
|
|
protected:
|
|
void transformChanged() override;
|
|
double aim_dist;
|
|
};
|
|
|
|
|
|
class QGLENGINE_CORE_EXPORT Light: public AimedObject {
|
|
friend class QGLView;
|
|
friend class RendererBase;
|
|
|
|
public:
|
|
enum Type {
|
|
Omni,
|
|
Cone,
|
|
Directional
|
|
};
|
|
|
|
Light(const QVector3D & p = QVector3D(), const QColor & c = Qt::white, float i = 1.);
|
|
virtual ObjectBase * clone(bool withChildren = true);
|
|
virtual void init() {
|
|
shadow_map.resize(512, 512);
|
|
is_init = true;
|
|
}
|
|
void apply();
|
|
|
|
float angle_start;
|
|
float angle_end;
|
|
float intensity;
|
|
float decay_const;
|
|
float decay_linear;
|
|
float decay_quadratic;
|
|
float decay_start;
|
|
float decay_end;
|
|
float size;
|
|
Type light_type;
|
|
Framebuffer shadow_map;
|
|
QMatrix4x4 shadow_matrix;
|
|
Map light_map;
|
|
};
|
|
|
|
template<class T>
|
|
inline T globject_cast(ObjectBase * object) {
|
|
return reinterpret_cast<T>(object);
|
|
}
|
|
|
|
template<class T>
|
|
inline T globject_cast(const ObjectBase * object) {
|
|
return reinterpret_cast<T>(object);
|
|
}
|
|
|
|
|
|
QGLENGINE_CORE_EXPORT QDataStream & operator<<(QDataStream & s, const ObjectBase::Preset & p);
|
|
QGLENGINE_CORE_EXPORT QDataStream & operator>>(QDataStream & s, ObjectBase::Preset & p);
|
|
QGLENGINE_CORE_EXPORT QDataStream & operator<<(QDataStream & s, const ObjectBase * p);
|
|
QGLENGINE_CORE_EXPORT QDataStream & operator>>(QDataStream & s, ObjectBase *& p);
|
|
|
|
inline ObjectBaseList lights2objectList(const QList<Light *> & v) {
|
|
ObjectBaseList ret;
|
|
foreach(Light * i, v)
|
|
ret << (ObjectBase *)i;
|
|
return ret;
|
|
}
|
|
inline ObjectBaseList cameras2objectList(const QList<Camera *> & v) {
|
|
ObjectBaseList ret;
|
|
foreach(Camera * i, v)
|
|
ret << (ObjectBase *)i;
|
|
return ret;
|
|
}
|
|
|
|
#endif // GLOBJECT_H
|