Skip to content

Commit db0e450

Browse files
committed
(feat)vk: 提交 gaussian splat 预览
1 parent 809dc76 commit db0e450

File tree

11 files changed

+425
-187
lines changed

11 files changed

+425
-187
lines changed

miniprogram/packageAPI/pages/ar/gaussian-splatting/gaussian-splatting.js

Lines changed: 175 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
1-
import { loadPly } from './util/handler-ply'
1+
import { loadPly } from './loaders/ply/ply-loader'
2+
import { loadSplat } from './loaders/splat/splat-loader'
23
import CameraWebGL from './webgl2/camera-webGL'
34
import CubeInstanceWebGL from './webgl2/cubeInstance-webGL'
45
import SplatWebGL from './webgl2/splat-webGL'
56

6-
const maxGaussians = 200000;
7-
// const renderScale = 0.474;
87
const renderScale = 1;
98

109
Component({
@@ -15,6 +14,8 @@ Component({
1514
heightScale: 1, // canvas高度缩放值
1615
renderByXRFrame: false, // 是否使用 xr-frame渲染
1716
renderByWebGL2: true, // 是否使用WebGL2渲染
17+
workerOn: true,
18+
maxGaussians: 600000,
1819
},
1920
lifetimes: {
2021
/**
@@ -25,7 +26,7 @@ Component({
2526

2627
console.log('[worker] 排序 worker 的创建')
2728
this.worker = wx.createWorker('workers/gaussianSplatting/index.js');
28-
console.log('[worker] 具体 worker', this._worker);
29+
console.log('[worker] 具体 worker', this.worker);
2930

3031
},
3132
detached() {
@@ -89,30 +90,110 @@ Component({
8990
} else if (this.data.renderByXRFrame) {
9091
this.initXRFrame();
9192
}
92-
93-
// 开始处理 ply 资源
94-
this.initPLY();
95-
96-
// 渲染循环
97-
// this.loopTimer = setInterval(this.requestRender.bind(this), 20);
98-
99-
// 仅渲染一次,通过触摸驱动
100-
// this.requestRender();
10193
},
102-
initPLY(){
94+
initPLY(id){
10395
console.log('== PLY Init start ==')
10496

105-
// const plySrc = 'http://10.9.169.132:8030/ply/point_cloud.ply';
106-
const plySrc = 'http://10.9.169.132:8030/ply/room.ply';
107-
// const plySrc = 'http://10.9.169.132:8030/ply/oneflower.ply';
108-
109-
110-
// const filePath = wx.env.USER_DATA_PATH + '/point.ply';
97+
const host = 'https://mmbizwxaminiprogram-1258344707.cos.ap-guangzhou.myqcloud.com/xr-frame/demo';
98+
// const host = 'http://10.9.169.120:8030'
99+
100+
let type;
101+
102+
// 加载 ply
103+
// type = 'ply';
104+
// const pcSrc = `${host}/ply/oneflower.cleaned.ply`;
105+
// const pcSrc = `${host}/ply/point_cloud.ply`;
106+
// const pcSrc = `${host}/ply/room.ply`;
107+
// const pcSrc = `${host}/ply/gs_USJ_Mario_enter.cleaned.ply`;
108+
// const pcSrc = `${host}/ply/oneflower.ply`;
109+
// const pcSrc = `${host}/ply/sakura.ply`;
110+
// const pcSrc = `${host}/ply/sakura.cleaned.ply`;
111+
// const pcSrc = `${host}/ply/sakura.compressed.ply`;
112+
113+
// 加载 splat
114+
type = 'splat';
115+
const pcSrc = `${host}/splat/${id}.splat`;
111116

117+
// Setup Camera
118+
switch(id) {
119+
case 'room':
120+
this.camera.updateCameraInfo(
121+
// target
122+
[0, 2, -1],
123+
// theta
124+
-Math.PI/2,
125+
// phi
126+
Math.PI/2,
127+
// raidus
128+
1
129+
)
130+
break;
131+
case 'garden':
132+
this.camera.updateCameraInfo(
133+
// target
134+
[0, 1, -1],
135+
// theta
136+
-Math.PI/2,
137+
// phi
138+
Math.PI/2,
139+
// raidus
140+
8
141+
)
142+
break;
143+
case 'stump':
144+
this.camera.updateCameraInfo(
145+
// target
146+
[0, -0.5, 0],
147+
// theta
148+
-Math.PI * 2 /3,
149+
// phi
150+
Math.PI * 2 /3,
151+
// raidus
152+
4
153+
)
154+
break;
155+
case 'oneflower':
156+
this.camera.updateCameraInfo(
157+
// target
158+
[0, 1.5, 3],
159+
// theta
160+
-Math.PI/2,
161+
// phi
162+
Math.PI/2,
163+
// raidus
164+
8
165+
)
166+
break;
167+
case 'usj':
168+
this.camera.updateCameraInfo(
169+
// target
170+
[0, -1, 0],
171+
// theta
172+
-Math.PI * 7 / 6,
173+
// phi
174+
Math.PI / 2,
175+
// raidus
176+
4
177+
)
178+
break;
179+
case 'sakura':
180+
this.camera.updateCameraInfo(
181+
// target
182+
[1.6, 0.5, 1],
183+
// theta
184+
Math.PI / 4,
185+
// phi
186+
Math.PI * 3 / 5,
187+
// raidus
188+
0.5
189+
)
190+
break;
191+
}
112192

193+
console.log('splat src', pcSrc)
113194

114195
wx.downloadFile({
115-
url: plySrc,
196+
url: pcSrc,
116197
timeout: 200000,
117198
success: (res) => {
118199
console.log("downloadFile 下载回调", res);
@@ -158,12 +239,23 @@ Component({
158239

159240
// console.log('buffer', buffer)
160241

161-
const plyInfo = loadPly(buffer);
242+
let info;
162243

163-
console.log("plyLoader return", plyInfo);
244+
const maxGaussians = this.data.maxGaussians;
245+
246+
switch (type) {
247+
case 'ply':
248+
info = loadPly(buffer, maxGaussians);
249+
console.log("plyLoader return", info);
250+
break;
251+
case 'splat':
252+
info = loadSplat(buffer, maxGaussians);
253+
console.log("splatLoader return", info);
254+
break;
255+
}
164256

165257
// 初始化 worker 相关
166-
this.initWorker(plyInfo, {
258+
this.initWorker(info, {
167259
maxGaussians
168260
});
169261

@@ -176,33 +268,6 @@ Component({
176268
})
177269
console.error('file size is 0')
178270
}
179-
180-
// fs.readFile({
181-
// filePath: filePath,
182-
// position: 0,
183-
// success: async (res) => {
184-
// console.log("readFile 读文件回调,结果返回为", res)
185-
186-
// const plyInfo = loadPly(res.data);
187-
188-
// console.log("plyLoader return", plyInfo);
189-
190-
// // 初始化 worker 相关
191-
// this.initWorker(plyInfo, {
192-
// maxGaussians
193-
// });
194-
195-
// },
196-
// fail(res) {
197-
// wx.hideLoading();
198-
// wx.showToast({
199-
// title: res.errMsg,
200-
// icon: 'none',
201-
// duration: 2000
202-
// })
203-
// console.error(res)
204-
// }
205-
// });
206271
},
207272
fail(res) {
208273
wx.hideLoading();
@@ -235,6 +300,8 @@ Component({
235300

236301
this.camera.isWorkerSorting = false;
237302

303+
const start = new Date().getTime()
304+
238305
const data = res.result.data
239306

240307
const gl = this.gl
@@ -265,7 +332,17 @@ Component({
265332

266333
this.gaussiansCount = data.gaussiansCount;
267334

268-
this.requestRender();
335+
console.log('gaussiansCount', this.gaussiansCount)
336+
337+
338+
const end = new Date().getTime()
339+
340+
const sortTime = `${((end - start)/1000).toFixed(3)}s`
341+
console.log(`updateBuffer ${sortTime}`)
342+
343+
// this.requestRender();
344+
this.canvas.requestAnimationFrame(this.requestRender.bind(this));
345+
269346
// console.log('execFunc_sort end')
270347
}
271348
})
@@ -284,17 +361,8 @@ Component({
284361
console.log('webgl2 context', gl);
285362

286363
// Setup Camera
287-
// Normal
288-
// const cameraParameters = {
289-
// up: [0, 1.0, 0.0],
290-
// // target: [0, 2.5, 2.5],
291-
// target: [0, 0, 0],
292-
// camera: [-Math.PI/2, Math.PI/2, 10], // theta phi radius
293-
// }
294-
// Room
295364
const cameraParameters = {
296365
up: [0, 1.0, 0.0],
297-
// target: [0, 2.5, 2.5],
298366
target: [0, 1, 0],
299367
camera: [-Math.PI/2, Math.PI/2, 4], // theta phi radius
300368
}
@@ -313,8 +381,20 @@ Component({
313381
},
314382
requestRender() {
315383
// console.log('requestRender')
384+
385+
// 限帧
386+
let now = Date.now()
387+
const last = this.lastRenderTime || 0;
388+
const mill = now - last
389+
if (mill < 30) {
390+
return
391+
}
392+
this.lastRenderTime = now
393+
316394
const gl = this.gl;
317395

396+
const start = new Date().getTime()
397+
318398
// Clear State
319399
gl.viewport(0, 0, gl.canvas.width, gl.canvas.height)
320400
gl.clearColor(0, 0, 0, 0.0);
@@ -323,6 +403,8 @@ Component({
323403
gl.disable(gl.DEPTH_TEST)
324404
gl.enable(gl.BLEND)
325405
gl.blendFunc(gl.ONE_MINUS_DST_ALPHA, gl.ONE)
406+
// gl.blendFuncSeparate(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE_MINUS_SRC_ALPHA)
407+
326408

327409
// clear
328410
gl.clear(gl.COLOR_BUFFER_BIT);
@@ -333,7 +415,12 @@ Component({
333415

334416
// this.drawCubeMesh(gl, projMatrix, viewMatrix)
335417

418+
336419
this.drawSplat(gl);
420+
421+
// const end = new Date().getTime()
422+
// const sortTime = `${((end - start)/1000).toFixed(4)}s`
423+
// console.log(`requestRender ${sortTime}`)
337424
},
338425
drawCubeMesh(gl, projMatrix, viewMatrix) {
339426
// mesh
@@ -413,8 +500,7 @@ Component({
413500
gl.uniformMatrix4fv(gl.getUniformLocation(program, 'projmatrix'), false, cam.vpm)
414501
gl.uniformMatrix4fv(gl.getUniformLocation(program, 'viewmatrix'), false, cam.vm)
415502

416-
417-
// Draw
503+
// Draw
418504
gl.drawArraysInstanced(gl.TRIANGLE_STRIP, 0, 4, this.gaussiansCount);
419505

420506
},
@@ -438,8 +524,33 @@ Component({
438524

439525
this.camera.update();
440526

441-
this.requestRender();
527+
// this.requestRender();
528+
this.canvas.requestAnimationFrame(this.requestRender.bind(this));
442529
},
530+
onTapControl(e) {
531+
const dataSet = e.target.dataset;
532+
533+
const id = dataSet.id;
534+
535+
// 开始处理 ply 资源
536+
this.initPLY(id);
537+
},
538+
changeMaxGaussianCount(e) {
539+
this.setData({
540+
maxGaussians: e.detail.value
541+
})
542+
543+
console.log('slider maxGaussians:', this.data.maxGaussians);
544+
},
545+
switchWorker(e) {
546+
this.setData({
547+
workerOn: e.detail.value
548+
})
549+
550+
this.camera.setWorkerOn(this.data.workerOn);
551+
552+
console.log('switch WorkerOn:', this.data.workerOn);
553+
}
443554
},
444555
})
445556

miniprogram/packageAPI/pages/ar/gaussian-splatting/gaussian-splatting.wxml

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,5 +17,26 @@
1717
<canvas type="webgl2" id="canvas" bindtouchstart="onTouchStartWebGL" bindtouchmove="onTouchMoveWebGL"></canvas>
1818
</view>
1919
</view>
20+
<view class="control-wrap">
21+
<view class="title">经典 Splat</view>
22+
<view class="block">
23+
<button class="btn" type="primary" data-id="room" bindtap="onTapControl">房间</button>
24+
<button class="btn" type="primary" data-id="garden" bindtap="onTapControl">花园</button>
25+
<button class="btn" type="primary" data-id="stump" bindtap="onTapControl">树桩</button>
26+
</view>
27+
<view class="title">自制 Splat</view>
28+
<view class="block">
29+
<button class="btn" type="primary" data-id="oneflower" bindtap="onTapControl">盆栽</button>
30+
<button class="btn" type="primary" data-id="usj" bindtap="onTapControl">USJ马里奥</button>
31+
<button class="btn" type="primary" data-id="sakura" bindtap="onTapControl">樱花小道</button>
32+
</view>
33+
</view>
34+
<view class="input-wrap">
35+
<view class="title">最大高斯球数</view>
36+
<slider class="slider" bindchange="changeMaxGaussianCount" min="0" max="1200000" value="{{maxGaussians}}" show-value/>
37+
<view class="checkbox-wrap"><p class="words">是否开启 worker 排序</p><switch class="checkbox" type="checkbox" checked="{{workerOn}}" bindchange="switchWorker"/></view>
38+
39+
40+
</view>
2041
</view>
2142

0 commit comments

Comments
 (0)