Skip to content

Latest commit

 

History

History
445 lines (334 loc) · 14.6 KB

File metadata and controls

445 lines (334 loc) · 14.6 KB

Themes

Set your presentation theme:
Black (default) - White - League - Sky - Beige - Simple
Serif - Blood - Night - Moon - Solarized

H:

SceneGraphs

Jean Pierre Charalambos
Universidad Nacional de Colombia
Presentation best seen online
See also the source code

H:

Index

  1. Intro
    • Active vs pasive transformations
    • Composition
    • Main spaces
  2. Modelling and view
  3. Matrix handling in the p5.treegl framework
  4. References

H:

Intro: Active vs passive transformations

Active Transformation (standard basis) vs Passive Transformation (change of basis)

  1. Check the p5 transformations tutorial first
  2. Check also the affine transformations presentation

N:

  • Standard = Canonical

V:

Intro: Affine transformations composition

Consider the following sequence of transformations:

$P_1=M_1P,$ $P_2=M_1M_2P_1,$ $...,$ $P_n=M_n^*P$

where $M_n^*=M_1M_2...M_n$

Observation: The above composed transform may be implemented either with low-level matrix multiplication (applyMatrix(matrix)) or with mid-level functions such as: translate(), rotate(), scale().

H:

Modelling and view

Consider the function axes() which draws the X (horizontal) and Y vertical) axes:

function axes() {
  push();
  // X-Axis
  strokeWeight(4);
  stroke(255, 0, 0);
  fill(255, 0, 0);
  line(0, 0, 100, 0);//horizontal red X-axis line
  text("X", 100 + 5, 0);
  // Y-Axis
  stroke(0, 0, 255);
  fill(0, 0, 255);
  line(0, 0, 0, 100);//vertical blue Y-axis line
  text("Y", 0, 100 + 15);
  pop();
}

V:

Modelling and view

let's first call the axes() function to see what it does:

function draw() {
  background(50);
  axes();
}

V:

Modelling and view

now let's call it again, but pre-translating it first:

function draw() {
  background(50);
  axes();
  translate(300, 180);//translation
  axes();//2nd call
}

V:

Modelling and view

let's add a rotation to the second axes() call:

function draw() {
  background(50);
  axes();
  translate(300, 180);
  rotate(QUARTER_PI / 2);//rotation after translation
  axes();//2nd call
}

V:

Modelling and view

let's do something similar with a third axes() call:

function draw() {
  background(50);
  axes();
  translate(300, 180);
  rotate(QUARTER_PI/2);
  axes();
  translate(260, -180);
  rotate(-QUARTER_PI);
  scale(1.5);//even scaling it
  axes();//3rd call
}

V:

Modelling and view

see the result when we animate only the first rotation;

function draw() {
  background(50);
  axes();
  translate(300, 180);
  rotate(QUARTER_PI/2 * frameCount);//animation line
  axes();
  translate(260, -180);
  rotate(-QUARTER_PI);
  scale(1.5);
  axes();
}

V:

Modelling and view

and now see the result when we animate only the second rotation;

function draw() {
  background(50);
  axes();
  translate(300, 180);
  rotate(QUARTER_PI/2);
  axes();
  translate(260, -180);
  rotate(-QUARTER_PI * frameCount);//animation line
  scale(1.5);
  axes();
}

V:

Modelling and view: Scene-graph

A scene-graph is a directed acyclic graph (DAG) of nodes which root is the world coordinate system

V:

Modelling and view: Scene-graph

Eyeless example

 World
  ^
  |
 L1
  ^
  |\
 L2  L3

Scenegraphs are simply and elegantly implemented by means of affine transformations using a matrix stack. See push() and pop()

V:

Modelling and view: Scene-graph

Eyeless example

 World
  ^
  |
 L1
  ^
  |\
 L2  L3
function drawModel() {
  // define a local node L1 (respect to the world)
  push(); // saves current matrix transform (I)
  affineTransform1(); // resulting in: I * affineTransform1()
  drawL1();
  // define a local node L2 respect to L1
  push(); // saves current matrix transform (I * affineTransform1())
  affineTransform2(); // resulting in: I * affineTransform1() * affineTransform2()
  drawL2();
  // "return" to L1
  pop(); // removes the top of the stack, restoring I * affineTransform1()
  // define a local coordinate system L3 respect to L1
  push(); // saves current matrix transform (I * affineTransform1())
  affineTransform3(); // resulting in: I * affineTransform1() * affineTransform3()
  drawL3();
  // return to L1
  pop(); // removes the top of the stack, restoring I * affineTransform1()
  // return to World
  pop(); // removes the top of the stack, restoring I
}

V:

Modelling and view: Scene-graph

Eyeless example

V:

Modelling and view: Scene-graph

View transform (eye-node)

 World
  ^
  |\
... Eye
  ^
  |\
... ...

Let the eye node transform be defined, like it is with any other node, as: $M_{eye}^*$

The eye transform is therefore: $\left.M_{eye}^{*}\right.^{-1}$

For example, for an eye node transform: $M_{eye}^*=T(x,y,z)R(\beta)S(s)$

The eye transform would be: $\left.M_{eye}^{*}\right.^{-1}=S(1/s)R(-\beta)T(-x,-y,-z)$

N:

$M_{eye}^*$ would position (orient, scale, ...) the eye node in the world, but want it to be the other way around (i.e., draw the scene from the eye point-of-view)

V:

Modelling and view: Scene-graph

View example

 World
  ^
  |\
 L1 Eye
  ^
  |\
 L2  L3
function draw() {
  // the following sequence would position (orient, scale, ...) the eye node in the world:
  // translate(eyePosition.x, eyePosition.y);
  // rotate(eyeOrientation);
  // scale(eyeScaling)
  // drawEye();
  scale(1/eyeScaling);
  rotate(-eyeOrientation);
  translate(-eyePosition.x, -eyePosition.y);
  drawModel();
}

V:

Modelling and view: Scene-graph

View example

H:

Matrix handling in p5.treegl

Intro: Geometry data mapping

  • The model matrix ($M$) maps from (object) node space to world space
  • The view matrix ($V$) maps from world space to eye space
  • The projection ($P$) matrix maps from eye space to clip space

Composing all three, i.e., $P * V * M$, would thus map from object space to clip space

V:

Matrix handling in p5.treegl

Intro: Matrix stack naming conventions

  1. When the bottom of the matrix stack is filled with the identity matrix ($I$), its top is referred to as the model matrix
  2. When the bottom of the matrix stack is filled with the view matrix ($V$), its top is referred to as the modelview matrix

V:

Matrix handling in p5.treegl

  1. iMatrix(): Returns the identity matrix.
  2. tMatrix(matrix): Returns the tranpose of matrix.
  3. invMatrix(matrix): Returns the inverse of matrix.
  4. axbMatrix(a, b): Returns the product of the a and b matrices.
  5. lMatrix(from, to): Returns the 4x4 matrix that transforms locations (points) from matrix from to matrix to.
  6. dMatrix(from, to): Returns the 3x3 matrix that transforms displacements (vectors) from matrix from to matrix to. The nMatrix below is a special case of this one.

Observation: All returned matrices are instances of p5.Matrix.

V:

Matrix handling in p5.treegl

  1. treeLocation(vector, [{[from = SCREEN], [to = WORLD], [pMatrix], [vMatrix], [eMatrix], [pvMatrix], [pvInvMatrix]}]): transforms locations (points) from matrix from to matrix to.
  2. treeDisplacement(vector, [{[from = EYE], [to = WORLD], [vMatrix], [eMatrix], [pMatrix]}]): transforms displacements (vectors) from matrix from to matrix to.

Observations

  1. Returned transformed vectors are instances of p5.Vector.
  2. from and to may also be specified as either: 'WORLD', 'EYE', 'SCREEN' or 'NDC'.
  3. When no matrix params are passed the renderer current values are used instead.

V:

Matrix handling in p5.treegl

  1. pMatrix(): Returns the current projection matrix.
  2. mvMatrix([{[vMatrix], [mMatrix]}]): Returns the modelview matrix.
  3. mMatrix([{[eMatrix], [mvMatrix]}]): Returns the model matrix.
  4. eMatrix(): Returns the current eye matrix (the inverse of vMatrix()). In addition to p5 and p5.RendererGL instances, this method is also available to p5.Camera objects.
  5. vMatrix(): Returns the view matrix (the inverse of eMatrix()). In addition to p5 and p5.RendererGL instances, this method is also available to p5.Camera objects.
  6. pvMatrix([{[pMatrix], [vMatrix]}]): Returns the projection times view matrix.
  7. pvInvMatrix([{[pMatrix], [vMatrix], [pvMatrix]}]): Returns the pvMatrix inverse.
  8. nMatrix([{[vMatrix], [mMatrix], [mvMatrix]}]): Returns the normal matrix.

Observations

  1. All returned matrices are instances of p5.Matrix.
  2. When no matrix params are passed the renderer current values are used instead.

V:

Matrix handling in p5.treegl

  1. lPlane([pMatrix]): Returns the left clipping plane.
  2. rPlane([pMatrix]): Returns the right clipping plane.
  3. bPlane([pMatrix]): Returns the bottom clipping plane.
  4. tPlane([pMatrix]): Returns the top clipping plane.
  5. nPlane([pMatrix]): Returns the near clipping plane.
  6. fPlane([pMatrix]): Returns the far clipping plane.
  7. fov([pMatrix]): Returns the vertical field-of-view (fov) in radians.
  8. hfov([pMatrix]): Returns the horizontal field-of-view (hfov) in radians.

Observation: when no projection (pMatrix) matrix is passed the renderer current value is used instead.

H:

References