-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathindex.js
54 lines (48 loc) · 2.26 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
// this function converts rotation angles to forward and up vectors
// we use the aircraft terms – HEADING, PITCH, ROLL – to denote axes of rotation
// https://en.wikipedia.org/wiki/Aircraft_principal_axes
//
// we use trigonometric functions to establish relationships between the vectors
// and ensure they each circumscribe a sphere as they rotate
const principalAxesToOrientation = (y = 0, p = 0, r = 0) => {
const { yaw = 0, pitch = 0, roll = 0 } = typeof y === 'object'
? y
: { yaw: y, pitch: p, roll: r };
// vector determining which way the listener is facing
const forward = {};
// vector determining the rotation of the listener's head
// where no rotation means the head is pointing up
const up = {};
// Yaw (a.k.a. heading) is the rotation around the Y axis
// convert to radians first
const yawRad = yaw * (Math.PI / 180);
// at 0 degrees, the X component should be 0
//so we calculate it using sin(), which starts at 0
forward.x = Math.sin(yawRad);
// at 0 degrees, the Z component should be -1,
// because the negative Z axis points *away from* the listener
// so we calculate it using cos(), which starts at 1
// with a phase shift of 90 degrees (or PI radians)
forward.z = Math.cos(yawRad + Math.PI);
// Pitch is the rotation around the X axis
// we can use it to calculate both vectors' Y components
const pitchRad = pitch * (Math.PI / 180);
// Forward Y component should start at 0
forward.y = Math.sin(pitchRad);
// Up Y component should start at 1 (top of the head pointing up)
up.y = Math.cos(pitchRad);
// Roll is the rotation around the Z axis
const rollRad = roll * (Math.PI / 180);
// both X and Y components should start at 0
// (top of the head pointing directly upwards)
up.x = Math.sin(rollRad);
up.z = Math.sin(rollRad);
return { forward, up };
};
const calculateListenerOrientation = principalAxesToOrientation;
// PannerNode orientation is a special case where there's no pitch rotation,
// i.e. we only calculate the `forward` vector, and we take into account that
// by default, the panner is pointing to the right
const calculatePannerOrientation = (yaw, pitch) =>
principalAxesToOrientation(yaw, pitch).forward;
module.exports = { calculatePannerOrientation, calculateListenerOrientation };