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!