Hi there,
i have made a clone of the TCastleExamineNavigation class called TCADNavigationClass.
As a first step i tried to change the Zoom Method. In CAD Applications it is a normal behaviour that if i Zoom then the centerpoint of zoom is not the center of the Viewport but the point where the mouseposition is.
My idea was to retrieve the actual worldposition of current mousepoint then make the zoom and after that again retrieve the actual worldposition of current mousepoint and make then a Translation so that both matches again. I failed completely to do that 
can someone please point me in the right direction about that?
thanks Michael
Family of methods PositionFromXxx
, PositionToXxx
on TCastleViewport ( Castle Game Engine: CastleViewport: Class TCastleViewport ) should be of help here.
E.g. PositionToCameraPlane
can convert mouse coordinates (if you set ContainerCoordinates
parameter to true
, then you can pass there directly e.g. Event.MousePosition
) into coordinates in 3D world in the viewport.
PositionFromWorld
can convert 3D coordinate inside viewport back into UI coordinates. Note that it doesn’t have ContainerCoordinates
parameter (contrary to most other PositionTo/PositionFrom methods) and behaves like ContainerCoordinates
was false
, so it returns position relative to viewport position. But you can convert it using LocalToContainerPosition
to get position in “container coordinates” if necessary.
Thank you for the answer, i was working with an older CGE Version that has not PositionFromXX Methods. Now i downloaded the latest version but it does not compile with latest FPC 3.3.1 There is an error in CastleStringUtils.pas on line 2339.
Result := R.Replace(NamePattern, {$ifdef FPC}@{$endif} C.ReplaceCallback);
castlestringutils.pas(2339,79) Error: Incompatible type for arg no. 2: Got “<procedure variable type of function(TRegExpr):UnicodeString(1200) of object;Register>”, expected “<procedure variable type of function(TRegExpr):AnsiString(0) of object;Register>”
If you use FPC unstable (3.3.1), we assume you use the latest one – you should upgrade your FPC version.
More details:
Of course you can also use stable FPC, 3.2.2, to be more protected from such changes. We support FPC 3.2.0 and 3.2.2 now, and we generally recommend using the latest stable FPC.
Now i use FPC stable with latest CGE and it compiles fine now.
But i can’t get my zoom with center on MousePosition working.
I get Mouseposition with
MPos := ViewPort.Container.MousePosition; // ViewPort is assigned InternalViewport as TCastleViewport
Now i retrieve Position with
ViewPort.PositionToCameraPlane(MPos, true, 1, OldPosition);
After that the scale is made
Camera.Orthographic.Scale := Camera.Orthographic.Scale * Exp(-Factor);
Now i try to get the new position again with
ViewPort.PositionToCameraPlane(MPos, true, 1, NewPosition);
but OldPosition and NewPosition are always the same?
Hm, I suspect here 2 problems on CGE side. They are both possible and easy to fix, I’ll experiment later (if you can submit a reproducible testcase with a problem to https://github.com/castle-engine/castle-engine/issues that would be appreciated though).
My suspicions:
-
PositionToCameraPlane
doesn’t account for Camera.Orthographic.Scale
. This camera scaling is done in a special way. If you know you always have orthographic projection, then PositionTo2DWorld
will work better, it definitely accounts for Camera.Orthographic.Scale
.
-
You’ll land at a different problem though: PositionToXxx
rely on projection parameters that are updated every frame, not immediately after Camera.Orthographic.Scale
change in code. You can workaround it temporarily by removing the condition if not FProjection.Initialized then...
inside TCastleViewport.PositionToPrerequisites
implementation in src/scene/castleviewport.pas
. Then PositionTo2DWorld
should be fully reliable.
As I emphasize, both problems can be just fixed on CGE side, i.e. to make both PositionToCameraPlane
and PositionTo2DWorld
reliable automatically in such case. If you can submit a simple testcase showing the problem now, that will make it easier to experiment for me 
thank you very much. I have opened an issue with a little testproject appended.
Normally in CAD applications i use only orthographic view but not 2D
1 Like
Fixed in We need to call PositionToPrerequisites before every PositionToXxx · castle-engine/castle-engine@81659c4 · GitHub , thanks for the testcase – this made testing this easy.
In the end my suspicion AD 1 was incorrect but suspicion AD 2 was correct. PositionToCameraPlane
was doing correct calculation, it already took Camera.Orthographic.Scale
into account, but it didn’t react to changing Camera.Orthographic.Scale
immediately, it was only updating the output next frame. This is now fixed.
Your application now presents a nice zoom to mouse position!
Notes:
-
If you update to latest CGE, you will have to do some fixes in cadnavigation, some code you copied from TCastleExamineNavigation
needs adjusting after Vectors changes, to avoid a trap with modifying a temporary value – Castle Game Engine . In short, just try to compile it, and replace reported places (4, as far as I recall) from
V[xxx]
to
V.InternalData[xxx]
-
Note that comparing vectors like V1 <> V2
compares them tolerating tiny epsilon differences. Better use TVector3.PerfectlyEquals(....)
if you want exact comparison.
In case of this code, I would actually completely avoid the
if (OldPosition <> NewPosition) then
check. You can just use Translation := Translation + NewPosition - OldPosition;
without any check, changing camera position is really instant. (and this check will usually be true
anyway, so you will more often waste a bit of time doing the check, than you will save time by avoiding Translation
change.)
-
I like this modification 
I think both scaling ways (to screen center, to point under mouse) make sense in general CGE. Looking at authoring software I know, it’s also using various approaches: Blender zooms to center, while Spine (2D animation software) zooms to point under mouse (much like with your CADNavigation). Oh, I can actually change Blender to also do this: “Preferences->Navigation->Zoom To Mouse Position” makes Blender also work like this (and it works in both perspective and orthographic projection). So it’s a confirmation in my eyes that this is a useful feature that we’d like in CGE 
I’d welcome PR to add this to CGE, as an option to our TCastleExamineNavigation
. I’d say this should be activated by a Boolean property TCastleExamineNavigation.ZoomToMousePosition
(consistent with Blender name, consistent with our MousePosition
field).
And ideally it should also work in perspective projection. (Though we could allow PR making it working only in orthogonal, documenting that in the long run it should also affect perspective.)
-
In general, better check PositionToCameraPlane
result and abort if any of them returns false
. This may happen in perspective and only when camera has extremely wide field of view, like 180 or almost like it.
So I understand this is not a concern in your case (orthographic), but in general I’d advise to check it, to be secure from this extreme edge-case.
Thank you very much!
It is working