Skip to content

Commit

Permalink
data block driven
Browse files Browse the repository at this point in the history
  • Loading branch information
dylanebert committed Dec 9, 2023
1 parent 3ee7e43 commit cb39268
Show file tree
Hide file tree
Showing 23 changed files with 669 additions and 692 deletions.
2 changes: 1 addition & 1 deletion examples/camera-updates/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ const progressIndicator = document.getElementById("progress-indicator") as HTMLP

const renderer = new SPLAT.WebGLRenderer(canvas);
const scene = new SPLAT.Scene();
const camera = scene.camera!.object;
const camera = scene.findObjectOfType(SPLAT.Camera) as SPLAT.Camera;
const controls = new SPLAT.OrbitControls(scene, canvas);

async function main() {
Expand Down
38 changes: 22 additions & 16 deletions examples/editor/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@ const progressIndicator = document.getElementById("progress-indicator") as HTMLP

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 object: SPLAT.Object3D;
let splat: SPLAT.Splat;

function getSplatCorners(position: SPLAT.Vector3, rotation: SPLAT.Quaternion, scale: SPLAT.Vector3) {
const localCorners = [
Expand Down Expand Up @@ -77,19 +78,23 @@ function findIntersectedSplat(origin: SPLAT.Vector3, direction: SPLAT.Vector3) {
let closestSplat = null;
let minDistance = Infinity;

for (let i = 0; i < object.vertexCount; i++) {
for (let i = 0; i < splat.data.vertexCount; i++) {
const position = new SPLAT.Vector3(
object.positions[3 * i + 0],
object.positions[3 * i + 1],
object.positions[3 * i + 2],
splat.data.positions[3 * i + 0],
splat.data.positions[3 * i + 1],
splat.data.positions[3 * i + 2],
);
const rotation = new SPLAT.Quaternion(
object.rotations[4 * i + 1],
object.rotations[4 * i + 2],
object.rotations[4 * i + 3],
-object.rotations[4 * i + 0],
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 scale = new SPLAT.Vector3(object.scales[3 * i + 0], object.scales[3 * i + 1], object.scales[3 * i + 2]);
const corners = getSplatCorners(position, rotation, scale);
const triangles = [
[corners[0], corners[1], corners[2]],
Expand All @@ -109,7 +114,7 @@ function findIntersectedSplat(origin: SPLAT.Vector3, direction: SPLAT.Vector3) {

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

const handleResize = () => {
Expand All @@ -121,10 +126,10 @@ async function main() {
const y = -(event.clientY / canvas.clientHeight) * 2 + 1;
const clipSpaceCoords = new SPLAT.Vector4(x, y, -1, 1);

const inverseProjectionMatrix = camera.projectionMatrix.invert();
const inverseProjectionMatrix = camera.data.projectionMatrix.invert();
const cameraSpaceCoords = clipSpaceCoords.multiply(inverseProjectionMatrix);

const inverseViewMatrix = camera.viewMatrix.invert();
const inverseViewMatrix = camera.data.viewMatrix.invert();
const worldSpaceCoords = cameraSpaceCoords.multiply(inverseViewMatrix);
const worldSpacePosition = new SPLAT.Vector3(
worldSpaceCoords.x / worldSpaceCoords.w,
Expand All @@ -137,7 +142,7 @@ async function main() {

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

Expand All @@ -147,13 +152,14 @@ async function main() {
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);
object.addSplat(position, rotation, scale, color);
console.log(`Adding splat at position ${position}, rotation ${rotation}, scale ${scale}, color ${color}`);
// splat.addSplat(position, rotation, scale, color);
}
};

const frame = () => {
controls.update();
renderer.render(scene, camera);
renderer.render(scene);

requestAnimationFrame(frame);
};
Expand Down
25 changes: 12 additions & 13 deletions examples/scene-transformations/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,22 +12,21 @@ async function main() {
// Load the scene
const name = "bonsai";
const url = `https://huggingface.co/datasets/dylanebert/3dgs/resolve/main/${name}/${name}-7k.splat`;
const object = await SPLAT.Loader.LoadAsync(url, scene, (progress) => (progressIndicator.value = progress * 100));
const splat = await SPLAT.Loader.LoadAsync(url, scene, (progress) => (progressIndicator.value = progress * 100));
progressDialog.close();

// Transform it
const splatFilter = object.getComponent(SPLAT.SplatFilter)!;
const rotation = new SPLAT.Vector3(0, 0, 0);
const translation = new SPLAT.Vector3(-0.2, 0.2, 0);
const scaling = new SPLAT.Vector3(1.5, 1.5, 1.5);
const limitSize = 3.0;
object.rotation = SPLAT.Quaternion.FromEuler(rotation);
object.position = translation;
object.scale = scaling;
splatFilter.limitBox(-limitSize, limitSize, -limitSize, limitSize, -limitSize, limitSize);
splatFilter.applyPosition();
splatFilter.applyRotation();
splatFilter.applyScale();
splat.rotation = SPLAT.Quaternion.FromEuler(rotation);
splat.position = translation;
splat.scale = scaling;
splat.data.limitBox(-limitSize, limitSize, -limitSize, limitSize, -limitSize, limitSize);
splat.applyPosition();
splat.applyRotation();
splat.applyScale();

const handleResize = () => {
renderer.setSize(canvas.clientWidth, canvas.clientHeight);
Expand All @@ -42,11 +41,11 @@ async function main() {

const onKeyDown = (e: KeyboardEvent) => {
if (e.key === "PageUp") {
object.scale = new SPLAT.Vector3(1.1, 1.1, 1.1);
splatFilter.applyScale();
splat.scale = new SPLAT.Vector3(1.1, 1.1, 1.1);
splat.applyScale();
} else if (e.key === "PageDown") {
object.scale = new SPLAT.Vector3(0.9, 0.9, 0.9);
splatFilter.applyScale();
splat.scale = new SPLAT.Vector3(0.9, 0.9, 0.9);
splat.applyScale();
}
};

Expand Down
75 changes: 10 additions & 65 deletions src/cameras/Camera.ts
Original file line number Diff line number Diff line change
@@ -1,76 +1,21 @@
import { CameraData } from "./CameraData";
import { Object3D } from "../core/Object3D";
import { Quaternion } from "../math/Quaternion";
import { Matrix3 } from "../math/Matrix3";
import { Matrix4 } from "../math/Matrix4";
import { Vector3 } from "../math/Vector3";
import { Component } from "../core/Component";

class Camera extends Component {
fx: number = 1132;
fy: number = 1132;
near: number = 0.1;
far: number = 100;
class Camera extends Object3D {
private _data: CameraData;

projectionMatrix: Matrix4;
viewMatrix: Matrix4;
viewProj: Matrix4;
constructor(camera: CameraData | undefined = undefined) {
super();

update: (width: number, height: number) => void;
this._data = camera ? camera : new CameraData();

constructor(object: Object3D) {
super(object);

const getViewMatrix = (): Matrix4 => {
const R = Matrix3.RotationFromQuaternion(this.object.rotation).buffer;
const t = this.object.position.flat();
const camToWorld = [
[R[0], R[1], R[2], 0],
[R[3], R[4], R[5], 0],
[R[6], R[7], R[8], 0],
[
-t[0] * R[0] - t[1] * R[3] - t[2] * R[6],
-t[0] * R[1] - t[1] * R[4] - t[2] * R[7],
-t[0] * R[2] - t[1] * R[5] - t[2] * R[8],
1,
],
].flat();
return new Matrix4(...camToWorld);
};

this.projectionMatrix = new Matrix4();
this.viewMatrix = new Matrix4();
this.viewProj = new Matrix4();

this.update = (width: number, height: number) => {
// prettier-ignore
this.projectionMatrix = new Matrix4(
2 * this.fx / width, 0, 0, 0,
0, -2 * this.fy / height, 0, 0,
0, 0, this.far / (this.far - this.near), 1,
0, 0, -(this.far * this.near) / (this.far - this.near), 0
);
this.viewMatrix = getViewMatrix();
this.viewProj = this.projectionMatrix.multiply(this.viewMatrix);
this.update = () => {
this.data.update(this.position, this.rotation);
};
}

static Create(
position: Vector3 = new Vector3(0, 0, -5),
rotation: Quaternion = new Quaternion(),
fx: number = 1132,
fy: number = 1132,
near: number = 0.1,
far: number = 100,
): Camera {
const object = new Object3D();
object.position = position;
object.rotation = rotation;
const camera = object.addComponent(Camera);
camera.fx = fx;
camera.fy = fy;
camera.near = near;
camera.far = far;
return camera;
get data() {
return this._data;
}
}

Expand Down
127 changes: 127 additions & 0 deletions src/cameras/CameraData.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
import { Quaternion } from "../math/Quaternion";
import { Matrix3 } from "../math/Matrix3";
import { Matrix4 } from "../math/Matrix4";
import { Vector3 } from "../math/Vector3";

class CameraData {
private _fx: number = 1132;
private _fy: number = 1132;
private _near: number = 0.1;
private _far: number = 100;

private _width: number = 512;
private _height: number = 512;

private _projectionMatrix: Matrix4 = new Matrix4();
private _viewMatrix: Matrix4 = new Matrix4();
private _viewProj: Matrix4 = new Matrix4();

update: (position: Vector3, rotation: Quaternion) => void;
setSize: (width: number, height: number) => void;

private _updateProjectionMatrix: () => void;

constructor() {
this._updateProjectionMatrix = () => {
// prettier-ignore
this._projectionMatrix = new Matrix4(
2 * this.fx / this.width, 0, 0, 0,
0, -2 * this.fy / this.height, 0, 0,
0, 0, this.far / (this.far - this.near), 1,
0, 0, -(this.far * this.near) / (this.far - this.near), 0
);

this._viewProj = this.projectionMatrix.multiply(this.viewMatrix);
};

this.update = (position: Vector3, rotation: Quaternion) => {
const R = Matrix3.RotationFromQuaternion(rotation).buffer;
const t = position.flat();

// prettier-ignore
this._viewMatrix = new Matrix4(
R[0], R[1], R[2], 0,
R[3], R[4], R[5], 0,
R[6], R[7], R[8], 0,
-t[0] * R[0] - t[1] * R[3] - t[2] * R[6],
-t[0] * R[1] - t[1] * R[4] - t[2] * R[7],
-t[0] * R[2] - t[1] * R[5] - t[2] * R[8],
1,
);

this._viewProj = this.projectionMatrix.multiply(this.viewMatrix);
};

this.setSize = (width: number, height: number) => {
this._width = width;
this._height = height;
this._updateProjectionMatrix();
};
}

get fx() {
return this._fx;
}

set fx(fx: number) {
if (this._fx !== fx) {
this._fx = fx;
this._updateProjectionMatrix();
}
}

get fy() {
return this._fy;
}

set fy(fy: number) {
if (this._fy !== fy) {
this._fy = fy;
this._updateProjectionMatrix();
}
}

get near() {
return this._near;
}

set near(near: number) {
if (this._near !== near) {
this._near = near;
this._updateProjectionMatrix();
}
}

get far() {
return this._far;
}

set far(far: number) {
if (this._far !== far) {
this._far = far;
this._updateProjectionMatrix();
}
}

get width() {
return this._width;
}

get height() {
return this._height;
}

get projectionMatrix() {
return this._projectionMatrix;
}

get viewMatrix() {
return this._viewMatrix;
}

get viewProj() {
return this._viewProj;
}
}

export { CameraData };
Loading

0 comments on commit cb39268

Please sign in to comment.