# [cairo] Rotations with Quaternions

Bill Spitzak spitzak at gmail.com
Mon Jan 22 20:33:55 UTC 2018

```I had some nice images that made the message too big, but actually arrived
at some conclusions that don't use the images anyway. Basically my thoughts
on this:

1. Although only a 3x3 matrix is needed to specify an perspective
transform, if you want to use 3D rotations you need to use 4x4 matrix. This
is because the result of a rotation depends on the position of the camera
from the rotation origin and also the projection (ie fov) being used, and
describing that requires more than 9 numbers. I feel supporting 4x4 matrix
is not a good idea and thus supporting 3D rotations is not a good idea.

2. It looks like perspective could be supported by premultiplying by the
matrix [[1 0 0] [0 1 0] [px py 1]] (in row-major order such that
cairo_matrix_t is [[xx xy x0] [yx yy y0] [0 0 1]]. px is 1/x where x is the
location of the vanishing point on the x axis, and py is 1/y for the y
axis. I think Cairo needs to track the w and not normalize after each
matrix multiply.

3. It may be useless to specify z in 3D transforms. At first I thought it
was completely useless, but it does appear that multiplying the matrix by
[x y z] produces movement that looks perpendicular to the xy plane where
z=1 is the plane, while z=0 is the distance the camera is from the plane.

4. Perspective produces all kinds of questions about font and line width.
IMHO it should *not* be applied to these, as the result is the same as what
could be achieved by drawing a surface and the projecting that. Also it
would break every stroke and font optimization.

5. I then concluded that a far more useful api is that perspective *only*
changes the mapping of source images and has no effect on anything else.
This limits it to what I think is the only useful part of 3D transforms. A
proposed method that would be useful to a lot of software is to allow four
(I incorrectly said 3) xy->uv pairs to be specified. These say that the
position uv in the source lands at xy in the CTM. This would allow a client
to do it's own 3d transforms and then correctly texture-map a quad by
setting the uv of the corners. You could also do three xy->uvw mappings
which would allow a client to texture-map a triangle.

On Fri, Jan 19, 2018 at 3:36 PM, Bryce Harrington <bryce at osg.samsung.com>
wrote:

> On Wed, Jan 10, 2018 at 02:13:39PM -0500, cecashon at aol.com wrote:
> >
> >
> > Hi Bryce,
> >
> > A 3x3 matrix should might work for quaternion rotations. In the sample
> > code this is reduced to a 2x2 matrix, or four variables for each
> > circle rotation, by using initial reference points but that wouldn't
> > work in general to preserve rotations. There would be a need to keep
> > the z component of a plane to make the rotations additive. If you
> > assumed z=0 then a first rotation would work but not a second or it
> > wouldn't work as expected.
> >
>
> The code I've been hacking on adds to Cairo a 3x3 matrix with the 9th
> element fixed to 1 (so effectively is an 8-element matrix).  If that
> last element is needed, it shouldn't be too hard to add in subsequently;
> I've hidden the matrix definition internally so it'd be no API break to
> change, just making sure all the math accounts for the transformation.
>
> > This probably is something difficult to add to Cairo. There are a lot
> > of places that the cairo_matrix_t touches in the code. Also I think
> > there would be a need for a new matrix for quaternion rotations and if
> > that is done then you run into further difficulties such as the order
> > of matrix multiplication. A lot of speculation at this point.
>
> Yes, it is proving to be rather difficult.  Actually, just expanding the
> cairo_matrix_t definition to include projection wasn't too bad, but
> keeping the cairo_matrix_t API intact and adding projection as a new
> matrix type is rather invasive - everywhere that uses cairo_matrix_t
> needs updated to handle a cairo_matrix3_t.
>
> But, I'm working my way through it, and I think once that's in place
> then I think the quaternion rotation is doable.  Since internally Cairo
> assumes a 2D surface (Z=0), perhaps some flattening operation would
> allow using 9-elements externally and avoid a lot of logical mess by
> using 8 internally.
>
> > I got going on this to figure out 3d rotations using Cairo's api. I
> > could get some special case rotations in 3d but not something that
> > would work for a gyro. Working on putting together a little gyro
> > widget with Cairo and GTK.
> >
> > I am not familiar with the internals of Cairo. I have looked around a
> > little but I don't have a test setup with the current version. Do you
> > have any suggestions for putting together a test setup? I would be
> > interested in getting a test build set up that I could experiment
> > with. Also to take a look at what you have going with projections.
>
> Depends on what operating system you're on.
>
> If you're on Linux it's just `apt-get build-dep libcairo2-dev` or the
> equivalent for your distro to install the build dependencies, checkout
> the code from git, and build it.  See INSTALL and README.
>
> There's more tips on the download page and elsewhere, although can't
> vouch for how current the directions are:
>
>     https://cairographics.org/end_to_end_build_for_win32/
>
> For experimenting with the matrix code, the good thing is that even just
> the image backend will be suitable, so don't have to worry about driver
> issues at least.  :-)
>
> Bryce
> --
> cairo mailing list
> cairo at cairographics.org
> https://lists.cairographics.org/mailman/listinfo/cairo
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.cairographics.org/archives/cairo/attachments/20180122/b63d68ed/attachment.html>
```