Next Tuesday via Zoom!

Transformations

Translate

Rotate

Scale

Frame of Reference

X

Y

Z

World Frame

Frame of Reference

X

Y

Z

Object Frame

Frame of Reference

X

Y

Z

Object Frame

Frame of Reference

X

Y

Z

Eye Frame

Camera

(Eye)

cos(T)   -sin(T)   0   0

sin(T)   cos(T)   0    0

    0          0        1    0

    0          0       0     1

rotation around Z

cos(T/2)

sin(T/2) * 0

sin(T/2) * 0

sin(T/2) * 1

Matrix

Quaternion

w

x

y

z

with angle T

cos(T)   -sin(T)   0   0

sin(T)   cos(T)   0    0

    0          0        1    0

    0          0       0     1

2, 2, 2

with T = Pi/2

0

0

1

2 Pi

Pi

Pi/2

1.5 Pi

-1

-2, 2, 2

cos(T/2)

sin(T/2) * 0

sin(T/2) * 0

sin(T/2) * 1

Quaternion

w

x

y

z

~0.7

~0.7

0

0

Pi/2 /2 == Pi/4

~0.7

0

0

~0.7

0

2

2

2

w

x

y

z

*

Quaternion

?

~0.7

0

0

~0.7

0

2

2

2

*

~0.7

- 0

- 0

- ~0.7

Inverse

page 64, Gortler: 3D Computer Graphics

~0.7

0

0

~0.7

0

2

2

2

w

x

y

z

*

Quaternion

~0.7

0

0

~0.7

0

2

2

2

*

~0.7

- 0

- 0

- ~0.7

Inverse

page 64, Gortler: 3D Computer Graphics

  0

- 2

  2

  2

sin(T/2) * 0

sin(T/2) * 0

sin(T/2) * 1

cos(T/2)

Quaternion

x

y

z

w

T is the angle

0 0 1 is the axis

var q = new THREE.Quaternion( x, y, z, w );
var q = new THREE.Quaternion( 1, 1, 1, 1 );

1 = sin( ? /2) * ?

1 = sin( ? /2) * ?

1 = sin( ? /2) * ?

1 = cos( ? /2)

x

y

z

w

0

0

1

2 Pi

Pi

Pi/2

1.5 Pi

-1

sin(T/2) * 0

sin(T/2) * 0

sin(T/2) * 1

cos(T/2)

Quaternion

x

y

z

w

T is the angle

0 0 1 is the axis

var q = new THREE.Quaternion( x, y, z, w );
var q = new THREE.Quaternion( sin( T / 2 ) * x , 
                              sin( T / 2 ) * y , 
                              sin( T / 2 ) * z , 
                              cos( T / 2 ) );

0

0

1

2 Pi

Pi

Pi/2

1.5 Pi

-1


      function animate() {

        requestAnimationFrame( animate );

        for (var t in window.ALL_TORUSES) {


          t = ALL_TORUSES[t];

          var T = Math.PI / 2; // 180 degrees

          // around the y axis
          var x = Math.sin( T / 2 ) * 0; // = 0
          var y = Math.sin( T / 2 ) * 1;
          var z = Math.sin( T / 2 ) * 0; // = 0
          var w = Math.cos( T / 2 );

          var q = new THREE.Quaternion( x, y, z, w);

          t.quaternion.slerp( q, 0.01 );

        }


        // and here..
        controls.update();
        renderer.render( scene, camera );
        
      };

I almost failed highschool because of math!

var q = new THREE.Quaternion( sin( T / 2 ) * x , 
                              sin( T / 2 ) * y , 
                              sin( T / 2 ) * z , 
                              cos( T / 2 ) );

0

0

1

2 Pi

Pi

Pi/2

1.5 Pi

-1

90°

180°

270°

360°

180°

around Y-axis

T is the angle

x y z is the axis

 T = Math.PI

0, 1, 0

var q = new THREE.Quaternion( Math.sin( Math.PI / 2 ) * 0 , 
                              Math.sin( Math.PI / 2 ) * 1 , 
                              Math.sin( Math.PI / 2 ) * 0 , 
                              Math.cos( Math.PI / 2 ) );
var q = new THREE.Quaternion( sin( T / 2 ) * x , 
                              sin( T / 2 ) * y , 
                              sin( T / 2 ) * z , 
                              cos( T / 2 ) );

0

0

1

2 Pi

Pi

Pi/2

1.5 Pi

-1

90°

180°

270°

360°

270°

around Z-axis

T is the angle

x y z is the axis

 T = 1.5 * Math.PI

0, 0, 1

var q = new THREE.Quaternion( Math.sin( 1.5 * Math.PI / 2 ) * 0 , 
                              Math.sin( 1.5 * Math.PI / 2 ) * 0 , 
                              Math.sin( 1.5 * Math.PI / 2 ) * 1 , 
                              Math.cos( 1.5 * Math.PI / 2 ) );
var q = new THREE.Quaternion( sin( T / 2 ) * x , 
                              sin( T / 2 ) * y , 
                              sin( T / 2 ) * z , 
                              cos( T / 2 ) );

0

0

1

2 Pi

Pi

Pi/2

1.5 Pi

-1

90°

180°

270°

360°

90°

around X-axis

T is the angle

x y z is the axis

 T = Math.PI / 2

1, 0, 0

var q = new THREE.Quaternion( Math.sin( Math.PI / 2 / 2 ) * 1 , 
                              Math.sin( Math.PI / 2 / 2 ) * 0 , 
                              Math.sin( Math.PI / 2 / 2 ) * 0 , 
                              Math.cos( Math.PI / 2 / 2 ) );

cos(T)   -sin(T)   0   0

sin(T)   cos(T)   0    0

    0          0        1    0

    0          0       0     1

2, 2, 2

with T = Pi/2

0

0

1

2 Pi

Pi

Pi/2

1.5 Pi

-1

-2, 2, 2

cos(T/2)

sin(T/2) * 0

sin(T/2) * 0

sin(T/2) * 1

Quaternion

w

x

y

z

~0.7

~0.7

0

0

Rigid Body Transformation

Quaternion

Translation Vector

w

x

y

z

x

y

z

0

Scaling

x, y, z

Euler Angles

Gimbal Lock

Quaternions fixes this!

Arcball

Trackball

Controls

OrbitControls

Arcball

Trackball

Controls

Natural Feeling

Spins twice as fast

Completely path independent

Both:

Map 2D to 3D Sphere

esay to implement with Quaternions

Picking

or unprojecting from 2D to 3D

zNear

Ray

Position (x,y,z)

Invisible Plane

raycaster = THREE.Raycaster();
raycaster.setFromCamera(vp_coords_near, camera);
intersects = raycaster.intersectObject( invisiblePlane );

Raycasting

Click to select an object

Framebuffer (hidden)

1

2

3

4

gl.readPixels

(r, g, b, a)

Object Picking

Framebuffer (hidden)

1

2

3

4

( 1, 0, 0, 1 )

( 0, 1, 0, 1 )

( 1, 1, 0, 1 )

( 0, 0, 1, 1 )

( 0, 0, 0, 1 )

gl.readPixels

(r, g, b, a)

map to object ID

( 0, 1, 0, 1 )

2

Object Picking

Object Picking

Raycasting

More complex

Quick'n'Dirty

Very precise (Face picking)

Object precision

Occlusion not a problem

Objects can be hidden

Object Picking

Raycasting

More complex

Quick'n'Dirty

Very precise (Face picking)

Object precision

Occlusion not a problem

Objects can be hidden

raycaster = THREE.Raycaster();
raycaster.setFromCamera(vp_coords_near, camera);
intersects = raycaster.intersectObject( scene.children );

Framebuffer (hidden)

1

2

3

4

( 1, 0, 0, 1 )

( 0, 1, 0, 1 )

( 1, 1, 0, 1 )

( 0, 0, 1, 1 )

( 0, 0, 0, 1 )

gl.readPixels

(r, g, b, a)

map to object ID

( 0, 1, 0, 1 )

2

Object Picking

Sir Isaac Newton 1666

r    g    b    a

alpha

0: fully transparent

     ....

255: fully opaque

0: minimum

     ....

255: maximum

red

green

blue

All image formats (PNG, JPEG, BMP...)

4 channels

r    g    b    

0: minimum

     ....

255: maximum

red

green

blue

All image formats (PNG, JPEG, BMP...)

3 channels

g

0: minimum

     ....

255: maximum

grayscale

All image formats (PNG, JPEG, BMP...)

1 channel

r    g    b    a

alpha

0: fully transparent

     ....

255: fully opaque

0: minimum

     ....

255: maximum

red

green

blue

Three.js

r    g    b    a

alpha

0: fully transparent

     ....

1: fully opaque

0: minimum

     ....

1: maximum

red

green

blue

XTK or GLSL

#000000

#ffffff

minimum

maximum

Hex

#00000000

#ffffffff

minimum

maximum

Hex8

alpha

alpha

HSL

H:

S:

L:

Hue

Saturation

Lightness

0/360°

180°

240°

65%

40%

0%

100%

0%

100%

hsl(240, 65%, 40%)

rgb(36, 36, 168)

#2424a8

Gamut

range of colors in an imaging system

r    g    b    a

alpha

0

 :

255

red

green

blue

0

 :

255

0

 :

255

0

 :

255

1 byte

1 byte

1 byte

1 byte

connect XTK or Three.js with Tweakpane!

$ python -m http.server
$ cd 05/
$ git pull
<script type="module">
  
// ...

  
import { AnaglyphEffect } from 'three/addons/effects/AnaglyphEffect.js';
  
let effect; 
 
// ...
 
effect = new AnaglyphEffect( renderer );
effect.setSize( window.innerWidth, window.innerHeight );

// ...

function animate() {

  // ...

  effect.render( scene, camera ); // replace renderer. with effect.

  // ...

}

</script>

submit your music

Quiz due today!