[cairo] The right approach to projective transformations

Bill Spitzak spitzak at gmail.com
Tue Aug 31 10:48:41 PDT 2010

M Joonas Pihlaja wrote:
> On Mon, 30 Aug 2010, Behdad Esfahbod wrote:
>> I think if we are doing this projective thing, we should finally switch to an
>> opaque transformation struct.  This allows for the transformation to be
>> intelligently caching.  Cache the inverse, cache the determinant, cache
>> whether it's an integer translation only, etc.
> I think we can do this without making the existing transform API 
> obsolete.  Factor the complete mapping into two parts: a 2d affine map 
> followed by a more powerful projective map, and the existing transform 
> calls only work on the 2d affine part.  Existing client rendering 
> routines can then pretend they're drawing onto a normal plane as 
> before, even if that plane is twisted about later by a projective 
> part.

That is exactly what the proposed 3x3 matrix does. The existing 2D 
transforms can be easily converted to 3x3 matrix by adding a bottom row 
of 0,0,1 and multiplied by the existing one, and will then concatentate 
and produce the desired result.

You can't split this into "two steps" because otherwise attempts to do 
2D translations after a 3D transform are set up will not produce the 
desired result. For instance, Cairo functions will expect that drawing a 
0,0,1,1 square at a .5 scale will produce the same image as drawing a 
0,0,.5,.5 square. If you do "two steps" then the .5 scale would produce 
the result of doing the .5 scale *before* the perspective transform and 
thus produce a different result.

Also I am pretty certain that you cannot do this in any more efficient 
way than a 3x3 matrix multiply. Flags indicating aspects of the matrix 
contents (such as the bottom row being 0,0,1) can be used to skip 
multiplies to speed it up. But the basic algorithm is a 3x3 matrix.

More information about the cairo mailing list