cgal/Lab/demo/Lab/Plugins/Mesh_3/Volume_plane.h

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 */