sokobanni commited on
Commit
711a207
1 Parent(s): 796a5c2

Upload 6 files

Browse files
Files changed (7) hide show
  1. .gitattributes +4 -0
  2. index.html +24 -0
  3. main.js +295 -0
  4. model.splat +3 -0
  5. model2.splat +3 -0
  6. model3.splat +3 -0
  7. model4.splat +3 -0
.gitattributes CHANGED
@@ -33,3 +33,7 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
 
 
 
 
 
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
+ model.splat filter=lfs diff=lfs merge=lfs -text
37
+ model2.splat filter=lfs diff=lfs merge=lfs -text
38
+ model3.splat filter=lfs diff=lfs merge=lfs -text
39
+ model4.splat filter=lfs diff=lfs merge=lfs -text
index.html ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>RECON Labs Gaussian Splatting demo</title>
5
+ <meta charset="utf-8" />
6
+ <meta name="viewport"
7
+ content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1, user-scalable=no" />
8
+ </head>
9
+
10
+ <body style="background: black; overflow: hidden; margin: 0;">
11
+ <script async src="https://ga.jspm.io/npm:es-module-shims@1.5.1/dist/es-module-shims.js"
12
+ crossorigin="anonymous"></script>
13
+ <script type="importmap">
14
+ {
15
+ "imports": {
16
+ "three": "https://unpkg.com/three@0.157.0/build/three.module.js",
17
+ "three/addons/": "https://unpkg.com/three@0.157.0/examples/jsm/"
18
+ }
19
+ }
20
+ </script>
21
+ <script type="module" src="main.js"></script>
22
+
23
+ </body>
24
+ </html>
main.js ADDED
@@ -0,0 +1,295 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import * as THREE from "three";
2
+ import { OrbitControls } from "three/addons/controls/OrbitControls.js";
3
+ // Create the renderer
4
+ var renderer = new THREE.WebGLRenderer({ antialias: true });
5
+ renderer.setClearColor(0xffffff, 0);
6
+ renderer.setSize(window.innerWidth, window.innerHeight);
7
+ document.body.appendChild(renderer.domElement);
8
+
9
+ // Create the scene
10
+ const scene = new THREE.Scene();
11
+
12
+ // Create the camera
13
+ const camera = new THREE.PerspectiveCamera(
14
+ 45,
15
+ window.innerWidth / window.innerHeight,
16
+ 0.1,
17
+ 200.0
18
+ );
19
+ camera.position.set(0, 0, 3.0);
20
+ scene.add(camera);
21
+
22
+ // Create orbit controls
23
+ const controls = new OrbitControls(camera, renderer.domElement);
24
+ // controls.maxPolarAngle = (0.9 * Math.PI) / 2;
25
+ controls.enableDamping = true;
26
+ controls.dampingFactor = 0.5;
27
+
28
+ let sortReady = false;
29
+ function sortSplats(matrices, view) {
30
+ const vertexCount = matrices.length / 16;
31
+
32
+ let maxDepth = -Infinity;
33
+ let minDepth = Infinity;
34
+ let depthList = new Float32Array(vertexCount);
35
+ let sizeList = new Int32Array(depthList.buffer);
36
+ for (let i = 0; i < vertexCount; i++) {
37
+ let depth =
38
+ view[0] * matrices[i * 16 + 12] -
39
+ view[1] * matrices[i * 16 + 13] -
40
+ view[2] * matrices[i * 16 + 14];
41
+ depthList[i] = depth;
42
+ if (depth > maxDepth) maxDepth = depth;
43
+ if (depth < minDepth) minDepth = depth;
44
+ }
45
+
46
+ // This is a 16 bit single-pass counting sort
47
+ let depthInv = (256 * 256 - 1) / (maxDepth - minDepth);
48
+ let counts0 = new Uint32Array(256 * 256);
49
+ for (let i = 0; i < vertexCount; i++) {
50
+ sizeList[i] = ((depthList[i] - minDepth) * depthInv) | 0;
51
+ counts0[sizeList[i]]++;
52
+ }
53
+ let starts0 = new Uint32Array(256 * 256);
54
+ for (let i = 1; i < 256 * 256; i++)
55
+ starts0[i] = starts0[i - 1] + counts0[i - 1];
56
+ let depthIndex = new Uint32Array(vertexCount);
57
+ for (let i = 0; i < vertexCount; i++) depthIndex[starts0[sizeList[i]]++] = i;
58
+
59
+ let sortedMatrices = new Float32Array(vertexCount * 16);
60
+ for (let j = 0; j < vertexCount; j++) {
61
+ let i = depthIndex[j];
62
+ for (let k = 0; k < 16; k++) {
63
+ sortedMatrices[j * 16 + k] = matrices[i * 16 + k];
64
+ }
65
+ }
66
+
67
+ return sortedMatrices;
68
+ }
69
+
70
+ function createWorker(self) {
71
+ let sortFunction;
72
+ let matrices;
73
+ self.onmessage = (e) => {
74
+ if (e.data.sortFunction) {
75
+ eval(e.data.sortFunction);
76
+ sortFunction = sortSplats;
77
+ }
78
+ if (e.data.matrices) {
79
+ matrices = new Float32Array(e.data.matrices);
80
+ }
81
+ if (e.data.view) {
82
+ const view = new Float32Array(e.data.view);
83
+ const sortedMatrices = sortFunction(matrices, view);
84
+ self.postMessage({ sortedMatrices }, [sortedMatrices.buffer]);
85
+ }
86
+ };
87
+ }
88
+
89
+ const size = new THREE.Vector2();
90
+ renderer.getSize(size);
91
+ const focal = size.y / 2.0 / Math.tan(((camera.fov / 2.0) * Math.PI) / 180.0);
92
+
93
+ const geometry = new THREE.PlaneGeometry(4, 4);
94
+ const material = new THREE.ShaderMaterial({
95
+ uniforms: {
96
+ viewport: { value: new Float32Array([size.x, size.y]) },
97
+ focal: { value: focal },
98
+ },
99
+ vertexShader: `varying vec4 vColor;
100
+ varying vec2 vPosition;
101
+ uniform vec2 viewport;
102
+ uniform float focal;
103
+
104
+ void main () {
105
+ vec4 center = vec4(instanceMatrix[3][0], instanceMatrix[3][1], instanceMatrix[3][2], 1);
106
+ // Adjust View Pose
107
+ mat4 adjViewMatrix = inverse(viewMatrix);
108
+ adjViewMatrix[0][1] *= -1.0;
109
+ adjViewMatrix[1][0] *= -1.0;
110
+ adjViewMatrix[1][2] *= -1.0;
111
+ adjViewMatrix[2][1] *= -1.0;
112
+ adjViewMatrix[3][1] *= -1.0;
113
+ adjViewMatrix = inverse(adjViewMatrix);
114
+ mat4 modelView = adjViewMatrix * modelMatrix;
115
+
116
+ vec4 camspace = modelView * center;
117
+ vec4 pos2d = projectionMatrix * mat4(1,0,0,0,0,-1,0,0,0,0,1,0,0,0,0,1) * camspace;
118
+
119
+ float bounds = 1.2 * pos2d.w;
120
+ if (pos2d.z < -pos2d.w || pos2d.x < -bounds || pos2d.x > bounds
121
+ || pos2d.y < -bounds || pos2d.y > bounds) {
122
+ gl_Position = vec4(0.0, 0.0, 2.0, 1.0);
123
+ return;
124
+ }
125
+
126
+ mat3 J = mat3(
127
+ focal / camspace.z, 0., -(focal * camspace.x) / (camspace.z * camspace.z),
128
+ 0., -focal / camspace.z, (focal * camspace.y) / (camspace.z * camspace.z),
129
+ 0., 0., 0.
130
+ );
131
+
132
+ mat3 W = transpose(mat3(modelView));
133
+ mat3 T = W * J;
134
+ mat3 cov = transpose(T) * mat3(instanceMatrix) * T;
135
+
136
+ vec2 vCenter = vec2(pos2d) / pos2d.w;
137
+
138
+ float diagonal1 = cov[0][0] + 0.3;
139
+ float offDiagonal = cov[0][1];
140
+ float diagonal2 = cov[1][1] + 0.3;
141
+
142
+ float mid = 0.5 * (diagonal1 + diagonal2);
143
+ float radius = length(vec2((diagonal1 - diagonal2) / 2.0, offDiagonal));
144
+ float lambda1 = mid + radius;
145
+ float lambda2 = max(mid - radius, 0.1);
146
+ vec2 diagonalVector = normalize(vec2(offDiagonal, lambda1 - diagonal1));
147
+ vec2 v1 = min(sqrt(2.0 * lambda1), 1024.0) * diagonalVector;
148
+ vec2 v2 = min(sqrt(2.0 * lambda2), 1024.0) * vec2(diagonalVector.y, -diagonalVector.x);
149
+
150
+ vColor = vec4(instanceMatrix[0][3], instanceMatrix[1][3], instanceMatrix[2][3], instanceMatrix[3][3]);
151
+ vPosition = position.xy;
152
+
153
+ gl_Position = vec4(
154
+ vCenter
155
+ + position.x * v2 / viewport * 2.0
156
+ + position.y * v1 / viewport * 2.0, 0.0, 1.0);
157
+ }`,
158
+ fragmentShader: `varying vec4 vColor;
159
+ varying vec2 vPosition;
160
+
161
+ void main () {
162
+ float A = -dot(vPosition, vPosition);
163
+ if (A < -4.0) discard;
164
+ float B = exp(A) * vColor.a;
165
+ gl_FragColor = vec4(B * vColor.rgb, B);
166
+ }`,
167
+ });
168
+
169
+ material.blending = THREE.CustomBlending;
170
+ material.blendEquation = THREE.AddEquation;
171
+ material.blendSrc = THREE.OneMinusDstAlphaFactor;
172
+ material.blendDst = THREE.OneFactor;
173
+ material.blendSrcAlpha = THREE.OneMinusDstAlphaFactor;
174
+ material.blendDstAlpha = THREE.OneFactor;
175
+ material.depthTest = false;
176
+ material.needsUpdate = true;
177
+
178
+ window.addEventListener("resize", () => {
179
+ renderer.getSize(size);
180
+ const focal =
181
+ size.y /
182
+ 2.0 /
183
+ Math.tan(((camera.components.camera.data.fov / 2.0) * Math.PI) / 180.0);
184
+ material.uniforms.viewport.value[0] = size.x;
185
+ material.uniforms.viewport.value[1] = size.y;
186
+ material.uniforms.focal.value = focal;
187
+ });
188
+ const urlParams = new URLSearchParams(window.location.search);
189
+ const name = urlParams.get('url');
190
+
191
+ console.log(name);
192
+
193
+ fetch(name)
194
+ .then((data) => data.blob())
195
+ .then((res) => res.arrayBuffer())
196
+ .then((buffer) => {
197
+ const rowLength = 3 * 4 + 3 * 4 + 4 + 4;
198
+ const vertexCount = Math.floor(buffer.byteLength / rowLength);
199
+ const f_buffer = new Float32Array(buffer);
200
+ const u_buffer = new Uint8Array(buffer);
201
+
202
+ const matrices = new Float32Array(vertexCount * 16);
203
+ for (let i = 0; i < vertexCount; i++) {
204
+ const quat = new THREE.Quaternion(
205
+ (u_buffer[32 * i + 28 + 1] - 128) / 128.0,
206
+ (u_buffer[32 * i + 28 + 2] - 128) / 128.0,
207
+ -(u_buffer[32 * i + 28 + 3] - 128) / 128.0,
208
+ (u_buffer[32 * i + 28 + 0] - 128) / 128.0
209
+ );
210
+ const center = new THREE.Vector3(
211
+ f_buffer[8 * i + 0],
212
+ f_buffer[8 * i + 1],
213
+ -f_buffer[8 * i + 2]
214
+ );
215
+ const scale = new THREE.Vector3(
216
+ f_buffer[8 * i + 3 + 0],
217
+ f_buffer[8 * i + 3 + 1],
218
+ f_buffer[8 * i + 3 + 2]
219
+ );
220
+
221
+ const mtx = new THREE.Matrix4();
222
+ mtx.makeRotationFromQuaternion(quat);
223
+ mtx.transpose();
224
+ mtx.scale(scale);
225
+ const mtx_t = mtx.clone();
226
+ mtx.transpose();
227
+ mtx.premultiply(mtx_t);
228
+ mtx.setPosition(center);
229
+
230
+ // RGBA
231
+ mtx.elements[3] = u_buffer[32 * i + 24 + 0] / 255;
232
+ mtx.elements[7] = u_buffer[32 * i + 24 + 1] / 255;
233
+ mtx.elements[11] = u_buffer[32 * i + 24 + 2] / 255;
234
+ mtx.elements[15] = u_buffer[32 * i + 24 + 3] / 255;
235
+
236
+ for (let j = 0; j < 16; j++) {
237
+ matrices[i * 16 + j] = mtx.elements[j];
238
+ }
239
+ }
240
+
241
+ const view = new Float32Array([
242
+ camera.matrixWorld.elements[2],
243
+ camera.matrixWorld.elements[6],
244
+ camera.matrixWorld.elements[10],
245
+ ]);
246
+
247
+ const iMesh = new THREE.InstancedMesh(geometry, material, vertexCount);
248
+ iMesh.frustumCulled = false;
249
+ iMesh.instanceMatrix.array = sortSplats(matrices, view);
250
+ iMesh.instanceMatrix.needsUpdate = true;
251
+ scene.add(iMesh);
252
+
253
+ const worker = new Worker(
254
+ URL.createObjectURL(
255
+ new Blob(["(", createWorker.toString(), ")(self)"], {
256
+ type: "application/javascript",
257
+ })
258
+ )
259
+ );
260
+
261
+ worker.postMessage(
262
+ {
263
+ sortFunction: sortSplats.toString(),
264
+ matrices: matrices.buffer,
265
+ },
266
+ [matrices.buffer]
267
+ );
268
+
269
+ worker.onmessage = (e) => {
270
+ iMesh.instanceMatrix.array = new Float32Array(e.data.sortedMatrices);
271
+ iMesh.instanceMatrix.needsUpdate = true;
272
+ sortReady = true;
273
+ };
274
+ sortReady = true;
275
+
276
+ function animate() {
277
+ requestAnimationFrame(animate);
278
+ if (sortReady) {
279
+ sortReady = false;
280
+ const view = new Float32Array([
281
+ camera.matrixWorld.elements[2],
282
+ camera.matrixWorld.elements[6],
283
+ camera.matrixWorld.elements[10],
284
+ ]);
285
+ worker.postMessage({ view }, [view.buffer]);
286
+ }
287
+ controls.update();
288
+ renderer.render(scene, camera);
289
+ }
290
+
291
+ animate();
292
+ })
293
+ .catch((error) => {
294
+ console.error(error);
295
+ });
model.splat ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:fc13c3175fd4ef56b291919bee4b256110943b17b8ff324f64c11bbc1bf20d05
3
+ size 57567904
model2.splat ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:8894494d89669bc90995ec867c8b3dc536dacb03e34d5b43496e47faac996179
3
+ size 44875776
model3.splat ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:64e009733fc0f939880e1578b9371b4d5b1df729b382f70799b54c9cc62a23b3
3
+ size 43826048
model4.splat ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:d1079b75516487384dbe383bd4dae6e1d34afdffa6642c0437f3ed5d9d8ee648
3
+ size 37803424