Daniel Haehn PRO
Hi, I am a biomedical imaging and visualization researcher who investigates how computational methods can accelerate biological and medical research.
ReRank
DeepSee
Patrick Cozzi and Liz Dailey
Updates coming!
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
implement this in python and show that 0,-2,2,2 is the output!
~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
implement this in python and show that 0,-2,2,2 is the output!
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
How would you encode "2" as rgba?
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
Let's do it!!!
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
By Daniel Haehn
Hi, I am a biomedical imaging and visualization researcher who investigates how computational methods can accelerate biological and medical research.