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

scaling without position change follows cursor perfectly

parent 13bf1b9a
No related branches found
No related tags found
1 merge request!2Plane interaction
......@@ -97,6 +97,70 @@ void PlanePlugin::slotKeyReleaseEvent(QKeyEvent *_event) {
* @param _event the event that occured
*/
void PlanePlugin::slotMouseEvent(QMouseEvent *_event) {
// auto determinant = [](ACG::Vec3f const &c1, ACG::Vec3f const &c2,
// ACG::Vec3f const &c3) -> float {
// return (c1[0] * c2[1] * c3[2]) + (c2[0] * c3[1] * c1[2]) +
// (c3[0] * c1[1] * c2[2]) - (c3[0] * c2[1] * c1[2]) -
// (c2[0] * c1[1] * c3[2]) - (c1[0] * c3[1] * c2[2]);
// };
/// only works in constrained cases
// auto rayPlaneIntersection =
// [&determinant](ACG::Vec3f const &s1, ACG::Vec3f const &s2,
// ACG::Vec3f const &p, ACG::Vec3f const &q,
// ACG::Vec3f const &r, float &alpha, float &beta) {
// /// implementation of cramers rule to compute closed form
// solution for
// /// plane ray intersections (closed form solution) problematic
// if ray
// /// points away or converges to parallel to plane
// /// s1 and s2 are two points that define the ray (origin &
// origin+dir)
// /// p,q,r span a triangle that defines the plane
// /// alpha & beta are return params for the barycentric
// coordinates
// /// alpha belongs to p, beta belongs to q
// const auto denom = determinant(s1, r - p, r - q);
// alpha = determinant(s1, r - s2, r - q) / denom;
// beta = determinant(s1, r - p, r - s2) / denom;
// };
/// modification of triangleIntersection
auto rayPlaneIntersection = [](ACG::Vec3d const &origin,
ACG::Vec3d const &dir, ACG::Vec3d const &p,
ACG::Vec3d const &q, ACG::Vec3d const &r,
double &alpha, double &beta) -> bool {
{
ACG::Vec3d edge1, edge2, tvec, pvec, qvec;
double det, inv_det;
edge1 = q - p;
edge2 = r - p;
pvec = dir % edge2;
det = edge1 | pvec;
constexpr double EPSILON = std::numeric_limits<double>::epsilon() * 1e2;
if (det > -EPSILON && det < EPSILON)
return false;
inv_det = 1.f / det;
tvec = origin - p;
alpha = (tvec | pvec) * inv_det;
qvec = tvec % edge1;
beta = (dir | qvec) * inv_det;
/// we don't really care about legal barycentric coordinates, however if
/// you really want to know if you are inside the defining triangle,
/// there you go
if (alpha < 0.0 || alpha > 1.0)
return false;
if (beta < 0.0 || alpha + beta > 1.0)
return false;
return true;
}
};
if (PluginFunctions::pickMode() == PLANE)
createPlane_->slotMouseEvent(_event);
if (PluginFunctions::pickMode() == PLANE_RESIZE) {
......@@ -114,24 +178,19 @@ void PlanePlugin::slotMouseEvent(QMouseEvent *_event) {
lastObjId_ = obj->id();
if (curPlane_) {
origPlane_ = curPlane_->plane();
QPoint position = _event->pos();
/// view coords in screenspace, with flipped y-axis
/// view coords in screenspace, with flipped y-axis at depth of
/// plane
ACG::Vec3d viewCoords = ACG::Vec3d(
position.x(),
PluginFunctions::viewerProperties().glState().context_height() -
position.y(),
0.5);
.5);
viewStartCoord_ = 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;
PluginFunctions::viewerProperties().glState().viewing_ray(
......@@ -168,10 +227,12 @@ void PlanePlugin::slotMouseEvent(QMouseEvent *_event) {
std::cerr << "target_idx: " << target_idx << std::endl;
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;
// 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;
if (target_idx == 0)
return;
......@@ -179,7 +240,6 @@ void PlanePlugin::slotMouseEvent(QMouseEvent *_event) {
// 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;
}
......@@ -199,28 +259,44 @@ void PlanePlugin::slotMouseEvent(QMouseEvent *_event) {
QPoint position = _event->pos();
/// view coords in screenspace, with flipped y-axis
/// matrix to transform points from image plane to curPlane_
auto plane = origPlane_;
/// view coords in worldspace, with flipped y-axis
const auto viewCoord = ACG::Vec3d(
position.x(),
PluginFunctions::viewerProperties().glState().context_height() -
position.y(),
0.5);
const auto screenSpaceDiff = viewCoord - lastFrameCoord_;
.5);
/// 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;
/// get the world position by intersecting plane equation with ray
ACG::Vec3d origin;
ACG::Vec3d dir;
PluginFunctions::viewerProperties().glState().viewing_ray(
viewCoord[0], viewCoord[1], origin, dir);
{
double u = -3.1415926539, v = -3.1415926539;
const auto center = plane.position;
const auto xdir = plane.xDirection / 2.;
const auto ydir = plane.yDirection / 2.;
const auto p0 = ACG::Vec3d{center + xdir + ydir};
const auto p1 = ACG::Vec3d{center + xdir - ydir};
const auto p2 = ACG::Vec3d{center - xdir - ydir};
/// we can assume that most of the time, there wont be an
/// intersection. but as we only check one half of the triangle, the
/// other will always be outside
/// we dont really care about the result here
rayPlaneIntersection(origin, dir, p0, p1, p2, u, v);
const auto w = 1. - (u + v);
currWorldPos_ = (w * p0) + (u * p1) + (v * p2);
}
const auto worldSpaceUpdate = (currWorldPos_ - result_) / 1.;
/// update to corresponding corner later
const auto distClickOrigin = plane.position + (.5f * plane.xDirection) +
(.5f * plane.yDirection);
/// we want to scale our plane, we will do so in 3 steps:
/// 1. translate to origin
......@@ -230,13 +306,6 @@ void PlanePlugin::slotMouseEvent(QMouseEvent *_event) {
/// 5. translate back to updated target position (old origin +
/// .5*updatevector
const auto lastWorldSpace =
PluginFunctions::viewerProperties().glState().unproject(
lastFrameCoord_);
const auto currWorldSpace =
PluginFunctions::viewerProperties().glState().unproject(viewCoord);
const auto diffWorldSpace = currWorldSpace - lastWorldSpace;
/// 1. transform to origin
auto transform = ACG::GLMatrixf(ACG::Matrix4x4f());
transform.identity();
......@@ -253,23 +322,27 @@ void PlanePlugin::slotMouseEvent(QMouseEvent *_event) {
/// 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;
auto scale =
ACG::Vec3f{(worldSpaceUpdate + distClickOrigin) / distClickOrigin};
scale[2] = 1; /// we dont do anything in z-dir
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});
transform.translate(ACG::Vec3f{diffWorldSpace / 2});
// transform.translate(ACG::Vec3f{worldSpaceUpdate / 2});
plane.transform(transform);
std::cerr << "new pos: " << plane.position << std::endl;
std::cerr << "worldSpaceUpdate: " << worldSpaceUpdate << std::endl;
std::cerr << "[world] start pos: " << result_ << std::endl;
std::cerr << "[world] curr pos: " << currWorldPos_ << std::endl;
std::cerr << "[world] plane.pos: " << plane.position << std::endl;
std::cerr << "scale: " << scale << std::endl;
curPlane_->plane() = plane; /// overwrite plane
/// 0 corner
if (pickedCorner_ == 1) {
......@@ -279,9 +352,6 @@ void PlanePlugin::slotMouseEvent(QMouseEvent *_event) {
}
/// 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) {
......@@ -289,8 +359,6 @@ void PlanePlugin::slotMouseEvent(QMouseEvent *_event) {
if (lastObjId_ > 0)
emit updatedObject(lastObjId_, UPDATE_GEOMETRY);
lastFrameCoord_ = viewCoord;
}
break;
......@@ -303,7 +371,6 @@ void PlanePlugin::slotMouseEvent(QMouseEvent *_event) {
pickedCorner_ = 0;
result_ = ACG::Vec3d{.0};
viewStartCoord_ = ACG::Vec3d{.0};
lastFrameCoord_ = ACG::Vec3d{.0};
curPlane_ = nullptr;
lastObjId_ = -1;
......
......@@ -3,23 +3,29 @@
#include <QObject>
#include <ObjectTypes/Plane/Plane.hh>
#include <ObjectTypes/Plane/QtPlaneSelect.hh>
#include <ObjectTypes/PolyMesh/PolyMesh.hh>
#include <ObjectTypes/TriangleMesh/TriangleMesh.hh>
#include <OpenFlipper/BasePlugin/BaseInterface.hh>
#include <OpenFlipper/BasePlugin/MouseInterface.hh>
#include <OpenFlipper/BasePlugin/KeyInterface.hh>
#include <OpenFlipper/BasePlugin/PickingInterface.hh>
#include <OpenFlipper/BasePlugin/LoadSaveInterface.hh>
#include <OpenFlipper/BasePlugin/LoggingInterface.hh>
#include <OpenFlipper/BasePlugin/MouseInterface.hh>
#include <OpenFlipper/BasePlugin/PickingInterface.hh>
#include <OpenFlipper/BasePlugin/ScriptInterface.hh>
#include <OpenFlipper/BasePlugin/ToolbarInterface.hh>
#include <OpenFlipper/BasePlugin/LoadSaveInterface.hh>
#include <OpenFlipper/common/Types.hh>
#include <ObjectTypes/PolyMesh/PolyMesh.hh>
#include <ObjectTypes/TriangleMesh/TriangleMesh.hh>
#include <ObjectTypes/Plane/Plane.hh>
#include <ObjectTypes/Plane/QtPlaneSelect.hh>
class PlanePlugin : public QObject, BaseInterface, MouseInterface, KeyInterface, PickingInterface,
LoggingInterface, ToolbarInterface, ScriptInterface, LoadSaveInterface
{
class PlanePlugin : public QObject,
BaseInterface,
MouseInterface,
KeyInterface,
PickingInterface,
LoggingInterface,
ToolbarInterface,
ScriptInterface,
LoadSaveInterface {
Q_OBJECT
Q_INTERFACES(BaseInterface)
Q_INTERFACES(MouseInterface)
......@@ -32,7 +38,6 @@ class PlanePlugin : public QObject, BaseInterface, MouseInterface, KeyInterface,
Q_PLUGIN_METADATA(IID "org.OpenFlipper.Plugins.Plugin-Plane")
signals:
// BaseInterface
void updateView();
......@@ -53,7 +58,8 @@ class PlanePlugin : public QObject, BaseInterface, MouseInterface, KeyInterface,
void defineViewMode(QString _mode, QStringList _usedWidgets);
// KeyInterfae
void registerKey(int _key, Qt::KeyboardModifiers _modifiers, QString _description, bool _multiUse = false);
void registerKey(int _key, Qt::KeyboardModifiers _modifiers,
QString _description, bool _multiUse = false);
// PickingInterface
void addPickMode(const std::string _mode);
......@@ -65,7 +71,6 @@ class PlanePlugin : public QObject, BaseInterface, MouseInterface, KeyInterface,
void log(Logtype _type, QString _message);
void log(QString _message);
private slots:
// BaseInterface
......@@ -81,8 +86,8 @@ class PlanePlugin : public QObject, BaseInterface, MouseInterface, KeyInterface,
// KeyInterface:
void slotKeyReleaseEvent(QKeyEvent *_event);
bool getIntersectionParams(BaseObjectData& _obj, ACG::Vec3d& _center, double& _radius );
bool getIntersectionParams(BaseObjectData &_obj, ACG::Vec3d &_center,
double &_radius);
public:
PlanePlugin();
......@@ -100,16 +105,15 @@ class PlanePlugin : public QObject, BaseInterface, MouseInterface, KeyInterface,
/// get the points from the intersection between mesh and plane
template <class MeshT>
std::vector< ACG::Vec3d > getIntersectionPoints ( MeshT* _mesh ,
uint _fh ,
ACG::Vec3d _planeNormal ,
ACG::Vec3d _planePoint,
bool& _closed );
std::vector<ACG::Vec3d>
getIntersectionPoints(MeshT *_mesh, uint _fh, ACG::Vec3d _planeNormal,
ACG::Vec3d _planePoint, bool &_closed);
/// get an edge of the mesh that is cut by the plane
template <class MeshT>
typename MeshT::EdgeHandle
getCuttedEdge(MeshT& _mesh, ACG::Vec3d& _planeNormal, ACG::Vec3d& _planePoint);
typename MeshT::EdgeHandle getCuttedEdge(MeshT &_mesh,
ACG::Vec3d &_planeNormal,
ACG::Vec3d &_planePoint);
/** @} */
......@@ -125,7 +129,6 @@ class PlanePlugin : public QObject, BaseInterface, MouseInterface, KeyInterface,
/// Create a plane node when position/normal have been drawn
void slotCreatePlaneTriggered();
private:
// Plane Selection Tools
QtPlaneSelect *createPlane_;
......@@ -140,12 +143,13 @@ class PlanePlugin : public QObject, BaseInterface, MouseInterface, KeyInterface,
// world space coords of the dragging start position (through raycast)
ACG::Vec3d result_{.0};
ACG::Vec3d currWorldPos_{.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;
Plane origPlane_;
int lastObjId_ = -1;
/** @} */
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment