Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
P
Plugin-Plane
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Deploy
Releases
Model registry
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
OpenFlipper-Free
Plugin-Plane
Commits
3ed9a4b8
Commit
3ed9a4b8
authored
4 years ago
by
Zain Selman
Browse files
Options
Downloads
Patches
Plain Diff
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
!2
Plane interaction
Changes
2
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
PlanePlugin.cc
+313
-243
313 additions, 243 deletions
PlanePlugin.cc
PlanePlugin.hh
+20
-10
20 additions, 10 deletions
PlanePlugin.hh
with
333 additions
and
253 deletions
PlanePlugin.cc
+
313
−
243
View file @
3ed9a4b8
...
...
@@ -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
]
=
.0
f
;
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
;
}
...
...
This diff is collapsed.
Click to expand it.
PlanePlugin.hh
+
20
−
10
View file @
3ed9a4b8
...
...
@@ -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
;
/** @} */
//===========================================================================
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment