mirror of https://github.com/CGAL/cgal
644 lines
22 KiB
C++
644 lines
22 KiB
C++
#ifndef CGAL_VOLUME_PLANE_H
|
|
#define CGAL_VOLUME_PLANE_H
|
|
|
|
#include <CGAL/Three/Scene_item_rendering_helper.h>
|
|
|
|
#include <vector>
|
|
#include <cassert>
|
|
|
|
#include <QDebug>
|
|
#include <CGAL/Qt/qglviewer.h>
|
|
|
|
#include "Volume_plane_interface.h"
|
|
#include "create_sphere.h"
|
|
#include <QOpenGLVertexArrayObject>
|
|
#include <QOpenGLBuffer>
|
|
#include <QOpenGLShaderProgram>
|
|
#include <QMouseEvent>
|
|
#include <CGAL/Three/Three.h>
|
|
#include <CGAL/Three/Viewer_interface.h>
|
|
#include <CGAL/Three/Triangle_container.h>
|
|
#include <CGAL/Three/Edge_container.h>
|
|
#include <CGAL/Qt/constraint.h>
|
|
#include <CGAL/Qt/debug.h>
|
|
|
|
using namespace CGAL::Three;
|
|
typedef Triangle_container Tc;
|
|
typedef Edge_container Ec;
|
|
typedef Viewer_interface Vi;
|
|
|
|
#if !defined(NDEBUG)
|
|
inline
|
|
void printGlError(CGAL::Three::Viewer_interface* viewer, unsigned int line) {
|
|
CGAL::Qt::opengl_check_errors(viewer, line);
|
|
}
|
|
#else
|
|
inline
|
|
void printGlError(CGAL::Three::Viewer_interface*, unsigned int) {
|
|
}
|
|
#endif
|
|
|
|
template<int Dim>
|
|
class Length_constraint : public CGAL::qglviewer::WorldConstraint {
|
|
public:
|
|
Length_constraint(double max_) : max_(max_) { }
|
|
|
|
void constrainTranslation(CGAL::qglviewer::Vec& t, CGAL::qglviewer::Frame* const frame) {
|
|
WorldConstraint::constrainTranslation(t, frame);
|
|
CGAL::qglviewer::Vec pos = frame->position();
|
|
const CGAL::qglviewer::Vec offset = static_cast<CGAL::Three::Viewer_interface*>(CGAL::QGLViewer::QGLViewerPool().first())->offset();
|
|
double start = pos[Dim] - offset[Dim];
|
|
double end = t[Dim];
|
|
start += end;
|
|
if(start > max_ || (start < 0)) {
|
|
t[Dim] = 0.0;
|
|
}
|
|
}
|
|
|
|
private:
|
|
double max_;
|
|
};
|
|
|
|
struct x_tag {};
|
|
struct y_tag {};
|
|
struct z_tag {};
|
|
|
|
template<typename Tag>
|
|
class Volume_plane : public Volume_plane_interface, public Tag {
|
|
private :
|
|
float tx, ty, tz;
|
|
public:
|
|
Volume_plane(float tx, float ty, float tz);
|
|
|
|
void invalidateOpenGLBuffers()
|
|
{
|
|
const CGAL::qglviewer::Vec offset = static_cast<CGAL::Three::Viewer_interface*>(CGAL::QGLViewer::QGLViewerPool().first())->offset();
|
|
mFrame_->setPosition(offset.x, offset.y, offset.z);
|
|
}
|
|
bool eventFilter(QObject *, QEvent *);
|
|
void compute_bbox()const
|
|
{
|
|
compute_bbox(*this);
|
|
}
|
|
|
|
void compute_bbox(x_tag)const
|
|
{
|
|
setBbox(Bbox(tx,ty,tz,
|
|
tx, ty+(adim_ - 1) * yscale_, tz+(bdim_ - 1) * zscale_));
|
|
}
|
|
|
|
void compute_bbox(y_tag)const
|
|
{
|
|
setBbox(Bbox(tx,ty,tz,
|
|
tx+(adim_ - 1) * xscale_, ty, tz+(bdim_ - 1) * zscale_));
|
|
}
|
|
|
|
void compute_bbox(z_tag)const
|
|
{
|
|
setBbox(Bbox(tx,ty,tz,
|
|
tx+(adim_ - 1) * xscale_,ty+ (bdim_ - 1) * yscale_, tz));
|
|
}
|
|
|
|
void setData(unsigned int adim, unsigned int bdim, unsigned int cdim,
|
|
float xscale, float yscale, float zscale, std::vector<float>& colors);
|
|
|
|
virtual ~Volume_plane();
|
|
|
|
Volume_plane* clone() const { return nullptr; }
|
|
|
|
virtual RenderingMode renderingMode() const { return Flat; }
|
|
bool supportsRenderingMode(RenderingMode m) const { return m == Flat; }
|
|
|
|
QString toolTip() const { return "Plane through a volume"; }
|
|
QString name() const { return name(*this); }
|
|
|
|
bool isFinite() const { return true; }
|
|
bool isEmpty() const { return false; }
|
|
bool manipulatable() const { return true; }
|
|
|
|
unsigned int cube() {return currentCube; }
|
|
|
|
void draw(Viewer_interface* viewer)const;
|
|
|
|
unsigned int aDim() const { return adim_; }
|
|
unsigned int bDim() const { return bdim_; }
|
|
unsigned int cDim() const { return cdim_; }
|
|
|
|
CGAL::qglviewer::Vec translationVector() const { return translationVector(*this); }
|
|
|
|
unsigned int getCurrentCube() const { return currentCube; }
|
|
|
|
// uses a public init function to enable construction in
|
|
// threads without gl-context
|
|
void init(Viewer_interface* viewer)
|
|
{
|
|
if(!isInit(viewer))
|
|
initGL(viewer);
|
|
viewer->makeCurrent();
|
|
getTriangleContainer(1)->reset_vbos(ALL);
|
|
drawSpheres(*this);
|
|
getTriangleContainer(1)->allocate(
|
|
Tc::Flat_vertices,
|
|
v_spheres.data(),
|
|
static_cast<int>(v_spheres.size()*sizeof(float)));
|
|
getTriangleContainer(1)->allocate(
|
|
Tc::Flat_normals,
|
|
n_spheres.data(),
|
|
static_cast<int>(n_spheres.size()*sizeof(float)));
|
|
getTriangleContainer(1)->allocate(
|
|
Tc::Facet_centers,
|
|
c_spheres.data(),
|
|
static_cast<int>(c_spheres.size()*sizeof(float)));
|
|
|
|
nb_vertices = v_spheres.size();
|
|
nb_centers = c_spheres.size();
|
|
v_rec.resize(0);
|
|
getEdgeContainer(0)->reset_vbos(ALL);
|
|
drawRectangle(*this, !viewer->isOpenGL_4_3());
|
|
getEdgeContainer(0)->allocate(Ec::Vertices,
|
|
v_rec.data(),
|
|
static_cast<int>(v_rec.size()*sizeof(float)));
|
|
nb_edges = v_rec.size();
|
|
is_grabbing = false;
|
|
|
|
// for each vertex
|
|
getTriangleContainer(0)->reset_vbos(ALL);
|
|
vertices.resize(0);
|
|
indices.resize(0);
|
|
vertices.reserve(bdim_ * adim_ * 3);
|
|
for(unsigned int i = 0; i < adim_; ++i)
|
|
{
|
|
for(unsigned int j = 0; j < bdim_; ++j)
|
|
{
|
|
buildVertex(vertices, i, j);
|
|
}
|
|
}
|
|
|
|
assert(vertices.size() == (3 * adim_ * bdim_));
|
|
|
|
// for each patch
|
|
for(unsigned int j = 0; j < adim_ - 1; ++j) {
|
|
for(unsigned int k = 0; k < bdim_ - 1; ++k) {
|
|
//0
|
|
indices.push_back( j * bdim_ + k );
|
|
assert(indices.back() < (vertices.size() / 3));
|
|
|
|
//1
|
|
indices.push_back( j * bdim_ + (k + 1) );
|
|
assert(indices.back() < (vertices.size() / 3));
|
|
|
|
//3
|
|
indices.push_back( (j+1) * bdim_ + (k+1) );
|
|
assert(indices.back() < (vertices.size() / 3));
|
|
|
|
//0
|
|
indices.push_back( j * bdim_ + k );
|
|
assert(indices.back() < (vertices.size() / 3));
|
|
|
|
//3
|
|
indices.push_back( (j+1) * bdim_ + (k+1) );
|
|
assert(indices.back() < (vertices.size() / 3));
|
|
|
|
//2
|
|
indices.push_back( (j+1) * bdim_ + (k) );
|
|
assert(indices.back() < (vertices.size() / 3));
|
|
|
|
}
|
|
}
|
|
|
|
assert((indices.size() / 6) == (adim_ - 1) * (bdim_ - 1));
|
|
getTriangleContainer(0)->allocate(
|
|
Tc::Vertex_indices,
|
|
indices.data(),
|
|
static_cast<int>(sizeof(unsigned int) * indices.size()));
|
|
getTriangleContainer(0)->allocate(
|
|
Tc::Smooth_vertices,
|
|
vertices.data(),
|
|
static_cast<int>(sizeof(float) * vertices.size()));
|
|
getTriangleContainer(0)->allocate(
|
|
Tc::VColors,
|
|
colors_.data(),
|
|
static_cast<int>(colors_.size()*sizeof(float)));
|
|
nb_idx = indices.size();
|
|
}
|
|
|
|
private:
|
|
bool is_grabbing;
|
|
|
|
CGAL::qglviewer::Vec translationVector(x_tag) const {
|
|
return CGAL::qglviewer::Vec(xscale_, 0.0, 0.0);
|
|
}
|
|
CGAL::qglviewer::Vec translationVector(y_tag) const {
|
|
return CGAL::qglviewer::Vec(0.0, yscale_, 0.0);
|
|
}
|
|
CGAL::qglviewer::Vec translationVector(z_tag) const {
|
|
return CGAL::qglviewer::Vec(0.0, 0.0, zscale_);
|
|
}
|
|
|
|
void buildVertex(std::vector<float>& out, unsigned int i, unsigned int j) {
|
|
buildVertex(out, i, j, *this);
|
|
}
|
|
|
|
void buildVertex(std::vector<float>& out, unsigned int i, unsigned int j, x_tag) {
|
|
out.push_back(0.0f);
|
|
out.push_back(i * yscale_);
|
|
out.push_back(j * zscale_);
|
|
}
|
|
|
|
void buildVertex(std::vector<float>& out, unsigned int i, unsigned int j, y_tag) {
|
|
out.push_back(i * xscale_);
|
|
out.push_back(0.0f);
|
|
out.push_back(j * zscale_);
|
|
}
|
|
|
|
void buildVertex(std::vector<float>& out, unsigned int i, unsigned int j, z_tag) {
|
|
out.push_back(i * xscale_);
|
|
out.push_back(j * yscale_);
|
|
out.push_back(0.0f);
|
|
}
|
|
|
|
unsigned int adim_, bdim_, cdim_;
|
|
double xscale_, yscale_, zscale_;
|
|
mutable int currentCube;
|
|
mutable std::vector<float> v_rec;
|
|
mutable std::vector<float> v_spheres;
|
|
mutable std::vector<float> n_spheres;
|
|
mutable std::vector<float> c_spheres;
|
|
mutable std::size_t nb_vertices;
|
|
mutable std::size_t nb_centers;
|
|
mutable std::size_t nb_edges;
|
|
mutable std::size_t nb_idx;
|
|
mutable double sphere_radius;
|
|
mutable std::vector< float > colors_;
|
|
mutable std::vector< float > vertices;
|
|
mutable std::vector<unsigned int> indices;
|
|
|
|
|
|
QString name(x_tag) const { return tr("X Slice for %1").arg(name_); }
|
|
QString name(y_tag) const { return tr("Y Slice for %2").arg(name_); }
|
|
QString name(z_tag) const { return tr("Z Slice for %2").arg(name_); }
|
|
|
|
//according to the tag, a,b,c dim change but not the scale. We look for the max dimension of the whole image.
|
|
//A high scale factor will often go with a low dimension, to compensate it. So we don't want a max being the
|
|
//higher scale * the higher dim, hence the tag specialization.
|
|
//TODO: set the scale factors according to the dimensipon to avoid doing that.
|
|
double compute_maxDim(x_tag) const
|
|
{
|
|
double max_a((adim_ - 1) * yscale_),
|
|
max_b((bdim_ - 1) * zscale_),
|
|
max_c((cdim_ - 1) * xscale_);
|
|
|
|
return (std::max)((std::max)(max_a, max_b), max_c);
|
|
}
|
|
|
|
double compute_maxDim(y_tag) const
|
|
{
|
|
double max_a((adim_ - 1) * xscale_),
|
|
max_b((bdim_ - 1) * zscale_),
|
|
max_c((cdim_ - 1) * yscale_);
|
|
|
|
return (std::max)((std::max)(max_a, max_b), max_c);
|
|
}
|
|
|
|
double compute_maxDim(z_tag) const
|
|
{
|
|
double max_a((adim_ - 1) * xscale_),
|
|
max_b((bdim_ - 1) * yscale_),
|
|
max_c((cdim_ - 1) * zscale_);
|
|
|
|
return (std::max)((std::max)(max_a, max_b), max_c);
|
|
}
|
|
|
|
void drawRectangle(x_tag, bool is_loop) const {
|
|
|
|
|
|
v_rec.push_back(0.0f); v_rec.push_back(0.0f); v_rec.push_back(0.0f);
|
|
v_rec.push_back(0.0f); v_rec.push_back((adim_ - 1) * yscale_); v_rec.push_back(0.0f);
|
|
if(!is_loop){
|
|
v_rec.push_back(0.0f); v_rec.push_back((adim_ - 1) * yscale_); v_rec.push_back(0.0f);
|
|
}
|
|
v_rec.push_back(0.0f); v_rec.push_back((adim_ - 1) * yscale_); v_rec.push_back((bdim_ - 1) * zscale_);
|
|
if(!is_loop){
|
|
v_rec.push_back(0.0f); v_rec.push_back((adim_ - 1) * yscale_); v_rec.push_back((bdim_ - 1) * zscale_);
|
|
}
|
|
v_rec.push_back(0.0f); v_rec.push_back(0.0f); v_rec.push_back((bdim_ - 1) * zscale_);
|
|
if(!is_loop)
|
|
{
|
|
v_rec.push_back(0.0f); v_rec.push_back(0.0f); v_rec.push_back((bdim_ - 1) * zscale_);
|
|
v_rec.push_back(0.0f); v_rec.push_back(0.0f); v_rec.push_back(0.0f);
|
|
}
|
|
|
|
|
|
}
|
|
|
|
void drawRectangle(y_tag, bool is_loop) const {
|
|
v_rec.push_back(0.0f); v_rec.push_back(0.0f); v_rec.push_back(0.0f);
|
|
v_rec.push_back((adim_ - 1) * xscale_);v_rec.push_back(0.0f); v_rec.push_back(0.0f);
|
|
if(!is_loop){
|
|
v_rec.push_back((adim_ - 1) * xscale_);v_rec.push_back(0.0f); v_rec.push_back(0.0f);
|
|
}
|
|
v_rec.push_back((adim_ - 1) * xscale_);v_rec.push_back(0.0f);v_rec.push_back( (bdim_ - 1) * zscale_);
|
|
if(!is_loop){
|
|
v_rec.push_back((adim_ - 1) * xscale_);v_rec.push_back(0.0f);v_rec.push_back( (bdim_ - 1) * zscale_);
|
|
}
|
|
v_rec.push_back(0.0f); v_rec.push_back(0.0f); v_rec.push_back((bdim_ - 1) * zscale_);
|
|
if(!is_loop){
|
|
v_rec.push_back(0.0f); v_rec.push_back(0.0f); v_rec.push_back((bdim_ - 1) * zscale_);
|
|
v_rec.push_back(0.0f); v_rec.push_back(0.0f); v_rec.push_back(0.0f);
|
|
}
|
|
}
|
|
|
|
void drawRectangle(z_tag, bool is_loop) const {
|
|
v_rec.push_back(0.0f); v_rec.push_back(0.0f); v_rec.push_back(0.0f);
|
|
v_rec.push_back((adim_ - 1) * xscale_); v_rec.push_back(0.0f); v_rec.push_back(0.0f);
|
|
if(!is_loop){
|
|
v_rec.push_back((adim_ - 1) * xscale_); v_rec.push_back(0.0f); v_rec.push_back(0.0f);
|
|
}
|
|
v_rec.push_back((adim_ - 1) * xscale_); v_rec.push_back((bdim_ - 1) * yscale_); v_rec.push_back(0.0f);
|
|
if(!is_loop){
|
|
v_rec.push_back((adim_ - 1) * xscale_); v_rec.push_back((bdim_ - 1) * yscale_); v_rec.push_back(0.0f);
|
|
}
|
|
v_rec.push_back(0.0f); v_rec.push_back((bdim_ - 1) * yscale_); v_rec.push_back(0.0f);
|
|
if(!is_loop){
|
|
v_rec.push_back(0.0f); v_rec.push_back((bdim_ - 1) * yscale_); v_rec.push_back(0.0f);
|
|
v_rec.push_back(0.0f); v_rec.push_back(0.0f); v_rec.push_back(0.0f);
|
|
}
|
|
}
|
|
|
|
void drawSpheres(x_tag) const
|
|
{
|
|
double max_dim = compute_maxDim(x_tag());
|
|
sphere_radius = max_dim / 40.0f;
|
|
create_flat_sphere(1.0f, v_spheres, n_spheres, 18);
|
|
|
|
c_spheres.push_back(0.0f); c_spheres.push_back((adim_ - 1) * yscale_/2.0f + 1.1*sphere_radius); c_spheres.push_back(0.0f);
|
|
|
|
c_spheres.push_back(0.0f); c_spheres.push_back((adim_ - 1) * yscale_ ); c_spheres.push_back((bdim_ - 1) * zscale_/2.0f + 1.1*sphere_radius);
|
|
|
|
c_spheres.push_back(0.0f); c_spheres.push_back((adim_ - 1) * yscale_/2.0f + 1.1*sphere_radius); c_spheres.push_back((bdim_ - 1 ) * zscale_);
|
|
|
|
c_spheres.push_back(0.0f); c_spheres.push_back(0.0f); c_spheres.push_back((bdim_ - 1) * zscale_/2.0f + 1.1*sphere_radius);
|
|
|
|
}
|
|
|
|
void drawSpheres(y_tag) const
|
|
{
|
|
double max_dim = compute_maxDim(y_tag());
|
|
sphere_radius = max_dim / 40.0f;
|
|
create_flat_sphere(1.0f, v_spheres, n_spheres,18);
|
|
|
|
c_spheres.push_back((adim_ - 1) * xscale_/2.0f); c_spheres.push_back(0.0f); c_spheres.push_back(0.0f);
|
|
c_spheres.push_back((adim_ - 1) * xscale_); c_spheres.push_back(0.0f); c_spheres.push_back((bdim_ - 1) * zscale_/2.0f);
|
|
c_spheres.push_back((adim_ - 1) * xscale_/2.0f); c_spheres.push_back(0.0f); c_spheres.push_back((bdim_ - 1) * zscale_);
|
|
c_spheres.push_back(0.0f); c_spheres.push_back(0.0f); c_spheres.push_back((bdim_ - 1) * zscale_/2.0f);
|
|
}
|
|
|
|
void drawSpheres(z_tag) const
|
|
{
|
|
double max_dim = compute_maxDim(z_tag());
|
|
sphere_radius = max_dim / 40.0f;
|
|
create_flat_sphere(1.0f, v_spheres, n_spheres,18);
|
|
|
|
c_spheres.push_back(0.0f); c_spheres.push_back((bdim_ - 1) * yscale_/2.0f - 1.1*sphere_radius); c_spheres.push_back(0.0f);
|
|
c_spheres.push_back((adim_ - 1) * xscale_/2.0f-1.1*sphere_radius); c_spheres.push_back((bdim_ - 1) * yscale_); c_spheres.push_back(0.0f);
|
|
c_spheres.push_back((adim_ - 1) * xscale_); c_spheres.push_back((bdim_ - 1) * yscale_/2.0f-1.1*sphere_radius); c_spheres.push_back(0.0f);
|
|
c_spheres.push_back((adim_ - 1) * xscale_/2.0f-1.1*sphere_radius); c_spheres.push_back(0.0f); c_spheres.push_back(0.0f);
|
|
}
|
|
|
|
CGAL::qglviewer::Constraint* setConstraint(x_tag) {
|
|
CGAL::qglviewer::AxisPlaneConstraint* c = new Length_constraint<0>(cdim_ * xscale_);
|
|
c->setRotationConstraintType(CGAL::qglviewer::AxisPlaneConstraint::FORBIDDEN);
|
|
c->setTranslationConstraint(CGAL::qglviewer::AxisPlaneConstraint::AXIS, CGAL::qglviewer::Vec(1.0f, 0.0f, 0.0f));
|
|
return c;
|
|
}
|
|
|
|
CGAL::qglviewer::Constraint* setConstraint(y_tag) {
|
|
CGAL::qglviewer::AxisPlaneConstraint* c = new Length_constraint<1>(cdim_ * yscale_);
|
|
c->setRotationConstraintType(CGAL::qglviewer::AxisPlaneConstraint::FORBIDDEN);
|
|
c->setTranslationConstraint(CGAL::qglviewer::AxisPlaneConstraint::AXIS, CGAL::qglviewer::Vec(0.0f, 1.0f, 0.0f));
|
|
return c;
|
|
}
|
|
|
|
CGAL::qglviewer::Constraint* setConstraint(z_tag) {
|
|
CGAL::qglviewer::AxisPlaneConstraint* c = new Length_constraint<2>(cdim_ * zscale_);
|
|
c->setRotationConstraintType(CGAL::qglviewer::AxisPlaneConstraint::FORBIDDEN);
|
|
c->setTranslationConstraint(CGAL::qglviewer::AxisPlaneConstraint::AXIS, CGAL::qglviewer::Vec(0.0f, 0.0f, 1.0f));
|
|
return c;
|
|
}
|
|
|
|
void updateCurrentCube() const {
|
|
currentCube = getTranslation();
|
|
|
|
}
|
|
|
|
GLdouble getTranslation() const { return getTranslation(*this); }
|
|
GLdouble getTranslation(x_tag) const {
|
|
const CGAL::qglviewer::Vec offset = static_cast<CGAL::Three::Viewer_interface*>(CGAL::QGLViewer::QGLViewerPool().first())->offset();
|
|
return (mFrame_->matrix()[12] - offset.x)/ xscale_;
|
|
}
|
|
GLdouble getTranslation(y_tag) const {
|
|
const CGAL::qglviewer::Vec offset = static_cast<CGAL::Three::Viewer_interface*>(CGAL::QGLViewer::QGLViewerPool().first())->offset();
|
|
return (mFrame_->matrix()[13] - offset.y)/ yscale_;
|
|
}
|
|
GLdouble getTranslation(z_tag) const {
|
|
const CGAL::qglviewer::Vec offset = static_cast<CGAL::Three::Viewer_interface*>(CGAL::QGLViewer::QGLViewerPool().first())->offset();
|
|
return (mFrame_->matrix()[14] - offset.z)/ zscale_ ;
|
|
}
|
|
|
|
void initializeBuffers(CGAL::Three::Viewer_interface* viewer) const
|
|
{
|
|
getTriangleContainer(0)->getVbo(Tc::VColors)->offset
|
|
= (currentCube*int(sizeof(float))) * (bdim_) * (adim_) * 3;
|
|
getTriangleContainer(1)->initializeBuffers(viewer);
|
|
getTriangleContainer(1)->setFlatDataSize(nb_vertices);
|
|
getTriangleContainer(1)->setCenterSize(nb_centers);
|
|
getTriangleContainer(0)->initializeBuffers(viewer);
|
|
getTriangleContainer(0)->setIdxSize(nb_idx);
|
|
getEdgeContainer(0)->initializeBuffers(viewer);
|
|
getEdgeContainer(0)->setFlatDataSize(nb_edges);
|
|
v_spheres.clear();
|
|
v_spheres.shrink_to_fit();
|
|
n_spheres.clear();
|
|
n_spheres.shrink_to_fit();
|
|
//not the centers, they are used for picking
|
|
v_rec.clear();
|
|
v_rec.shrink_to_fit();
|
|
vertices.clear();
|
|
vertices.shrink_to_fit();
|
|
indices.clear();
|
|
indices.shrink_to_fit();
|
|
}
|
|
};
|
|
|
|
template<typename T>
|
|
Volume_plane<T>::Volume_plane(float tx, float ty, float tz)
|
|
: Volume_plane_interface(new CGAL::qglviewer::ManipulatedFrame),
|
|
tx(tx), ty(ty), tz(tz)
|
|
{
|
|
const CGAL::qglviewer::Vec offset = static_cast<CGAL::Three::Viewer_interface*>(CGAL::QGLViewer::QGLViewerPool().first())->offset();
|
|
mFrame_->setPosition(offset.x, offset.y, offset.z);
|
|
sphere_Slider = new QSlider(Qt::Horizontal);
|
|
sphere_Slider->setValue(40);
|
|
sphere_Slider->setMinimum(1);
|
|
sphere_Slider->setMaximum(100);
|
|
setTriangleContainer(1, new Tc(Vi::PROGRAM_SPHERES, false));
|
|
setTriangleContainer(0, new Tc(Vi::PROGRAM_NO_SELECTION, true));
|
|
setEdgeContainer(0, new Ec(Three::mainViewer()->isOpenGL_4_3()
|
|
? PROGRAM_SOLID_WIREFRAME
|
|
: PROGRAM_NO_SELECTION, false));
|
|
|
|
}
|
|
template<typename T>
|
|
void Volume_plane<T>::setData(unsigned int adim, unsigned int bdim, unsigned int cdim, float xscale, float yscale, float zscale, std::vector<float> &colors)
|
|
{
|
|
adim_ = adim;
|
|
bdim_ = bdim;
|
|
cdim_= cdim;
|
|
xscale_ = xscale;
|
|
yscale_ =yscale;
|
|
zscale_ = zscale;
|
|
currentCube = 0;
|
|
colors_.swap(colors);
|
|
mFrame_->setConstraint(setConstraint(*this));
|
|
v_spheres.resize(0);
|
|
n_spheres.resize(0);
|
|
c_spheres.resize(0);
|
|
}
|
|
template<typename T>
|
|
Volume_plane<T>::~Volume_plane() {
|
|
delete sphere_Slider;
|
|
}
|
|
|
|
template<typename T>
|
|
void Volume_plane<T>::draw(Viewer_interface *viewer) const {
|
|
double cur_cube = currentCube;
|
|
updateCurrentCube();
|
|
if(cur_cube != currentCube)
|
|
{
|
|
for(CGAL::QGLViewer*v : CGAL::QGLViewer::QGLViewerPool()){
|
|
v->setProperty("need_update", true);
|
|
}
|
|
}
|
|
if(viewer->property("need_update").toBool())
|
|
{
|
|
setBuffersInit(viewer, false);
|
|
viewer->setProperty("need_update", false);
|
|
}
|
|
if(!isInit(viewer))
|
|
initGL(viewer);
|
|
{
|
|
setBuffersInit(viewer, false);
|
|
}
|
|
if ( ! getBuffersInit(viewer))
|
|
{
|
|
initializeBuffers(viewer);
|
|
setBuffersInit(viewer, true);
|
|
}
|
|
|
|
|
|
viewer->glDepthRangef(0.00001f,0.99999f);
|
|
GLdouble mat[16];
|
|
viewer->camera()->getModelViewProjectionMatrix(mat);
|
|
QMatrix4x4 f;
|
|
for(int i=0; i<16; i++)
|
|
{
|
|
f.data()[i] = (float)mFrame_->matrix()[i];
|
|
}
|
|
|
|
f.translate(QVector3D(tx, ty, tz));
|
|
getEdgeContainer(0)->setFrameMatrix(f);
|
|
printGlError(viewer, __LINE__);
|
|
QVector2D vp(viewer->width(), viewer->height());
|
|
getEdgeContainer(0)->setViewport(vp);
|
|
getEdgeContainer(0)->setWidth(4.0f);
|
|
getEdgeContainer(0)->setColor(QColor(Qt::black));
|
|
viewer->glDepthRangef(0.00005f, 0.99995f);
|
|
getEdgeContainer(0)->draw(viewer, true);
|
|
viewer->glDepthRangef(0.0,1.0);
|
|
|
|
|
|
getTriangleContainer(0)->setFrameMatrix(f);
|
|
getTriangleContainer(0)->draw(viewer, false);
|
|
printGlError(viewer, __LINE__);
|
|
|
|
//hide spheres if only 1 plane.
|
|
if(aDim() <= 1 ||
|
|
bDim() <= 1 ||
|
|
cDim() <=1)
|
|
return;
|
|
double max_dim = compute_maxDim(*this);
|
|
sphere_radius = max_dim/20.0f * sphere_Slider->value()/100.0f;
|
|
getTriangleContainer(1)->getVbo(Tc::Radius)->bind();
|
|
getTriangleContainer(1)->getVao(viewer)->program->setAttributeValue("radius", sphere_radius);
|
|
getTriangleContainer(1)->getVbo(Tc::Radius)->release();
|
|
getTriangleContainer(1)->setColor(this->color());
|
|
getTriangleContainer(1)->setFrameMatrix(f);
|
|
getTriangleContainer(1)->draw(viewer, true);
|
|
}
|
|
|
|
|
|
|
|
//intercept events for picking
|
|
template<typename T>
|
|
bool Volume_plane<T>::eventFilter(QObject *sender, QEvent *event)
|
|
{
|
|
CGAL::Three::Viewer_interface* viewer = qobject_cast<CGAL::Three::Viewer_interface*>(sender);
|
|
if(!viewer)
|
|
return false;
|
|
if(event->type() == QEvent::MouseButtonPress)
|
|
{
|
|
QMouseEvent* e = static_cast<QMouseEvent*>(event);
|
|
if(e->modifiers() == Qt::NoModifier)
|
|
{
|
|
//pick
|
|
bool found = false;
|
|
viewer->makeCurrent();
|
|
CGAL::qglviewer::Vec pos = viewer->camera()->pointUnderPixel(e->pos(), found);
|
|
if(!found)
|
|
return false;
|
|
found = false;
|
|
//check the found point is on a sphere
|
|
pos = manipulatedFrame()->inverse().inverseCoordinatesOf(pos);
|
|
float sq_radius = sphere_radius * sphere_radius;
|
|
CGAL::qglviewer::Vec center;
|
|
//is the picked point on the sphere ?
|
|
for (int i=0; i<4; ++i)
|
|
{
|
|
center = CGAL::qglviewer::Vec(c_spheres[i*3]+tx, c_spheres[i*3+1]+ty, c_spheres[i*3+2]+tz);
|
|
if(
|
|
(center.x - pos.x) * (center.x - pos.x) +
|
|
(center.y - pos.y) * (center.y - pos.y) +
|
|
(center.z - pos.z) * (center.z - pos.z)
|
|
<= sq_radius)
|
|
{
|
|
found = true;
|
|
break;
|
|
}
|
|
}
|
|
if(!found)
|
|
return false;
|
|
is_grabbing = true;
|
|
emitSelection();
|
|
viewer->setManipulatedFrame(manipulatedFrame());
|
|
viewer->setMouseBinding(
|
|
Qt::NoModifier,
|
|
Qt::LeftButton,
|
|
CGAL::qglviewer::FRAME,
|
|
CGAL::qglviewer::TRANSLATE);
|
|
}
|
|
}
|
|
else if(event->type() == QEvent::MouseButtonRelease && is_grabbing)
|
|
{
|
|
is_grabbing = false;
|
|
viewer->setMouseBinding(
|
|
Qt::NoModifier,
|
|
Qt::LeftButton,
|
|
CGAL::qglviewer::CAMERA,
|
|
CGAL::qglviewer::ROTATE);
|
|
redraw();
|
|
}
|
|
return false;
|
|
}
|
|
|
|
#endif /* CGAL_VOLUME_PLANE_H */
|