Skip to content
Snippets Groups Projects
Commit 3ed9a4b8 authored by Zain Selman's avatar Zain Selman :speech_balloon:
Browse files

can somewhat scale it properly now. todo: make view dependency and improve scale behavior

parent 4b680f85
No related branches found
No related tags found
1 merge request!2Plane interaction
......@@ -29,22 +29,22 @@ void PlanePlugin::initializePlugin() {
emit registerKey(Qt::Key_Escape, Qt::NoModifier, "Cancel Plane", true);
}
//------------------------------------------------------------------------------
/** \brief Second initialization phase
*
*/
void PlanePlugin::pluginsInitialized()
{
void PlanePlugin::pluginsInitialized() {
setDescriptions();
emit addPickMode(PLANE);
emit addPickMode(PLANE_RESIZE);
createPlane_ = new QtPlaneSelect( PluginFunctions::viewerProperties().glState() );
connect( createPlane_, SIGNAL( signalTriggerCut( ) ), this, SLOT( slotCreatePlaneTriggered() ) );
createPlane_ =
new QtPlaneSelect(PluginFunctions::viewerProperties().glState());
connect(createPlane_, SIGNAL(signalTriggerCut()), this,
SLOT(slotCreatePlaneTriggered()));
connect(createPlane_, SIGNAL(updateViewProxy()), this, SIGNAL(updateView()));
// Add a Toolbar
......@@ -53,14 +53,16 @@ void PlanePlugin::pluginsInitialized()
planeNodeAction_ = new QAction(tr("&Create Plane"), this);
planeNodeAction_->setCheckable(true);
planeNodeAction_->setStatusTip(tr("Create a Plane Node"));
planeNodeAction_->setIcon(QIcon(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+"plane_plane.png") );
connect(planeNodeAction_, SIGNAL(triggered()), this, SLOT(slotCreatePlaneNode()) );
planeNodeAction_->setIcon(QIcon(OpenFlipper::Options::iconDirStr() +
OpenFlipper::Options::dirSeparator() +
"plane_plane.png"));
connect(planeNodeAction_, SIGNAL(triggered()), this,
SLOT(slotCreatePlaneNode()));
toolbar->addAction(planeNodeAction_);
emit addToolbar(toolbar);
}
/*******************************************************************************
PickingInterface implementation
*******************************************************************************/
......@@ -82,12 +84,10 @@ KeyInterface implementation
* @param _event the event that occured
*/
void PlanePlugin::slotKeyReleaseEvent(QKeyEvent* _event) {
if (PluginFunctions::pickMode() == PLANE)
createPlane_->slotKeyReleaseEvent(_event);
}
/*******************************************************************************
MouseInterface implementation
*******************************************************************************/
......@@ -97,127 +97,214 @@ void PlanePlugin::slotKeyReleaseEvent( QKeyEvent* _event){
* @param _event the event that occured
*/
void PlanePlugin::slotMouseEvent(QMouseEvent* _event) {
if (PluginFunctions::pickMode() == PLANE)
createPlane_->slotMouseEvent(_event);
if (PluginFunctions::pickMode() == PLANE_RESIZE) {
switch( _event->type() )
{
case QEvent::MouseButtonPress:
{
switch (_event->type()) {
case QEvent::MouseButtonPress: {
ACG::Vec3d sourcePoint3D;
size_t node_idx, target_idx;
if (PluginFunctions::scenegraphPick(ACG::SceneGraph::PICK_ANYTHING,
_event->pos(),
node_idx,
target_idx,
&sourcePoint3D))
{
_event->pos(), node_idx, target_idx,
&sourcePoint3D)) {
BaseObjectData* obj = nullptr;
if (PluginFunctions::getPickedObject(node_idx, obj)) {
// is picked object Plane?
PlaneObject* curPlane = PluginFunctions::planeObject(obj);
if (curPlane) {
curPlane_ = PluginFunctions::planeObject(obj);
lastObjId_ = obj->id();
if (curPlane_) {
QPoint position = _event->pos();
/// view coords in screenspace, with flipped y-axis
ACG::Vec3d viewCoords =
ACG::Vec3d(position.x(),
PluginFunctions::viewerProperties()
.glState()
.context_height() -
position.y(),
0.5);
QPoint position = _event->pos();
viewStartCoord_ = viewCoords;
ACG::Vec3d viewCoords = ACG::Vec3d(position.x(), PluginFunctions::viewerProperties().glState().context_height() - position.y(), 0.5);
ACG::Vec3d hitPoint = PluginFunctions::viewerProperties().glState().unproject(viewCoords);
/// coordinates of the point clicked in worldspace
/// however not so nice, because less precise than raycasting and
/// has issues with spheres that are actually hit
ACG::Vec3d hitPoint =
PluginFunctions::viewerProperties().glState().unproject(
viewCoords);
// Example for getting the viewing Ray
ACG::Vec3d origin;
ACG::Vec3d direction;
PluginFunctions::viewerProperties().glState().viewing_ray(position.x(), PluginFunctions::viewerProperties().glState().context_height() - position.y(), origin, direction);
// Hit the plane
if (target_idx == 0) {
return;
PluginFunctions::viewerProperties().glState().viewing_ray(
position.x(),
PluginFunctions::viewerProperties()
.glState()
.context_height() -
position.y(),
origin, viewDirection_);
/// obtain the 4 corners of the plane
std::vector<ACG::Vec3d> corners;
{
corners.reserve(4);
const auto center = curPlane_->plane().position;
const auto xdir = curPlane_->plane().xDirection / 2.;
const auto ydir = curPlane_->plane().yDirection / 2.;
corners.emplace_back(ACG::Vec3f{center + xdir + ydir});
corners.emplace_back(ACG::Vec3f{center + xdir - ydir});
corners.emplace_back(ACG::Vec3f{center - xdir - ydir});
corners.emplace_back(ACG::Vec3f{center - xdir + ydir});
}
// We hit a corner so start dragging
dragging_ = true;
pickedCorner_ = target_idx;
// Hit the plane 0 corner
if (target_idx == 1) {
ACG::GLMatrixf mWVP = PluginFunctions::viewerProperties().glState().modelview();
std::cerr << "Hit corner 1" << std::endl;
std::cerr << "Coordinates due to plane:" << std::endl;
std::cerr << curPlane->plane().position << std::endl;
std::cerr << "With Modelview Applied:" << std::endl;
std::cerr << mWVP.transform_point(curPlane->plane().position) << std::endl;
std::cerr << "Coordinates due to picking:" << std::endl;
std::cerr << hitPoint << std::endl;
std::cerr << "Or" << std::endl;
ACG::Vec3d test = curPlane->plane().position - 0.5 * curPlane->plane().xDirection - 0.5 * curPlane->plane().yDirection;
std::cerr << test << std::endl;
std::cerr << mWVP.transform_point(test) << std::endl;
// curPlane->plane().setSize(1.0,0.5);
/// compute intersection
{
const auto ray_length = 1e6;
const auto ray_end = origin + (viewDirection_ * ray_length);
const auto intersect =
ACG::Geometry::edgeConvexPolygonIntersection(
corners, origin, ray_end, result_);
if (!intersect) return;
}
// Hit the plane x corner
if (target_idx == 2) {
std::cerr << "intersection found at: " << result_ << std::endl;
}
std::cerr << "target_idx: " << target_idx << std::endl;
// Hit the plane xy corner
if (target_idx == 3) {
ACG::Vec3d test = curPlane_->plane().position -
0.5 * curPlane_->plane().xDirection -
0.5 * curPlane_->plane().yDirection;
std::cerr << "plane 0 corner worldspace: "<< test << std::endl;
}
// Hit the plane y
if (target_idx == 4) {
if (target_idx == 0) return;
}
// We hit a corner so start dragging
dragging_ = true;
pickedCorner_ = target_idx;
lastFrameCoord_ = viewCoords;
std::cerr << "Picked a plane! and id" << target_idx << std::endl;
std::cerr << "Picked a plane and id: " << target_idx << std::endl;
}
}
}
std::cerr << "Mouse_Down" << std::endl;
break;
}
case QEvent::MouseMove:
{
case QEvent::MouseMove: {
std::cerr << "Mouse_Move" << std::endl;
// We are actually dragging a corner
if ( dragging_) {
if (dragging_ && curPlane_) {
std::cerr << "Dragging!" << std::endl;
QPoint position = _event->pos();
/// view coords in screenspace, with flipped y-axis
const auto viewCoord = ACG::Vec3d(position.x(),PluginFunctions::viewerProperties().glState().context_height() -position.y(), 0.5);
const auto viewStartCoord = ACG::Vec3d{viewStartCoord_[0], viewStartCoord_[1], viewStartCoord_[2]};
const auto screenSpaceDiff = viewCoord - lastFrameCoord_;
/// matrix to transform points from image plane to curPlane_
auto & plane = curPlane_->plane();
// ACG::GLMatrixf mvp = PluginFunctions::viewerProperties().glState().modelview();
// const auto dragStart = mvp.transform_point(viewStartCoord);
// const auto dragEnd = mvp.transform_point(viewCoord);
// const auto update = dragEnd - dragStart;
// const auto cen = mvp.transform_point(ACG::Vec3d{0,0,0});
// std::cerr << "################\nplane center: " << plane.position << std::endl;
// std::cerr << "center: " << cen << std::endl;
// std::cerr << "drag start: " << dragStart << std::endl;
// std::cerr << "drag end: " << dragEnd << std::endl;
/// we want to scale our plane, we will do so in 3 steps:
/// 1. translate to origin
/// 2. rotate to be planar
/// 3. scale
/// 4. rotate back
/// 5. translate back to updated target position (old origin + .5*updatevector
/// 1. transform to origin
auto transform = ACG::GLMatrixf(ACG::Matrix4x4f());
transform.identity();
transform.translate(ACG::Vec3f{-plane.position});
/// 2. rotate to be planar
const auto n0 = ACG::Vec3f{plane.normal};
const auto x = n0.dot(viewDirection_);
const auto y = std::sqrt(1 - (x * x));
const auto angle = std::atan2(y,x);
std::cerr << "angle: " << angle << std::endl;
// if(angle != 0.)
// transform.rotate(angle, n0.cross(n1));
/// 3. scale by half updates length
/// todo: adjust to screen space
ACG::Vec3f scale = ACG::Vec3f{screenSpaceDiff};
scale[0] = (scale[0] / (scale[0] + 500)) + 1;
scale[1] = (scale[1] / (scale[1] + 500)) + 1;
scale[2] = .0f;
transform.scale(scale);
std::cerr << "scale: " << scale << std::endl;
/// 4. rotate back
// transform.rotate(-angle, n0.cross(n1));
/// 4. translate back
transform.translate(ACG::Vec3f{plane.position});
plane.transform(transform);
std::cerr << "new pos: " << plane.position << std::endl;
/// 0 corner
if(pickedCorner_ == 1)
{
}
/// x corner
if(pickedCorner_ == 2)
{
}
/// xy corner
if(pickedCorner_ == 3)
{
// plane.setPlane(plane.position, plane.xDirection * 1.1, plane.yDirection * 1.1f);
// std::cerr << "plane pos: " << plane.position << std::endl;
}
/// y corner
if(pickedCorner_ == 4)
{
}
if (lastObjId_ > 0)
emit updatedObject(lastObjId_, UPDATE_GEOMETRY);
lastFrameCoord_ = viewCoord;
}
break;
}
case QEvent::MouseButtonRelease:
{
case QEvent::MouseButtonRelease: {
std::cerr << "Mouse_Release" << std::endl;
// Stop dragging operation
// Stop dragging operation reset all properties
dragging_ = false;
pickedCorner_ = 0;
result_ = ACG::Vec3d{.0};
viewStartCoord_ = ACG::Vec3d{.0};
lastFrameCoord_ = ACG::Vec3d{.0};
curPlane_ = nullptr;
lastObjId_ = -1;
break;
}
default:
break;
}
}
}
/*******************************************************************************
......@@ -229,8 +316,7 @@ void PlanePlugin::slotMouseEvent( QMouseEvent* _event ) {
/** \brief Plane Node Button
*
*/
void PlanePlugin::slotCreatePlaneNode( )
{
void PlanePlugin::slotCreatePlaneNode() {
PluginFunctions::actionMode(Viewer::PickingMode);
PluginFunctions::pickMode(PLANE);
}
......@@ -238,19 +324,15 @@ void PlanePlugin::slotCreatePlaneNode( )
//------------------------------------------------------------------------------
void PlanePlugin::slotCreatePlaneTriggered() {
// get object
BaseObjectData* obj;
if ( PluginFunctions::getPickedObject( createPlane_->getNode() , obj) )
{
if (PluginFunctions::getPickedObject(createPlane_->getNode(), obj)) {
if (obj == nullptr) {
emit log(LOGERR, "Unable to get object");
return;
}
// generate a plane object
int planeId = -1;
......@@ -271,18 +353,17 @@ void PlanePlugin::slotCreatePlaneTriggered(){
double radius;
if (getIntersectionParams(*obj, center, radius)) {
radius = 1.5 * radius;
radius = std::min(radius, PluginFunctions::sceneRadius());
currentPlane->plane().setPlane(center, normal);
currentPlane->plane().setSize(2.0 * radius, 2.0 * radius);
} else {
std::cerr << "unable to get intersection params" << std::endl;
currentPlane->plane().setPlane(point, normal);
currentPlane->plane().setSize( PluginFunctions::sceneRadius(), PluginFunctions::sceneRadius());
currentPlane->plane().setSize(PluginFunctions::sceneRadius(),
PluginFunctions::sceneRadius());
}
currentPlane->planeNode()->show();
......@@ -293,8 +374,8 @@ void PlanePlugin::slotCreatePlaneTriggered(){
//------------------------------------------------------------------------------
bool PlanePlugin::getIntersectionParams(BaseObjectData& _obj, ACG::Vec3d& _center, double& _radius ) {
bool PlanePlugin::getIntersectionParams(BaseObjectData& _obj,
ACG::Vec3d& _center, double& _radius) {
ACG::Vec3d point = createPlane_->getSourcePoint();
ACG::Vec3d normal = createPlane_->getNormal();
......@@ -302,55 +383,45 @@ bool PlanePlugin::getIntersectionParams(BaseObjectData& _obj, ACG::Vec3d& _cente
std::vector<ACG::Vec3d> linePoints;
bool closed = false;
if (_obj.dataType(DATA_TRIANGLE_MESH)) {
TriMesh* mesh = PluginFunctions::triMesh(&_obj);
if ( mesh == nullptr )
return false;
if (mesh == nullptr) return false;
// get a edge of the mesh that is cut by the plane
TriMesh::EdgeHandle eh = getCuttedEdge(*mesh, normal, point);
if ( !eh.is_valid() )
return false;
if (!eh.is_valid()) return false;
TriMesh::FaceHandle fh = mesh->face_handle(mesh->halfedge_handle(eh, 0));
if (!fh.is_valid())
fh = mesh->face_handle( mesh->halfedge_handle(eh, 1) );
if (!fh.is_valid()) fh = mesh->face_handle(mesh->halfedge_handle(eh, 1));
// get all intersection points
linePoints = getIntersectionPoints(mesh, fh.idx(), normal, point, closed);
} else {
PolyMesh* mesh = PluginFunctions::polyMesh(&_obj);
if ( mesh == nullptr )
return false;
if (mesh == nullptr) return false;
// get a edge of the mesh that is cut by the plane
PolyMesh::EdgeHandle eh = getCuttedEdge(*mesh, normal, point);
if ( !eh.is_valid() )
return false;
if (!eh.is_valid()) return false;
PolyMesh::FaceHandle fh = mesh->face_handle(mesh->halfedge_handle(eh, 0));
if (!fh.is_valid())
fh = mesh->face_handle( mesh->halfedge_handle(eh, 1) );
if (!fh.is_valid()) fh = mesh->face_handle(mesh->halfedge_handle(eh, 1));
// get all intersection points
linePoints = getIntersectionPoints(mesh, fh.idx(), normal, point, closed);
}
if ( linePoints.empty() )
return false;
if (linePoints.empty()) return false;
_center = ACG::Vec3d(0.0, 0.0, 0.0);
for (uint i=0; i < linePoints.size(); i++)
_center += linePoints[i];
for (uint i = 0; i < linePoints.size(); i++) _center += linePoints[i];
_center /= (double)linePoints.size();
......@@ -359,8 +430,7 @@ bool PlanePlugin::getIntersectionParams(BaseObjectData& _obj, ACG::Vec3d& _cente
for (uint i = 0; i < linePoints.size(); i++) {
double dist = (_center - linePoints[i]).norm();
if (dist > _radius)
_radius = dist;
if (dist > _radius) _radius = dist;
}
return true;
}
......
......@@ -137,6 +137,16 @@ class PlanePlugin : public QObject, BaseInterface, MouseInterface, KeyInterface,
// In Picking Mode for plane resize, which corner did we pick?
int pickedCorner_;
// world space coords of the dragging start position (through raycast)
ACG::Vec3d result_{.0};
// view space coords of the dragging start position
ACG::Vec3d viewStartCoord_{.0};
ACG::Vec3d lastFrameCoord_{.0};
ACG::Vec3d viewDirection_{.0};
// currently dragged plane
PlaneObject* curPlane_ = nullptr;
int lastObjId_ = -1;
/** @} */
//===========================================================================
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment