Decomposition into several matrices
This commit is contained in:
parent
115ab9c3c2
commit
9a05f717fc
|
@ -4,6 +4,7 @@
|
|||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>CG1 MDI</title>
|
||||
<script id="MathJax-script" async src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js"></script>
|
||||
<script src="matrix-math.js"></script>
|
||||
<script src="shader.js"></script>
|
||||
<script src="script.js"></script>
|
||||
|
@ -61,28 +62,18 @@
|
|||
#controls {
|
||||
left: 20px;
|
||||
}
|
||||
|
||||
#interpolate {
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="display">
|
||||
<canvas id="cv"></canvas>
|
||||
<div id="stats">
|
||||
FPS: <span id="fps"></span> - <span id="ms"></span>
|
||||
</div>
|
||||
|
||||
<div id="controls">
|
||||
<div>
|
||||
Click & Drag to move camera
|
||||
</div>
|
||||
<div>
|
||||
Scroll to zoom
|
||||
</div>
|
||||
<div>
|
||||
LookAt Matrix: <input type="range" min=0 max=1 step=0.01 value=0 id="interpolateLookAt" autocomplete="off">
|
||||
</div>
|
||||
<div>
|
||||
Projection Matrix: <input type="range" min=0 max=1 step=0.01 value=0 id="interpolateProjection" autocomplete="off" disabled="yes">
|
||||
<div style="margin-left: 20px;">Invert Z-Axis: <input type="checkbox" id="invertZAxis" checked autocomplete="off"></div>
|
||||
FPS: <span id="fps"></span> - <span id="ms"></span>
|
||||
</div>
|
||||
<div>
|
||||
Use virtual camera: <input type="checkbox" id="displayMatricesVirtually" checked autocomplete="off">
|
||||
|
@ -91,6 +82,62 @@
|
|||
Backface Culling: <input type="checkbox" id="backfaceCulling" autocomplete="off">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="controls">
|
||||
<div>
|
||||
$$
|
||||
\color{red}
|
||||
\begin{pmatrix}
|
||||
1 & 0 & 0 & 0 \\
|
||||
0 & 1 & 0 & 0 \\
|
||||
0 & 0 & -1 & 0 \\
|
||||
0 & 0 & 0 & 1
|
||||
\end{pmatrix}
|
||||
\begin{pmatrix}
|
||||
\frac{2}{r-l} & 0 & 0 & 0 \\
|
||||
0 & \frac{2}{t-b} & 0 & 0 \\
|
||||
0 & 0 & \frac{2}{f-n} & 0 \\
|
||||
0 & 0 & 0 & 1
|
||||
\end{pmatrix}
|
||||
\begin{pmatrix}
|
||||
1 & 0 & 0 & - \frac{r+l}{2} \\
|
||||
0 & 1 & 0 & - \frac{t+b}{2} \\
|
||||
0 & 0 & 1 & \frac{n+f}{2} \\
|
||||
0 & 0 & 0 & 1
|
||||
\end{pmatrix}
|
||||
\begin{pmatrix}
|
||||
1 & 0 & 0 & 0 \\
|
||||
0 & 1 & 0 & 0 \\
|
||||
0 & 0 & 1 + \frac{f}{n} & f \\
|
||||
0 & 0 & - \frac{1}{n} & 0
|
||||
\end{pmatrix}
|
||||
\color{green}
|
||||
\begin{pmatrix}
|
||||
u_x & u_y & u_z & 0 \\
|
||||
v_x & v_y & v_z & 0 \\
|
||||
n_x & n_y & n_z & 0 \\
|
||||
0 & 0 & 0 & 1
|
||||
\end{pmatrix}
|
||||
\begin{pmatrix}
|
||||
1 & 0 & 0 & -e_x \\
|
||||
0 & 1 & 0 & -e_y \\
|
||||
0 & 0 & 1 & -e_z \\
|
||||
0 & 0 & 0 & 1
|
||||
\end{pmatrix}
|
||||
$$
|
||||
<input id="interpolate" type="range" min="0" max="6" step="0.01" value="6" autocomplete="off" list="steplist">
|
||||
<datalist id="steplist">
|
||||
<option>1</option>
|
||||
<option>2</option>
|
||||
<option>3</option>
|
||||
<option>4</option>
|
||||
<option>5</option>
|
||||
</datalist>
|
||||
</div>
|
||||
<div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -173,6 +173,32 @@ function mat4BuildLookAt(out, eye, look, up) {
|
|||
out[2] = n[0]; out[6] = n[1]; out[10] = n[2]; out[14] = t[2];
|
||||
out[3] = 0; out[7] = 0; out[11] = 0; out[15] = 1;
|
||||
}
|
||||
function mat4BuildLookAt1(out, eye, look, up) {
|
||||
out[0] = 1; out[4] = 0; out[8] = 0; out[12] = -eye[0];
|
||||
out[1] = 0; out[5] = 1; out[9] = 0; out[13] = -eye[1];
|
||||
out[2] = 0; out[6] = 0; out[10] = 1; out[14] = -eye[2];
|
||||
out[3] = 0; out[7] = 0; out[11] = 0; out[15] = 1;
|
||||
}
|
||||
function mat4BuildLookAt2(out, eye, look, up) {
|
||||
let n = [];
|
||||
let u = [];
|
||||
let v = [];
|
||||
|
||||
vec3Subtract(n, eye, look);
|
||||
|
||||
vec3CrossProduct(u, up, n);
|
||||
|
||||
vec3CrossProduct(v, n, u);
|
||||
|
||||
vec3Normalise(n, n);
|
||||
vec3Normalise(u, u);
|
||||
vec3Normalise(v, v);
|
||||
|
||||
out[0] = u[0]; out[4] = u[1]; out[8] = u[2]; out[12] = 0;
|
||||
out[1] = v[0]; out[5] = v[1]; out[9] = v[2]; out[13] = 0;
|
||||
out[2] = n[0]; out[6] = n[1]; out[10] = n[2]; out[14] = 0;
|
||||
out[3] = 0; out[7] = 0; out[11] = 0; out[15] = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* builds a projection matrix, overwriting out
|
||||
|
@ -209,6 +235,43 @@ function mat4BuildPerspective(out, fovy, aspect, n, f) {
|
|||
|
||||
mat4BuildProjection(out, r, l, t, b, n, f);
|
||||
}
|
||||
function mat4BuildPerspective1(out, fovy, aspect, n, f) {
|
||||
mat4Identity(out);
|
||||
out[10] = 1.0 + f / n;
|
||||
out[11] = -1.0 / n;
|
||||
out[14] = f;
|
||||
out[15] = 0.0;
|
||||
}
|
||||
function mat4BuildPerspective2(out, fovy, aspect, n, f) {
|
||||
let t = n * Math.tan(0.5 * fovy);
|
||||
let b = -t;
|
||||
|
||||
let r = aspect * t;
|
||||
let l = -r;
|
||||
|
||||
mat4Identity(out);
|
||||
out[12] = -(r + l) / 2.0;
|
||||
out[13] = -(t + b) / 2.0;
|
||||
out[14] = (f + n) / 2.0;
|
||||
}
|
||||
function mat4BuildPerspective3(out, fovy, aspect, n, f) {
|
||||
let t = n * Math.tan(0.5 * fovy);
|
||||
let b = -t;
|
||||
|
||||
let r = aspect * t;
|
||||
let l = -r;
|
||||
|
||||
mat4Identity(out);
|
||||
|
||||
out[0] = 2.0 / (r - l);
|
||||
out[5] = 2.0 / (t - b);
|
||||
out[10] = 2.0 / (f - n);
|
||||
}
|
||||
function mat4BuildPerspective4(out, fovy, aspect, n, f) {
|
||||
mat4Identity(out);
|
||||
out[10] = -1.0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* linearly interpolates between a and b, storing the result in out
|
||||
|
|
|
@ -28,6 +28,8 @@ let lastFrame = Date.now();
|
|||
let interpolateProjection = 0;
|
||||
let interpolateLookAt = 0;
|
||||
|
||||
let interpolate = [0, 0, 0, 0, 0, 0];
|
||||
|
||||
let displayMatricesVirtually = true;
|
||||
let virtualRealInterpolation = 1;
|
||||
|
||||
|
@ -64,34 +66,37 @@ async function init() {
|
|||
|
||||
|
||||
// input handling
|
||||
document.getElementById("interpolateProjection").addEventListener("input", (e) => {
|
||||
interpolateProjection = e.target.value;
|
||||
if (interpolateProjection <= 0) {
|
||||
document.getElementById("interpolateLookAt").disabled = "";
|
||||
} else {
|
||||
document.getElementById("interpolateLookAt").disabled = "yes";
|
||||
document.getElementById("interpolate").addEventListener("input", (e) => {
|
||||
let t = 6.0 - e.target.value;
|
||||
if (t <= 2.0) {
|
||||
interpolateLookAt = t / 2.0;
|
||||
interpolateProjection = 0.0;
|
||||
invertZAxis = false;
|
||||
}
|
||||
});
|
||||
document.getElementById("invertZAxis").addEventListener("input", (e) => {
|
||||
invertZAxis = e.target.checked;
|
||||
});
|
||||
document.getElementById("interpolateLookAt").addEventListener("input", (e) => {
|
||||
interpolateLookAt = e.target.value;
|
||||
if (interpolateLookAt >= 1) {
|
||||
document.getElementById("interpolateProjection").disabled = "";
|
||||
} else {
|
||||
document.getElementById("interpolateProjection").disabled = "yes";
|
||||
else if (t <= 5.0) {
|
||||
interpolateLookAt = 1.0;
|
||||
interpolateProjection = (t - 2.0) / 3.0;
|
||||
invertZAxis = false;
|
||||
}
|
||||
else {
|
||||
interpolateLookAt = 1.0;
|
||||
interpolateProjection = 1.0;
|
||||
invertZAxis = true;
|
||||
}
|
||||
for (let i = 0; i < 6; ++i) {
|
||||
if (i > t) {
|
||||
interpolate[i] = 0.0;
|
||||
}
|
||||
else if (i+1 > t) {
|
||||
interpolate[i] = t - Math.floor(t);
|
||||
}
|
||||
else {
|
||||
interpolate[i] = 1.0;
|
||||
}
|
||||
}
|
||||
});
|
||||
document.getElementById("displayMatricesVirtually").addEventListener("input", (e) => {
|
||||
displayMatricesVirtually = e.target.checked;
|
||||
if (!displayMatricesVirtually) {
|
||||
document.getElementById("invertZAxis").checked = true;
|
||||
document.getElementById("invertZAxis").disabled = true;
|
||||
} else {
|
||||
document.getElementById("invertZAxis").checked = invertZAxis;
|
||||
document.getElementById("invertZAxis").disabled = false;
|
||||
}
|
||||
});
|
||||
document.getElementById("backfaceCulling").addEventListener("input", (e) => {
|
||||
if (e.target.checked) {
|
||||
|
@ -531,8 +536,37 @@ async function draw() {
|
|||
let inverseVirtualViewMatrix = [];
|
||||
mat4Inverse(inverseVirtualViewMatrix, virtualViewMatrix);
|
||||
|
||||
mat4Interpolate(virtualProjectionMatrix, identity, virtualProjectionMatrix, interpolateProjection);
|
||||
mat4Interpolate(virtualViewMatrix, identity, virtualViewMatrix, interpolateLookAt);
|
||||
// interpolated view matrix
|
||||
let virtualViewMatrix1 = [];
|
||||
mat4BuildLookAt1(virtualViewMatrix1, virtualCameraPosition, virtualCameraLookAt, virtualCameraUp);
|
||||
mat4Interpolate(virtualViewMatrix1, identity, virtualViewMatrix1, interpolate[0]);
|
||||
|
||||
let virtualViewMatrix2 = [];
|
||||
mat4BuildLookAt2(virtualViewMatrix2, virtualCameraPosition, virtualCameraLookAt, virtualCameraUp);
|
||||
mat4Interpolate(virtualViewMatrix2, identity, virtualViewMatrix2, interpolate[1]);
|
||||
|
||||
mat4Multiply(virtualViewMatrix, virtualViewMatrix2, virtualViewMatrix1);
|
||||
|
||||
// interpolated projection matrix
|
||||
let virtualProjectionMatrix1 = [];
|
||||
mat4BuildPerspective1(virtualProjectionMatrix1, 90.0 / 180.0 * Math.PI, cv.width / cv.height, 0.9, 5);
|
||||
mat4Interpolate(virtualProjectionMatrix1, identity, virtualProjectionMatrix1, interpolate[2]);
|
||||
|
||||
let virtualProjectionMatrix2 = [];
|
||||
mat4BuildPerspective2(virtualProjectionMatrix2, 90.0 / 180.0 * Math.PI, cv.width / cv.height, 0.9, 5);
|
||||
mat4Interpolate(virtualProjectionMatrix2, identity, virtualProjectionMatrix2, interpolate[3]);
|
||||
|
||||
let virtualProjectionMatrix3 = [];
|
||||
mat4BuildPerspective3(virtualProjectionMatrix3, 90.0 / 180.0 * Math.PI, cv.width / cv.height, 0.9, 5);
|
||||
mat4Interpolate(virtualProjectionMatrix3, identity, virtualProjectionMatrix3, interpolate[4]);
|
||||
|
||||
let virtualProjectionMatrix4 = [];
|
||||
mat4BuildPerspective4(virtualProjectionMatrix4, 90.0 / 180.0 * Math.PI, cv.width / cv.height, 0.9, 5);
|
||||
mat4Interpolate(virtualProjectionMatrix4, identity, virtualProjectionMatrix4, interpolate[5]);
|
||||
|
||||
mat4Multiply(virtualProjectionMatrix, virtualProjectionMatrix4, virtualProjectionMatrix3);
|
||||
mat4Multiply(virtualProjectionMatrix, virtualProjectionMatrix, virtualProjectionMatrix2);
|
||||
mat4Multiply(virtualProjectionMatrix, virtualProjectionMatrix, virtualProjectionMatrix1);
|
||||
|
||||
gl.uniformMatrix4fv(virtualProjectionLocation, gl.FALSE, new Float32Array(virtualProjectionMatrix));
|
||||
|
||||
|
|
Loading…
Reference in New Issue