Board index FlightGear Development Canvas

Canvas HUD : how to rotate+translate  Topic is solved

Canvas is FlightGear's new fully scriptable 2D drawing system that will allow you to easily create new instruments, HUDs and even GUI dialogs and custom GUI widgets, without having to write C++ code and without having to rebuild FlightGear.

Canvas HUD : how to rotate+translate

Postby Flying toaster » Sat Jan 05, 2013 7:04 pm

Hello,

First thing, happy new year to you all,

I am working on a translation of the F-20 HUD from the old framework to Canvas/Nasal API.
Right now I am getting a little lost in the way rotation are handled on SVG objects imported in a canvas. I have tried many ways (standard setRotation, createTransform ... I even hand built the transformation matrix).
Yet the HUD ladder is rotating around a point that is not the proper one.

Is there a way to have a transform stack (i.e. multiplying matrices instead of overwritting them) such as the one found in OpenGL and the XML model file.
I thought the createTransform call did that but does not seem to work though, but then again I may be doing it wrong.

Cheers

Enrique
Flying toaster
 
Posts: 348
Joined: Wed Nov 29, 2006 6:25 am
Location: Toulouse France

Re: Canvas HUD : how to rotate+translate

Postby TheTom » Sat Jan 05, 2013 8:10 pm

createTransform creates a new matrix on top of the existing matrix stack. A while ago I've added an example for a HUD built using the Canvas to the wiki: http://wiki.flightgear.org/Canvas_HUD
It doesn't use SVG but manually creates everything instead. As loading an SVG should basically do the same than handcrafting icons there shouldn't be much of a difference.
TheTom
 
Posts: 321
Joined: Sun Oct 09, 2011 10:20 am

Re: Canvas HUD : how to rotate+translate

Postby Flying toaster » Sat Jan 05, 2013 10:57 pm

Thank you for the advice but I still cannot get it to work

Here is the code
Code: Select all
#F-20 HUD main module

#angular definitions
#up angle 1.73 deg
#left/right angle 5.5 deg
#down angle 10.2 deg
#total size 11x11.93 deg
#center at 118,37
#pixels per deg = 21.458507963

var HUDcanvas= canvas.new({
                           "name": "f-20 HUD",
                           "size": [1024,1024],
                           "view": [256,256],                       
                           "mipmapping": 1     
                          });                         
                         
HUDcanvas.addPlacement({"node": "HudImage"});
HUDcanvas.setColorBackground(0.36, 1, 0.3, 0.00);

# Create a group for the parsed elements
var SVGfile = HUDcanvas.createGroup();
 
# Parse an SVG file and add the parsed elements to the given group
canvas.parsesvg(SVGfile, "Aircraft/F-20/Nasal/HUD/HUD.svg");
SVGfile.setTranslation (-20.0, 37.0);
 
var ladder = SVGfile.getElementById("ladder");
ladder.setCenter (265,-12.0);
var VV = SVGfile.getElementById("VelocityVector");
var KIAS = SVGfile.getElementById("KIAS");
KIAS.setFont("condensed.txf").setFontSize(15, 1.4);
var Alt = SVGfile.getElementById("Alt");
Alt.setFont("condensed.txf").setFontSize(11, 1.4);
var AltThousands = SVGfile.getElementById("AltThousands");
AltThousands.setFont("condensed.txf").setFontSize(15, 1.4);


var ladder_pitch = ladder.createTransform();
var ladder_roll = ladder.createTransform();


var ladder_rot_cos = 0.0;
var ladder_rot_sin = 0.0;

var ladder_center_x = 265.0;
var ladder_center_y = 12.0;

var roll_rad = 0.0;
var pitch_offset = 0.0;
var f1 = 0.0;

var updateHud = func ()

  roll_rad = -roll*3.14159/180.0;
  #pitch_offset = pitch* 21.458507963;
  #ladder_rot_cos = math.cos(roll_rad);
  #ladder_rot_sin = math.sin(roll_rad);
  #ladder_transform.a.setDoubleValue(ladder_rot_cos);
  #ladder_transform.b.setDoubleValue(ladder_rot_sin);
  #ladder_transform.c.setDoubleValue(-ladder_rot_sin);
  #ladder_transform.d.setDoubleValue(ladder_rot_cos); 
  #f1 = 1.0 - ladder_rot_cos;
  #ladder_transform.e.setDoubleValue(ladder_center_x * f1
                                    #-
                                    #ladder_rot_sin * ladder_center_y);
  #ladder_transform.f.setDoubleValue(ladder_center_y * f1
                                    #+
                                    #ladder_rot_sin * ladder_center_x
                                    #+ pitch_offset);
                         
  ladder_roll.setRotation (roll_rad);                               
  ladder_pitch.setTranslation (0.0,pitch* 21.458507963);
 
  KIAS.setText (sprintf("%3.0f",IAS));
  Alt.setText (sprintf("%3.0f",altitude_ft-int(altitude_ft/1000.0)*1000.0));
  AltThousands.setText (sprintf("%2.0f",altitude_ft/1000.0));
}




I am still a bit puzzle by the following code in the API.nas file for Canvas
Code: Select all
  # Create a new transformation matrix
  #
  # @param vals Default values (Vector of 6 elements)
  createTransform: func(vals = nil)
  {
    var node = me._node.addChild("tf", 1); # tf[0] is reserved for
                                           # setRotation
    return Transform.new(node, vals);
  },


I particularly note the comment tf[0] is reserved for setRotation. Any clue of why it is so and what could be the consequences ?
Flying toaster
 
Posts: 348
Joined: Wed Nov 29, 2006 6:25 am
Location: Toulouse France

Re: Canvas HUD : how to rotate+translate

Postby TheTom » Sun Jan 06, 2013 10:14 am

You should probably change the order of creating the transforms for pitch and roll as normally one would rotate first and then move according to roll and then move according to pitch up and down. Keep in mind that rotations always happens around the origin of the local coordinate frame of the object being rotated. For a rotation around another point you would need to move the object first until the center coincides with the local origin then rotate and afterwards move back. Instead of applying three transformations there exists a shortcut to pass the center of rotation as second argument to setRotation.

To further shorten the code an especially to allow rotating objects imported from SVG there exists setRotation also for canvas Elements (not only Transformation) and additionally setCenter which instead of passing the center as an argument sets the center which is being used while calling setRotation on this element. setCenter only affects setRotation of this not object but not for any matrix added with createTransform. If you set the center of rotation in Inkscape (switch to rotate mode and drag the cross to the center of rotation) it is automatically loaded with setCenter so you just need to call setRotation and automatically get a rotation around the correct center.

You don't need to care about tf[0] being reserved as it only reserves the index 0 and doesn't affect anything if not used. createTransform creates a new matrix with the next unused index starting at 1 (0 is reserved). If you later call setRotation directly on an element a new Transform will be created but this time using tf[0] to ensure it is applied before all other matrices and therefore rotating the object around its own center before being moved around.

For the HUD I'd set the rotation center correctly inside Inkscape and later on just call ladder.setRotation to rotate for changes in the roll angle. Afterwards create a Transform and use setTranslate for changes in pitch angle.
TheTom
 
Posts: 321
Joined: Sun Oct 09, 2011 10:20 am

Re: Canvas HUD : how to rotate+translate

Postby zakalawe » Sun Jan 06, 2013 10:36 am

BTW, at some point we need to convert the generic HUD to sue the canvas - not a job I'm looking forward too - so I'm likely to steal any ideas and pieces I can to make my life easier. If anyone who actually uses HUDs wants to help with such an effort, please let me know.
zakalawe
 
Posts: 1152
Joined: Sat Jul 19, 2008 4:48 pm
Location: Edinburgh, Scotland
Callsign: G-ZKLW
Version: next
OS: Mac

Re: Canvas HUD : how to rotate+translate

Postby Flying toaster » Sun Jan 06, 2013 3:59 pm

TheTom wrote in Sun Jan 06, 2013 10:14 am:You should probably change the order of creating the transforms for pitch and roll as normally one would rotate first and then move according to roll and then move according to pitch up and down. Keep in mind that rotations always happens around the origin of the local coordinate frame of the object being rotated. For a rotation around another point you would need to move the object first until the center coincides with the local origin then rotate and afterwards move back. Instead of applying three transformations there exists a shortcut to pass the center of rotation as second argument to setRotation.

Actually, if you want the ladder to rotate around the center of the HUD, you would need first to make the pitch translation and then the roll translation around the center of the HUD. But anyway the order of the transformations do not seem to be working anyway on my issue.

TheTom wrote in Sun Jan 06, 2013 10:14 am:To further shorten the code an especially to allow rotating objects imported from SVG there exists setRotation also for canvas Elements (not only Transformation) and additionally setCenter which instead of passing the center as an argument sets the center which is being used while calling setRotation on this element. setCenter only affects setRotation of this not object but not for any matrix added with createTransform. If you set the center of rotation in Inkscape (switch to rotate mode and drag the cross to the center of rotation) it is automatically loaded with setCenter so you just need to call setRotation and automatically get a rotation around the correct center.

I also tried many times to use the shortcut for the element instead of the transform, only to stumble again.
Regarding the use of the center of rotation in Inkscape, It does not bring any change. On the other hand this could be expected since this center of rotation is rather a GUI helper for inkscape rather than core SVG as shown in the following piece from the inkscape SVG
Code: Select all
    <g
       id="ladder"
       inkscape:transform-center-y="-3.1326595"
       inkscape:transform-center-x="0.1894036">


The weirdest phenomenon is that the coordinates I found for the "center" of the ladder (256, -12 ... or at least this is where a setCenter will give the best results) have nothing to do whatsoever with the original SVG file (where the center is at absolute coordinates 118, 37). Still beats me.

TheTom wrote in Sun Jan 06, 2013 10:14 am:You don't need to care about tf[0] being reserved as it only reserves the index 0 and doesn't affect anything if not used. createTransform creates a new matrix with the next unused index starting at 1 (0 is reserved). If you later call setRotation directly on an element a new Transform will be created but this time using tf[0] to ensure it is applied before all other matrices and therefore rotating the object around its own center before being moved around.

For the HUD I'd set the rotation center correctly inside Inkscape and later on just call ladder.setRotation to rotate for changes in the roll angle. Afterwards create a Transform and use setTranslate for changes in pitch angle.


Still searching for a root cause to all this, but at one point I am afraid it is going to be RTFS :(
Flying toaster
 
Posts: 348
Joined: Wed Nov 29, 2006 6:25 am
Location: Toulouse France

Re: Canvas HUD : how to rotate+translate

Postby TheTom » Sun Jan 06, 2013 10:53 pm

Flying toaster wrote in Sun Jan 06, 2013 3:59 pm:Regarding the use of the center of rotation in Inkscape, It does not bring any change. On the other hand this could be expected since this center of rotation is rather a GUI helper for inkscape rather than core SVG as shown in the following piece from the inkscape SVG

I'm using Inkscape for creating some of the instruments/displays I'm working on so I've made the SVG parser to also interpret the center of rotation. Although after looking at the code again I wonder how this could work for me. It should contain the offset of the rotation center from the real center. I think I have to check if it works just by chance for my used files or if it works for more general cases too (Currently I'm only using it for simple lines used as dials inside gauges).

Also I've not done every aspect of SVG. Only really basic things are parsed and more complex things just ignored. Currently it supports everything I need, if there is need for more just shout and I'll see if we can support it :)

Flying toaster wrote in Sun Jan 06, 2013 3:59 pm:Still searching for a root cause to all this, but at one point I am afraid it is going to be RTFS :(

setRotation really just combines a rotation with two translations -> translate(-center[0], -center[1]) * rotate * translate(center[0], center[1])

You can also have a look in the property browser and check the bounding box (/canvas/by-index/texture[i]/[group[j]+]/path[j]/bounding-box) and use its coordinates to determine the correct center of rotation.

If you want you can give me a working example and I'll have a look at it.
TheTom
 
Posts: 321
Joined: Sun Oct 09, 2011 10:20 am

Re: Canvas HUD : how to rotate+translate

Postby Flying toaster » Mon Jan 07, 2013 9:37 pm

Interestingly enough the bounding box for a SVG group (<g>) generated by inkscape is ... 0,0,0,0 ! ... Might explain a few things if not everything.
I am using groups because it allows moving the whole pitch ladder rather than individual bits arounds.
It may have the extra benefit of hierarchical animation even though, right now, I am not quite sure it works (haven't tried though).
You can find a link to the current version of the aircraft (and HUD) in this post

Thanks once more for the help

Enrique
Flying toaster
 
Posts: 348
Joined: Wed Nov 29, 2006 6:25 am
Location: Toulouse France

Re: Canvas HUD : how to rotate+translate

Postby TheTom » Mon Jan 07, 2013 10:19 pm

Flying toaster wrote in Mon Jan 07, 2013 9:37 pm:Interestingly enough the bounding box for a SVG group (<g>) generated by inkscape is ... 0,0,0,0 ! ... Might explain a few things if not everything.

I meant the boundingbox inside FlightGear, but never mind - for groups is currently no bounding box exposed at all.

Flying toaster wrote in Mon Jan 07, 2013 9:37 pm:I am using groups because it allows moving the whole pitch ladder rather than individual bits arounds.

Right, without groups it would be a very tedious task ;)

The correct center is approximately (117, 832). (Open the XML-Editor inside Inkscape and have a look at the path definition 'd'. It tells you the coordinates used)

Using the same center than specified inside Inkscape has now moved upwards on my todo list. Meanwhile please just have a look at the path coordinates :)
TheTom
 
Posts: 321
Joined: Sun Oct 09, 2011 10:20 am

Re: Canvas HUD : how to rotate+translate

Postby TheTom » Wed Jan 09, 2013 12:07 pm

Support for inkscape-center-x/y should now be fixed. Call 'updateCenter' once to get the correct center calculated and afterwards just use setRotation as before:

Code: Select all
# init
var ladder = eng.getElementById("ladder").updateCenter();

# update
ladder.setRotation(roll_rad);
TheTom
 
Posts: 321
Joined: Sun Oct 09, 2011 10:20 am

Re: Canvas HUD : how to rotate+translate

Postby Gijs » Fri Jul 12, 2013 9:42 pm

Is there a particular reason why we have to explicitly call the function? Would be nice if it would automatically retrieve the center. I think it's far more likely for any random rotation to apply around the center of an object than around the origin of the canvas...
Airports: EHAM, EHLE, KSFO
Aircraft: 747-400
User avatar
Gijs
Moderator
 
Posts: 9362
Joined: Tue Jul 03, 2007 2:55 pm
Location: Amsterdam/Delft, the Netherlands
Callsign: PH-GYS
Version: Git
OS: Windows 10

Re: Canvas HUD : how to rotate+translate

Postby TheTom » Mon Jul 15, 2013 9:02 pm

I'm not quite sure what was the exact reason. I've now changed it to update the center automatically if the according properties are set in the svg file.

Gijs wrote in Fri Jul 12, 2013 9:42 pm:I think it's far more likely for any random rotation to apply around the center of an object than around the origin of the canvas...

But is the center the origin of the object coordinate system (which is how transformations in any 2d/3d environment work) or the center of the objects bounding box/sphere etc. (which is not necessarily unique)?
TheTom
 
Posts: 321
Joined: Sun Oct 09, 2011 10:20 am

Re: Canvas HUD : how to rotate+translate

Postby Flying toaster » Sun Sep 08, 2013 7:31 pm

at long last I made it work (on version 2.12rc)
Still an issue when using Rembrandt (at first I thought it was an interference with bloom but deactivating it does not change a lot):
Image
Image
In general Rembrandt messes up the colors of any material that is emissive.
Any thought on how to compensate for that ?
Flying toaster
 
Posts: 348
Joined: Wed Nov 29, 2006 6:25 am
Location: Toulouse France

Re: Canvas HUD : how to rotate+translate  

Postby Flying toaster » Tue Oct 29, 2013 6:48 pm

Fixed the rembrandt issue... To my real shame.
The rectangle on which the canvas was drawn was not registered as a transparent object
The fix is adding the following code in the cockpit object file
Code: Select all
<effect>
 <inherits-from>Effects/model-transparent</inherits-from>
...
 <object-name>HudImage</object-name>
</effect>
Flying toaster
 
Posts: 348
Joined: Wed Nov 29, 2006 6:25 am
Location: Toulouse France


Return to Canvas

Who is online

Users browsing this forum: No registered users and 1 guest