When we first looked at moving the camera or another 3D object we thought left was step negative X and Up was step negative Y and forward was step plus Z. If you want to reorient this object then in fact it is not so easy. In the case of our camera we want it to travel forward and backward along the local Z axis which is not the same as incrementing the global Z value.
I produced my sketch diagrams and cobbled together a solution that worked within some parameters but had problems as you moved the camera around more. In the end a looked at what the TControl3D offers and an easy solution just fell out.
In the end to obtain the new absolute position of the control create a local offset point [0,0,distance to move forward] and then use the TControl3D’s own LocalToAbsolute3D function.
Procedure MoveControlAlongLocalZAxis(AControl:TControl3D; Var APositionPoint: TPoint3D; ADistance: Real); Var Offset, OtherSolution: TPoint3D; begin Offset:= TPoint3D.Create(0,0,ADistance); APositionPoint:=AControl.LocalToAbsolute3D(Offset); end;
Using a timer to increment object positions and angles produced a very processor intensive and clumsy presentation. This was resolved by calculating an end position or angle after a larger time span and setting up float animations to get there thus making use of the graphics processor.
Procedure StartLocationTrackingAnimation(ATarget: TFMXObject; Const ALocationProperty: String; AEnd: TPoint3D; ADuration: single); Var LPopNameX, LPopNameY, LPopNameZ: String; Begin LPopNameX := ALocationProperty + '.X'; LPopNameY := ALocationProperty + '.Y'; LPopNameZ := ALocationProperty + '.Z'; ATarget.AnimateFloat(LPopNameX, AEnd.X, ADuration, TAnimationType.InOut); ATarget.AnimateFloat(LPopNameY, AEnd.Y, ADuration, TAnimationType.InOut); ATarget.AnimateFloat(LPopNameZ, AEnd.Z, ADuration, TAnimationType.InOut); End; procedure TFlyingCamera.MoveForward(ADistance: Real); Var LPositionPoint: TPoint3D; begin LPositionPoint := Position.Point; MoveControlAlongLocalZAxis(Self, LPositionPoint, ADistance); StartLocationTrackingAnimation(Self, 'Position', LPositionPoint, FSpeedTimer.Interval / 1000); UpdateHeadUpDisplay; end;
In the libraries provided the MoveControlAlongLocalZAxis function and the float animation technique are used to create “projectiles” from each “wing” converging to the point directly “ahead”. The projectile base control starts off when you hit the space bar with the same orientation as the camera or viewport and “moves forward” but the visual components are offset in X so as to appear to come from each wing. The float animations are set up to reduce the offset to zero as the “projectile” reaches its furthest point forward.
At the start the projectiles converge to the center of the “gun sight” but if the camera is panned to extremes the projectiles become more erratic. I have no idea why this is but it is a similar effect to that observed in being unable to find the origin after panning the camera in the previous blog. The camera alignment seem to be out of wack with the reference plain.