251 lines
7.0 KiB
C++
251 lines
7.0 KiB
C++
/*
|
|
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_service.h"
|
|
#include "renderer.h"
|
|
#include "qglview.h"
|
|
#include "glmesh.h"
|
|
#include <qad_types.h>
|
|
|
|
using namespace QGLEngineShaders;
|
|
|
|
|
|
RendererService::RendererService(Renderer * r_): r(r_) {
|
|
line_width = 1;
|
|
current_handle = htNoHandle;
|
|
mat_xyz.resize(3);
|
|
color_xyz.resize(3);
|
|
const QVector3D _rot[3] = {QVector3D(0,1,0), QVector3D(-1,0,0), QVector3D(0,0,1)};
|
|
for (int i = 0; i < 3; ++i) {
|
|
QMatrix4x4 m;
|
|
m.rotate(90., _rot[i]);
|
|
mat_xyz[i] = m;
|
|
color_xyz[i] = QVector4D(0,0,0,0.667);
|
|
color_xyz[i][i] = 1.;
|
|
}
|
|
axis_camera = new Camera();
|
|
axis_camera->setAim(QVector3D());
|
|
axis_camera->setFOV(45.);
|
|
axis_mesh = Primitive::arrow(12);
|
|
size_vp_scale = size_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);
|
|
handle_move_mesh = Primitive::arrow(12, 0.06);
|
|
handle_rotate_mesh = Primitive::arrow(12, 0.03);
|
|
Mesh * m = Primitive::torus(30, 12, 0.5, 0.06);
|
|
m->translatePoints(QVector3D(0., 0., 0.75));
|
|
handle_rotate_mesh->append(m);
|
|
delete m;
|
|
handle_scale_mesh = Primitive::cylinder(12, 0.06, 0.06, 0.85);
|
|
m = Primitive::ellipsoid(12, 12, 0.3, 0.3, 0.3);
|
|
m->translatePoints(QVector3D(0., 0., 0.85));
|
|
handle_scale_mesh->append(m);
|
|
delete m;
|
|
handle_move_mesh ->scalePoints(7.5);
|
|
handle_rotate_mesh->scalePoints(7.5);
|
|
handle_scale_mesh ->scalePoints(7.5);
|
|
}
|
|
|
|
|
|
RendererService::~RendererService() {
|
|
delete box_mesh;
|
|
delete box_mesh_f;
|
|
delete omni_mesh;
|
|
delete omni_mesh_f;
|
|
delete axis_camera;
|
|
delete axis_mesh;
|
|
delete handle_move_mesh;
|
|
delete handle_rotate_mesh;
|
|
delete handle_scale_mesh;
|
|
}
|
|
|
|
|
|
void RendererService::init(int width, int height) {
|
|
fillXYZObjects();
|
|
axis_mesh->loadObjects(r->view, cur_objects);
|
|
resize(width, height);
|
|
}
|
|
|
|
|
|
void RendererService::resize(int width, int height) {
|
|
axis_viewport = preferredIconSize(10.);
|
|
line_width = lineThickness();
|
|
size_vp_scale = 25. * appScale() / qMax(qMin(width, height), 1);
|
|
//qDebug() << axis_viewport;
|
|
}
|
|
|
|
|
|
QMatrix4x4 RendererService::invariantSizeMatrix(QVector3D p) {
|
|
QVector4D pos = QVector4D(p, 1.);
|
|
double dist = -(v_mat * pos).z();
|
|
QMatrix4x4 m;
|
|
m.translate(pos.toVector3D());
|
|
m.scale(dist * size_full_scale);
|
|
return m;
|
|
}
|
|
|
|
|
|
void RendererService::fillXYZObjects() {
|
|
cur_objects.resize(3);
|
|
for (int i = 0; i < 3; ++i) {
|
|
cur_objects[i].color = color_xyz[i];
|
|
mat_xyz[i].transposed().copyDataTo(cur_objects[i].modelmatrix);
|
|
}
|
|
}
|
|
|
|
|
|
void RendererService::fillOmniObjects() {
|
|
QList<Light*> ll = r->view->scene()->lights_used;
|
|
Object o;
|
|
cur_objects.clear();
|
|
foreach (Light * l, ll) {
|
|
QMatrix4x4 m = invariantSizeMatrix(l->worldPos());
|
|
m.transposed().copyDataTo(o.modelmatrix);
|
|
o.object_id = l->id_;
|
|
cur_objects << o;
|
|
}
|
|
}
|
|
|
|
|
|
void RendererService::fillHandleObjects(QVector3D center, HandleType first, QMatrix4x4 add_mat) {
|
|
cur_objects.resize(3);
|
|
for (int i = 0; i < 3; ++i) {
|
|
cur_objects[i].color = color_xyz[i];
|
|
QMatrix4x4 m = invariantSizeMatrix(center);
|
|
m = m * add_mat * mat_xyz[i];
|
|
cur_objects[i].object_id = first + i;
|
|
m.transposed().copyDataTo(cur_objects[i].modelmatrix);
|
|
}
|
|
}
|
|
|
|
|
|
bool RendererService::fillCurrentHandleObjects() {
|
|
QList<ObjectBase*> sol = r->view->scene()->selectedObjects(true);
|
|
if (sol.isEmpty()) return false;
|
|
selection_center = QVector3D();
|
|
Box3D bb;
|
|
foreach (ObjectBase * o, sol) {
|
|
o->calculateBoundingBox();
|
|
bb |= o->boundingBox();
|
|
}
|
|
if (bb.isEmpty())
|
|
selection_center = sol[0]->worldPos();
|
|
else
|
|
selection_center = bb.center();
|
|
axis_mat = QMatrix4x4();
|
|
if ((sol.size() == 1) && (current_handle >= htRotateX)) {
|
|
axis_mat.rotate(sol[0]->angles_.z(), 0., 0., 1.);
|
|
axis_mat.rotate(sol[0]->angles_.y(), 0., 1., 0.);
|
|
axis_mat.rotate(sol[0]->angles_.x(), 1., 0., 0.);
|
|
}
|
|
fillHandleObjects(selection_center, current_handle, axis_mat);
|
|
return true;
|
|
}
|
|
|
|
|
|
void RendererService::setObjectsColor(QVector<Object> & ol, QColor col) {
|
|
QVector4D cv = QColor2QVector(col);
|
|
for (int i = 0; i < ol.size(); ++i)
|
|
ol[i].color = cv;
|
|
}
|
|
|
|
|
|
void RendererService::renderService() {
|
|
QOpenGLShaderProgram * prog = 0;
|
|
QOpenGLExtraFunctions * f = r->view;
|
|
size_full_scale = tan(r->view->camera()->FOV() / 2. * deg2rad) * size_vp_scale;
|
|
v_mat = r->view->camera()->fullViewMatrix();
|
|
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_FILL);
|
|
glDisable(GL_CULL_FACE);
|
|
r->setUniformCamera(prog, r->view->camera());
|
|
fillOmniObjects();
|
|
|
|
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(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);
|
|
|
|
}
|
|
if (r->bindShader(Renderer::srServiceFill, &prog)) {
|
|
r->setUniformCamera(prog, r->view->camera());
|
|
|
|
/// handles
|
|
if (fillCurrentHandleObjects()) {
|
|
f->glEnable(GL_BLEND);
|
|
f->glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
|
Mesh * hm = currentHandleMesh();
|
|
if (hm) {
|
|
hm->loadObjects(r->view, cur_objects);
|
|
hm->draw(f, 3);
|
|
}
|
|
f->glDisable(GL_BLEND);
|
|
}
|
|
|
|
/// axis
|
|
f->glViewport(0, 0, axis_viewport.width(), axis_viewport.height());
|
|
axis_camera->setPos(-r->view->camera()->direction() * 3.);
|
|
r->setUniformCamera(prog, axis_camera, true, axis_viewport);
|
|
axis_mesh->draw(f, 3);
|
|
f->glViewport(0, 0, r->view->width(), r->view->height());
|
|
|
|
}
|
|
f->glDisable(GL_MULTISAMPLE);
|
|
}
|
|
|
|
|
|
Mesh * RendererService::currentHandleMesh() {
|
|
switch (current_handle) {
|
|
case htMoveX :
|
|
case htMoveY :
|
|
case htMoveZ : return handle_move_mesh;
|
|
case htRotateX:
|
|
case htRotateY:
|
|
case htRotateZ: return handle_rotate_mesh;
|
|
case htScaleX :
|
|
case htScaleY :
|
|
case htScaleZ : return handle_scale_mesh;
|
|
default: break;
|
|
}
|
|
return 0;
|
|
}
|