Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

change Camera controls on SketchFab stile #24

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
.DS_Store

splats
81 changes: 68 additions & 13 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,15 @@
border-radius: 10px;
font-size: x-small;
}

#collections {
background: rgba(0,0,0,0.6);
white-space: pre-wrap;
padding: 10px;
border-radius: 10px;
font-size: x-small;
}

body.nohf .nohf {
display: none;
}
Expand All @@ -199,14 +208,22 @@ <h3 class="nohf">WebGL 3D Gaussian Splat Viewer</h3>
<details>
<summary>Use mouse or arrow keys to navigate.</summary>

<div id="instructions">movement (arrow keys)
- left/right arrow keys to strafe side to side
- up/down arrow keys to move forward/back
- space to jump
<div id="instructions">Main navigation (mouse+QE)
- click left and drag to orbit
- middle click and drag up/down to move
- q/e to correct orbit

camera angle (wasd)
- a/d to turn camera left/right
- w/s to tilt camera up/down
- press v to hash curent view to url string
- drag and drop .ply file to convert to .splat

movement (WASD shuter like)
- a/d keys to strafe side to side
- w/s keys to move forward/back
- click right and drag to Look around

camera angle (arrow key)
- left/right to turn camera left/right
- up/down to tilt camera up/down
- q/e to roll camera counterclockwise/clockwise
- i/k and j/l to orbit

Expand All @@ -216,10 +233,6 @@ <h3 class="nohf">WebGL 3D Gaussian Splat Viewer</h3>
- ctrl key + scroll to move forward/back
- shift + scroll to move up/down or strafe

mouse
- click and drag to orbit
- right click (or ctrl/cmd key) and drag up/down to move

touch (mobile)
- one finger to orbit
- two finger pinch to move forward/back
Expand All @@ -232,11 +245,53 @@ <h3 class="nohf">WebGL 3D Gaussian Splat Viewer</h3>
other
- press 0-9 to switch to one of the pre-loaded camera views
- press p to resume default animation
- drag and drop .ply file to convert to .splat
</div>

</details>

<details>
<summary>My collections.</summary>

<div id="collections"></div>
<script>
var home = location.href.split('?')[0]
var store = "splats/";
// Функция для чтения CSV-файла
function readCSV(file, callback) {
var request = new XMLHttpRequest();
request.open("GET", file, true);
request.onreadystatechange = function() {
if (request.readyState === 4 && request.status === 200) {
var data = request.responseText;
callback(data);
}
};
request.send();
}
// Функция для создания HTML из CSV данных
function createHTMLFromCSV(csvData) {
var lines = csvData.split("\n");
var outputDiv = document.getElementById("collections");
var html = '';

for (var i = 0; i < lines.length; i++) {
var parts = lines[i].split(";");
if (parts.length === 3) {
var title = parts[0];
var filename = parts[1];
var params = parts[2];

// Создаем HTML для каждой строки данных
html += '<a class="myLink" href="'+ home + "?url=" + store + filename + '#' + params + '">' + title + '</a><br>';
}
}
// Вставляем созданный HTML в элемент с id "output"
outputDiv.innerHTML = html;
}
// Читаем CSV-файл и создаем HTML
readCSV(store+"all.csv", createHTMLFromCSV);
</script>

</details>
</div>

<div id="progress"></div>
Expand Down
98 changes: 42 additions & 56 deletions main.js
Original file line number Diff line number Diff line change
Expand Up @@ -722,23 +722,19 @@ void main () {

`.trim();

let defaultViewMatrix = [
0.47, 0.04, 0.88, 0, -0.11, 0.99, 0.02, 0, -0.88, -0.11, 0.47, 0, 0.07,
0.03, 6.55, 1,
];
let defaultViewMatrix = [-0.02,-0.52,0.85,0,0.5,0.73,0.47,0,-0.87,0.44,0.24,0,0.07,-1.78,5.18,1];
let viewMatrix = defaultViewMatrix;
async function main() {
let carousel = true;
let carousel = true;
const params = new URLSearchParams(location.search);
try {
viewMatrix = JSON.parse(decodeURIComponent(location.hash.slice(1)));
carousel = false;
} catch (err) {}
const url = new URL(
// "nike.splat",
// location.href,
params.get("url") || "train.splat",
"https://huggingface.co/cakewalk/splat-data/resolve/main/",
params.get("url") || "chest.splat",
//"https://huggingface.co/datasets/Nehc/splats/resolve/main/",
location.href+"splats/",
);
const req = await fetch(url, {
mode: "cors", // no-cors, *cors, same-origin
Expand Down Expand Up @@ -931,6 +927,8 @@ async function main() {
activeKeys = [];
});

let startX, startY, down, d=4;

window.addEventListener(
"wheel",
(e) => {
Expand Down Expand Up @@ -962,65 +960,73 @@ async function main() {
(-10 * (e.deltaY * scale)) / innerHeight,
);
inv[13] = preY;
} else {
} else if (e.altKey) {
let d = 4;
inv = translate4(inv, 0, 0, d);
inv = rotate4(inv, -(e.deltaX * scale) / innerWidth, 0, 1, 0);
inv = rotate4(inv, (e.deltaY * scale) / innerHeight, 1, 0, 0);
inv = translate4(inv, 0, 0, -d);
} else {
inv = translate4(
inv,
0,
0,
(e.deltaY * scale) / innerHeight,
);
d-=(e.deltaY * scale) / innerHeight
}

viewMatrix = invert4(inv);
},
{ passive: false },
);

let startX, startY, down;
canvas.addEventListener("mousedown", (e) => {
carousel = false;
e.preventDefault();
startX = e.clientX;
startY = e.clientY;
down = e.ctrlKey || e.metaKey ? 2 : 1;
down = e.ctrlKey || e.metaKey || e.button > 0 ? 2 : 1;
down = e.button == 2 ? 3 : down;
});
canvas.addEventListener("contextmenu", (e) => {
carousel = false;
e.preventDefault();
startX = e.clientX;
startY = e.clientY;
down = 2;
});

canvas.addEventListener("mousemove", (e) => {
e.preventDefault();
let inv = invert4(viewMatrix);
if (down == 1) {
let inv = invert4(viewMatrix);
let dx = (5 * (e.clientX - startX)) / innerWidth;
let dy = (5 * (e.clientY - startY)) / innerHeight;
let d = 4;

inv = translate4(inv, 0, 0, d);
inv = rotate4(inv, dx, 0, 1, 0);
inv = rotate4(inv, -dy, 1, 0, 0);
inv = translate4(inv, 0, 0, -d);
// let postAngle = Math.atan2(inv[0], inv[10])
// inv = rotate4(inv, postAngle - preAngle, 0, 0, 1)
// console.log(postAngle)
viewMatrix = invert4(inv);

startX = e.clientX;
startY = e.clientY;

} else if (down == 2) {
let inv = invert4(viewMatrix);
// inv = rotateY(inv, );
let preY = inv[13];
inv = translate4(
inv,
(-10 * (e.clientX - startX)) / innerWidth,
(-3 * (e.clientX - startX)) / innerWidth,
(-3 * (e.clientY - startY)) / innerHeight,
0,
(10 * (e.clientY - startY)) / innerHeight,
);
inv[13] = preY;
viewMatrix = invert4(inv);

startX = e.clientX;
startY = e.clientY;

} else if (down == 3) {
let dx = (5 * (e.clientX - startX)) / innerWidth;
let dy = (5 * (e.clientY - startY)) / innerHeight;
inv = rotate4(inv, dx, 0, 1, 0);
inv = rotate4(inv, -dy, 1, 0, 0);
viewMatrix = invert4(inv);

startX = e.clientX;
Expand Down Expand Up @@ -1068,8 +1074,6 @@ async function main() {

let d = 4;
inv = translate4(inv, 0, 0, d);
// inv = translate4(inv, -x, -y, -z);
// inv = translate4(inv, x, y, z);
inv = rotate4(inv, dx, 0, 1, 0);
inv = rotate4(inv, -dy, 1, 0, 0);
inv = translate4(inv, 0, 0, -d);
Expand Down Expand Up @@ -1155,36 +1159,18 @@ async function main() {
const frame = (now) => {
let inv = invert4(viewMatrix);

if (activeKeys.includes("ArrowUp")) {
if (activeKeys.includes("Shift")) {
inv = translate4(inv, 0, -0.03, 0);
} else {
let preY = inv[13];
inv = translate4(inv, 0, 0, 0.1);
inv[13] = preY;
}
}
if (activeKeys.includes("ArrowDown")) {
if (activeKeys.includes("Shift")) {
inv = translate4(inv, 0, 0.03, 0);
} else {
let preY = inv[13];
inv = translate4(inv, 0, 0, -0.1);
inv[13] = preY;
}
}
if (activeKeys.includes("ArrowLeft"))
inv = translate4(inv, -0.03, 0, 0);
//
if (activeKeys.includes("ArrowRight"))
inv = translate4(inv, 0.03, 0, 0);
// inv = rotate4(inv, 0.01, 0, 1, 0);
if (activeKeys.includes("KeyA")) inv = rotate4(inv, -0.01, 0, 1, 0);
if (activeKeys.includes("KeyD")) inv = rotate4(inv, 0.01, 0, 1, 0);
if (activeKeys.includes("ArrowLeft")) inv = rotate4(inv, -0.01, 0, 1, 0);
if (activeKeys.includes("ArrowRight")) inv = rotate4(inv, 0.01, 0, 1, 0);
if (activeKeys.includes("ArrowUp")) inv = rotate4(inv, 0.005, 1, 0, 0);
if (activeKeys.includes("ArrowDown")) inv = rotate4(inv, -0.005, 1, 0, 0);

if (activeKeys.includes("KeyW")) inv = translate4(inv, 0, 0, 0.1);
if (activeKeys.includes("KeyA")) inv = translate4(inv, -0.03, 0, 0);
if (activeKeys.includes("KeyS")) inv = translate4(inv, 0, 0, -0.1);
if (activeKeys.includes("KeyD")) inv = translate4(inv, 0.03, 0, 0);

if (activeKeys.includes("KeyQ")) inv = rotate4(inv, 0.01, 0, 0, 1);
if (activeKeys.includes("KeyE")) inv = rotate4(inv, -0.01, 0, 0, 1);
if (activeKeys.includes("KeyW")) inv = rotate4(inv, 0.005, 1, 0, 0);
if (activeKeys.includes("KeyS")) inv = rotate4(inv, -0.005, 1, 0, 0);

const gamepads = navigator.getGamepads ? navigator.getGamepads() : [];
let isJumping = activeKeys.includes("KeySpace");
Expand Down