git-svn-id: svn://db.shs.com.ru/libs@627 a8b55f48-bf90-11e4-a774-851b48703e85
This commit is contained in:
@@ -44,7 +44,7 @@ Mesh * assimpMesh(const aiMesh * m) {
|
||||
|
||||
QVector<QVector3D> & v(ret->vertices()); v.resize(vcnt);
|
||||
QVector<QVector2D> & t(ret->texcoords()); t.resize(vcnt);
|
||||
QVector< Vector3i> & ind(ret->indices());
|
||||
QVector< Vector3i> & ind(ret->indicesTriangles());
|
||||
|
||||
for (int i = 0; i < vcnt; ++i)
|
||||
v[i] = fromAiVector3D(m->mVertices[i]);
|
||||
|
||||
@@ -26,10 +26,11 @@ using namespace QGLEngineShaders;
|
||||
|
||||
static int _count = 0;
|
||||
|
||||
Mesh::Mesh(): buffer_geom(GL_ARRAY_BUFFER, GL_STATIC_DRAW),
|
||||
buffer_ind (GL_ELEMENT_ARRAY_BUFFER, GL_STATIC_DRAW),
|
||||
buffer_obj (GL_ARRAY_BUFFER, GL_STREAM_DRAW),
|
||||
buffer_sel (GL_ARRAY_BUFFER, GL_STREAM_DRAW) {
|
||||
Mesh::Mesh(GLenum geom_type_): geom_type(geom_type_),
|
||||
buffer_geom(GL_ARRAY_BUFFER, GL_STATIC_DRAW),
|
||||
buffer_ind (GL_ELEMENT_ARRAY_BUFFER, GL_STATIC_DRAW),
|
||||
buffer_obj (GL_ARRAY_BUFFER, GL_STREAM_DRAW),
|
||||
buffer_sel (GL_ARRAY_BUFFER, GL_STREAM_DRAW) {
|
||||
vao = 0;
|
||||
hash_ = 0;
|
||||
changed = hash_changed = objects_changed = selected_changed = true;
|
||||
@@ -49,6 +50,8 @@ Mesh * Mesh::clone() {
|
||||
c->normals_ = normals_ ;
|
||||
c->texcoords_ = texcoords_;
|
||||
c->triangles_ = triangles_;
|
||||
c->lines_ = lines_;
|
||||
c->geom_type = geom_type;
|
||||
c->hash_ = hash_;
|
||||
c->hash_changed = hash_changed;
|
||||
//qDebug() << "clone VBO";
|
||||
@@ -163,7 +166,8 @@ bool Mesh::rebuffer(QOpenGLExtraFunctions * f) {
|
||||
v.tex = texcoords_ [i];
|
||||
}
|
||||
int gsize = data_.size() * sizeof(Vertex);
|
||||
int isize = triangles_.size() * sizeof(Vector3i);
|
||||
int tsize = triangles_.size() * sizeof(Vector3i);
|
||||
int lsize = lines_.size() * sizeof(Vector2i);
|
||||
f->glBindVertexArray(vao);
|
||||
|
||||
buffer_geom.bind(f);
|
||||
@@ -172,8 +176,13 @@ bool Mesh::rebuffer(QOpenGLExtraFunctions * f) {
|
||||
prepareDrawGeom(f);
|
||||
|
||||
buffer_ind.bind(f);
|
||||
buffer_ind.resize(f, isize);
|
||||
buffer_ind.load(f, triangles_.constData(), isize);
|
||||
if (geom_type == GL_TRIANGLES) {
|
||||
buffer_ind.resize(f, tsize);
|
||||
buffer_ind.load(f, triangles_.constData(), tsize);
|
||||
} else {
|
||||
buffer_ind.resize(f, lsize);
|
||||
buffer_ind.load(f, lines_.constData(), lsize);
|
||||
}
|
||||
|
||||
buffer_obj.bind(f);
|
||||
prepareDrawObj(f);
|
||||
@@ -247,10 +256,13 @@ void Mesh::draw(QOpenGLExtraFunctions * f, int count) {
|
||||
if (isEmpty()) return;
|
||||
if (!isInit()) init(f);
|
||||
if (changed) rebuffer(f);
|
||||
//qDebug() << "draw" << vert_count << count;
|
||||
//qDebug() << "draw" << geom_type << vert_count << count;
|
||||
|
||||
f->glBindVertexArray(vao);
|
||||
f->glDrawElementsInstanced(GL_TRIANGLES, triangles_.size() * 3, GL_UNSIGNED_INT, 0, count);
|
||||
if (geom_type == GL_TRIANGLES)
|
||||
f->glDrawElementsInstanced(geom_type, triangles_.size() * 3, GL_UNSIGNED_INT, 0, count);
|
||||
else
|
||||
f->glDrawElementsInstanced(geom_type, lines_.size() * 2, GL_UNSIGNED_INT, 0, count);
|
||||
f->glBindVertexArray(0);
|
||||
}
|
||||
|
||||
@@ -262,6 +274,7 @@ void Mesh::clear() {
|
||||
bitangents_.clear();
|
||||
texcoords_.clear();
|
||||
triangles_.clear();
|
||||
lines_.clear();
|
||||
data_.clear();
|
||||
changed = hash_changed = true;
|
||||
}
|
||||
@@ -290,6 +303,7 @@ uint Mesh::hash() const {
|
||||
hash_ ^= qHashBits(normals_ .constData(), normals_ .size() * sizeof(QVector3D));
|
||||
hash_ ^= qHashBits(texcoords_.constData(), texcoords_.size() * sizeof(QVector2D));
|
||||
hash_ ^= qHashBits(triangles_.constData(), triangles_.size() * sizeof( Vector3i));
|
||||
hash_ ^= qHashBits(lines_ .constData(), lines_ .size() * sizeof( Vector2i));
|
||||
}
|
||||
return hash_;
|
||||
}
|
||||
@@ -327,6 +341,10 @@ void Mesh::append(const Mesh * m) {
|
||||
for (int i = 0; i < tri.size(); ++i)
|
||||
tri[i] += vcnt;
|
||||
triangles_.append(tri);
|
||||
QVector<Vector2i> lin = m->lines_;
|
||||
for (int i = 0; i < lin.size(); ++i)
|
||||
lin[i] += vcnt;
|
||||
lines_.append(lin);
|
||||
}
|
||||
|
||||
|
||||
@@ -336,7 +354,7 @@ bool Mesh::saveToFile(const QString & filename) {
|
||||
QByteArray ba;
|
||||
if (f.open(QFile::WriteOnly)) {
|
||||
QDataStream out(&ba, QFile::WriteOnly);
|
||||
out << vertices_ << normals_ << texcoords_ << triangles_;
|
||||
out << vertices_ << normals_ << texcoords_ << triangles_ << lines_;
|
||||
ba = qCompress(ba);
|
||||
f.resize(0);
|
||||
f.write(ba);
|
||||
@@ -356,7 +374,7 @@ bool Mesh::loadFromFile(const QString & filename) {
|
||||
if (ba.isEmpty()) return false;
|
||||
ba = qUncompress(ba);
|
||||
QDataStream in(ba);
|
||||
in >> vertices_ >> normals_ >> texcoords_ >> triangles_;
|
||||
in >> vertices_ >> normals_ >> texcoords_ >> triangles_ >> lines_;
|
||||
changed = hash_changed = true;
|
||||
f.close();
|
||||
return !isEmpty();
|
||||
@@ -397,7 +415,8 @@ Box3D Mesh::boundingBox() const {
|
||||
QDataStream & operator <<(QDataStream & s, const Mesh * m) {
|
||||
ChunkStream cs;
|
||||
//qDebug() << "place VBO" << m.vertices_.size() << m.normals_.size() << m.texcoords_.size() << m.colors_.size() << "...";
|
||||
cs.add(1, m->vertices_).add(2, m->normals_).add(3, m->texcoords_).add(6, m->triangles_);
|
||||
cs.add(1, m->vertices_).add(2, m->normals_).add(3, m->texcoords_)
|
||||
.add(6, m->triangles_).add(7, m->lines_).add(10, int(m->geom_type));
|
||||
//qDebug() << "place VBO done" << cs.data().size() << "...";
|
||||
s << /*qCompress*/(cs.data()); return s;
|
||||
}
|
||||
@@ -411,10 +430,12 @@ QDataStream & operator >>(QDataStream & s, Mesh *& m) {
|
||||
ChunkStream cs(s);
|
||||
while (!cs.atEnd()) {
|
||||
switch (cs.read()) {
|
||||
case 1: cs.get(m->vertices_ ); break;
|
||||
case 2: cs.get(m->normals_ ); break;
|
||||
case 3: cs.get(m->texcoords_); break;
|
||||
case 6: cs.get(m->triangles_); break;
|
||||
case 1 : cs.get(m->vertices_ ); break;
|
||||
case 2 : cs.get(m->normals_ ); break;
|
||||
case 3 : cs.get(m->texcoords_); break;
|
||||
case 6 : cs.get(m->triangles_); break;
|
||||
case 7 : cs.get(m->lines_ ); break;
|
||||
case 10: m->geom_type = cs.getData<int>(); break;
|
||||
}
|
||||
}
|
||||
m->changed = true;
|
||||
|
||||
@@ -32,7 +32,7 @@ class Mesh
|
||||
friend QDataStream & operator <<(QDataStream & s, const Mesh * m);
|
||||
friend QDataStream & operator >>(QDataStream & s, Mesh *& m);
|
||||
public:
|
||||
Mesh();
|
||||
Mesh(GLenum geom_type_ = GL_TRIANGLES);
|
||||
~Mesh();
|
||||
|
||||
Mesh * clone();
|
||||
@@ -50,6 +50,7 @@ public:
|
||||
|
||||
int verticesCount() const {return vertices_.size();}
|
||||
int trianglesCount() const {return triangles_.size();}
|
||||
int linesCount() const {return lines_.size();}
|
||||
bool isInit() const {return vao != 0;}
|
||||
bool isEmpty() const {return vertices_.isEmpty();}
|
||||
uint hash() const;
|
||||
@@ -57,10 +58,12 @@ public:
|
||||
QVector<QVector3D> & vertices () {changed = hash_changed = true; return vertices_;}
|
||||
QVector<QVector3D> & normals () {changed = hash_changed = true; return normals_;}
|
||||
QVector<QVector2D> & texcoords() {changed = hash_changed = true; return texcoords_;}
|
||||
QVector< Vector3i> & indices () {changed = hash_changed = true; return triangles_;}
|
||||
QVector< Vector3i> & indicesTriangles() {changed = hash_changed = true; return triangles_;}
|
||||
QVector< Vector2i> & indicesLines () {changed = hash_changed = true; return lines_;}
|
||||
|
||||
void translatePoints(const QVector3D & dp);
|
||||
void scalePoints (const QVector3D & dp);
|
||||
void scalePoints (const double & s) {scalePoints(QVector3D(s, s, s));}
|
||||
void append(const Mesh * m);
|
||||
|
||||
bool saveToFile(const QString & filename);
|
||||
@@ -80,9 +83,10 @@ private:
|
||||
QVector<QVector3D> vertices_, normals_, tangents_, bitangents_;
|
||||
QVector<QVector2D> texcoords_;
|
||||
QVector< Vector3i> triangles_;
|
||||
QVector< Vector2i> lines_;
|
||||
|
||||
QVector<QGLEngineShaders::Vertex> data_;
|
||||
GLenum vao;
|
||||
GLenum vao, geom_type;
|
||||
Buffer buffer_geom, buffer_ind, buffer_obj, buffer_sel;
|
||||
mutable uint hash_;
|
||||
mutable bool hash_changed;
|
||||
|
||||
@@ -29,6 +29,8 @@ class ObjectBase
|
||||
friend class QGLView;
|
||||
friend class Scene;
|
||||
friend class Renderer;
|
||||
friend class RendererService;
|
||||
friend class RendererSelection;
|
||||
friend QDataStream & operator <<(QDataStream & s, const ObjectBase * p);
|
||||
friend QDataStream & operator >>(QDataStream & s, ObjectBase *& p);
|
||||
friend QDataStream & operator >>(QDataStream & s, Scene *& p);
|
||||
|
||||
@@ -27,7 +27,7 @@ Mesh * Primitive::plane(float width, float length) {
|
||||
QVector<QVector3D> & v(ret->vertices ());
|
||||
QVector<QVector3D> & n(ret->normals ());
|
||||
QVector<QVector2D> & t(ret->texcoords());
|
||||
QVector< Vector3i> & i(ret->indices ());
|
||||
QVector< Vector3i> & i(ret->indicesTriangles ());
|
||||
float hw = width / 2.f, hl = length / 2.f;
|
||||
for (int j = 0; j < 4; ++j) n << QVector3D(0., 0., 1.);
|
||||
t << QVector2D(0., 0.) << QVector2D(0., 1.) << QVector2D(1., 1.) << QVector2D(1., 0.);
|
||||
@@ -43,7 +43,7 @@ Mesh * Primitive::cube(float width, float length, float height) {
|
||||
QVector<QVector3D> & v(ret->vertices ());
|
||||
QVector<QVector3D> & n(ret->normals ());
|
||||
QVector<QVector2D> & t(ret->texcoords());
|
||||
QVector< Vector3i> & i(ret->indices ());
|
||||
QVector< Vector3i> & i(ret->indicesTriangles ());
|
||||
float hs = 0.5f;
|
||||
int si = 0;
|
||||
QMatrix4x4 mat;
|
||||
@@ -92,7 +92,7 @@ Mesh * Primitive::ellipsoid(int segments_wl, int segments_h, float width, float
|
||||
QVector<QVector3D> & v(ret->vertices ());
|
||||
QVector<QVector3D> & n(ret->normals ());
|
||||
QVector<QVector2D> & t(ret->texcoords());
|
||||
QVector< Vector3i> & ind(ret->indices());
|
||||
QVector< Vector3i> & ind(ret->indicesTriangles());
|
||||
double hh = height / 2.f;
|
||||
int hseg = segments_h + 1, wlseg = segments_wl + 1;
|
||||
double crw, crl, a, ch, twl;
|
||||
@@ -131,7 +131,7 @@ Mesh * Primitive::disc(int segments, float width, float length, bool up) {
|
||||
QVector<QVector3D> & v(ret->vertices ());
|
||||
QVector<QVector3D> & n(ret->normals ());
|
||||
QVector<QVector2D> & t(ret->texcoords());
|
||||
QVector< Vector3i> & ind(ret->indices());
|
||||
QVector< Vector3i> & ind(ret->indicesTriangles());
|
||||
|
||||
segments = qMax(segments + 1, 4);
|
||||
QVector3D cp;
|
||||
@@ -176,7 +176,7 @@ Mesh * Primitive::cone(int segments, float width, float length, float height) {
|
||||
QVector<QVector3D> & v(ret->vertices ());
|
||||
QVector<QVector3D> & n(ret->normals ());
|
||||
QVector<QVector2D> & t(ret->texcoords());
|
||||
QVector< Vector3i> & ind(ret->indices());
|
||||
QVector< Vector3i> & ind(ret->indicesTriangles());
|
||||
|
||||
int seg = qMax(segments + 1, 4);
|
||||
double rx = width / 2., ry = length / 2.;
|
||||
@@ -212,7 +212,7 @@ Mesh * Primitive::cylinder(int segments, float width, float length, float height
|
||||
QVector<QVector3D> & v(ret->vertices ());
|
||||
QVector<QVector3D> & n(ret->normals ());
|
||||
QVector<QVector2D> & t(ret->texcoords());
|
||||
QVector< Vector3i> & ind(ret->indices());
|
||||
QVector< Vector3i> & ind(ret->indicesTriangles());
|
||||
|
||||
int seg = qMax(segments + 1, 4);
|
||||
double rx = width / 2., ry = length / 2.;
|
||||
@@ -261,3 +261,66 @@ Mesh * Primitive::arrow(int segments, float thick, float angle) {
|
||||
delete m;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
Mesh * Primitive::cubeFrame(float width, float length, float height) {
|
||||
Mesh * ret = new Mesh(GL_LINES);
|
||||
QVector3D scale(width, length, height);
|
||||
QVector<QVector3D> & v(ret->vertices ());
|
||||
QVector<QVector3D> & n(ret->normals ());
|
||||
QVector<QVector2D> & t(ret->texcoords());
|
||||
QVector< Vector2i> & i(ret->indicesLines());
|
||||
float hs = 0.5f;
|
||||
v << QVector3D(-hs, -hs, -hs) << QVector3D(-hs, hs, -hs) << QVector3D( hs, hs, -hs) << QVector3D( hs, -hs, -hs);
|
||||
v << QVector3D(-hs, -hs, hs) << QVector3D(-hs, hs, hs) << QVector3D( hs, hs, hs) << QVector3D( hs, -hs, hs);
|
||||
for (int j = 0; j < 8; ++j) {
|
||||
v[j] *= scale;
|
||||
t << QVector2D(0, 0);
|
||||
n << QVector3D(0,0,1);
|
||||
}
|
||||
for (int j = 0; j < 4; ++j) {
|
||||
i << Vector2i(j, (j + 1) % 4);
|
||||
i << Vector2i(j, j + 4);
|
||||
i << Vector2i(j + 4, (j + 1) % 4 + 4);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
Mesh * Primitive::ellipsoidFrame(int segments_wl, int segments_h, float width, float length, float height) {
|
||||
Mesh * ret = new Mesh(GL_LINES);
|
||||
QVector<QVector3D> & v(ret->vertices ());
|
||||
QVector<QVector3D> & n(ret->normals ());
|
||||
QVector<QVector2D> & t(ret->texcoords());
|
||||
QVector< Vector2i> & ind(ret->indicesLines());
|
||||
double hh = height / 2.f;
|
||||
int hseg = segments_h + 1, wlseg = segments_wl + 1;
|
||||
double crw, crl, a, ch, twl;
|
||||
|
||||
QVector3D cp;
|
||||
for (int i = 0; i <= hseg; i++) {
|
||||
ch = -cos((double)i / hseg * M_PI);
|
||||
cp.setZ(ch * hh);
|
||||
twl = sqrt(1. - ch * ch) / 2.;
|
||||
crw = twl * width;
|
||||
crl = twl * length;
|
||||
int cvcnt = wlseg * 2;
|
||||
for (int j = 0; j < cvcnt; j++) {
|
||||
a = (double)j / (cvcnt - 1) * M_2PI;
|
||||
cp.setX(crl * cos(a));
|
||||
cp.setY(crw * sin(a));
|
||||
v << cp; t << QVector2D((double)j / (cvcnt - 1), ch/2.f + 0.5f);
|
||||
int si = v.size() - 1;
|
||||
if (j > 0 && i > 0) {
|
||||
ind << Vector2i(si, si - 1);
|
||||
ind << Vector2i(si - cvcnt, si);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
n.resize(v.size());
|
||||
for (int i = 0; i < v.size(); i++)
|
||||
n[i] = v[i].normalized();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -40,6 +40,10 @@ Mesh * cylinder(int segments, float width = 1., float length = 1., float height
|
||||
Mesh * arrow(int segments = 16, float thick = 0.04, float angle = 30.); // length = 1
|
||||
|
||||
|
||||
Mesh * cubeFrame(float width = 1., float length = 1., float height = 1.);
|
||||
|
||||
Mesh * ellipsoidFrame(int segments_wl, int segments_h, float width = 1., float length = 1., float height = 1.);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -29,6 +29,7 @@ class Scene: public QObject {
|
||||
friend class Renderer;
|
||||
friend class RendererMaterial;
|
||||
friend class RendererService;
|
||||
friend class RendererSelection;
|
||||
friend class ObjectBase;
|
||||
friend class Light;
|
||||
friend QDataStream & operator <<(QDataStream & s, const Scene * p);
|
||||
|
||||
@@ -275,6 +275,14 @@ void lengthenVector(QVector3D & v, const float & l) {
|
||||
}
|
||||
|
||||
|
||||
Vector2i::Vector2i(const QString & str) {
|
||||
QString s = str.trimmed();
|
||||
int i = s.indexOf("\t");
|
||||
p0 = s.left(i).toInt(); s = s.right(s.length() - i - 1);
|
||||
p1 = s.toInt();
|
||||
}
|
||||
|
||||
|
||||
Vector3i::Vector3i(const QString & str) {
|
||||
QString s = str.trimmed();
|
||||
int i = s.indexOf("\t");
|
||||
|
||||
@@ -178,6 +178,8 @@ class RendererBase;
|
||||
class Renderer;
|
||||
class RendererMaterial;
|
||||
class RendererService;
|
||||
class RendererSelection;
|
||||
|
||||
|
||||
struct Box3D {
|
||||
GLfloat x;
|
||||
@@ -211,6 +213,33 @@ struct Box3D {
|
||||
|
||||
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;}
|
||||
|
||||
|
||||
#pragma pack(push, 1)
|
||||
struct Vector2i {
|
||||
Vector2i(int p0_ = 0, int p1_ = 0) {p0 = p0_; p1 = p1_;}
|
||||
Vector2i(const QString & str);
|
||||
Vector2i movedX(const int & o) {return Vector2i(p0 + o, p1);}
|
||||
Vector2i movedY(const int & o) {return Vector2i(p0, p1 + o);}
|
||||
Vector2i moved(const int & x, const int & y) {return Vector2i(p0 + x, p1 + y);}
|
||||
GLint p0;
|
||||
GLint p1;
|
||||
bool operator ==(const Vector2i & o) const {return p0 == o.p0 && p1 == o.p1;}
|
||||
bool operator !=(const Vector2i & o) const {return p0 != o.p0 || p1 != o.p1;}
|
||||
void operator +=(int v) {p0 += v; p1 += v;}
|
||||
QVector2D toQVector2D() const {return QVector2D(p0, p1);}
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
inline Vector2i operator +(const Vector2i & f, const Vector2i & s) {return Vector2i(f.p0 + s.p0, f.p1 + s.p1);}
|
||||
inline Vector2i operator -(const Vector2i & f, const Vector2i & s) {return Vector2i(f.p0 - s.p0, f.p1 - s.p1);}
|
||||
inline Vector2i operator /(const Vector2i & f, const int & s) {return Vector2i(f.p0 / s, f.p1 / s);}
|
||||
inline uint qHash(const Vector2i & v) {return v.p0 ^ ((v.p1 << 8) | (v.p1 >> 24));}
|
||||
inline QDebug operator <<(QDebug d, const Vector2i & v) {d.nospace() << "{" << v.p0 << ", " << v.p1 << "}"; return d.space();}
|
||||
|
||||
inline QDataStream & operator <<(QDataStream & s, const Vector2i & v) {s << v.p0 << v.p1; return s;}
|
||||
inline QDataStream & operator >>(QDataStream & s, Vector2i & v) {s >> v.p0 >> v.p1; return s;}
|
||||
|
||||
|
||||
#pragma pack(push, 1)
|
||||
struct Vector3i {
|
||||
Vector3i(int p0_ = 0, int p1_ = 0, int p2_ = 0) {p0 = p0_; p1 = p1_; p2 = p2_;}
|
||||
@@ -238,6 +267,7 @@ inline QDebug operator <<(QDebug d, const Vector3i & v) {d.nospace() << "{" << v
|
||||
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;}
|
||||
|
||||
|
||||
QVector3D vectorFromString(const QString & str);
|
||||
QColor colorFromString(const QString & str);
|
||||
inline QVector4D QColor2QVector(const QColor & c) {return QVector4D(c.redF(), c.greenF(), c.blueF(), c.alphaF());}
|
||||
|
||||
@@ -91,7 +91,7 @@ QGLView::QGLView(): OpenGLWindow(), renderer_(this) {
|
||||
//camera().aim_ = camera().pos_;
|
||||
ktm_.restart();
|
||||
|
||||
Mesh * m = Primitive::cube();
|
||||
Mesh * m = Primitive::ellipsoidFrame(5,5);
|
||||
ObjectBase * o = new ObjectBase(m);
|
||||
o->setColor(Qt::cyan);
|
||||
scene()->addObject(o);
|
||||
|
||||
@@ -39,6 +39,7 @@ class QGLView: public OpenGLWindow
|
||||
friend class Renderer;
|
||||
friend class RendererMaterial;
|
||||
friend class RendererService;
|
||||
friend class RendererSelection;
|
||||
Q_OBJECT
|
||||
Q_PROPERTY (QColor backColor READ backColor WRITE setBackColor)
|
||||
Q_PROPERTY (float lineWidth READ lineWidth WRITE setLineWidth)
|
||||
|
||||
@@ -28,25 +28,22 @@ using namespace QGLEngineShaders;
|
||||
|
||||
|
||||
Renderer::Renderer(QGLView * view_): RendererBase(view_),
|
||||
fbo_selection(view_, 4),
|
||||
fbo_ds (view_, 5, true , GL_RGBA16F),
|
||||
fbo_out (view_, 3, false, GL_RGBA16F),
|
||||
fbo_hsmall (view_, 1, false, GL_RGB16F ),
|
||||
rend_mat(this), rend_service(this) {
|
||||
rend_mat(this), rend_service(this), rend_selection(this) {
|
||||
quad = Primitive::plane(2., 2.);
|
||||
sel_frame = quad->clone();
|
||||
cam_light = new Light();
|
||||
cam_light->intensity = 0.75;
|
||||
cam_light->setName("Camera_Light");
|
||||
line_thick_ = 2.;
|
||||
id_hover = 0;
|
||||
|
||||
shader_files[srSelectionFill ] = "selection.glsl";
|
||||
shader_files[srSelectionHalo ] = "selection_halo.glsl";
|
||||
shader_files[srSelectionApply] = "selection_apply.glsl";
|
||||
shader_files[srSelectionFrame] = "selection_frame.glsl";
|
||||
|
||||
shader_files[srService] = "service.glsl";
|
||||
shader_files[srServiceFill ] = "service_fill.glsl";
|
||||
shader_files[srServiceFrame] = "service_frame.glsl";
|
||||
|
||||
shader_files[srGeometryPass] = "ds_geom.glsl";
|
||||
shader_files[srLightingPass] = "ds_light.glsl";
|
||||
@@ -70,13 +67,11 @@ Renderer::Renderer(QGLView * view_): RendererBase(view_),
|
||||
<< ShaderPair("dof", &shader_dof);*/
|
||||
exposure_ = 1.;
|
||||
edit_mode = need_init_shaders = is_camera_light = true;
|
||||
proc_sel_pbo = false;
|
||||
}
|
||||
|
||||
|
||||
Renderer::~Renderer() {
|
||||
delete quad;
|
||||
delete sel_frame;
|
||||
delete cam_light;
|
||||
qDeleteAll(shaders.values());
|
||||
}
|
||||
@@ -86,6 +81,7 @@ void Renderer::init(int width, int height) {
|
||||
resize(width, height);
|
||||
rend_mat.init(width, height);
|
||||
rend_service.init(width, height);
|
||||
rend_selection.init(width, height);
|
||||
initQuad(quad);
|
||||
initTextureArrays();
|
||||
need_init_shaders = true;
|
||||
@@ -95,12 +91,10 @@ void Renderer::init(int width, int height) {
|
||||
void Renderer::resize(int width, int height) {
|
||||
rend_mat.resize(width, height);
|
||||
rend_service.resize(width, height);
|
||||
fbo_selection.enablePixelBuffer();
|
||||
fbo_selection.resize(width, height);
|
||||
rend_selection.resize(width, height);
|
||||
fbo_ds .resize(width, height);
|
||||
fbo_out .resize(width, height);
|
||||
fbo_hsmall .resize(width / 16, height / 16);
|
||||
line_thick_ = lineThickness() + 1.;
|
||||
}
|
||||
|
||||
|
||||
@@ -139,28 +133,6 @@ void Renderer::releaseShader() {
|
||||
}
|
||||
|
||||
|
||||
void Renderer::generateObjectsID(Scene & scene) {
|
||||
ids.clear();
|
||||
QMapIterator<Mesh*, QList<ObjectBase*> > it(scene.geometries_used);
|
||||
while (it.hasNext()) {
|
||||
it.next();
|
||||
foreach (ObjectBase * o, it.value()) {
|
||||
uint id = qHash(o);
|
||||
ids[id] = o;
|
||||
o->id_ = id;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Renderer::fillSelectionsBuffer(const QList<ObjectBase *> & ol) {
|
||||
cur_selections_.resize(ol.size());
|
||||
for (int i = 0; i < ol.size(); ++i) {
|
||||
cur_selections_[i] = (ol[i]->isSelected(true) ? 1 : 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Renderer::fillObjectsBuffer(const QList<ObjectBase *> & ol, RenderPass pass) {
|
||||
cur_objects_.resize(ol.size());
|
||||
for (int i = 0; i < ol.size(); ++i) {
|
||||
@@ -195,94 +167,14 @@ void Renderer::renderObjects(Scene & scene, RenderPass pass) {
|
||||
}
|
||||
if (mesh->selected_changed && edit_mode) {
|
||||
mesh->selected_changed = false;
|
||||
fillSelectionsBuffer(it.value());
|
||||
mesh->loadSelections(f, cur_selections_);
|
||||
rend_selection.fillSelectionsBuffer(it.value());
|
||||
mesh->loadSelections(f, rend_selection.cur_selections_);
|
||||
}
|
||||
mesh->draw(f, it.value().size());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Renderer::renderSelection(Scene & scene) {
|
||||
QOpenGLShaderProgram * prog = 0;
|
||||
if (bindShader(srSelectionFill, &prog)) {
|
||||
view->hov_objects.clear();
|
||||
id_hover = 0;
|
||||
if (fbo_selection.queriedPoints() > 0) {
|
||||
if (fbo_selection.queriedPoints() == 1) {
|
||||
id_hover = fbo_selection.getPoint();
|
||||
view->hov_objects.resize(1);
|
||||
view->hov_objects[0] = ids.value(id_hover);
|
||||
//qDebug() << id_hover;
|
||||
} else {
|
||||
QVector<uint> points = fbo_selection.getPoints();
|
||||
QSet<uint> ids_hover;
|
||||
foreach (uint i, points)
|
||||
ids_hover << i;
|
||||
view->hov_objects.clear();
|
||||
foreach (uint i, ids_hover)
|
||||
view->hov_objects << ids.value(i);
|
||||
//qDebug() << ids_hover;
|
||||
}
|
||||
}
|
||||
|
||||
fbo_selection.bind();
|
||||
|
||||
fbo_selection.setWriteBuffers();
|
||||
glEnableDepth();
|
||||
glClearFramebuffer(QColor(0,0,0,0));
|
||||
setUniformCamera(prog, view->camera());
|
||||
renderObjects(scene, rpSelection);
|
||||
//mouse_rect = fbo_selection.rect();
|
||||
if (mouse_rect.isNull())
|
||||
fbo_selection.queryPoint(0, mouse_pos);
|
||||
else
|
||||
fbo_selection.queryPoints(0, mouse_rect);
|
||||
|
||||
//qDebug() << id_hover;
|
||||
fbo_selection.bindColorTextures();
|
||||
fbo_selection.setWriteBuffers();
|
||||
if (!view->hoverHalo_ && !view->selectionHalo_)
|
||||
glClearFramebuffer(QColor(0,0,0,0), false);
|
||||
else {
|
||||
bindShader(srSelectionHalo, &prog);
|
||||
setUniformHalo(prog, "hover" , view->hoverHaloColor() , view->hoverHaloFillAlpha());
|
||||
setUniformHalo(prog, "selection", view->selectionHaloColor(), view->selectionHaloFillAlpha());
|
||||
prog->setUniformValue("has_hover" , view->hoverHalo_ && (id_hover > 0) ? 1.f : 0.f);
|
||||
prog->setUniformValue("has_selection", view->selectionHalo_ ? 1.f : 0.f);
|
||||
prog->setUniformValue("fb_hover" , (int)sbrSrcHover);
|
||||
prog->setUniformValue("fb_selection", (int)sbrSrcSelect);
|
||||
prog->setUniformValue("hover_id", QVector4D(float( id_hover & 0xFF) / 255.f,
|
||||
float((id_hover >> 8 ) & 0xFF) / 255.f,
|
||||
float((id_hover >> 16) & 0xFF) / 255.f,
|
||||
float((id_hover >> 24) & 0xFF) / 255.f));
|
||||
renderQuad(prog, quad, view->camera());
|
||||
}
|
||||
|
||||
fbo_selection.release();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Renderer::renderSelectionFrame() {
|
||||
QOpenGLShaderProgram * prog = 0;
|
||||
if (bindShader(srSelectionFrame, &prog)) {
|
||||
QMatrix4x4 mat;
|
||||
double mrx = mouse_rect.x(), mrw = mouse_rect.width() , vw = view->width();
|
||||
double mry = mouse_rect.y(), mrh = mouse_rect.height(), vh = view->height();
|
||||
mat.translate(-1. + (mrw + mrx*2) / vw, 1. - (mrh + mry*2) / vh, 0.);
|
||||
mat.scale(mrw / vw, mrh / vh, 0.);
|
||||
initQuad(sel_frame, mat);
|
||||
prog->setUniformValue("size", QVector2D(mrw / vw, mrh / vh));
|
||||
prog->setUniformValue("thickness", line_thick_);
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
renderQuad(prog, sel_frame);
|
||||
glDisable(GL_BLEND);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Renderer::renderScene() {
|
||||
initShaders();
|
||||
QOpenGLExtraFunctions * f = view;
|
||||
@@ -295,7 +187,7 @@ void Renderer::renderScene() {
|
||||
if (scene_changed || scene.need_reload_materials) {
|
||||
if (scene.need_reload_materials)
|
||||
maps_hash = 0;
|
||||
generateObjectsID(scene);
|
||||
rend_selection.generateObjectsID(scene);
|
||||
reloadMaterials(scene);
|
||||
if (edit_mode)
|
||||
recreateMaterialThumbnails();
|
||||
@@ -321,7 +213,7 @@ void Renderer::renderScene() {
|
||||
|
||||
/// selection
|
||||
if (edit_mode) {
|
||||
renderSelection(scene);
|
||||
rend_selection.renderSelection(scene);
|
||||
}
|
||||
|
||||
/// geometry pass
|
||||
@@ -362,20 +254,8 @@ void Renderer::renderScene() {
|
||||
|
||||
/// apply hovers and selection frame
|
||||
if (edit_mode) {
|
||||
if (bindShader(srSelectionApply, &prog)) {
|
||||
fbo_selection.bindColorTextures();
|
||||
fbo_out.bindColorTexture(0);
|
||||
prog->setUniformValue("fb_out" , 0);
|
||||
prog->setUniformValue("fb_hover" , (int)sbrHovered );
|
||||
prog->setUniformValue("fb_select", (int)sbrSelected);
|
||||
renderQuad(prog, quad, cam);
|
||||
|
||||
if (!mouse_rect.isNull()) {
|
||||
renderSelectionFrame();
|
||||
}
|
||||
|
||||
rend_service.renderService();
|
||||
}
|
||||
rend_selection.drawSelection(fbo_out);
|
||||
rend_service.renderService();
|
||||
} else {
|
||||
fbo_out.blit(0, 0, 0, fbo_out.rect(), QRect(QPoint(), view->size()));
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include "renderer_base.h"
|
||||
#include "renderer_material.h"
|
||||
#include "renderer_service.h"
|
||||
#include "renderer_selection.h"
|
||||
#include <QQueue>
|
||||
|
||||
|
||||
@@ -29,6 +30,7 @@ class Renderer: public RendererBase {
|
||||
friend class QGLView;
|
||||
friend class RendererMaterial;
|
||||
friend class RendererService;
|
||||
friend class RendererSelection;
|
||||
enum RenderPass {
|
||||
rpSolid,
|
||||
rpTransparent,
|
||||
@@ -44,7 +46,8 @@ class Renderer: public RendererBase {
|
||||
srSelectionFrame,
|
||||
|
||||
// Service
|
||||
srService,
|
||||
srServiceFill,
|
||||
srServiceFrame,
|
||||
|
||||
// Deferred shading
|
||||
srGeometryPass,
|
||||
@@ -58,12 +61,6 @@ class Renderer: public RendererBase {
|
||||
dbrEmissionBitangX,
|
||||
dbrSpeedBitangXY,
|
||||
};
|
||||
enum SelectionBufferRole {
|
||||
sbrSrcHover,
|
||||
sbrSrcSelect,
|
||||
sbrHovered,
|
||||
sbrSelected
|
||||
};
|
||||
|
||||
public:
|
||||
Renderer(QGLView * view_);
|
||||
@@ -80,22 +77,18 @@ public:
|
||||
void recreateMaterialThumbnails(bool force_all = false) {rend_mat.recreateMaterialThumbnails(force_all);}
|
||||
|
||||
protected:
|
||||
void generateObjectsID(Scene & scene);
|
||||
void fillSelectionsBuffer(const QList<ObjectBase *> & ol);
|
||||
void fillObjectsBuffer(const QList<ObjectBase*> & ol, RenderPass pass);
|
||||
void reloadObjects();
|
||||
void renderObjects(Scene & scene, RenderPass pass);
|
||||
void renderSelection(Scene & scene);
|
||||
void renderSelectionFrame();
|
||||
|
||||
bool bindShader(ShaderRole role, QOpenGLShaderProgram ** ret = 0);
|
||||
void initShaders();
|
||||
void releaseShader();
|
||||
|
||||
private:
|
||||
float exposure_, line_thick_;
|
||||
bool edit_mode, proc_sel_pbo, need_init_shaders, is_camera_light;
|
||||
Framebuffer fbo_selection, fbo_ds, fbo_out, fbo_hsmall;
|
||||
float exposure_;
|
||||
bool edit_mode, need_init_shaders, is_camera_light;
|
||||
Framebuffer fbo_ds, fbo_out, fbo_hsmall;
|
||||
/*QOpenGLShaderProgram * shader_fxaa, * shader_ds_0, * shader_ds_1, * shader_hdr, * shader_small;
|
||||
QOpenGLShaderProgram * shader_bloom_0, * shader_bloom_1, * shader_motion_blur, * shader_fbo_add;
|
||||
QOpenGLShaderProgram * shader_shadow, * shader_ssr, * shader_ssr_blur, * shader_ssr_merge;
|
||||
@@ -105,12 +98,11 @@ private:
|
||||
|
||||
RendererMaterial rend_mat;
|
||||
RendererService rend_service;
|
||||
RendererSelection rend_selection;
|
||||
|
||||
Mesh * quad, * sel_frame;
|
||||
Mesh * quad;
|
||||
Light * cam_light;
|
||||
|
||||
QHash<uint, ObjectBase * > ids;
|
||||
uint id_hover;
|
||||
QPoint mouse_pos;
|
||||
QRect mouse_rect;
|
||||
QMatrix4x4 prev_view, prev_proj;
|
||||
|
||||
@@ -50,7 +50,6 @@ protected:
|
||||
QVector<QGLEngineShaders::QGLMaterial> cur_materials_;
|
||||
QVector<QGLEngineShaders::QGLLightParameter> cur_lights_params_;
|
||||
QVector<QGLEngineShaders::QGLLightPosition> cur_lights_pos_;
|
||||
QVector<uchar> cur_selections_;
|
||||
Buffer buffer_materials;
|
||||
Buffer buffer_lights, buffer_lights_pos;
|
||||
Texture2DArray textures_empty, textures_maps;
|
||||
|
||||
184
qglengine/renderer_selection.cpp
Normal file
184
qglengine/renderer_selection.cpp
Normal file
@@ -0,0 +1,184 @@
|
||||
/*
|
||||
QGLView
|
||||
Copyright (C) 2019 Ivan Pelipenko peri4ko@yandex.ru
|
||||
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#define GL_GLEXT_PROTOTYPES
|
||||
#include <QOpenGLExtraFunctions>
|
||||
#include "renderer_selection.h"
|
||||
#include "qglview.h"
|
||||
#include "glmesh.h"
|
||||
#include <qad_types.h>
|
||||
|
||||
using namespace QGLEngineShaders;
|
||||
|
||||
|
||||
RendererSelection::RendererSelection(Renderer * r_): r(r_),
|
||||
fbo_selection(r->view, 4) {
|
||||
sel_frame = Primitive::plane(2., 2.);
|
||||
id_hover = 0;
|
||||
line_thick_ = 2.;
|
||||
}
|
||||
|
||||
|
||||
RendererSelection::~RendererSelection() {
|
||||
delete sel_frame;
|
||||
}
|
||||
|
||||
|
||||
void RendererSelection::init(int width, int height) {
|
||||
resize(width, height);
|
||||
}
|
||||
|
||||
|
||||
void RendererSelection::resize(int width, int height) {
|
||||
fbo_selection.enablePixelBuffer();
|
||||
fbo_selection.resize(width, height);
|
||||
line_thick_ = lineThickness() + 1.;
|
||||
}
|
||||
|
||||
|
||||
void RendererSelection::generateObjectsID(Scene & scene) {
|
||||
ids.clear();
|
||||
QMapIterator<Mesh*, QList<ObjectBase*> > it(scene.geometries_used);
|
||||
while (it.hasNext()) {
|
||||
it.next();
|
||||
foreach (ObjectBase * o, it.value()) {
|
||||
uint id = qHash(o);
|
||||
ids[id] = o;
|
||||
o->id_ = id;
|
||||
}
|
||||
}
|
||||
foreach (ObjectBase * o, scene.lights_used) {
|
||||
uint id = qHash(o);
|
||||
ids[id] = o;
|
||||
o->id_ = id;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void RendererSelection::fillSelectionsBuffer(const QList<ObjectBase *> & ol) {
|
||||
cur_selections_.resize(ol.size());
|
||||
for (int i = 0; i < ol.size(); ++i) {
|
||||
cur_selections_[i] = (ol[i]->isSelected(true) ? 1 : 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void RendererSelection::renderSelection(Scene & scene) {
|
||||
QOpenGLShaderProgram * prog = 0;
|
||||
QGLView * view = r->view;
|
||||
if (r->bindShader(Renderer::srSelectionFill, &prog)) {
|
||||
view->hov_objects.clear();
|
||||
id_hover = 0;
|
||||
if (fbo_selection.queriedPoints() > 0) {
|
||||
if (fbo_selection.queriedPoints() == 1) {
|
||||
id_hover = fbo_selection.getPoint();
|
||||
view->hov_objects.resize(1);
|
||||
view->hov_objects[0] = ids.value(id_hover);
|
||||
//qDebug() << id_hover;
|
||||
} else {
|
||||
QVector<uint> points = fbo_selection.getPoints();
|
||||
QSet<uint> ids_hover;
|
||||
foreach (uint i, points)
|
||||
ids_hover << i;
|
||||
view->hov_objects.clear();
|
||||
foreach (uint i, ids_hover)
|
||||
view->hov_objects << ids.value(i);
|
||||
//qDebug() << ids_hover;
|
||||
}
|
||||
}
|
||||
|
||||
fbo_selection.bind();
|
||||
|
||||
fbo_selection.setWriteBuffers();
|
||||
glEnableDepth();
|
||||
glClearFramebuffer(QColor(0,0,0,0));
|
||||
r->setUniformCamera(prog, view->camera());
|
||||
r->renderObjects(scene, Renderer::rpSelection);
|
||||
view->glClear(GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
RendererService & rs(r->rend_service);
|
||||
rs.fillOmniObjects();
|
||||
rs.omni_mesh->loadObjects(view, rs.cur_objects);
|
||||
fillSelectionsBuffer(light2objectList(scene.lights_used));
|
||||
rs.omni_mesh->loadSelections(view, cur_selections_);
|
||||
rs.omni_mesh->draw(view, rs.cur_objects.size());
|
||||
|
||||
//mouse_rect = fbo_selection.rect();
|
||||
if (r->mouse_rect.isNull())
|
||||
fbo_selection.queryPoint(0, r->mouse_pos);
|
||||
else
|
||||
fbo_selection.queryPoints(0, r->mouse_rect);
|
||||
|
||||
//qDebug() << id_hover;
|
||||
fbo_selection.bindColorTextures();
|
||||
fbo_selection.setWriteBuffers();
|
||||
if (!view->hoverHalo_ && !view->selectionHalo_)
|
||||
glClearFramebuffer(QColor(0,0,0,0), false);
|
||||
else {
|
||||
r->bindShader(Renderer::srSelectionHalo, &prog);
|
||||
r->setUniformHalo(prog, "hover" , view->hoverHaloColor() , view->hoverHaloFillAlpha());
|
||||
r->setUniformHalo(prog, "selection", view->selectionHaloColor(), view->selectionHaloFillAlpha());
|
||||
prog->setUniformValue("has_hover" , view->hoverHalo_ && (id_hover > 0) ? 1.f : 0.f);
|
||||
prog->setUniformValue("has_selection", view->selectionHalo_ ? 1.f : 0.f);
|
||||
prog->setUniformValue("fb_hover" , (int)sbrSrcHover);
|
||||
prog->setUniformValue("fb_selection", (int)sbrSrcSelect);
|
||||
prog->setUniformValue("hover_id", QVector4D(float( id_hover & 0xFF) / 255.f,
|
||||
float((id_hover >> 8 ) & 0xFF) / 255.f,
|
||||
float((id_hover >> 16) & 0xFF) / 255.f,
|
||||
float((id_hover >> 24) & 0xFF) / 255.f));
|
||||
r->renderQuad(prog, r->quad, view->camera());
|
||||
}
|
||||
|
||||
fbo_selection.release();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void RendererSelection::renderSelectionFrame() {
|
||||
QOpenGLShaderProgram * prog = 0;
|
||||
if (r->bindShader(Renderer::srSelectionFrame, &prog)) {
|
||||
QMatrix4x4 mat;
|
||||
double mrx = r->mouse_rect.x(), mrw = r->mouse_rect.width() , vw = r->view->width();
|
||||
double mry = r->mouse_rect.y(), mrh = r->mouse_rect.height(), vh = r->view->height();
|
||||
mat.translate(-1. + (mrw + mrx*2) / vw, 1. - (mrh + mry*2) / vh, 0.);
|
||||
mat.scale(mrw / vw, mrh / vh, 0.);
|
||||
r->initQuad(sel_frame, mat);
|
||||
prog->setUniformValue("size", QVector2D(mrw / vw, mrh / vh));
|
||||
prog->setUniformValue("thickness", line_thick_);
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
r->renderQuad(prog, sel_frame);
|
||||
glDisable(GL_BLEND);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void RendererSelection::drawSelection(Framebuffer & fbo_out, int index_out) {
|
||||
QOpenGLShaderProgram * prog = 0;
|
||||
if (r->bindShader(Renderer::srSelectionApply, &prog)) {
|
||||
fbo_selection.bindColorTextures();
|
||||
fbo_out.bindColorTexture(index_out);
|
||||
prog->setUniformValue("fb_out" , 0);
|
||||
prog->setUniformValue("fb_hover" , (int)sbrHovered );
|
||||
prog->setUniformValue("fb_select", (int)sbrSelected);
|
||||
r->renderQuad(prog, r->quad, r->view->camera());
|
||||
if (!r->mouse_rect.isNull()) {
|
||||
renderSelectionFrame();
|
||||
}
|
||||
}
|
||||
}
|
||||
65
qglengine/renderer_selection.h
Normal file
65
qglengine/renderer_selection.h
Normal file
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
QGLView
|
||||
Copyright (C) 2019 Ivan Pelipenko peri4ko@yandex.ru
|
||||
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef RENDERER_SELECTION_H
|
||||
#define RENDERER_SELECTION_H
|
||||
|
||||
#include "renderer_service.h"
|
||||
#include <QHash>
|
||||
|
||||
|
||||
class RendererSelection {
|
||||
friend class QGLView;
|
||||
friend class Renderer;
|
||||
|
||||
public:
|
||||
RendererSelection(Renderer * r_);
|
||||
virtual ~RendererSelection();
|
||||
|
||||
void init(int width, int height);
|
||||
void resize(int width, int height);
|
||||
|
||||
protected:
|
||||
enum SelectionBufferRole {
|
||||
sbrSrcHover,
|
||||
sbrSrcSelect,
|
||||
sbrHovered,
|
||||
sbrSelected
|
||||
};
|
||||
|
||||
void generateObjectsID(Scene & scene);
|
||||
void fillSelectionsBuffer(const QList<ObjectBase *> & ol);
|
||||
void renderSelection(Scene & scene);
|
||||
void renderSelectionFrame();
|
||||
void drawSelection(Framebuffer & fbo_out, int index_out = 0);
|
||||
QList<ObjectBase*> light2objectList(const QList<Light*> & v) {QList<ObjectBase*> ret; foreach (Light*i, v) ret << (ObjectBase*)i; return ret;}
|
||||
|
||||
private:
|
||||
Renderer * r;
|
||||
|
||||
Framebuffer fbo_selection;
|
||||
Mesh * sel_frame;
|
||||
float line_thick_;
|
||||
|
||||
QVector<uchar> cur_selections_;
|
||||
QHash<uint, ObjectBase * > ids;
|
||||
uint id_hover;
|
||||
|
||||
};
|
||||
|
||||
#endif // RENDERER_selection_H
|
||||
@@ -41,13 +41,23 @@ RendererService::RendererService(Renderer * r_): r(r_) {
|
||||
QMatrix4x4 m; m.rotate(90., _rot[i]);
|
||||
m.transposed().copyDataTo(axis_objects[i].modelmatrix);
|
||||
}
|
||||
box_vp_scale = 1.;
|
||||
box_mesh = Primitive::cube();
|
||||
box_vp_scale = box_full_scale = 1.;
|
||||
box_mesh = Primitive::cube();
|
||||
box_mesh_f = Primitive::cubeFrame();
|
||||
omni_mesh = Primitive::ellipsoid(2, 1);
|
||||
omni_mesh_f = Primitive::ellipsoidFrame(2, 1);
|
||||
omni_mesh ->scalePoints(1.5);
|
||||
omni_mesh_f->scalePoints(1.5);
|
||||
box_mesh ->scalePoints(1.3);
|
||||
omni_mesh ->scalePoints(1.3);
|
||||
}
|
||||
|
||||
|
||||
RendererService::~RendererService() {
|
||||
delete box_mesh;
|
||||
delete box_mesh_f;
|
||||
delete omni_mesh;
|
||||
delete omni_mesh_f;
|
||||
delete axis_camera;
|
||||
delete axis_mesh;
|
||||
}
|
||||
@@ -62,25 +72,26 @@ void RendererService::init(int width, int height) {
|
||||
void RendererService::resize(int width, int height) {
|
||||
axis_viewport = preferredIconSize(10.);
|
||||
line_width = lineThickness();
|
||||
box_vp_scale = 30. * appScale() / qMax(qMin(width, height), 1);
|
||||
box_vp_scale = 25. * appScale() / qMax(qMin(width, height), 1);
|
||||
//qDebug() << axis_viewport;
|
||||
}
|
||||
|
||||
|
||||
void RendererService::fillBoxObjects() {
|
||||
box_objects.clear();
|
||||
void RendererService::fillOmniObjects() {
|
||||
cur_objects.clear();
|
||||
Object o;
|
||||
QList<Light*> ll = r->view->scene()->lights_used;
|
||||
QMatrix4x4 v_mat = r->view->camera()->viewMatrix() * r->view->camera()->offsetMatrix();
|
||||
QMatrix4x4 lmat;
|
||||
double vps = tan(r->view->camera()->FOV() / 2. * deg2rad) * box_vp_scale;
|
||||
box_full_scale = tan(r->view->camera()->FOV() / 2. * deg2rad) * box_vp_scale;
|
||||
foreach (Light * l, ll) {
|
||||
QVector4D lpos = QVector4D(l->worldPos(), 1.);
|
||||
double dist = -(v_mat * lpos).z();
|
||||
QMatrix4x4 lmat;
|
||||
lmat.translate(lpos.toVector3D());
|
||||
lmat.scale(dist * vps);
|
||||
lmat.scale(dist * box_full_scale);
|
||||
lmat.transposed().copyDataTo(o.modelmatrix);
|
||||
box_objects << o;
|
||||
o.object_id = l->id_;
|
||||
cur_objects << o;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -95,32 +106,35 @@ void RendererService::setObjectsColor(QVector<Object> & ol, QColor col) {
|
||||
void RendererService::renderService() {
|
||||
QOpenGLShaderProgram * prog = 0;
|
||||
QOpenGLExtraFunctions * f = r->view;
|
||||
if (r->bindShader(Renderer::srService, &prog)) {
|
||||
f->glEnable(GL_MULTISAMPLE);
|
||||
glEnableDepth();
|
||||
f->glClear(GL_DEPTH_BUFFER_BIT);
|
||||
glEnableDepth();
|
||||
|
||||
f->glEnable(GL_MULTISAMPLE);
|
||||
glEnableDepth();
|
||||
f->glClear(GL_DEPTH_BUFFER_BIT);
|
||||
if (r->bindShader(Renderer::srServiceFrame, &prog)) {
|
||||
prog->setUniformValue("qgl_ProjMatrix", r->view->camera()->projectionMatrix(r->view->aspect));
|
||||
|
||||
/// lights
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
||||
//glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
||||
glDisable(GL_CULL_FACE);
|
||||
r->setUniformCamera(prog, r->view->camera());
|
||||
fillBoxObjects();
|
||||
fillOmniObjects();
|
||||
|
||||
setObjectsColor(box_objects, Qt::white);
|
||||
glLineWidth(line_width*3);
|
||||
box_mesh->loadObjects(f, box_objects);
|
||||
box_mesh->draw(f, box_objects.size());
|
||||
setObjectsColor(cur_objects, Qt::white);
|
||||
prog->setUniformValue("line_width", 2.f);
|
||||
prog->setUniformValue("z_offset", 0.f);
|
||||
omni_mesh_f->loadObjects(f, cur_objects);
|
||||
omni_mesh_f->draw(f, cur_objects.size());
|
||||
|
||||
setObjectsColor(box_objects, Qt::black);
|
||||
glLineWidth(line_width);
|
||||
box_mesh->loadObjects(f, box_objects);
|
||||
box_mesh->draw(f, box_objects.size());
|
||||
setObjectsColor(cur_objects, Qt::black);
|
||||
prog->setUniformValue("line_width", 1.f);
|
||||
prog->setUniformValue("z_offset", -1.E-3f);
|
||||
omni_mesh_f->loadObjects(f, cur_objects);
|
||||
omni_mesh_f->draw(f, cur_objects.size());
|
||||
|
||||
glEnable(GL_CULL_FACE);
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
||||
//glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
||||
|
||||
}
|
||||
if (r->bindShader(Renderer::srServiceFill, &prog)) {
|
||||
|
||||
/// axis
|
||||
f->glViewport(0, 0, axis_viewport.width(), axis_viewport.height());
|
||||
@@ -130,7 +144,6 @@ void RendererService::renderService() {
|
||||
axis_mesh->draw(f, axis_objects.size());
|
||||
f->glViewport(0, 0, r->view->width(), r->view->height());
|
||||
|
||||
|
||||
f->glDisable(GL_MULTISAMPLE);
|
||||
}
|
||||
f->glDisable(GL_MULTISAMPLE);
|
||||
}
|
||||
|
||||
@@ -26,6 +26,8 @@
|
||||
|
||||
class RendererService {
|
||||
friend class QGLView;
|
||||
friend class Renderer;
|
||||
friend class RendererSelection;
|
||||
|
||||
public:
|
||||
RendererService(Renderer * r_);
|
||||
@@ -34,19 +36,20 @@ public:
|
||||
void init(int width, int height);
|
||||
void resize(int width, int height);
|
||||
|
||||
void fillBoxObjects();
|
||||
void fillOmniObjects();
|
||||
void setObjectsColor(QVector<QGLEngineShaders::Object> & ol, QColor col);
|
||||
void renderService();
|
||||
|
||||
private:
|
||||
Renderer * r;
|
||||
|
||||
Mesh * axis_mesh, * box_mesh;
|
||||
QVector<QGLEngineShaders::Object> axis_objects, box_objects;
|
||||
Mesh * axis_mesh, * box_mesh_f, * omni_mesh_f;
|
||||
Mesh * box_mesh, * omni_mesh;
|
||||
QVector<QGLEngineShaders::Object> axis_objects, cur_objects;
|
||||
Camera * axis_camera;
|
||||
QSize axis_viewport;
|
||||
int line_width;
|
||||
double box_vp_scale;
|
||||
double box_vp_scale, box_full_scale;
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -133,6 +133,7 @@ void main(void) {
|
||||
//calcLight(0, normal, v);
|
||||
|
||||
qgl_FragColor.rgb = max(vec3(0), li * diffuse + si * specular + emission);
|
||||
//qgl_FragColor.rgb = vec3(1);
|
||||
qgl_FragColor.a = 1;
|
||||
|
||||
|
||||
|
||||
48
qglengine/shaders/service_frame.glsl
Normal file
48
qglengine/shaders/service_frame.glsl
Normal file
@@ -0,0 +1,48 @@
|
||||
// vert //
|
||||
|
||||
out vec4 object_color_g;
|
||||
out float mat_scale;
|
||||
|
||||
void main(void) {
|
||||
gl_Position = qgl_ftransform();
|
||||
object_color_g = qgl_ObjectColor;
|
||||
mat_scale = pow(qgl_ModelMatrix[0][0] * qgl_ModelMatrix[1][1] * qgl_ModelMatrix[2][2], 0.3333);
|
||||
}
|
||||
|
||||
|
||||
// geom //
|
||||
|
||||
layout (lines) in;
|
||||
layout (triangle_strip, max_vertices = 4) out;
|
||||
|
||||
in float mat_scale[];
|
||||
in vec4 object_color_g[];
|
||||
out vec4 object_color;
|
||||
|
||||
uniform float line_width, z_offset;
|
||||
uniform mat4 qgl_ProjMatrix;
|
||||
|
||||
void main(void) {
|
||||
object_color = object_color_g[0];
|
||||
vec2 dir = normalize(gl_in[0].gl_Position.xy - gl_in[1].gl_Position.xy);
|
||||
vec2 side = cross(vec3(dir, 0), vec3(0, 0, 1)).xy;
|
||||
vec4 vo = vec4(0, 0, z_offset, 0);
|
||||
float dts = 0.05 * line_width * mat_scale[0];
|
||||
dir *= dts;
|
||||
side *= dts;
|
||||
gl_Position = gl_in[0].gl_Position + vec4((dir + side), 0, 0)*qgl_ProjMatrix + vo; EmitVertex();
|
||||
gl_Position = gl_in[0].gl_Position + vec4((dir - side), 0, 0)*qgl_ProjMatrix + vo; EmitVertex();
|
||||
gl_Position = gl_in[1].gl_Position - vec4((dir - side), 0, 0)*qgl_ProjMatrix + vo; EmitVertex();
|
||||
gl_Position = gl_in[1].gl_Position - vec4((dir + side), 0, 0)*qgl_ProjMatrix + vo; EmitVertex();
|
||||
EndPrimitive();
|
||||
}
|
||||
|
||||
|
||||
// frag //
|
||||
|
||||
in vec4 object_color;
|
||||
uniform float scale;
|
||||
|
||||
void main(void) {
|
||||
qgl_FragColor = object_color;
|
||||
}
|
||||
Reference in New Issue
Block a user