Last modified: 2025-03-26 15:15:40
< 2025-03-25 2025-03-27 >I'm imagining a compiled shader that will draw the grab handle at the position specified in a uniform, and then some code that will detect when you click on the grab handle, and while you're dragging it will work out where you've dragged it to, either constrained along a line, or along a defined plane, or parallel to the viewing plane.
And then while you're dragging it it will continually update the "property" associated with it.
Is it going to be more efficient to draw it with a shader layer, or with canvas? Don't really care at this point, shader layer probably better because then we can have lighting.
So plan is:
grabhandle.js
or whateverTreeNode
s have some way to specify which of their properties need GrabHandle
s, and which line/plane they're constrained to, if anyui.js
has some way to instantiate GrabHandle
sGrabHandle
can monitor click/drag events on the glCanvas
main.js
lets each GrabHandle
render its ShaderLayer
to the sceneDo I want to be using proper "deferred rendering" so that depth information is retained between shader layers? The issue is that the grab handles will be drawn on top of each other in whatever order they're drawn, instead of properly occluding based on depth. Don't worry about it for now, just get one grab handle to work.
OK, I have it drawing a red circle on the scene, and it respects the coordinate system, and I can drag it left/right along the X axis, but the dragging doesn't quite work right when I'm not looking directly at the XY plane.
I actually think GrabHandle
wants to just yield a scalar quantity
if it is constrained to motion along an axis. You'll initialise it
with an origin, an axis, and a scalar quantity. It starts out at
origin + axis * scalar
. And whenever it moves it reports back its
new scalar. And you can optionally give it a minimum/maximum value.
Currently I have a test circle that resizes the default box object in X, but yeah still broken when coordinate system is rotated.
When I rotate the XY plane by 90 degrees, the Y axis is inverted, is it somehow applying the rotation matrix backwards?
OK I have noticed that the sketch editor also has issues. The coordinate system inside the sketch editor, while internally-consistent, does not actually match the coordinate system of the wider object.
The coordinate rotate buttons always rotate around Z instead of around the viewing axis.
OK, the problem was that screenToWorld()
and worldToScreen()
were
using the rotation matrix the wrong way around. That's fixed now, and
the sketch editor is sorted, and now the grab handles no longer need
the Y axis inverting.
The only remaining problem with the grab handle is it doesn't move as far as your mouse moves. The ratio that it is wrong by seems to depend on the rotation angle of the scene and not on the zoom level.
Amazing, fixed now!
So now I have 1 GrabHandle
hardcoded to affect the base box size.
What I want instead is whatever node is selected should have grab handles for adjusting its properties. For now only scalar properties, we can maybe do vector grab handles later.
I've made the TreeNode
class let you specify grabHandles()
where
you just return a mapping of property names to origin and axis vectors,
and then the ui.js
deals with turning them into grab handles when the
object is selected.
Works pretty well, but:
roundRadius
handle should be positioned at an edge, but when you change the diameter of the cylinder the edge movesTransform
nodes, the grab handles don't correspond to the actual final positionAlso should I make it draw the axis indicator with a separate shader instead of part of the main one?
Would then be handy to draw an axis indicator showing the coordinate system of the "secondary node".
Also I kind of do want transforms from the tree to propagate to the secondary node, so that it is drawn in its actual position instead of always at the origin.
But maybe instead of the whole "applyToSecondary" thing, we just
have some way for document
to tell us the net transform that is applied
to the secondary node? Or is "applyToSecondary" the most convenient
way to do that?