Skip to content

Commit

Permalink
editor example refactor checkpoint
Browse files Browse the repository at this point in the history
  • Loading branch information
dylanebert committed Dec 10, 2023
1 parent 9382952 commit eaeed45
Show file tree
Hide file tree
Showing 2 changed files with 113 additions and 113 deletions.
117 changes: 4 additions & 113 deletions examples/editor/src/main.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import * as SPLAT from "gsplat";
import { findIntersectedPoint } from "./utils";

const canvas = document.getElementById("canvas") as HTMLCanvasElement;
const progressDialog = document.getElementById("progress-dialog") as HTMLDialogElement;
Expand All @@ -8,113 +9,10 @@ const renderer = new SPLAT.WebGLRenderer(canvas);
const scene = new SPLAT.Scene();
const camera = scene.findObjectOfType(SPLAT.Camera) as SPLAT.Camera;
const controls = new SPLAT.OrbitControls(scene, canvas, 0, 0);
let splat: SPLAT.Splat;

function getSplatCorners(position: SPLAT.Vector3, rotation: SPLAT.Quaternion, scale: SPLAT.Vector3) {
const localCorners = [
new SPLAT.Vector3(-0.5, -0.5, 0),
new SPLAT.Vector3(0.5, -0.5, 0),
new SPLAT.Vector3(0.5, 0.5, 0),
new SPLAT.Vector3(-0.5, 0.5, 0),
];

const worldCorners = localCorners.map((corner) => {
corner = corner.multiply(scale).multiply(4);
corner = rotation.apply(corner);
corner = corner.add(position);
return corner;
});

return worldCorners;
}

function rayIntersectsTriangle(origin: SPLAT.Vector3, direction: SPLAT.Vector3, triangle: SPLAT.Vector3[]) {
const EPISLON = 0.000001;
const vertex0 = triangle[0];
const vertex1 = triangle[1];
const vertex2 = triangle[2];

let edge1 = new SPLAT.Vector3();
let edge2 = new SPLAT.Vector3();
let h = new SPLAT.Vector3();
let s = new SPLAT.Vector3();
let q = new SPLAT.Vector3();

edge1 = vertex1.subtract(vertex0);
edge2 = vertex2.subtract(vertex0);
h = direction.cross(edge2);
const a = edge1.dot(h);

if (a > -EPISLON && a < EPISLON) {
return null;
}

const f = 1.0 / a;
s = origin.subtract(vertex0);
const u = f * s.dot(h);

if (u < 0.0 || u > 1.0) {
return null;
}

q = s.cross(edge1);
const v = f * direction.dot(q);

if (v < 0.0 || u + v > 1.0) {
return null;
}

const t = f * edge2.dot(q);

if (t > EPISLON) {
const intersectionPoint = origin.add(direction.multiply(t));
return { distance: t, point: intersectionPoint };
} else {
return null;
}
}

function findIntersectedSplat(origin: SPLAT.Vector3, direction: SPLAT.Vector3) {
let closestSplat = null;
let minDistance = Infinity;

for (let i = 0; i < splat.data.vertexCount; i++) {
const position = new SPLAT.Vector3(
splat.data.positions[3 * i + 0],
splat.data.positions[3 * i + 1],
splat.data.positions[3 * i + 2],
);
const rotation = new SPLAT.Quaternion(
splat.data.rotations[4 * i + 1],
splat.data.rotations[4 * i + 2],
splat.data.rotations[4 * i + 3],
-splat.data.rotations[4 * i + 0],
);
const scale = new SPLAT.Vector3(
splat.data.scales[3 * i + 0],
splat.data.scales[3 * i + 1],
splat.data.scales[3 * i + 2],
);
const corners = getSplatCorners(position, rotation, scale);
const triangles = [
[corners[0], corners[1], corners[2]],
[corners[0], corners[2], corners[3]],
];
for (const triangle of triangles) {
const intersection = rayIntersectsTriangle(origin, direction, triangle);
if (intersection && intersection.distance < minDistance) {
minDistance = intersection.distance;
closestSplat = i;
}
}
}

return closestSplat;
}

async function main() {
const url = "https://huggingface.co/datasets/dylanebert/3dgs/resolve/main/bonsai/bonsai-7k-mini.splat";
splat = await SPLAT.Loader.LoadAsync(url, scene, (progress) => (progressIndicator.value = progress * 100));
const bonsai = await SPLAT.Loader.LoadAsync(url, scene, (progress) => (progressIndicator.value = progress * 100));
progressDialog.close();

const handleResize = () => {
Expand All @@ -140,21 +38,14 @@ async function main() {
const origin = camera.position;
const direction = worldSpacePosition.subtract(origin).normalize();

const closestSplat = findIntersectedSplat(origin, direction);
const closestSplat = findIntersectedPoint(bonsai, origin, direction);
if (closestSplat !== null) {
console.log(`Clicked on splat ${closestSplat}`);
}
};

const handleKeyDown = (event: KeyboardEvent) => {
if (event.key === " ") {
const position = new SPLAT.Vector3(Math.random() * 2 - 1, Math.random() * 2 - 1, Math.random() * 2 - 1);
const rotation = SPLAT.Quaternion.FromEuler(new SPLAT.Vector3(0.01, 0.01, 0.01));
const scale = new SPLAT.Vector3(1, 1, 1).multiply(0.02);
const color = new SPLAT.Color32(255, 0, 0);
console.log(`Adding splat at position ${position}, rotation ${rotation}, scale ${scale}, color ${color}`);
// splat.addSplat(position, rotation, scale, color);
}
console.log(event.key);
};

const frame = () => {
Expand Down
109 changes: 109 additions & 0 deletions examples/editor/src/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
import * as SPLAT from "gsplat";

function getSplatCorners(position: SPLAT.Vector3, rotation: SPLAT.Quaternion, scale: SPLAT.Vector3) {
const localCorners = [
new SPLAT.Vector3(-0.5, -0.5, 0),
new SPLAT.Vector3(0.5, -0.5, 0),
new SPLAT.Vector3(0.5, 0.5, 0),
new SPLAT.Vector3(-0.5, 0.5, 0),
];

const worldCorners = localCorners.map((corner) => {
corner = corner.multiply(scale).multiply(4);
corner = rotation.apply(corner);
corner = corner.add(position);
return corner;
});

return worldCorners;
}

function rayIntersectsTriangle(origin: SPLAT.Vector3, direction: SPLAT.Vector3, triangle: SPLAT.Vector3[]) {
const EPISLON = 0.000001;
const vertex0 = triangle[0];
const vertex1 = triangle[1];
const vertex2 = triangle[2];

let edge1 = new SPLAT.Vector3();
let edge2 = new SPLAT.Vector3();
let h = new SPLAT.Vector3();
let s = new SPLAT.Vector3();
let q = new SPLAT.Vector3();

edge1 = vertex1.subtract(vertex0);
edge2 = vertex2.subtract(vertex0);
h = direction.cross(edge2);
const a = edge1.dot(h);

if (a > -EPISLON && a < EPISLON) {
return null;
}

const f = 1.0 / a;
s = origin.subtract(vertex0);
const u = f * s.dot(h);

if (u < 0.0 || u > 1.0) {
return null;
}

q = s.cross(edge1);
const v = f * direction.dot(q);

if (v < 0.0 || u + v > 1.0) {
return null;
}

const t = f * edge2.dot(q);

if (t > EPISLON) {
const intersectionPoint = origin.add(direction.multiply(t));
return { distance: t, point: intersectionPoint };
} else {
return null;
}
}

function findIntersectedPoint(splat: SPLAT.Splat, origin: SPLAT.Vector3, direction: SPLAT.Vector3) {
let closestPoint = null;
let minDistance = Infinity;

for (let i = 0; i < splat.data.vertexCount; i++) {
const position = new SPLAT.Vector3(
splat.data.positions[3 * i + 0],
splat.data.positions[3 * i + 1],
splat.data.positions[3 * i + 2],
);

const rotation = new SPLAT.Quaternion(
splat.data.rotations[4 * i + 1],
splat.data.rotations[4 * i + 2],
splat.data.rotations[4 * i + 3],
-splat.data.rotations[4 * i + 0],
);

const scale = new SPLAT.Vector3(
splat.data.scales[3 * i + 0],
splat.data.scales[3 * i + 1],
splat.data.scales[3 * i + 2],
);

const corners = getSplatCorners(position, rotation, scale);
const triangles = [
[corners[0], corners[1], corners[2]],
[corners[0], corners[2], corners[3]],
];

for (const triangle of triangles) {
const intersection = rayIntersectsTriangle(origin, direction, triangle);
if (intersection && intersection.distance < minDistance) {
minDistance = intersection.distance;
closestPoint = i;
}
}
}

return closestPoint;
}

export { findIntersectedPoint };

0 comments on commit eaeed45

Please sign in to comment.