- Assignment 3 reminder.
- Assignment 4.

Last class we introduced a model of a graphical object that has three parts:

- A basic object that fits within a unit square.
- A transformation matrix.
- The inverse of the transformation matrix.

Suppose the object is defined by N points,

- or equivalently by 1 point and N-1 vectors.

We define it transformation matrix as follows

- Each of the the points/vectors is multiplied by the modelling matrix
Mm.
- The object now has its origin at the origin of screen coordinates.

- Rotate the object until its coordinate axes, which are vectors,
coincide with the coordinate axes of the super-object.
- Translate the object to make its origin coincide with the highest level super-object of which it is a part.
- The matrix is now Mt1
***Mr1***Mm

- Repeat level by level until you get to the level of the object itself
- The matrix is now Mtj*Mrj*Mt(j-1)*Mr(j-1)*...*Mt1*Mr1*Mm
- This is used for drawing.

- The inverse matrix is Mminv*Mr1inv*Mt1inv*...*Mrjinv*Mtjinv.
- This is used for picking

- Translation
- dx, dy - how far to translate in each direction

- Rotate
- x, y - the centre of the rotation (its fixed point)
- theta - the angle of rotation
Hint. In the math.h function sin(t) t is measured in radians.

- Basic matrix rotates about the origin.

- Scale
- x, y, m - the line perpendicular to the direction of scaling (its fixed points)
- s - the amount of scaling that occurs.
- Basic matrix scales along the x-axis, perpendicular to the y-axis.

- Reflection
- x, y, m - the line in which reflection occurs (its fixed points)
- Basic matrix reflects in the y-axis.

Each of the parameters of every transformation must be obtained (usually from the user) in order to update the model.

Interface

- We need to get four numbers

Remember the basic scaling matrix

- It scales along the x-axis; its fixed points are the y-axis.
- points move parallel to the x-axis;
- the farther from the y-axis, the farther they move.

- To scale generally we will obtain four parameters that determine the
transformation
- x, y, m, s

How do we use these parameters to obtain the right transformation matrix?

- Transform the line to coincide with the y-axis
- Use s to scale along the x-axis
- Transform back to the original coordinate system

- Transform the line to coincide with the y-axis
- x, y is on the line, so translate x, y to the origin.
Now the line goes through the origin.

- m is the slope of the line, dy/dx.
m is tan(t) where t is the angle the line makes with the x-axis.

(90 - t is the angle the line makes with the y-axis.)

Rotate the line into the y-axis

Hint. There are two choices for the angle t. (See atan() in the math library.) Which choice you make has a profound affect on the operation of the user interface for scaling. Please understand what it is and make you interface with a considered answer to this problem.

- x, y is on the line, so translate x, y to the origin.
- Scale using the basic scaling matrix.
- Invert the transformations that brought the line into the y-axis.

What we've been doing is based on linear algebra. (Really affine algebra.)

- It is linear because it commutes with linear operations
- point/vector addition,
- vector scalar multiplication

Drawing a line is a linear operation on its end points.

- We can transform the end points,
then draw, and

- the entire line goes to the `right' place.
`Right' means `where the user expects'.

Thus, we can draw an object made of straight lines by

- tranforming the end points of the lines,
- then drawing lines that connect them

This does not work for curves, like ellipses

- Why?
- What can you do instead?

When we draw on the screen we use the painter's algorithm

for ( backmost to frontmost ) { draw( whatever ); }

`whatever' consists of two parts

- a basic shape
- a transformation

- In assignment 5 you see code specifically designed to draw a square,
which would occur in a draw procedure like
void draw( whatever ) { switch ( whatever.type ) { case square : drawSquare( whatever.transform ); ... } }

This code takes advantage of commutation between interpolation (for drawing the inside and the edges) and transformation (for finding the ends of the edges).

- This code pretty obviously generalizes to convex polygon drawing. And
convex polygon drawing is easy to put into graphics hardware.
- Put the transform into a hardware matrix multiplier.
- Push the vertices through one after another.
- Pipeline the vertices straight to interpolation hardware.
- Scan convert to get the fill, if desired.

Picking has two variations

- Select topmost versus select all.
- Select with point versus select with area.

Picking is strongly related to drawing

for ( frontmost to backmost ) { if ( inside( whatever ) ) { select( whatever ); } }

- The inside test is also strongly related to the drawing code.
- draw - find the points inside a shape.
- inside - find if a point is inside a shape.

Both drawing and picking must be fast.

- Drawing must meet limits imposed by perception of simultaneity.
- Picking happens when the user's attention is focussed at the pointer.
We must complete

- picking
- redrawing

fast enough that the user perceives no lag.

Three important ideas to speed up picking. Remember that almost all inside tests fail so failing fast is important.

- Inside tests that are ANDs can terminate at the first failure. E.g.
Each line segment generates a half-plane test.
(Not necessarily true in hardware.)

- Make most failures fast. E.g. first test against a bounding rectangle.
- Skip most of the failing tests. E.g. use an auxiliary data structure like a quad-tree.

How do we apply these ideas to testing for inside a Jinn's bottle?

Return to: