DAY 14
0
Modern Web

## 使相機看著目標

### `matrix4.lookAt()`

``````matrix4.lookAt(
cameraPosition,
target,
up,
)
``````

``````[
?, ?, ?, 0,
?, ?, ?, 0,
?, ?, ?, 0,
cameraPosition.x, cameraPosition.y, cameraPosition.z, 1,
]
``````

``````export const matrix4 = {
// ...
subtractVectors: (a, b) => ([
a[0] - b[0], a[1] - b[1], a[2] - b[2]
]),
cross: (a, b) => ([
a[1] * b[2] - a[2] * b[1],
a[2] * b[0] - a[0] * b[2],
a[0] * b[1] - a[1] * b[0],
]),
normalize: v => {
const length = Math.sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
// make sure we don't divide by 0.
if (length > 0.00001) {
return [v[0] / length, v[1] / length, v[2] / length];
} else {
return [0, 0, 0];
}
},
// ...
}
``````

``````export const matrix4 = {
// ...
lookAt: (cameraPosition, target, up) => {
const kHat = matrix4.normalize(
matrix4.subtractVectors(cameraPosition, target)
);
const iHat = matrix4.normalize(matrix4.cross(up, kHat));
const jHat = matrix4.normalize(matrix4.cross(kHat, iHat));

return [
iHat[0], iHat[1], iHat[2], 0,
jHat[0], jHat[1], jHat[2], 0,
kHat[0], kHat[1], kHat[2], 0,
cameraPosition[0],
cameraPosition[1],
cameraPosition[2],
1,
];
},
// ...
}
``````

### 使用 `matrix4.lookAt()`

``````const cameraMatrix = matrix4.lookAt([250, 0, 400], [250, 0, 0], [0, 1, 0]);
``````

### 移動相機

`````` // async function setup() {
// ...
return {
gl,
program, attributes, uniforms,
buffers, modelBufferArrays,
state: {
fieldOfView: 45 * Math.PI / 180,
translate: [150, 100, 0],
scale: [1, 1, 1],
+      cameraPosition: [250, 0, 400],
+      cameraVelocity: [0, 0, 0],
},
time: 0,

};
``````

`render()` 中讓 `matrix4.lookAt()` 串上剛建立的狀態：

``````-  const cameraMatrix = matrix4.lookAt([250, 0, 400], [250, 0, 0], [0, 1, 0]);
+  const cameraMatrix = matrix4.lookAt(state.cameraPosition, [250, 0, 0], [0, 1, 0]);
``````

``````function startLoop(app, now = 0) {
const timeDiff = now - app.time;
app.time = now;

app.state.cameraPosition[0] += app.state.cameraVelocity[0] * timeDiff;
app.state.cameraPosition[1] += app.state.cameraVelocity[1] * timeDiff;
app.state.cameraPosition[2] += app.state.cameraVelocity[2] * timeDiff;
document.getElementById('camera-position').textContent = (
`cameraPosition: [\${app.state.cameraPosition.map(f => f.toFixed(2)).join(', ')}]`
);

render(app, timeDiff);
requestAnimationFrame(now => startLoop(app, now));
}
``````